Merge pull request #156 from anandpdoshi/master

Email Digest and patch to remove duplicate entries created in Table Mapper Detail
This commit is contained in:
Nabin Hait 2011-12-13 05:37:41 -08:00
commit dcac0e7565
43 changed files with 1510 additions and 157 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -124,7 +124,7 @@ pscript.make_ac_tree = function() {
var imgsrc=null;
var has_children = true;
if(cl[i].group_or_ledger=='Ledger') {
var imgsrc = 'images/icons/page.gif';
var imgsrc = 'lib/images/icons/page.gif';
has_children = false;
}
var t = tree.addNode(n, cl[i].account_name, imgsrc,tree.std_onclick, has_children ? tree.std_onexp : null);
@ -137,7 +137,7 @@ pscript.make_ac_tree = function() {
var imgsrc=null;
var has_children = true;
if(cl[i].group_or_ledger=='Ledger') {
var imgsrc = 'images/icons/page.gif';
var imgsrc = 'lib/images/icons/page.gif';
has_children = false;
}
var t = tree.addNode(n, cl[i].cost_center_name, imgsrc,tree.std_onclick, has_children ? tree.std_onexp : null);
@ -254,7 +254,7 @@ pscript.make_group_area = function(type) {
// refresh
ref_btn = $a(pscript.group_area, 'div', '', {fontSize: '14px',marginBottom: '8px', marginTop: '24px', fontWeight: 'bold'});
ref_btn.innerHTML = '<img src="images/icons/page_refresh.gif" style="margin-right: 8px"><span class="link_type">Refresh Tree</span>';
ref_btn.innerHTML = '<img src="lib/images/icons/page_refresh.gif" style="margin-right: 8px"><span class="link_type">Refresh Tree</span>';
ref_btn.onclick= function() {
pscript.cur_node.clear_child_nodes();
pscript.cur_node.expand();
@ -312,7 +312,7 @@ pscript.make_ledger_area = function() {
//General ledger report link
pscript.gl_rep = $a(pscript.ledger_area, 'div','', {fontSize: '14px',marginBottom: '8px', fontWeight: 'bold'});
pscript.gl_rep.innerHTML = '<img src="images/icons/report.png" style="margin-right: 8px"><span class="link_type">Open Ledger</span>';
pscript.gl_rep.innerHTML = '<img src="lib/images/icons/report.png" style="margin-right: 8px"><span class="link_type">Open Ledger</span>';
pscript.gl_rep.onclick = function(){ pscript.make_report('gl'); }
//Budget report link

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,8 +10,20 @@ pscript.onload_dashboard = function() {
pscript.dashboard_settings = {
company: sys_defaults.company,
start: dateutil.obj_to_str(dateutil.add_days(new Date(), -180)),
end: dateutil.obj_to_str(new Date()),
start: (function() {
var start_date = dateutil.add_days(new Date(), -180);
var year_start_date = dateutil.str_to_obj(sys_defaults.year_start_date);
if (start_date < year_start_date) { start_date = year_start_date; }
console.log(start_date);
return dateutil.obj_to_str(start_date);
})(),
end: (function() {
var end_date = new Date();
var year_end_date = dateutil.str_to_obj(sys_defaults.year_end_date);
if (end_date > year_end_date) { end_date = year_end_date; }
console.log(end_date);
return dateutil.obj_to_str(end_date);
})(),
interval: 30
}

View File

@ -134,18 +134,26 @@ class DashboardWidget:
print acc
raise e
return self.glc.get_as_on_balance(acc, self.get_fiscal_year(start), start, debit_or_credit, lft, rgt)
fiscal_year = self.get_fiscal_year(start)
if fiscal_year:
return self.glc.get_as_on_balance(acc, fiscal_year, start, debit_or_credit, lft, rgt)
else:
webnotes.msgprint('Please select the START DATE and END DATE such that\
they fall within <b>fiscal year(s)</b> as defined in\
Setup > System > Fiscal Year.', raise_exception=1)
def get_fiscal_year(self, dt):
"""
get fiscal year from date
"""
import webnotes
return webnotes.conn.sql("""
fiscal_year = webnotes.conn.sql("""
select name from `tabFiscal Year`
where year_start_date <= %s and
DATE_ADD(year_start_date, INTERVAL 1 YEAR) >= %s
""", (dt, dt))[0][0]
""", (dt, dt))
return fiscal_year and (fiscal_year[0] and fiscal_year[0][0]) or None
def get_creation_trend(self, doctype, start, end):
"""

View File

@ -0,0 +1,75 @@
import webnotes
def execute():
"""
* Reload email_digest doctype
* Create default email digest
"""
from webnotes.modules.module_manager import reload_doc
# Minor fix in print_format doctype
#reload_doc('core', 'doctype', 'print_format')
reload_doc('setup', 'doctype', 'email_digest')
global create_default_email_digest
create_default_email_digest()
def create_default_email_digest():
"""
* Weekly Digest
* For all companies
* Recipients: System Managers
* Full content
* Disabled by default
"""
from webnotes.model.doc import Document
companies_list = webnotes.conn.sql("SELECT company_name FROM `tabCompany`", as_list=1)
global get_system_managers
system_managers = get_system_managers()
for company in companies_list:
if company and company[0]:
edigest = Document('Email Digest')
edigest.name = "Default Weekly Digest - " + company[0]
edigest.company = company[0]
edigest.frequency = 'Weekly'
edigest.recipient_list = system_managers
edigest.new_leads = 1
edigest.new_enquiries = 1
edigest.new_quotations = 1
edigest.new_sales_orders = 1
edigest.new_purchase_orders = 1
edigest.new_transactions = 1
edigest.payables = 1
edigest.payments = 1
edigest.expenses_booked = 1
edigest.invoiced_amount = 1
edigest.collections = 1
edigest.income = 1
edigest.bank_balance = 1
exists = webnotes.conn.sql("""\
SELECT name FROM `tabEmail Digest`
WHERE name = %s""", edigest.name)
if (exists and exists[0]) and exists[0][0]:
continue
else:
edigest.save(1)
def get_system_managers():
"""
Returns a string of system managers' email addresses separated by \n
"""
system_managers_list = webnotes.conn.sql("""\
SELECT DISTINCT p.name
FROM tabUserRole ur, tabProfile p
WHERE
ur.parent = p.name AND
ur.role='System Manager' AND
p.docstatus<2 AND
p.enabled=1 AND
p.name not in ('Administrator', 'Guest')""", as_list=1)
return "\n".join([sysman[0] for sysman in system_managers_list])

View File

@ -53,7 +53,7 @@ def execute():
Install print formats
"""
from webnotes.modules.module_manager import reload_doc
#reload_doc('core', 'doctype', 'print_format')
reload_doc('core', 'doctype', 'print_format')
#copy_doctype_to_pfs()
global pf_to_install

View File

@ -112,17 +112,26 @@
null,
{
'description' : function(data_row) {
if(data_row.serial_no) {
return (
data_row.description +
'<div style="padding-left: 15px;"><i>Serial No.:' +
((data_row.serial_no.indexOf('\n')>-1)?'<br />':'&nbsp;') +
data_row.serial_no + '</i></div>'
);
} else {
return data_row.description;
var to_append = ''
if(data_row.adj_rate){
to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
data_row.description = data_row.description + to_append;
}
}
if(data_row.serial_no) {
to_append = '<div style="padding-left: 15px;"><i>Serial No.:' +
((data_row.serial_no.indexOf('\n')>-1)?'<br />':'&nbsp;') +
data_row.serial_no + '</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
data_row.description = data_row.description + to_append;
}
}
return data_row.description;
}
}
);
@ -176,7 +185,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td><h1>Delivery Note</h1></td></tr>
<tr><td><script>'<h1>' + (doc.select_print_heading || 'Delivery Note') + '</h1>'</script></td></tr>
<tr><td><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>

View File

@ -135,17 +135,26 @@
null,
{
'description' : function(data_row) {
if(data_row.serial_no) {
return (
data_row.description +
'<div style="padding-left: 15px;"><i>Serial No.:' +
((data_row.serial_no.indexOf('\n')>-1)?'<br />':'&nbsp;') +
data_row.serial_no + '</i></div>'
);
} else {
return data_row.description;
var to_append = ''
if(data_row.adj_rate){
to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
data_row.description = data_row.description + to_append;
}
}
if(data_row.serial_no) {
to_append = '<div style="padding-left: 15px;"><i>Serial No.:' +
((data_row.serial_no.indexOf('\n')>-1)?'<br />':'&nbsp;') +
data_row.serial_no + '</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
data_row.description = data_row.description + to_append;
}
}
return data_row.description;
}
}
);
@ -199,7 +208,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><div><h1>Delivery Note</h1></div></td></tr>
<tr><td colspan=2><div><script>'<h1>' + (doc.select_print_heading || 'Delivery Note') + '</h1>'</script></div></td></tr>
<tr><td colspan=2><div style="height:15px"></div></td></tr>
</thead>
<tbody>
@ -303,4 +312,3 @@
</tfoot>
</table>
</div>

View File

@ -134,17 +134,26 @@
null,
{
'description' : function(data_row) {
if(data_row.serial_no) {
return (
data_row.description +
'<div style="padding-left: 15px;"><i>Serial No.:' +
((data_row.serial_no.indexOf('\n')>-1)?'<br />':'&nbsp;') +
data_row.serial_no + '</i></div>'
);
} else {
return data_row.description;
var to_append = ''
if(data_row.adj_rate){
to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
data_row.description = data_row.description + to_append;
}
}
if(data_row.serial_no) {
to_append = '<div style="padding-left: 15px;"><i>Serial No.:' +
((data_row.serial_no.indexOf('\n')>-1)?'<br />':'&nbsp;') +
data_row.serial_no + '</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
data_row.description = data_row.description + to_append;
}
}
return data_row.description;
}
}
);
@ -198,7 +207,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><h1>Delivery Note</h1></td></tr>
<tr><td colspan=2><script>'<h1>' + (doc.select_print_heading || 'Delivery Note') + '</h1>'</script></td></tr>
<tr><td colspan=2><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -298,5 +307,3 @@
</tfoot>
</table>
</div>

