From 5103454642e516353e8b9a4327fd0d14d41720c8 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Tue, 5 Jun 2018 10:44:36 +0530 Subject: [PATCH] New Report Address and Contacts (#14307) * New Report Address and Contacts * Fix codacy * Add links to report in module pages --- erpnext/config/accounts.py | 6 + erpnext/config/buying.py | 4 +- erpnext/config/selling.py | 4 +- .../report/address_and_contacts/__init__.py | 0 .../address_and_contacts.js | 34 +++++ .../address_and_contacts.json | 33 +++++ .../address_and_contacts.py | 120 ++++++++++++++++++ 7 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 erpnext/selling/report/address_and_contacts/__init__.py create mode 100644 erpnext/selling/report/address_and_contacts/address_and_contacts.js create mode 100644 erpnext/selling/report/address_and_contacts/address_and_contacts.json create mode 100644 erpnext/selling/report/address_and_contacts/address_and_contacts.py diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index 636c160d39..a53442115c 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -459,6 +459,12 @@ def get_data(): "is_query_report": True, "name": "Sales Payment Summary", "doctype": "Sales Invoice" + }, + { + "type": "report", + "is_query_report": True, + "name": "Address And Contacts", + "doctype": "Address" } ] }, diff --git a/erpnext/config/buying.py b/erpnext/config/buying.py index e20d514a23..270519e4e8 100644 --- a/erpnext/config/buying.py +++ b/erpnext/config/buying.py @@ -198,13 +198,13 @@ def get_data(): { "type": "report", "is_query_report": True, - "name": "Addresses And Contacts", + "name": "Address And Contacts", "label": "Supplier Addresses And Contacts", "doctype": "Address", "route_options": { "party_type": "Supplier" } - }, + } ] }, { diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py index 496617ac77..029fdac284 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -120,7 +120,7 @@ def get_data(): { "type": "report", "is_query_report": True, - "name": "Addresses And Contacts", + "name": "Address And Contacts", "label": _("Sales Partner Addresses And Contacts"), "doctype": "Address", "route_options": { @@ -230,7 +230,7 @@ def get_data(): { "type": "report", "is_query_report": True, - "name": "Addresses And Contacts", + "name": "Address And Contacts", "label": _("Customer Addresses And Contacts"), "doctype": "Address", "route_options": { diff --git a/erpnext/selling/report/address_and_contacts/__init__.py b/erpnext/selling/report/address_and_contacts/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.js b/erpnext/selling/report/address_and_contacts/address_and_contacts.js new file mode 100644 index 0000000000..383f18b496 --- /dev/null +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.js @@ -0,0 +1,34 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Address And Contacts"] = { + "filters": [ + { + "reqd": 1, + "fieldname":"party_type", + "label": __("Party Type"), + "fieldtype": "Link", + "options": "DocType", + "get_query": function() { + return { + "filters": { + "name": ["in","Customer,Supplier,Sales Partner"], + } + } + } + }, + { + "fieldname":"party_name", + "label": __("Party Name"), + "fieldtype": "Dynamic Link", + "get_options": function() { + let party_type = frappe.query_report_filters_by_name.party_type.get_value(); + if(!party_type) { + frappe.throw(__("Please select Party Type first")); + } + return party_type; + } + } + ] +} diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.json b/erpnext/selling/report/address_and_contacts/address_and_contacts.json new file mode 100644 index 0000000000..da38babbdc --- /dev/null +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.json @@ -0,0 +1,33 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2018-06-01 09:32:13.088771", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Test", + "modified": "2018-06-01 09:39:39.604944", + "modified_by": "Administrator", + "module": "Selling", + "name": "Address And Contacts", + "owner": "Administrator", + "ref_doctype": "Address", + "report_name": "Address And Contacts", + "report_type": "Script Report", + "roles": [ + { + "role": "Sales User" + }, + { + "role": "Purchase User" + }, + { + "role": "Maintenance User" + }, + { + "role": "Accounts User" + } + ] +} \ No newline at end of file diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.py b/erpnext/selling/report/address_and_contacts/address_and_contacts.py new file mode 100644 index 0000000000..0a46d2c36f --- /dev/null +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.py @@ -0,0 +1,120 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from six.moves import range +from six import iteritems +import frappe + + +field_map = { + "Contact": [ "first_name", "last_name", "phone", "mobile_no", "email_id", "is_primary_contact" ], + "Address": [ "address_line1", "address_line2", "city", "state", "pincode", "country", "is_primary_address" ] +} + +def execute(filters=None): + columns, data = get_columns(filters), get_data(filters) + return columns, data + +def get_columns(filters): + party_type = filters.get("party_type") + party_type_value = get_party_group(party_type) + return [ + "{party_type}:Link/{party_type}".format(party_type=party_type), + "{party_value_type}::150".format(party_value_type = frappe.unscrub(str(party_type_value))), + "Address Line 1", + "Address Line 2", + "City", + "State", + "Postal Code", + "Country", + "Is Primary Address:Check", + "First Name", + "Last Name", + "Phone", + "Mobile No", + "Email Id", + "Is Primary Contact:Check" + ] + +def get_data(filters): + party_type = filters.get("party_type") + party = filters.get("party_name") + party_group = get_party_group(party_type) + + return get_party_addresses_and_contact(party_type, party, party_group) + +def get_party_addresses_and_contact(party_type, party, party_group): + data = [] + filters = None + party_details = frappe._dict() + + if not party_type: + return [] + + if party: + filters = { "name": party } + + fetch_party_list = frappe.get_list(party_type, filters=filters, fields=["name", party_group], as_list=True) + party_list = [d[0] for d in fetch_party_list] + party_groups = {} + for d in fetch_party_list: + party_groups[d[0]] = d[1] + + for d in party_list: + party_details.setdefault(d, frappe._dict()) + + party_details = get_party_details(party_type, party_list, "Address", party_details) + party_details = get_party_details(party_type, party_list, "Contact", party_details) + + for party, details in iteritems(party_details): + addresses = details.get("address", []) + contacts = details.get("contact", []) + if not any([addresses, contacts]): + result = [party] + result.append(party_groups[party]) + result.extend(add_blank_columns_for("Contact")) + result.extend(add_blank_columns_for("Address")) + data.append(result) + else: + addresses = map(list, addresses) + contacts = map(list, contacts) + + max_length = max(len(addresses), len(contacts)) + for idx in range(0, max_length): + result = [party] + result.append(party_groups[party]) + address = addresses[idx] if idx < len(addresses) else add_blank_columns_for("Address") + contact = contacts[idx] if idx < len(contacts) else add_blank_columns_for("Contact") + result.extend(address) + result.extend(contact) + + data.append(result) + return data + +def get_party_details(party_type, party_list, doctype, party_details): + filters = [ + ["Dynamic Link", "link_doctype", "=", party_type], + ["Dynamic Link", "link_name", "in", party_list] + ] + fields = ["`tabDynamic Link`.link_name"] + field_map.get(doctype, []) + + records = frappe.get_list(doctype, filters=filters, fields=fields, as_list=True) + for d in records: + details = party_details.get(d[0]) + details.setdefault(frappe.scrub(doctype), []).append(d[1:]) + + return party_details + +def add_blank_columns_for(doctype): + return ["" for field in field_map.get(doctype, [])] + +def get_party_group(party_type): + if not party_type: return + group = { + "Customer": "customer_group", + "Supplier": "supplier_group", + "Sales Partner": "partner_type" + } + + return group[party_type] \ No newline at end of file