feat:Addition of custom fields in query reports

This commit is contained in:
deepeshgarg007 2019-04-07 20:24:11 +05:30
parent ff6cf8c3e3
commit f4061acf90
2 changed files with 133 additions and 41 deletions

View file

@ -17,6 +17,7 @@ from six import string_types, iteritems
from datetime import timedelta
from frappe.utils.file_manager import get_file
from frappe.utils import gzip_decompress
from frappe.model import no_value_fields
def get_report_doc(report_name):
doc = frappe.get_doc("Report", report_name)
@ -33,7 +34,7 @@ def get_report_doc(report_name):
return doc
def generate_report_result(report, filters=None, user=None):
def generate_report_result(report, filters=None, user=None, custom_columns=None):
status = None
if not user:
user = frappe.session.user
@ -83,10 +84,10 @@ def generate_report_result(report, filters=None, user=None):
data_to_be_printed = res[4]
if result:
result, columns = get_filtered_data(report.ref_doctype, columns, result, user, report.add_custom_fields_in_report)
result, columns = get_filtered_data(report.ref_doctype, columns, result, user, custom_columns)
# if cint(report.add_total_row) and result:
# result = add_total_row(result, columns)
if cint(report.add_total_row) and result:
result = add_total_row(result, columns)
return {
"result": result,
@ -160,7 +161,7 @@ def get_script(report_name):
@frappe.whitelist()
@frappe.read_only()
def run(report_name, filters=None, user=None):
def run(report_name, filters=None, user=None, custom_columns=None):
report = get_report_doc(report_name)
if not user:
@ -182,7 +183,7 @@ def run(report_name, filters=None, user=None):
dn = ""
result = get_prepared_report_result(report, filters, dn, user)
else:
result = generate_report_result(report, filters, user)
result = generate_report_result(report, filters, user, custom_columns)
result["add_total_row"] = report.add_total_row
@ -353,8 +354,27 @@ def add_total_row(result, columns, meta = None):
result.append(total_row)
return result
@frappe.whitelist()
def get_custom_fields(doctypes):
def get_filtered_data(ref_doctype, columns, data, user, add_custom_fields):
field_map = []
doclist = json.loads(doctypes)
for d in doclist:
fieldlist = [f.label for f in frappe.get_meta(d).fields \
if f.label and f.fieldname and f.fieldname not in no_value_fields
and f.fieldname not in ["naming_series"]
and f.fieldtype not in ["Section Break", "Column Break", "Table"]]
field_map.append({
"doctype": d,
"fields": fieldlist
})
return field_map
def get_filtered_data(ref_doctype, columns, data, user, custom_columns):
result = []
linked_doctypes = get_linked_doctypes(columns, data)
match_filters_per_doctype = get_user_match_filters(linked_doctypes, user=user)
@ -364,45 +384,42 @@ def get_filtered_data(ref_doctype, columns, data, user, add_custom_fields):
role_permissions = get_role_permissions(frappe.get_meta(ref_doctype), user)
if_owner = role_permissions.get("if_owner", {}).get("report")
doc_fields_map = {}
custom_field_value_map = {}
if custom_columns:
custom_field_value_map = {}
fields = json.loads(custom_columns)
custom_field_list = []
if add_custom_fields:
for doctype, field_list in iteritems(fields):
values = frappe.db.sql("select name, {fields} from `tab{doctype}` "
.format(fields = ", ".join(field_list), doctype=doctype), as_dict=1)
fields = frappe.db.sql(""" select dt, fieldname, fieldtype from `tabCustom Field`
where fieldtype not in ('Section Break', 'Column Break') and
dt in (%s)""" % ', '.join(['%s']* len(linked_doctypes)), tuple([doctype for doctype in linked_doctypes.keys()]), as_dict=1)
for d in fields:
doc_fields_map.setdefault(d.dt, [])
doc_fields_map.get(d.dt).append(d.fieldname)
columns.append({
"label": frappe.unscrub(d.fieldname),
"fieldname": d.filedname,
"fieldtype": d.fieldtype,
"width": 100
custom_field_list += field_list
for field in field_list:
columns.append({
"label": frappe.unscrub(field),
"fieldname": field,
"fieldtype": "Data",
"width": 100
})
for doctype in linked_doctypes.keys():
if doc_fields_map.get(doctype):
values = frappe.db.sql("select name, {fields} from `tab{doctype}` "
.format(fields = ", ".join(doc_fields_map.get(doctype)), doctype=doctype), as_dict=1)
for value in values:
custom_field_value_map.setdefault(value.name, value)
for value in values:
custom_field_value_map.setdefault(value.name, value)
columns_dict = get_columns_dict(columns)
columns_idx_map = [columns_dict.get(i) for i in range(len(columns))]
for row in data:
for index, column in enumerate(columns):
print(index,column)
if isinstance(row, dict) and column.get("fieldtype") == "Link":
fieldname = column.get("fieldname")
row.update({ "test_field": custom_field_value_map.get(row.get(fieldname),{}).get("test_field")})
else:
print("$$$$$$$$$$")
custom_field_value_map.get(row[index],{})
row.append(custom_field_value_map.get(row[index],{}).get("test_field"))
for index, column in enumerate(columns_idx_map):
for d in custom_field_list:
if column.get("fieldtype") == "Link" or column.get("fieldtype") == "Dynamic Link":
if isinstance(row, dict):
fieldname = column.get("fieldname")
row.update({ fieldname: custom_field_value_map.get(row.get(fieldname),{}).get(d)})
else:
fieldname = column.get("fieldname")
value = custom_field_value_map.get(row[index],{}).get(d)
if value:
row.append(value)
if match_filters_per_doctype:
for row in data:

View file

@ -269,7 +269,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
this.page.clear_fields();
}
refresh() {
refresh(values) {
this.toggle_message(true);
let filters = this.get_filter_values(true);
let query = frappe.utils.get_query_string(frappe.get_route_str());
@ -291,6 +291,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
args: {
report_name: this.report_name,
filters: filters,
custom_columns: values
},
callback: resolve,
always: () => this.page.btn_secondary.prop('disabled', false)
@ -418,7 +419,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
this.raw_data = data;
this.columns = this.prepare_columns(data.columns);
this.data = this.prepare_data(data.result);
this.custom_fields = this.get_dialog_fields();
this.tree_report = this.data.some(d => 'indent' in d);
}
@ -962,6 +963,22 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
action: () => frappe.set_route('List', 'Auto Email Report', {'report' : this.report_name}),
standard: true
},
{
label: __('Add Custom Fields'),
action: () => {
const d = new frappe.ui.Dialog({
title: __('Add Custom Fields'),
fields: this.custom_fields,
primary_action: (values) => {
this.refresh(values);
d.hide();
}
});
d.show();
},
standard: true
},
{
label: __('User Permissions'),
action: () => frappe.set_route('List', 'User Permission', {
@ -979,6 +996,64 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
];
}
get_linked_doctypes() {
let doctypes = [];
let dynamic_links = [];
let dynamic_doctypes = new Set();
this.columns.forEach(df => {
if (df.fieldtype == "Link" && df.options) {
doctypes.push(df.options);
}
else if (df.fieldtype == "Dynamic Link" && df.options) {
dynamic_links.push(df.options);
}
});
this.data.forEach(row => {
dynamic_links.forEach(field => {
if (row[field]){
dynamic_doctypes.add(row[field]);
}
})
})
doctypes = doctypes.concat(Array.from(dynamic_doctypes));
return doctypes;
}
get_dialog_fields() {
var dialog_fields = [];
const linked_doctypes = this.get_linked_doctypes();
frappe.call({
method: "frappe.desk.query_report.get_custom_fields",
args: {
doctypes: linked_doctypes
},
callback: function(r) {
r.message.forEach(df => {
dialog_fields.push({
label: __(df.doctype),
fieldname: df.doctype,
fieldtype: 'MultiCheck',
columns: 2,
options: df.fields
.map(f => ({
label: __(f),
value: f ? frappe.scrub(f) : null,
checked: 0
}))
});
});
}
});
return dialog_fields;
}
setup_report_wrapper() {
if (this.$report) return;