View File

@ -160,7 +160,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td><h1>Purchase Order</h1></td></tr>
<tr><td><script>'<h1>' + (doc.select_print_heading || 'Purchase Order') + '</h1>'</script></td></tr>
<tr><td><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -246,4 +246,3 @@
</tfoot>
</table>
</div>

View File

@ -183,7 +183,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><div><h1>Purchase Order</h1></div></td></tr>
<tr><td colspan=2><div><script>'<h1>' + (doc.select_print_heading || 'Purchase Order') + '</h1>'</script></div></td></tr>
<tr><td colspan=2><div style="height:15px"></div></td></tr>
</thead>
<tbody>
@ -273,4 +273,3 @@
</tfoot>
</table>
</div>

View File

@ -182,7 +182,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><h1>Purchase Order</h1></td></tr>
<tr><td colspan=2><script>'<h1>' + (doc.select_print_heading || 'Purchase Order') + '</h1>'</script></td></tr>
<tr><td colspan=2><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -268,5 +268,3 @@
</tfoot>
</table>
</div>

View File

@ -107,7 +107,22 @@
[// Here specify the column widths
'3%', '10%', '15%', '32%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -160,7 +175,9 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td><h1>Quotation</h1></td></tr>
<tr><td>
<script>'<h1>' + (doc.select_print_heading || 'Quotation') + '</h1>'</script>
</td></tr>
<tr><td><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -253,4 +270,3 @@
</tfoot>
</table>
</div>

View File

@ -130,7 +130,22 @@
[// Here specify the column widths
'3%', '10%', '15%', '32%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -183,7 +198,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><div><h1>Quotation</h1></div></td></tr>
<tr><td colspan=2><div><script>'<h1>' + (doc.select_print_heading || 'Quotation') + '</h1>'</script></div></td></tr>
<tr><td colspan=2><div style="height:15px"></div></td></tr>
</thead>
<tbody>
@ -280,4 +295,3 @@
</tfoot>
</table>
</div>

View File

@ -129,7 +129,22 @@
[// Here specify the column widths
'3%', '10%', '15%', '32%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -182,7 +197,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><h1>Quotation</h1></td></tr>
<tr><td colspan=2><script>'<h1>' + (doc.select_print_heading || 'Quotation') + '</h1>'</script></td></tr>
<tr><td colspan=2><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -275,5 +290,3 @@
</tfoot>
</table>
</div>

View File

@ -107,7 +107,22 @@
[// Here specify the column widths
'3%', '20%', '37%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -128,7 +143,6 @@
print_other_charges: function(parent) {
console.log(parent);
var oc = getchildren('RV Tax Detail', doc.name, 'other_charges');
var rows = '<table width=100%>\n';
for(var i=0; i<oc.length; i++) {
@ -161,7 +175,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td><h1>Invoice</h1></td></tr>
<tr><td><script>'<h1>' + (doc.select_print_heading || 'Invoice') + '</h1>'</script></td></tr>
<tr><td><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -258,4 +272,3 @@
</tfoot>
</table>
</div>

View File

@ -130,7 +130,22 @@
[// Here specify the column widths
'3%', '20%', '37%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -151,7 +166,6 @@
print_other_charges: function(parent) {
console.log(parent);
var oc = getchildren('RV Tax Detail', doc.name, 'other_charges');
var rows = '<table width=100%>\n';
for(var i=0; i<oc.length; i++) {
@ -184,7 +198,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><div><h1>Invoice</h1></div></td></tr>
<tr><td colspan=2><div><script>'<h1>' + (doc.select_print_heading || 'Invoice') + '</h1>'</script></div></td></tr>
<tr><td colspan=2><div style="height:15px"></div></td></tr>
</thead>
<tbody>
@ -285,4 +299,3 @@
</tfoot>
</table>
</div>

View File

@ -129,7 +129,22 @@
[// Here specify the column widths
'3%', '20%', '37%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -150,7 +165,6 @@
print_other_charges: function(parent) {
console.log(parent);
var oc = getchildren('RV Tax Detail', doc.name, 'other_charges');
var rows = '<table width=100%>\n';
for(var i=0; i<oc.length; i++) {
@ -183,7 +197,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><h1>Invoice</h1></td></tr>
<tr><td colspan=2><script>'<h1>' + (doc.select_print_heading || 'Invoice') + '</h1>'</script></td></tr>
<tr><td colspan=2><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -280,5 +294,3 @@
</tfoot>
</table>
</div>

View File

@ -107,7 +107,22 @@
[// Here specify the column widths
'3%', '20%', '37%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -160,7 +175,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td><h1>Sales Order</h1></td></tr>
<tr><td><script>'<h1>' + (doc.select_print_heading || 'Sales Order') + '</h1>'</script></td></tr>
<tr><td><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -257,4 +272,3 @@
</tfoot>
</table>
</div>

View File

@ -130,7 +130,22 @@
[// Here specify the column widths
'3%', '20%', '37%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -183,7 +198,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><div><h1>Sales Order</h1></div></td></tr>
<tr><td colspan=2><div><script>'<h1>' + (doc.select_print_heading || 'Sales Order') + '</h1>'</script></div></td></tr>
<tr><td colspan=2><div style="height:15px"></div></td></tr>
</thead>
<tbody>
@ -284,4 +299,3 @@
</tfoot>
</table>
</div>

View File

@ -129,7 +129,22 @@
[// Here specify the column widths
'3%', '20%', '37%', '5%',
'5%', '15%', '15%'
]
],
null,
null,
{
'description' : function(data_row) {
if(data_row.adj_rate) {
var to_append = '<div style="padding-left: 15px;"><i>Discount: ' +
data_row.adj_rate + '%</i></div>';
if(data_row.description.indexOf(to_append)==-1) {
return data_row.description + to_append;
} else { return data_row.description; }
} else {
return data_row.description;
}
}
}
);
// This code takes care of page breaks
@ -182,7 +197,7 @@
-->
<table class='header-table' cellspacing=0>
<thead>
<tr><td colspan=2><h1>Sales Order</h1></td></tr>
<tr><td colspan=2><script>'<h1>' + (doc.select_print_heading || 'Sales Order') + '</h1>'</script></td></tr>
<tr><td colspan=2><h3><script>cur_frm.docname</script></h3></td></tr>
</thead>
<tbody>
@ -279,5 +294,3 @@
</tfoot>
</table>
</div>

View File

@ -0,0 +1,7 @@
"""
Reload Task Doctype of Project Module
"""
def execute():
from webnotes.modules.module_manager import reload_doc
reload_doc('Projects', 'DocType', 'Ticket')

View File

@ -0,0 +1,22 @@
"""
Removes duplicate entries created in
"""
import webnotes
def execute():
res = webnotes.conn.sql("""\
SELECT a.name
FROM
`tabTable Mapper Detail` a,
`tabTable Mapper Detail` b
WHERE
a.parent = b.parent AND
a.from_table = b.from_table AND
a.to_table = b.to_table AND
a.from_field = b.from_field AND
a.to_field = b.to_field AND
a.name < b.name""")
if res and len(res)>0:
name_string = ", ".join(["'" + str(r[0]) + "'" for r in res])
res = webnotes.conn.sql("""\
DELETE FROM `tabTable Mapper Detail`
WHERE name IN (%s)""" % name_string)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -139,7 +139,7 @@ SalesBrowser.prototype.make_tree = function() {
var has_children = true;
if(cl[i].is_group=='No') {
var imgsrc = 'images/icons/page.gif';
var imgsrc = 'lib/images/icons/page.gif';
has_children = false;
}
var t = me.tree.addNode(n, cl[i].name, imgsrc,me.tree.std_onclick, has_children ? me.tree.std_onexp : null);
@ -219,7 +219,7 @@ SalesBrowser.prototype.first_level_node = function(){
var has_children = true;
if(cl[i].is_group=='No') {
var imgsrc = 'images/icons/page.gif';
var imgsrc = 'lib/images/icons/page.gif';
has_children = false;
}
me.tree_area.innerHTML = '';

View File

@ -0,0 +1,10 @@
table.profile-list {
text-align: left;
margin: auto;
line-height: 250%;
}
div.dialog-div {
text-align: 'center';
width: 100%;
}

View File

@ -0,0 +1,90 @@
cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.add_custom_button('View Now', function() {
$c_obj(make_doclist(dt, dn), 'get', '', function(r, rt) {
if(r.exc) {
msgprint(r.exc);
} else {
//console.log(arguments);
var d = new wn.widgets.Dialog({
title: 'Email Digest: ' + dn,
width: 800
});
$a(d.body, 'div', '', '', r['message'][1]);
d.show();
}
});
}, 1);
cur_frm.add_custom_button('Send Now', function() {
$c_obj(make_doclist(dt, dn), 'send', '', function(r, rt) {
if(r.exc) {
msgprint(r.exc);
} else {
//console.log(arguments);
msgprint('Message Sent');
}
});
}, 1);
}
cur_frm.cscript['Add Recipients'] = function(doc, dt, dn) {
// Get profile list
$c_obj(make_doclist(dt, dn), 'get_profiles', '', function(r, rt) {
if(r.exc) {
msgprint(r.exc);
} else {
// Open a dialog and display checkboxes against email addresses
doc = locals[dt][dn];
var d = new wn.widgets.Dialog({
title: 'Add Recipients',
width: 400
});
var dialog_div = $a(d.body, 'div', 'dialog-div', '', '');
var tab = make_table(dialog_div, r.profile_list.length+2, 2, '', ['15%', '85%']);
tab.className = 'profile-list';
var add_or_update = 'Add';
$.each(r.profile_list, function(i, v) {
var check = $a_input($td(tab, i+1, 0), 'checkbox');
check.value = v.name;
if(v.checked==1) {
check.checked = 1;
add_or_update = 'Update';
}
if(v.enabled==0) {
v.name = "<span style='color: red'>" + v.name + " (disabled user)</span>"
}
var profile = $a($td(tab, i+1, 1), 'span', '', '', v.name);
//profile.onclick = function() { check.checked = !check.checked; }
});
// Display add recipients button
if(r.profile_list.length>15) {
$btn($td(tab, 0, 1), add_or_update + ' Recipients', function() {
cur_frm.cscript.add_to_rec_list(doc, tab, r.profile_list.length);
});
}
$btn($td(tab, r.profile_list.length+1, 1), add_or_update + ' Recipients', function() {
cur_frm.cscript.add_to_rec_list(doc, tab, r.profile_list.length);
});
cur_frm.rec_dialog = d;
d.show();
}
});
}
cur_frm.cscript.add_to_rec_list = function(doc, tab, length) {
// add checked profiles to list of recipients
var rec_list = [];
for(var i = 1; i <= length; i++) {
var input = $($td(tab, i, 0)).find('input');
if(input.is(':checked')) {
rec_list.push(input.attr('value'));
}
}
doc.recipient_list = rec_list.join('\n');
//console.log(doc.recipient_list);
cur_frm.rec_dialog.hide();
cur_frm.refresh_fields();
}

View File

@ -0,0 +1,734 @@
import webnotes
class DocType:
def __init__(self, doc, doclist=[]):
self.doc, self.doclist = doc, doclist
self.sending = False
def get_profiles(self):
"""
Get a list of profiles
"""
import webnotes
profile_list = webnotes.conn.sql("""
SELECT name, enabled FROM tabProfile
WHERE docstatus=0 AND name NOT IN ('Administrator', 'Guest')
ORDER BY enabled DESC, name ASC""", as_dict=1)
if self.doc.recipient_list:
recipient_list = self.doc.recipient_list.split("\n")
else:
recipient_list = []
for p in profile_list:
if p['name'] in recipient_list: p['checked'] = 1
else: p['checked'] = 0
webnotes.response['profile_list'] = profile_list
def get_standard_data(self):
"""
Executes standard queries
"""
res = {}
query_dict = {
'invoiced_amount': self.generate_gle_query({
'type': 'invoiced_amount',
'field': 'debit',
'master_type': 'Customer',
}),
'payables': self.generate_gle_query({
'type': 'payables',
'field': 'credit',
'master_type': 'Supplier',
}),
'collections': self.generate_gle_query({
'type': 'collections',
'field': 'credit',
'master_type': 'Customer',
}),
'payments': self.generate_gle_query({
'type': 'payments',
'field': 'debit',
'master_type': 'Supplier',
}),
'income': self.generate_gle_query({
'type': 'income',
'debit_or_credit': 'Credit'
}),
'expenses_booked': self.generate_gle_query({
'type': 'expenses_booked',
'debit_or_credit': 'Debit'
}),
'bank_balance': self.generate_gle_query({
'type': 'bank_balance'
}),
'new_leads': self.generate_new_type_query({
'type': 'new_leads',
'doctype': 'Lead'
}),
'new_enquiries': self.generate_new_type_query({
'type': 'new_enquiries',
'doctype': 'Enquiry'
}),
'new_quotations': self.generate_new_type_query({
'type': 'new_quotations',
'doctype': 'Quotation',
'sum_col': 'grand_total'
}),
'new_sales_orders': self.generate_new_type_query({
'type': 'new_sales_orders',
'doctype': 'Receivable Voucher',
'sum_col': 'grand_total'
}),
'new_purchase_orders': self.generate_new_type_query({
'type': 'new_purchase_orders',
'doctype': 'Purchase Order',
'sum_col': 'grand_total'
}),
'new_transactions': self.generate_new_type_query({
'type': 'new_transactions',
'doctype': 'Feed'
}),
'stock_below_rl': ""
}
result = {}
for query in query_dict.keys():
if self.doc.fields[query]:
#webnotes.msgprint(query)
res = webnotes.conn.sql(query_dict[query], as_dict=1)
if query == 'income':
for r in res:
r['value'] = float(r['credit'] - r['debit'])
elif query in ['expenses_booked', 'bank_balance']:
for r in res:
r['value'] = float(r['debit'] - r['credit'])
#webnotes.msgprint(query)
#webnotes.msgprint(res)
result[query] = (res and len(res)==1) and res[0] or (res and res or None)
#webnotes.msgprint(result)
return result
def generate_gle_query(self, args):
"""
Returns generated query string based 'tabGL Entry' and 'tabAccount'
"""
self.process_args(args)
query = None
if args['type'] in ['invoiced_amount', 'payables']:
query = """
SELECT
IFNULL(SUM(IFNULL(gle.%(field)s, 0)), 0) AS '%(field)s',
%(common_select)s
FROM
%(common_from)s
WHERE
%(common_where)s AND
ac.master_type = '%(master_type)s' AND
%(start_date_condition)s AND
%(end_date_condition)s""" % args
elif args['type'] in ['collections', 'payments']:
args['bc_accounts_regex'] = self.get_bc_accounts_regex()
query = """
SELECT
IFNULL(SUM(IFNULL(gle.%(field)s, 0)), 0) AS '%(field)s',
%(common_select)s
FROM
%(common_from)s
WHERE
%(common_where)s AND
ac.master_type = '%(master_type)s' AND
gle.against REGEXP '%(bc_accounts_regex)s' AND
%(start_date_condition)s AND
%(end_date_condition)s""" % args
elif args['type'] in ['income', 'expenses_booked']:
query = """
SELECT
IFNULL(SUM(IFNULL(gle.debit, 0)), 0) AS 'debit',
IFNULL(SUM(IFNULL(gle.credit, 0)), 0) AS 'credit',
%(common_select)s
FROM
%(common_from)s
WHERE
%(common_where)s AND
ac.is_pl_account = 'Yes' AND
ac.debit_or_credit = '%(debit_or_credit)s' AND
%(start_date_condition)s AND
%(end_date_condition)s""" % args
elif args['type'] == 'bank_balance':
query = """
SELECT
ac.account_name AS 'name',
IFNULL(SUM(IFNULL(gle.debit, 0)), 0) AS 'debit',
IFNULL(SUM(IFNULL(gle.credit, 0)), 0) AS 'credit',
%(common_select)s
FROM
%(common_from)s
WHERE
%(common_where)s AND
ac.account_type = 'Bank or Cash' AND
%(end_date_condition)s
GROUP BY
ac.account_name""" % args
return query
def process_args(self, args):
"""
Adds common conditions in dictionary "args"
"""
start_date, end_date = self.get_start_end_dates()
if 'new' in args['type']:
args.update({
'company': self.doc.company,
'start_date': start_date,
'end_date': end_date,
'sum_if_reqd': ''
})
if args['type'] in ['new_quotations', 'new_sales_orders', 'new_purchase_orders']:
args['sum_if_reqd'] = "IFNULL(SUM(IFNULL(%(sum_col)s, 0)), 0) AS '%(sum_col)s'," % args
if args['type'] == 'new_transactions':
args['company_condition'] = ''
else:
args['company_condition'] = "company = '%(company)s' AND" % args
else:
args.update({
'common_select': "COUNT(*) AS 'count'",
'common_from': "`tabGL Entry` gle, `tabAccount` ac",
'common_where': """
gle.company = '%s' AND
gle.account = ac.name AND
ac.docstatus < 2 AND
IFNULL(gle.is_cancelled, 'No') = 'No'""" % self.doc.company,
'start_date_condition': "gle.posting_date >= '%s'" % start_date,
'end_date_condition': "gle.posting_date <= '%s'" % end_date
})
def get_start_end_dates(self):
"""
Returns start and end date depending on the frequency of email digest
"""
from datetime import datetime, date, timedelta
today = datetime.now().date()
year, month, day = today.year, today.month, today.day
if self.doc.frequency == 'Daily':
if self.sending:
start_date = end_date = today - timedelta(days=1)
else:
start_date = end_date = today
elif self.doc.frequency == 'Weekly':
if self.sending:
start_date = today - timedelta(days=today.weekday(), weeks=1)
end_date = start_date + timedelta(days=6)
else:
start_date = today - timedelta(days=today.weekday())
end_date = start_date + timedelta(days=6)
else:
import calendar
if self.sending:
if month == 1:
year = year - 1
prev_month = 12
else:
prev_month = month - 1
start_date = date(year, prev_month, 1)
last_day = calendar.monthrange(year, prev_month)[1]
end_date = date(year, prev_month, last_day)
else:
start_date = date(year, month, 1)
last_day = calendar.monthrange(year, month)[1]
end_date = date(year, month, last_day)
return start_date, end_date
def generate_new_type_query(self, args):
"""
Returns generated query string for calculating new transactions created
"""
self.process_args(args)
query = """
SELECT
%(sum_if_reqd)s
COUNT(*) AS 'count'
FROM
`tab%(doctype)s`
WHERE
docstatus < 2 AND
%(company_condition)s
creation >= '%(start_date)s' AND
creation <= '%(end_date)s'""" % args
return query
def get_bc_accounts_regex(self):
"""
Returns a regular expression of 'Bank or Cash' type account list
"""
bc_account_list = webnotes.conn.sql("""
SELECT name
FROM `tabAccount`
WHERE account_type = 'Bank or Cash'""", as_list=1)
return '(' + '|'.join([ac[0] for ac in bc_account_list]) + ')'
def get(self):
"""
* Execute Query
* Prepare Email Body from Print Format
"""
result, email_body = self.execute_queries()
#webnotes.msgprint(result)
#webnotes.msgprint(email_body)
return result, email_body
def execute_queries(self):
"""
* If standard==1, execute get_standard_data
* If standard==0, execute python code in custom_code field
"""
result = {}
if int(self.doc.use_standard)==1:
result = self.get_standard_data()
email_body = self.get_standard_body(result)
else:
result, email_body = self.execute_custom_code(self.doc)
#webnotes.msgprint(result)
return result, email_body
def execute_custom_code(self, doc):
"""
Execute custom python code
"""
pass
def send(self):
"""
* Execute get method
* Send email to recipients
"""
self.sending = True
result, email_body = self.get()
recipient_list = self.doc.recipient_list.split("\n")
# before sending, check if user is disabled or not
# do not send if disabled
profile_list = webnotes.conn.sql("SELECT name, enabled FROM tabProfile", as_dict=1)
for profile in profile_list:
if profile['name'] in recipient_list and profile['enabled'] == 0:
del recipient_list[recipient_list.index(profile['name'])]
from webnotes.utils.email_lib import sendmail
try:
sendmail(
recipients=recipient_list,
sender='notifications+email_digest@erpnext.com',
reply_to='support@erpnext.com',
subject=self.doc.frequency + ' Digest',
msg=email_body,
from_defs=1
)
except Exception, e:
webnotes.msgprint('There was a problem in sending your email. Please contact support@erpnext.com')
#webnotes.errprint(webnotes.getTraceback())
def on_update(self):
"""
"""
import webnotes
args = {
'db_name': webnotes.conn.get_value('Control Panel', '', 'account_id'),
'event': 'setup.doctype.email_digest.email_digest.send'
}
from webnotes.utils.scheduler import Scheduler
print "before scheduler"
sch = Scheduler()
sch.connect()
if self.doc.enabled == 1:
# Create scheduler entry
res = sch.conn.sql("""
SELECT * FROM Event
WHERE
db_name = %(db_name)s AND
event = %(event)s
""", args)
if not (res and res[0]):
args['next_execution'] = self.get_next_execution()
sch.conn.sql("""
INSERT INTO Event (db_name, event, `interval`, next_execution, recurring)
VALUES (%(db_name)s, %(event)s, 86400, %(next_execution)s, 1)
""", args)
else:
# delete scheduler entry
sch.clear(args['db_name'], args['event'])
print "after on update"
def get_next_sending(self):
"""
"""
# Get TimeZone
# Get System TimeZone
import time
from pytz import timezone
import datetime
import webnotes.defs
cp = webnotes.model.doc.Document('Control Panel','Control Panel')
app_tz = timezone(cp.time_zone)
server_tz = timezone(getattr(webnotes.defs, 'system_timezone'))
start_date, end_date = self.get_start_end_dates()
new_date = end_date + datetime.timedelta(days=1)
new_time = datetime.time(hour=6)
naive_dt = datetime.datetime.combine(new_date, new_time)
app_dt = app_tz.localize(naive_dt)
server_dt = server_tz.normalize(app_dt.astimezone(server_tz))
res = {
'app_dt': app_dt.replace(tzinfo=None),
'app_tz': app_tz,
'server_dt': server_dt.replace(tzinfo=None),
'server_tz': server_tz
}
from webnotes.utils import formatdate
str_date = formatdate(str(res['app_dt'].date()))
str_time = res['app_dt'].time().strftime('%I:%M')
self.doc.next_send = str_date + " at about " + str_time
return res
def get_next_execution(self):
"""
"""
from datetime import datetime, timedelta
dt_args = self.get_next_sending()
server_dt = dt_args['server_dt']
now_dt = datetime.now(dt_args['server_tz'])
if now_dt.time() <= server_dt.time():
next_date = now_dt.date()
else:
next_date = now_dt.date() + timedelta(days=1)
next_time = server_dt.time()
return datetime.combine(next_date, next_time)
def onload(self):
"""
"""
self.get_next_sending()
def get_standard_body(self, result):
"""
Generate email body depending on the result
"""
from webnotes.utils import fmt_money
from webnotes.model.doc import Document
company = Document('Company', self.doc.company)
currency = company.default_currency
def table(args):
if type(args['body']) == type(''):
table_body = """\
<tbody><tr>
<td style='padding: 5px; font-size: 24px; \
font-weight: bold; background: #F7F7F5'>""" + \
args['body'] + \
"""\
</td>
</tr></tbody>"""
elif type(args['body'] == type([])):
body_rows = []
for rows in args['body']:
for r in rows:
body_rows.append("""\
<tr>
<td style='padding: 5px; font-size: 24px; \
font-weight: bold; background: #F7F7F5'>""" \
+ r + """\
</td>
</tr>""")
body_rows.append("<tr><td style='background: #F7F7F5'><br></td></tr>")
table_body = "<tbody>" + "".join(body_rows) + "</tbody>"
table_head = """\
<thead><tr>
<td style='padding: 5px; background: #D8D8D4; font-size: 16px; font-weight: bold'>""" \
+ args['head'] + """\
</td>
</tr></thead>"""
return "<table style='border-collapse: collapse; width: 100%;'>" \
+ table_head \
+ table_body \
+ "</table>"
currency_amount_str = "<span style='color: grey; font-size: 12px'>%s</span> %s"
body_dict = {
'invoiced_amount': {
'table': 'invoiced_amount' in result and table({
'head': 'Invoiced Amount',
'body': currency_amount_str \
% (currency, fmt_money(result['invoiced_amount']['debit']))
}),
'idx': 300
},
'payables': {
'table': 'payables' in result and table({
'head': 'Payables',
'body': currency_amount_str \
% (currency, fmt_money(result['payables']['credit']))
}),
'idx': 200
},
'collections': {
'table': 'collections' in result and table({
'head': 'Collections',
'body': currency_amount_str \
% (currency, fmt_money(result['collections']['credit']))
}),
'idx': 301
},
'payments': {
'table': 'payments' in result and table({
'head': 'Payments',
'body': currency_amount_str \
% (currency, fmt_money(result['payments']['debit']))
}),
'idx': 201
},
'income': {
'table': 'income' in result and table({
'head': 'Income',
'body': currency_amount_str \
% (currency, fmt_money(result['income']['value']))
}),
'idx': 302
},
'expenses_booked': {
'table': 'expenses_booked' in result and table({
'head': 'Expenses Booked',
'body': currency_amount_str \
% (currency, fmt_money(result['expenses_booked']['value']))
}),
'idx': 202
},
'bank_balance': {
'table': 'bank_balance' in result and table({
'head': 'Bank Balance',
'body': [
[
"<span style='font-size: 16px; font-weight: normal'>%s</span>" % bank['name'],
currency_amount_str % (currency, fmt_money(bank['value']))
] for bank in result['bank_balance']
]
}),
'idx': 400
},
'new_leads': {
'table': 'new_leads' in result and table({
'head': 'New Leads',
'body': '%s' % result['new_leads']['count']
}),
'idx': 100
},
'new_enquiries': {
'table': 'new_enquiries' in result and table({
'head': 'New Enquiries',
'body': '%s' % result['new_enquiries']['count']
}),
'idx': 101
},
'new_quotations': {
'table': 'new_quotations' in result and table({
'head': 'New Quotations',
'body': '%s' % result['new_quotations']['count']
}),
'idx': 102
},
'new_sales_orders': {
'table': 'new_sales_orders' in result and table({
'head': 'New Sales Orders',
'body': '%s' % result['new_sales_orders']['count']
}),
'idx': 103
},
'new_purchase_orders': {
'table': 'new_purchase_orders' in result and table({
'head': 'New Purchase Orders',
'body': '%s' % result['new_purchase_orders']['count']
}),
'idx': 104
},
'new_transactions': {
'table': 'new_transactions' in result and table({
'head': 'New Transactions',
'body': '%s' % result['new_transactions']['count']
}),
'idx': 105
}
#'stock_below_rl':
}
table_list = []
# Sort these keys depending on idx value
bd_keys = sorted(body_dict, key=lambda x: body_dict[x]['idx'])
for k in bd_keys:
if self.doc.fields[k]:
table_list.append(body_dict[k]['table'])
result = []
i = 0
result = []
op_len = len(table_list)
while(True):
if i>=op_len:
break
elif (op_len - i) == 1:
result.append("""\
<tr>
<td style='width: 50%%; vertical-align: top;'>%s</td>
<td></td>
</tr>""" % (table_list[i]))
else:
result.append("""\
<tr>
<td style='width: 50%%; vertical-align: top;'>%s</td>
<td>%s</td>
</tr>""" % (table_list[i], table_list[i+1]))
i = i + 2
from webnotes.utils import formatdate
start_date, end_date = self.get_start_end_dates()
digest_daterange = self.doc.frequency=='Daily' \
and formatdate(str(start_date)) \
or (formatdate(str(start_date)) + " to " + (formatdate(str(end_date))))
email_body = """
<div style='width: 100%%'>
<div style='padding: 10px; margin: auto; text-align: center; line-height: 80%%'>
<p style='font-weight: bold; font-size: 24px'>%s</p>
<p style='font-size: 16px; color: grey'>%s</p>
<p style='font-size: 20px; font-weight: bold'>%s</p>
</div>
<table cellspacing=15 style='width: 100%%'>""" \
% ((self.doc.frequency + " Digest"), \
digest_daterange, self.doc.company) \
+ "".join(result) + """\
</table><br><p></p>
</div>"""
return email_body
def send():
"""
"""
edigest_list = webnotes.conn.sql("""
SELECT name FROM `tabEmail Digest`
WHERE enabled=1
""", as_list=1)
from webnotes.model.code import get_obj
from datetime import datetime, timedelta
now = datetime.now()
now_date = now.date()
now_time = (now + timedelta(hours=2)).time()
for ed in edigest_list:
if ed[0]:
ed_obj = get_obj('Email Digest', ed[0])
ed_obj.sending = True
dt_dict = ed_obj.get_next_sending()
send_date = dt_dict['server_dt'].date()
send_time = dt_dict['server_dt'].time()
if (now_date == send_date) and (send_time <= now_time):
#webnotes.msgprint('sending ' + ed_obj.doc.name)
ed_obj.send()
#else:
# webnotes.msgprint('not sending ' + ed_obj.doc.name)

View File

@ -3,24 +3,25 @@
# These values are common in all dictionaries
{
'creation': '2011-07-27 14:23:09',
'creation': '2011-11-28 13:11:56',
'docstatus': 0,
'modified': '2011-07-27 17:32:27',
'modified': '2011-12-08 19:21:26',
'modified_by': 'Administrator',
'owner': 'Administrator'
},
# These values are common for all DocType
{
'_last_update': '1311760331',
'_last_update': '1323352149',
'autoname': 'Prompt',
'colour': 'White:FFF',
'doctype': 'DocType',
'issingle': 1,
'document_type': 'System',
'module': 'Setup',
'name': '__common__',
'section_style': 'Simple',
'show_in_menu': 0,
'version': 4
'version': 78
},
# These values are common for all DocField
@ -29,23 +30,18 @@
'name': '__common__',
'parent': 'Email Digest',
'parentfield': 'fields',
'parenttype': 'DocType',
'permlevel': 0
'parenttype': 'DocType'
},
# These values are common for all DocPerm
{
'create': 1,
'doctype': 'DocPerm',
'idx': 1,
'name': '__common__',
'parent': 'Email Digest',
'parentfield': 'permissions',
'parenttype': 'DocType',
'permlevel': 0,
'read': 1,
'role': 'Administrator',
'write': 1
'role': 'System Manager'
},
# DocType, Email Digest
@ -56,34 +52,290 @@
# DocPerm
{
'doctype': 'DocPerm'
'cancel': 1,
'create': 1,
'doctype': 'DocPerm',
'permlevel': 0,
'write': 1
},
# DocPerm
{
'doctype': 'DocPerm',
'permlevel': 1
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'HTML',
'idx': 1,
'label': 'Body'
'fieldtype': 'Section Break',
'label': 'Settings',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'content_config',
'fieldtype': 'Text',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'enabled',
'fieldtype': 'Check',
'label': 'Enabled',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'company',
'fieldtype': 'Select',
'label': 'For Company',
'options': 'link:Company',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'allow_on_submit': 0,
'doctype': 'DocField',
'fieldname': 'frequency',
'fieldtype': 'Select',
'label': 'How frequently?',
'options': '\nDaily\nWeekly\nMonthly',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'depends_on': 'eval:doc.enabled',
'doctype': 'DocField',
'fieldname': 'next_send',
'fieldtype': 'Data',
'label': 'Next email will be sent on:',
'permlevel': 1
},
# DocField
{
'default': '1',
'doctype': 'DocField',
'fieldname': 'use_standard',
'fieldtype': 'Check',
'hidden': 1,
'idx': 2,
'label': 'Content Config'
'label': 'Use standard?',
'permlevel': 0,
'search_index': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'email_config',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Button',
'label': 'Add Recipients',
'permlevel': 0,
'trigger': 'Client'
},
# DocField
{
'description': 'Note: Email will not be sent to disabled users',
'doctype': 'DocField',
'fieldname': 'recipient_list',
'fieldtype': 'Text',
'label': 'Recipients',
'permlevel': 1,
'reqd': 1
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldtype': 'Section Break',
'label': 'Select Digest Content',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'new_leads',
'fieldtype': 'Check',
'label': 'New Leads',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'new_enquiries',
'fieldtype': 'Check',
'label': 'New Enquiries',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'new_quotations',
'fieldtype': 'Check',
'label': 'New Quotations',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'new_sales_orders',
'fieldtype': 'Check',
'label': 'New Sales Orders',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'new_purchase_orders',
'fieldtype': 'Check',
'label': 'New Purchase Orders',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'new_transactions',
'fieldtype': 'Check',
'label': 'New Transactions',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'payables',
'fieldtype': 'Check',
'label': 'Payables',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'payments',
'fieldtype': 'Check',
'label': 'Payments',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'expenses_booked',
'fieldtype': 'Check',
'label': 'Expenses Booked',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'invoiced_amount',
'fieldtype': 'Check',
'label': 'Invoiced Amount (Receivables)',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'collections',
'fieldtype': 'Check',
'label': 'Collections',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'income',
'fieldtype': 'Check',
'label': 'Income',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.use_standard',
'doctype': 'DocField',
'fieldname': 'bank_balance',
'fieldtype': 'Check',
'label': 'Bank Balance',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'stock_below_rl',
'fieldtype': 'Check',
'hidden': 1,
'idx': 3,
'label': 'Email Config'
'label': 'Stock Items below re-order level',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:!doc.use_standard',
'doctype': 'DocField',
'fieldtype': 'Section Break',
'label': 'Enter Custom Code',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:!doc.use_standard',
'doctype': 'DocField',
'fieldname': 'custom_code',
'fieldtype': 'Code',
'label': 'Custom Python Code',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:!doc.use_standard',
'doctype': 'DocField',
'fieldname': 'email_template',
'fieldtype': 'Code',
'label': 'Email Template',
'permlevel': 0
}
]

View File

@ -161,6 +161,7 @@ SetupData = function(cnty){
['Custom Field',1,'Custom Field','dt'+NEWLINE+'label'+NEWLINE+'fieldtype'+NEWLINE+'options','Add and manage custom fields on forms'],
['Email Settings',3,'Email Settings','','Outgoing email server and address'],
['Notification Settings',3,'Notification Control','','Automatic emails set at selected events'],
['Email Digest', 1, 'Email Digest', '', 'Schedule Daily / Weekly / Monthly Summary e-mails'],
['Company',1,'Company','id'+NEWLINE+'is_active'+NEWLINE+'email','Manage list of companies'],
['Fiscal Year',1,'Fiscal Year','id'+NEWLINE+'company'+NEWLINE+'is_active'+NEWLINE+'year','Manage list of fiscal years'],
['Personalize',3,'Personalize','','Set your banner'],
@ -168,7 +169,7 @@ SetupData = function(cnty){
['Import Data',2,'Import Data','','Import data from CSV files'],
['Manage Users',2,'My Company','','Add / remove users and manage their roles'],
['Web Forms',2,'Webforms','', 'Code to embed forms in yor website'],
['Permissions Manager',2,'Permission Engine','', 'Manage all permissions from one tool (beta)'],
['Permissions Manager',2,'Permission Engine','', 'Manage all permissions from one tool'],
//['Property Setter',1,'Property Setter','', 'Customize properties of a Form (DocType) or Field'],
['Customize Form View',3,'DocLayer','', 'Customize properties of a Form (DocType) or Field'],
['Print Formats', 1, 'Print Format', '', 'Manage Print Formats'],

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long