[minor] catch badly formed template while building help
This commit is contained in:
parent
ed63eb9719
commit
19e955f81d
6 changed files with 112 additions and 19 deletions
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
from frappe import _
|
||||
import frappe.desk.query_report
|
||||
from frappe.utils import cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.modules.export_file import export_to_files
|
||||
|
|
@ -48,6 +50,39 @@ class Report(Document):
|
|||
make_boilerplate("controller.py", self, {"name": self.name})
|
||||
make_boilerplate("controller.js", self, {"name": self.name})
|
||||
|
||||
def get_data(self, filters=None, limit=None):
|
||||
'''Run the report'''
|
||||
out = []
|
||||
|
||||
if self.report_type in ('Query Report', 'Script Report'):
|
||||
# query and script reports
|
||||
data = frappe.desk.query_report.run(self.name, filters=filters)
|
||||
out.append([d.split(':')[0] for d in data.get('columns')])
|
||||
out += data.get('result')
|
||||
else:
|
||||
# standard report
|
||||
params = json.loads(self.json)
|
||||
columns = params.get('columns')
|
||||
filters = params.get('filters')
|
||||
|
||||
def _format(parts):
|
||||
# sort by is saved as DocType.fieldname, covert it to sql
|
||||
return '`tab{0}`.`{1}`'.format(*parts)
|
||||
|
||||
order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order')
|
||||
if params.get('sort_by_next'):
|
||||
order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next')
|
||||
|
||||
result = frappe.get_list(self.ref_doctype, fields = [_format([c[1], c[0]]) for c in columns],
|
||||
filters=filters, order_by = order_by, as_list=True, limit=limit)
|
||||
|
||||
meta = frappe.get_meta(self.ref_doctype)
|
||||
|
||||
out.append([meta.get_label(c[0]) for c in columns])
|
||||
out = out + [list(d) for d in result]
|
||||
|
||||
return out
|
||||
|
||||
@Document.whitelist
|
||||
def toggle_disable(self, disable):
|
||||
self.db_set("disabled", cint(disable))
|
||||
|
|
|
|||
|
|
@ -1,10 +1,46 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
import frappe, json
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Report')
|
||||
|
||||
class TestReport(unittest.TestCase):
|
||||
pass
|
||||
def test_report_builder(self):
|
||||
if not frappe.db.exists('Report', 'User Activity Report'):
|
||||
frappe.get_doc(json.loads(user_activity_report)).insert()
|
||||
|
||||
report = frappe.get_doc('Report', 'User Activity Report')
|
||||
data = report.get_data()
|
||||
self.assertEquals(data[0][0], 'ID')
|
||||
self.assertEquals(data[0][1], 'User Type')
|
||||
self.assertTrue('Administrator' in [d[0] for d in data])
|
||||
|
||||
def test_query_report(self):
|
||||
report = frappe.get_doc('Report', 'Permitted Documents For User')
|
||||
data = report.get_data(filters={'user': 'Administrator', 'doctype': 'DocType'})
|
||||
self.assertEquals(data[0][0], 'Name')
|
||||
self.assertEquals(data[0][1], 'Module')
|
||||
self.assertTrue('Auto Email Report' in [d[0] for d in data])
|
||||
|
||||
# test standard report with child table
|
||||
user_activity_report = '''
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"is_standard": "No",
|
||||
"javascript": null,
|
||||
"json": "{\"filters\":[],\"columns\":[[\"name\",\"User\"],[\"user_type\",\"User\"],[\"first_name\",\"User\"],[\"last_name\",\"User\"],[\"last_active\",\"User\"],[\"role\",\"UserRole\"]],\"sort_by\":\"User.modified\",\"sort_order\":\"desc\",\"sort_by_next\":null,\"sort_order_next\":\"desc\"}",
|
||||
"modified": "2016-09-01 02:59:07.728890",
|
||||
"module": "Core",
|
||||
"name": "User Activity Report",
|
||||
"query": null,
|
||||
"ref_doctype": "User",
|
||||
"report_name": "User Activity Report",
|
||||
"report_type": "Report Builder"
|
||||
}
|
||||
'''
|
||||
|
|
|
|||
|
|
@ -60,9 +60,12 @@ def get_script(report_name):
|
|||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
def run(report_name, filters=()):
|
||||
def run(report_name, filters=None):
|
||||
report = get_report_doc(report_name)
|
||||
|
||||
if not filters:
|
||||
filters = []
|
||||
|
||||
if filters and isinstance(filters, basestring):
|
||||
filters = json.loads(filters)
|
||||
|
||||
|
|
@ -86,13 +89,13 @@ def run(report_name, filters=()):
|
|||
if report.is_standard=="Yes":
|
||||
method_name = get_report_module_dotted_path(module, report.name) + ".execute"
|
||||
res = frappe.get_attr(method_name)(frappe._dict(filters))
|
||||
|
||||
|
||||
columns, result = res[0], res[1]
|
||||
if len(res) > 2:
|
||||
message = res[2]
|
||||
if len(res) > 3:
|
||||
chart = res[3]
|
||||
|
||||
|
||||
if report.apply_user_permissions and result:
|
||||
result = get_filtered_data(report.ref_doctype, columns, result)
|
||||
|
||||
|
|
@ -124,14 +127,14 @@ def add_total_row(result, columns):
|
|||
else:
|
||||
fieldtype = col.get("fieldtype")
|
||||
options = col.get("options")
|
||||
|
||||
|
||||
for row in result:
|
||||
if fieldtype in ["Currency", "Int", "Float", "Percent"] and flt(row[i]):
|
||||
total_row[i] = flt(total_row[i]) + flt(row[i])
|
||||
|
||||
|
||||
if fieldtype == "Percent" and i not in has_percent:
|
||||
has_percent.append(i)
|
||||
|
||||
|
||||
if fieldtype=="Link" and options == "Currency":
|
||||
total_row[i] = result[0][i]
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ from frappe.model.document import Document
|
|||
from frappe.model.base_document import BaseDocument
|
||||
from frappe.model.db_schema import type_map
|
||||
from frappe.modules import load_doctype_module
|
||||
from frappe import _
|
||||
|
||||
def get_meta(doctype, cached=True):
|
||||
if cached:
|
||||
|
|
@ -117,7 +118,19 @@ class Meta(Document):
|
|||
return True if self.get_field(fieldname) else False
|
||||
|
||||
def get_label(self, fieldname):
|
||||
return self.get_field(fieldname).label
|
||||
'''Get label of the given fieldname'''
|
||||
df = self.get_field(fieldname)
|
||||
if df:
|
||||
label = df.label
|
||||
else:
|
||||
label = {
|
||||
'name': _('ID'),
|
||||
'owner': _('Created By'),
|
||||
'modified_by': _('Modified By'),
|
||||
'creation': _('Created On'),
|
||||
'modified': _('Last Modified On')
|
||||
}.get(fieldname) or _('No Label')
|
||||
return label
|
||||
|
||||
def get_options(self, fieldname):
|
||||
return self.get_field(fieldname).options
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from frappe.database import Database
|
|||
import os
|
||||
from markdown2 import markdown
|
||||
from bs4 import BeautifulSoup
|
||||
import jinja2.exceptions
|
||||
|
||||
def sync():
|
||||
# make table
|
||||
|
|
@ -113,17 +114,21 @@ class HelpDatabase(object):
|
|||
if fname.rsplit('.', 1)[-1] in ('md', 'html'):
|
||||
fpath = os.path.join(basepath, fname)
|
||||
with open(fpath, 'r') as f:
|
||||
content = frappe.render_template(unicode(f.read(), 'utf-8'),
|
||||
{'docs_base_url': '/assets/{app}_docs'.format(app=app)})
|
||||
try:
|
||||
content = frappe.render_template(unicode(f.read(), 'utf-8'),
|
||||
{'docs_base_url': '/assets/{app}_docs'.format(app=app)})
|
||||
|
||||
relpath = self.get_out_path(fpath)
|
||||
relpath = relpath.replace("user", app)
|
||||
content = markdown(content)
|
||||
title = self.make_title(basepath, fname, content)
|
||||
intro = self.make_intro(content)
|
||||
content = self.make_content(content, fpath, relpath)
|
||||
self.db.sql('''insert into help(path, content, title, intro, full_path)
|
||||
values (%s, %s, %s, %s, %s)''', (relpath, content, title, intro, fpath))
|
||||
except jinja2.exceptions.TemplateSyntaxError:
|
||||
print "Invalid Jinja Template for {0}. Skipping".format(fpath)
|
||||
|
||||
relpath = self.get_out_path(fpath)
|
||||
relpath = relpath.replace("user", app)
|
||||
content = markdown(content)
|
||||
title = self.make_title(basepath, fname, content)
|
||||
intro = self.make_intro(content)
|
||||
content = self.make_content(content, fpath, relpath)
|
||||
self.db.sql('''insert into help(path, content, title, intro, full_path)
|
||||
values (%s, %s, %s, %s, %s)''', (relpath, content, title, intro, fpath))
|
||||
doc_contents += "</ol>"
|
||||
self.db.sql('''insert into help(path, content, title, intro, full_path) values (%s, %s, %s, %s, %s)''',
|
||||
('/documentation/index', doc_contents, 'Documentation', '', ''))
|
||||
|
|
|
|||
|
|
@ -37,3 +37,4 @@ cryptography
|
|||
zxcvbn
|
||||
psutil
|
||||
unittest-xml-reporting
|
||||
xlwt
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue