Skip to content

Commit 541d8be

Browse files
committed
[complete] auto email report
1 parent 5cdab8d commit 541d8be

File tree

13 files changed

+189
-60
lines changed

13 files changed

+189
-60
lines changed

frappe/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,13 +1128,13 @@ def get_test_records(doctype):
11281128
else:
11291129
return []
11301130

1131-
def format_value(value, df, doc=None, currency=None):
1131+
def format_value(*args, **kwargs):
11321132
"""Format value with given field properties.
11331133
11341134
:param value: Value to be formatted.
1135-
:param df: DocField object with properties `fieldtype`, `options` etc."""
1135+
:param df: (Optional) DocField object with properties `fieldtype`, `options` etc."""
11361136
import frappe.utils.formatters
1137-
return frappe.utils.formatters.format_value(value, df, doc, currency=currency)
1137+
return frappe.utils.formatters.format_value(*args, **kwargs)
11381138

11391139
def get_print(doctype=None, name=None, print_format=None, style=None, html=None, as_pdf=False, doc=None):
11401140
"""Get Print Format for given document.

frappe/core/doctype/report/report.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def _format(parts):
8383

8484
return out
8585

86+
8687
@Document.whitelist
8788
def toggle_disable(self, disable):
8889
self.db_set("disabled", cint(disable))

frappe/email/doctype/auto_email_report/auto_email_report.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@ frappe.ui.form.on('Auto Email Report', {
2020
frm.trigger('show_filters');
2121
}
2222
}
23+
if(!frm.is_new()) {
24+
frm.add_custom_button(__('Download'), function() {
25+
var w = window.open(
26+
frappe.urllib.get_full_url(
27+
"/api/method/frappe.email.doctype.auto_email_report.auto_email_report.download?"
28+
+"name="+encodeURIComponent(frm.doc.name)));
29+
if(!w) {
30+
msgprint(__("Please enable pop-ups")); return;
31+
}
32+
});
33+
frm.add_custom_button(__('Send Now'), function() {
34+
frappe.call({
35+
method: 'frappe.email.doctype.auto_email_report.auto_email_report.send_now',
36+
args: {name: frm.doc.name},
37+
callback: function() {
38+
msgprint(__('Scheduled to send'));
39+
}
40+
});
41+
});
42+
}
2343
},
2444
show_filters: function(frm) {
2545
var wrapper = $(frm.get_field('filters_display').wrapper);

frappe/email/doctype/auto_email_report/auto_email_report.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@
294294
"label": "Format",
295295
"length": 0,
296296
"no_copy": 0,
297-
"options": "HTML\nXLS\nCSV",
297+
"options": "XLS\nHTML\nCSV",
298298
"permlevel": 0,
299299
"precision": "",
300300
"print_hide": 0,
@@ -369,7 +369,7 @@
369369
"issingle": 0,
370370
"istable": 0,
371371
"max_attachments": 0,
372-
"modified": "2016-09-01 05:36:00.898683",
372+
"modified": "2016-09-14 02:00:21.618956",
373373
"modified_by": "Administrator",
374374
"module": "Email",
375375
"name": "Auto Email Report",

frappe/email/doctype/auto_email_report/auto_email_report.py

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from frappe import _
88
from frappe.model.document import Document
99
import frappe.utils
10+
from frappe.utils.xlsutils import get_xls
11+
from frappe.utils.csvutils import to_csv
1012

1113
max_reports_per_user = 3
1214

@@ -20,65 +22,102 @@ def validate(self):
2022

2123
def validate_emails(self):
2224
'''Cleanup list of emails'''
23-
if ',' in self.emails:
24-
self.emails.replace(',', '\n')
25+
if ',' in self.email_to:
26+
self.email_to.replace(',', '\n')
2527

2628
valid = []
27-
for email in self.emails.split():
29+
for email in self.email_to.split():
2830
if email:
2931
frappe.utils.validate_email_add(email, True)
3032
valid.append(email)
3133

32-
self.emails = '\n'.join(valid)
34+
self.email_to = '\n'.join(valid)
3335

3436
def validate_report_count(self):
3537
'''check that there are only 3 enabled reports per user'''
3638
count = frappe.db.sql('select count(*) from `tabAuto Email Report` where user=%s and enabled=1', self.user)[0][0]
3739
if count > max_reports_per_user:
3840
frappe.throw(_('Only {0} emailed reports are allowed per user').format(max_reports_per_user))
3941

40-
def send(self):
42+
def get_report_content(self):
43+
'''Returns file in for the report in given format'''
4144
report = frappe.get_doc('Report', self.report)
42-
data = report.get_data(limit=500, user = self.user, filters = self.filters)
45+
raw = report.get_data(limit=500, user = self.user, filters = self.filters)
46+
47+
if self.format == 'HTML':
48+
return self.get_html_table(raw)
49+
50+
elif self.format == 'XLS':
51+
return get_xls(raw)
52+
53+
elif self.format == 'CSV':
54+
return to_csv(raw)
55+
56+
else:
57+
frappe.throw(_('Invalid Output Format'))
58+
59+
def get_html_table(self, data):
60+
return frappe.render_template('frappe/templates/includes/print_table.html', {
61+
'headings': data[0],
62+
'data': data[1:]
63+
})
4364

65+
def get_file_name(self):
66+
return "{0}.{1}".format(self.report.replace(" ", "-").replace("/", "-"), self.format.lower())
67+
68+
def send(self):
69+
data = self.get_report_content()
4470
message = '<p>{0}</p>'.format(_('{0} generated on {1}').format(self.name,
4571
frappe.utils.format_datetime(frappe.utils.now_datetime())))
46-
attachments = None
47-
48-
if self.report_format == 'HTML':
49-
message += self.get_html_table(data)
5072

51-
if self.report_format == 'XLS':
52-
attachments.append(self.get_xls())
73+
if self.format=='HTML':
74+
message += '<hr>' + data
75+
else:
76+
attachments = [{
77+
'fname': self.get_file_name(),
78+
'fcontent': data
79+
}]
5380

5481
frappe.sendmail(
55-
recipients = self.emails.split(),
82+
recipients = self.email_to.split(),
5683
subject = self.name,
5784
message = message,
5885
attachments = attachments
5986
)
6087

61-
def get_html_table(self, data):
62-
return ''
88+
@frappe.whitelist()
89+
def download(name):
90+
'''Download report locally'''
91+
auto_email_report = frappe.get_doc('Auto Email Report', name)
92+
auto_email_report.check_permission()
93+
data = auto_email_report.get_report_content()
6394

64-
def get_csv(self, data):
65-
return
95+
frappe.local.response.filecontent = data
96+
frappe.local.response.type = "download"
97+
frappe.local.response.filename = auto_email_report.get_file_name()
6698

67-
def get_xls(self, data):
68-
return
99+
@frappe.whitelist()
100+
def send_now(name):
101+
'''Send Auto Email report now'''
102+
auto_email_report = frappe.get_doc('Auto Email Report', name)
103+
auto_email_report.check_permission()
104+
auto_email_report.send()
69105

70106
def send_daily():
71107
'''Check reports to be sent daily'''
72108
now = frappe.utils.now_datetime()
73-
for report in frappe.get_all('Auto Email Report', {'enabled': 1, 'frequency': ('in', ('Daily', 'Weekly'))}):
109+
for report in frappe.get_all('Auto Email Report',
110+
{'enabled': 1, 'frequency': ('in', ('Daily', 'Weekly'))}):
74111
auto_email_report = frappe.get_doc('Auto Email Report', report.name)
112+
113+
# if not correct weekday, skip
75114
if auto_email_report.frequency=='Weekly':
76-
# if not correct weekday, skip
77115
if now.weekday()!={'Monday':0,'Tuesday':1,'Wednesday':2,
78116
'Thursday':3,'Friday':4,'Saturday':5,'Sunday':6}[auto_email_report.weekday]:
79117
continue
80118

81-
auto_email_report.send()
119+
auto_email_report.send()
120+
82121

83122
def send_monthly():
84123
'''Check reports to be sent monthly'''

frappe/model/document.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def get_latest(self):
136136
self.latest = frappe.get_doc(self.doctype, self.name)
137137
return self.latest
138138

139-
def check_permission(self, permtype, permlabel=None):
139+
def check_permission(self, permtype='read', permlabel=None):
140140
"""Raise `frappe.PermissionError` if not permitted"""
141141
if not self.has_permission(permtype):
142142
self.raise_no_permission_to(permlabel or permtype)

frappe/public/html/print_template.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1">
77
<meta name="description" content="">
88
<meta name="author" content="">
9-
<title>{%= title %}</title>
10-
<link href="{%= frappe.urllib.get_base_url() %}/assets/frappe/css/bootstrap.css" rel="stylesheet">
9+
<title>{{ title }}</title>
10+
<link href="{{ base_url }}/assets/frappe/css/bootstrap.css" rel="stylesheet">
1111
<link type="text/css" rel="stylesheet"
12-
href="{%= frappe.urllib.get_base_url() %}/assets/frappe/css/font-awesome.css">
12+
href="{{ base_url }}/assets/frappe/css/font-awesome.css">
1313
<style>
14-
{%= frappe.boot.print_css %}
14+
{{ print_css }}
1515
</style>
1616
</head>
1717
<body>
1818
<div class="print-format-gutter">
1919
<div class="print-format">
20-
{%= content %}
20+
{{ content }}
2121
</div>
2222
</div>
2323
</body>
Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,37 @@
11
<!-- title -->
2-
{% if(title) { %}
3-
<h2>{%= __(title) %}</h2>
2+
{% if title %}
3+
<h2>{{ __(title) }}</h2>
44
<hr>
5-
{% } %}
5+
{{ endif }}
66
<table class="table table-bordered">
77
<!-- heading -->
88
<thead>
99
<tr>
10-
{% var columns_length = columns.length;
11-
for (var i=0; i < columns_length; i++) {
12-
var col = columns[i]; %}
13-
{% if(col.name && col._id !== "_check") { %}
14-
<th style="min-width: {%= col.minWidth %}px"
15-
{% if(col.docfield && in_list(["Float", "Currency", "Int"],
16-
col.docfield.fieldtype)) { %}
10+
{% for col in columns %}
11+
{% if col.name && col._id !== "_check" %}
12+
<th style="min-width: {{ col.minWidth }}px"
13+
{% if col.docfield && in_list(["Float", "Currency", "Int"], col.docfield.fieldtype) %}
1714
class="text-right"
18-
{% } %}>{%= __(col.name) %}</th>
19-
{% } %}
20-
{% } %}
15+
{% endif %}>{{ __(col.name) }}</th>
16+
{% endif %}
17+
{% endfor %}
2118
</tr>
2219
</thead>
2320
<!-- body -->
2421
<tbody>
25-
{% for (var i=0, l= data.length; i < l; i++) {
26-
var row = data[i]; %}
22+
{% for row in data %}
2723
<tr>
28-
{% for(var c=0; c < columns_length; c++) { var col = columns[c];%}
29-
{% if(col.name && col._id !== "_check") { %}
30-
24+
{% for col in columns %}
25+
{% if col.name && col._id !== "_check" %}
26+
3127
{% var value = col.fieldname ? row[col.fieldname] : row[col.id]; %}
32-
33-
<td>{%= col.formatter
28+
29+
<td>{{ col.formatter
3430
? col.formatter(i, c, value, col, row, true)
35-
: value %}</td>
36-
{% } %}
37-
{% } %}
31+
: value }}</td>
32+
{% endif %}
33+
{% endfor %}
3834
</tr>
39-
{% } %}
35+
{% endfor %}
4036
</tbody>
4137
</table>

frappe/public/js/lib/microtemplate.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ frappe.render_grid = function(opts) {
9696
}
9797

9898
// render HTML wrapper page
99+
opts.base_url = frappe.urllib.get_base_url();
100+
opts.print_cess = frappe.boot.print_css;
99101
var html = frappe.render_template("print_template", opts);
100102

101103
var w = window.open();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<table cellpadding=2px cellspacing=0 border=1px style='width:100%; border-collapse:collapse;'>
2+
<thead>
3+
<tr>
4+
{% for col in headings %}
5+
<th>
6+
{{ col }}
7+
</th>
8+
{% endfor %}
9+
</tr>
10+
</thead>
11+
<tbody>
12+
{% for row in data %}
13+
<tr>
14+
{% for val in row %}
15+
<td>
16+
{{ frappe.format(val) }}
17+
</td>
18+
{% endfor %}
19+
</td>
20+
{% endfor %}
21+
</tbody>
22+
</table>

frappe/utils/formatters.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,29 @@
33

44
from __future__ import unicode_literals
55
import frappe
6+
import datetime
67
from frappe.utils import formatdate, fmt_money, flt, cstr, cint, format_datetime
78
from frappe.model.meta import get_field_currency, get_field_precision
89
import re
910

10-
def format_value(value, df, doc=None, currency=None, translated=False):
11-
# Convert dict to object if necessary
12-
if (isinstance(df, dict)):
11+
def format_value(value, df=None, doc=None, currency=None, translated=False):
12+
'''Format value based on given fieldtype, document reference, currency reference.
13+
If docfield info (df) is not given, it will try and guess based on the datatype of the value'''
14+
if not df:
15+
df = frappe._dict()
16+
if isinstance(value, datetime.datetime):
17+
df.fieldtype = 'Datetime'
18+
elif isinstance(value, datetime.date):
19+
df.fieldtype = 'Date'
20+
elif isinstance(value, int):
21+
df.fieldtype = 'Int'
22+
elif isinstance(value, float):
23+
df.fieldtype = 'Float'
24+
else:
25+
df.fieldtype = 'Data'
26+
27+
elif (isinstance(df, dict)):
28+
# Convert dict to object if necessary
1329
df = frappe._dict(df)
1430

1531
if value is None:

frappe/utils/jinja.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def get_allowed_functions_for_jenv():
7878
"frappe": {
7979
"_": frappe._,
8080
"get_url": frappe.utils.get_url,
81+
'format': frappe.format_value,
8182
"format_value": frappe.format_value,
8283
"format_date": frappe.utils.data.global_date_format,
8384
"form_dict": getattr(frappe.local, 'form_dict', {}),

0 commit comments

Comments
 (0)