From e3a3306b309f4a355b9469d4bfbd70ade679794c Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Wed, 12 Jun 2019 17:42:24 +0530 Subject: [PATCH 01/61] feat(customer): Add report to show item prices per Customer --- .../customer_wise_item_price/__init__.py | 0 .../customer_wise_item_price.js | 27 +++++ .../customer_wise_item_price.json | 43 ++++++++ .../customer_wise_item_price.py | 101 ++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 erpnext/selling/report/customer_wise_item_price/__init__.py create mode 100644 erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js create mode 100644 erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json create mode 100644 erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py diff --git a/erpnext/selling/report/customer_wise_item_price/__init__.py b/erpnext/selling/report/customer_wise_item_price/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js new file mode 100644 index 0000000000..d333c8be65 --- /dev/null +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js @@ -0,0 +1,27 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Customer-wise Item Price"] = { + "filters": [ + { + "label": __("Customer"), + "fieldname": "customer", + "fieldtype": "Link", + "options": "Customer", + "reqd": 1 + }, + { + "label": __("Item"), + "fieldname": "item", + "fieldtype": "Link", + "options": "Item", + "get_query": () => { + return { + query: "erpnext.controllers.queries.item_query", + filters: { 'is_sales_item': 1 } + } + } + } + ] +} diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json new file mode 100644 index 0000000000..998ba94a8b --- /dev/null +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json @@ -0,0 +1,43 @@ +{ + "add_total_row": 0, + "creation": "2019-06-12 03:25:36.263179", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Delta9", + "modified": "2019-06-12 03:25:36.263179", + "modified_by": "Administrator", + "module": "Selling", + "name": "Customer-wise Item Price", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Customer", + "report_name": "Customer-wise Item Price", + "report_type": "Script Report", + "roles": [ + { + "role": "Sales User" + }, + { + "role": "Stock Manager" + }, + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Sales Manager" + }, + { + "role": "Sales Master Manager" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py new file mode 100644 index 0000000000..bdd39229df --- /dev/null +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py @@ -0,0 +1,101 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals + +import frappe +from erpnext import get_default_company +from erpnext.accounts.party import get_party_details +from erpnext.stock.get_item_details import get_price_list_rate_for +from frappe import _ + + +def execute(filters=None): + if not filters: + filters = {} + + if not filters.get("customer"): + frappe.throw(_("Please select a Customer")) + + columns = get_columns(filters) + data = get_data(filters) + + return columns, data + + +def get_columns(filters=None): + return [ + { + "label": _("Item Code"), + "fieldname": "item_code", + "fieldtype": "Link", + "options": "Item", + "width": 150 + }, + { + "label": _("Item Name"), + "fieldname": "item_name", + "fieldtype": "Data", + "width": 200 + }, + { + "label": _("Selling Rate"), + "fieldname": "selling_rate", + "fieldtype": "Currency" + }, + { + "label": _("Available Stock"), + "fieldname": "available_stock", + "fieldtype": "Float", + "width": 150 + }, + { + "label": _("Price List"), + "fieldname": "price_list", + "fieldtype": "Link", + "options": "Price List", + "width": 120 + } + ] + + +def get_data(filters=None): + data = [] + customer_details = get_customer_details(filters) + items = get_selling_items(filters) + + for item in items: + price_list_rate = get_price_list_rate_for(customer_details, item.item_code) or 0.0 + available_stock = frappe.db.sql("SELECT sum(actual_qty) FROM `tabBin` WHERE item_code = %s", item.item_code) + available_stock = available_stock[0][0] if available_stock else None + + data.append({ + "item_code": item.item_code, + "item_name": item.item_name, + "selling_rate": price_list_rate, + "price_list": customer_details.get("price_list"), + "available_stock": available_stock, + }) + + return data + + +def get_customer_details(filters): + customer_details = get_party_details(party=filters.get("customer"), party_type="Customer") + customer_details.update({ + "company": get_default_company(), + "price_list": customer_details.get("selling_price_list") + }) + + return customer_details + + +def get_selling_items(filters): + if filters.get("item"): + item_filters = {"item_code": filters.get("item"), "is_sales_item": 1, "disabled": 0} + else: + item_filters = {"is_sales_item": 1, "disabled": 0} + + items = frappe.get_all("Item", filters=item_filters, fields=["item_code", "item_name"], order_by="item_name") + + return items \ No newline at end of file From 0426636a3270f23c6cccaa9ea519c850798c95fc Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Mon, 17 Jun 2019 12:11:04 +0530 Subject: [PATCH 02/61] fix(customer): Improve performance by reducing queries --- .../customer_wise_item_price/customer_wise_item_price.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py index bdd39229df..eb9273a562 100644 --- a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py @@ -62,12 +62,14 @@ def get_columns(filters=None): def get_data(filters=None): data = [] customer_details = get_customer_details(filters) + items = get_selling_items(filters) + item_stock_map = frappe.get_all("Bin", fields=["item_code", "sum(actual_qty) AS available"], group_by="item_code") + item_stock_map = {item.item_code: item.available for item in item_stock_map} for item in items: price_list_rate = get_price_list_rate_for(customer_details, item.item_code) or 0.0 - available_stock = frappe.db.sql("SELECT sum(actual_qty) FROM `tabBin` WHERE item_code = %s", item.item_code) - available_stock = available_stock[0][0] if available_stock else None + available_stock = item_stock_map.get(item.item_code) data.append({ "item_code": item.item_code, @@ -98,4 +100,4 @@ def get_selling_items(filters): items = frappe.get_all("Item", filters=item_filters, fields=["item_code", "item_name"], order_by="item_name") - return items \ No newline at end of file + return items From 1dc124cf757726389ffe30ce2ab6f30884b82851 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 10 Jul 2019 14:49:25 +0530 Subject: [PATCH 03/61] fix: Changed columns to new dict form --- .../stock/report/stock_ageing/stock_ageing.py | 79 +++++++++++++++++-- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 969284598c..f81e1c0b91 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -45,14 +45,83 @@ def get_average_age(fifo_queue, to_date): return (age_qty / total_qty) if total_qty else 0.0 def get_columns(filters): - columns = [_("Item Code") + ":Link/Item:100", _("Item Name") + "::100", _("Description") + "::200", - _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100"] + columns = [ + { + "label": _("Item Code"), + "fieldname": "item_code", + "fieldtype": "Link", + "options": "Item", + "width": 100 + }, + { + "label": _("Item Name"), + "fieldname": "item_name", + "fieldtype": "Data", + "width": 100 + }, + { + "label": _("Description"), + "fieldname": "description", + "fieldtype": "Data", + "width": 200 + }, + { + "label": _("Item Group"), + "fieldname": "item_group", + "fieldtype": "Link", + "options": "Item Group", + "width": 100 + }, + { + "label": _("Brand"), + "fieldname": "brand", + "fieldtype": "Link", + "options": "Brand", + "width": 100 + }] if filters.get("show_ageing_warehouse_wise"): - columns.extend([_("Warehouse") + ":Link/Warehouse:100"]) + columns +=[{ + "label": _("Warehouse"), + "fieldname": "warehouse", + "fieldtype": "Link", + "options": "Warehouse", + "width": 100 + }] - columns.extend([_("Available Qty") + ":Float:100", _("Average Age") + ":Float:100", - _("Earliest") + ":Int:80", _("Latest") + ":Int:80", _("UOM") + ":Link/UOM:100"]) + columns.extend([ + { + "label": _("Available Qty"), + "fieldname": "qty", + "fieldtype": "Float", + "width": 100 + }, + { + "label": _("Average Age"), + "fieldname": "average_age", + "fieldtype": "Float", + "width": 100 + }, + { + "label": _("Earliest"), + "fieldname": "earliest", + "fieldtype": "Int", + "width": 80 + }, + { + "label": _("Latest"), + "fieldname": "latest", + "fieldtype": "Int", + "width": 80 + }, + { + "label": _("UOM"), + "fieldname": "uom", + "fieldtype": "Link", + "options": "UOM", + "width": 100 + } + ]) return columns From 581d9310312830fef77ba3787c5964b1c72a4887 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 13 Jul 2019 21:58:32 +0530 Subject: [PATCH 04/61] fix: Enhancement in stock ageing report --- .../stock/report/stock_ageing/stock_ageing.js | 4 +- .../stock/report/stock_ageing/stock_ageing.py | 37 ++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.js b/erpnext/stock/report/stock_ageing/stock_ageing.js index aad8df426a..ccde61a167 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.js +++ b/erpnext/stock/report/stock_ageing/stock_ageing.js @@ -37,8 +37,8 @@ frappe.query_reports["Stock Ageing"] = { "options": "Brand" }, { - "fieldname":"show_ageing_warehouse_wise", - "label": __("Show Ageing Warehouse-wise"), + "fieldname":"show_warehouse_wise_stock", + "label": __("Show Warehouse-wise Stock"), "fieldtype": "Check", "default": 0 } diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index f81e1c0b91..54498934b3 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -14,7 +14,7 @@ def execute(filters=None): to_date = filters["to_date"] data = [] for item, item_dict in iteritems(item_details): - fifo_queue = item_dict["fifo_queue"] + fifo_queue = sorted(item_dict["fifo_queue"], key=lambda x: x[1]) details = item_dict["details"] if not fifo_queue: continue @@ -25,7 +25,7 @@ def execute(filters=None): row = [details.name, details.item_name, details.description, details.item_group, details.brand] - if filters.get("show_ageing_warehouse_wise"): + if filters.get("show_warehouse_wise_stock"): row.append(details.warehouse) row.extend([item_dict.get("total_qty"), average_age, @@ -80,7 +80,7 @@ def get_columns(filters): "width": 100 }] - if filters.get("show_ageing_warehouse_wise"): + if filters.get("show_warehouse_wise_stock"): columns +=[{ "label": _("Warehouse"), "fieldname": "warehouse", @@ -127,16 +127,34 @@ def get_columns(filters): def get_fifo_queue(filters): item_details = {} - for d in get_stock_ledger_entries(filters): - key = (d.name, d.warehouse) if filters.get('show_ageing_warehouse_wise') else d.name + transfered_item_details = {} + + sle = get_stock_ledger_entries(filters) + + for d in sle: + key = (d.name, d.warehouse) if filters.get('show_warehouse_wise_stock') else d.name item_details.setdefault(key, {"details": d, "fifo_queue": []}) fifo_queue = item_details[key]["fifo_queue"] + transfered_item_details.setdefault((d.voucher_no, d.name), []) + if d.voucher_type == "Stock Reconciliation": d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) if d.actual_qty > 0: - fifo_queue.append([d.actual_qty, d.posting_date]) + if filters.get('show_warehouse_wise_stock') and transfered_item_details.get((d.voucher_no, d.name)): + qty_to_add = d.actual_qty + while qty_to_add: + batch = transfered_item_details[(d.voucher_no, d.name)][0] + if 0 < batch[0] <= qty_to_add: + qty_to_add -= batch[0] + fifo_queue.append(batch) + transfered_item_details[((d.voucher_no, d.name))].pop(0) + else: + batch[0] -= qty_to_add + fifo_queue.append([qty_to_add, batch[1]]) + else: + fifo_queue.append([d.actual_qty, d.posting_date]) else: qty_to_pop = abs(d.actual_qty) while qty_to_pop: @@ -145,10 +163,11 @@ def get_fifo_queue(filters): # if batch qty > 0 # not enough or exactly same qty in current batch, clear batch qty_to_pop -= batch[0] - fifo_queue.pop(0) + transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) else: # all from current batch batch[0] -= qty_to_pop + transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) qty_to_pop = 0 item_details[key]["qty_after_transaction"] = d.qty_after_transaction @@ -163,7 +182,7 @@ def get_fifo_queue(filters): def get_stock_ledger_entries(filters): return frappe.db.sql("""select item.name, item.item_name, item_group, brand, description, item.stock_uom, - actual_qty, posting_date, voucher_type, qty_after_transaction, warehouse + actual_qty, posting_date, voucher_type, voucher_no, qty_after_transaction, warehouse from `tabStock Ledger Entry` sle, (select name, item_name, description, stock_uom, brand, item_group from `tabItem` {item_conditions}) item @@ -171,7 +190,7 @@ def get_stock_ledger_entries(filters): company = %(company)s and posting_date <= %(to_date)s {sle_conditions} - order by posting_date, posting_time, sle.creation"""\ + order by posting_date, posting_time, sle.creation, actual_qty"""\ .format(item_conditions=get_item_conditions(filters), sle_conditions=get_sle_conditions(filters)), filters, as_dict=True) From 4a7f370b15d547d0c8c7a4c9bec8e6f706c485e5 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 16 Jul 2019 16:08:50 +0530 Subject: [PATCH 05/61] fix: Consider serial no and batches in Stock ageing report --- .../stock/report/stock_ageing/stock_ageing.py | 69 +++++++++++++------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 54498934b3..7529ae6aa7 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -16,8 +16,9 @@ def execute(filters=None): for item, item_dict in iteritems(item_details): fifo_queue = sorted(item_dict["fifo_queue"], key=lambda x: x[1]) details = item_dict["details"] - if not fifo_queue: continue + if not fifo_queue or (not item_dict.get("total_qty")): continue + print(fifo_queue) average_age = get_average_age(fifo_queue, to_date) earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) @@ -39,8 +40,13 @@ def get_average_age(fifo_queue, to_date): batch_age = age_qty = total_qty = 0.0 for batch in fifo_queue: batch_age = date_diff(to_date, batch[1]) - age_qty += batch_age * batch[0] - total_qty += batch[0] + + if type(batch[0]) in ['int', 'float']: + age_qty += batch_age * batch[0] + total_qty += batch[0] + else: + age_qty += batch_age * 1 + total_qty += 1 return (age_qty / total_qty) if total_qty else 0.0 @@ -128,6 +134,7 @@ def get_columns(filters): def get_fifo_queue(filters): item_details = {} transfered_item_details = {} + serial_no_batch_purchase_details = {} sle = get_stock_ledger_entries(filters) @@ -142,7 +149,7 @@ def get_fifo_queue(filters): d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) if d.actual_qty > 0: - if filters.get('show_warehouse_wise_stock') and transfered_item_details.get((d.voucher_no, d.name)): + if transfered_item_details.get((d.voucher_no, d.name)): qty_to_add = d.actual_qty while qty_to_add: batch = transfered_item_details[(d.voucher_no, d.name)][0] @@ -154,21 +161,43 @@ def get_fifo_queue(filters): batch[0] -= qty_to_add fifo_queue.append([qty_to_add, batch[1]]) else: - fifo_queue.append([d.actual_qty, d.posting_date]) - else: - qty_to_pop = abs(d.actual_qty) - while qty_to_pop: - batch = fifo_queue[0] if fifo_queue else [0, None] - if 0 < batch[0] <= qty_to_pop: - # if batch qty > 0 - # not enough or exactly same qty in current batch, clear batch - qty_to_pop -= batch[0] - transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) + if d.serial_no or d.batch_no: + if d.serial_no: + for no in d.serial_no.split("\n"): + if serial_no_batch_purchase_details.get(no): + fifo_queue.append([no, serial_no_batch_purchase_details.get(no)]) + else: + serial_no_batch_purchase_details.setdefault(no, d.posting_date) + fifo_queue.append([no, d.posting_date]) + else: + if serial_no_batch_purchase_details.get(d.batch_no): + fifo_queue.append([d.batch_no, serial_no_batch_purchase_details.get(d.batch_no)]) + else: + serial_no_batch_purchase_details.setdefault(d.batch_no, d.posting_date) + fifo_queue.append([d.batch_no, d.posting_date]) + else: - # all from current batch - batch[0] -= qty_to_pop - transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) - qty_to_pop = 0 + fifo_queue.append([d.actual_qty, d.posting_date]) + else: + if d.serial_no or d.batch_no: + serial_no_list = d.serial_no.split("\n") + for serial_no in fifo_queue: + if serial_no[0] in serial_no_list: + fifo_queue.remove(serial_no) + else: + qty_to_pop = abs(d.actual_qty) + while qty_to_pop: + batch = fifo_queue[0] if fifo_queue else [0, None] + if 0 < batch[0] <= qty_to_pop: + # if batch qty > 0 + # not enough or exactly same qty in current batch, clear batch + qty_to_pop -= batch[0] + transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) + else: + # all from current batch + batch[0] -= qty_to_pop + transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) + qty_to_pop = 0 item_details[key]["qty_after_transaction"] = d.qty_after_transaction @@ -182,7 +211,7 @@ def get_fifo_queue(filters): def get_stock_ledger_entries(filters): return frappe.db.sql("""select item.name, item.item_name, item_group, brand, description, item.stock_uom, - actual_qty, posting_date, voucher_type, voucher_no, qty_after_transaction, warehouse + actual_qty, posting_date, voucher_type, voucher_no, serial_no, batch_no, qty_after_transaction, warehouse from `tabStock Ledger Entry` sle, (select name, item_name, description, stock_uom, brand, item_group from `tabItem` {item_conditions}) item @@ -190,7 +219,7 @@ def get_stock_ledger_entries(filters): company = %(company)s and posting_date <= %(to_date)s {sle_conditions} - order by posting_date, posting_time, sle.creation, actual_qty"""\ + order by posting_date, posting_time, sle.creation, actual_qty""" #nosec .format(item_conditions=get_item_conditions(filters), sle_conditions=get_sle_conditions(filters)), filters, as_dict=True) From 3877b5407cdd1c2caa4b76922031c8c4183ff59a Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 22 Jul 2019 15:30:18 +0530 Subject: [PATCH 06/61] fix: Remove batch --- .../stock/report/stock_ageing/stock_ageing.py | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 7529ae6aa7..790cd8fc26 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -6,6 +6,7 @@ import frappe from frappe import _ from frappe.utils import date_diff, flt from six import iteritems +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos def execute(filters=None): @@ -18,7 +19,6 @@ def execute(filters=None): details = item_dict["details"] if not fifo_queue or (not item_dict.get("total_qty")): continue - print(fifo_queue) average_age = get_average_age(fifo_queue, to_date) earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) @@ -151,39 +151,27 @@ def get_fifo_queue(filters): if d.actual_qty > 0: if transfered_item_details.get((d.voucher_no, d.name)): qty_to_add = d.actual_qty - while qty_to_add: - batch = transfered_item_details[(d.voucher_no, d.name)][0] - if 0 < batch[0] <= qty_to_add: - qty_to_add -= batch[0] - fifo_queue.append(batch) - transfered_item_details[((d.voucher_no, d.name))].pop(0) - else: - batch[0] -= qty_to_add - fifo_queue.append([qty_to_add, batch[1]]) + batch = transfered_item_details[(d.voucher_no, d.name)][0] + fifo_queue.append(batch) + transfered_item_details[((d.voucher_no, d.name))].pop(0) else: - if d.serial_no or d.batch_no: + if d.serial_no: if d.serial_no: - for no in d.serial_no.split("\n"): + for no in get_serial_nos(d.serial_no): if serial_no_batch_purchase_details.get(no): fifo_queue.append([no, serial_no_batch_purchase_details.get(no)]) else: serial_no_batch_purchase_details.setdefault(no, d.posting_date) fifo_queue.append([no, d.posting_date]) - else: - if serial_no_batch_purchase_details.get(d.batch_no): - fifo_queue.append([d.batch_no, serial_no_batch_purchase_details.get(d.batch_no)]) - else: - serial_no_batch_purchase_details.setdefault(d.batch_no, d.posting_date) - fifo_queue.append([d.batch_no, d.posting_date]) - else: fifo_queue.append([d.actual_qty, d.posting_date]) else: if d.serial_no or d.batch_no: - serial_no_list = d.serial_no.split("\n") - for serial_no in fifo_queue: - if serial_no[0] in serial_no_list: - fifo_queue.remove(serial_no) + if d.serial_no: + serial_no_list = d.serial_no.split("\n") + for serial_no in fifo_queue: + if serial_no[0] in serial_no_list: + fifo_queue.remove(serial_no) else: qty_to_pop = abs(d.actual_qty) while qty_to_pop: From d9cc84892be7cafac01540a9124b95d65c7a7153 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 22 Jul 2019 15:56:41 +0530 Subject: [PATCH 07/61] fix: Use get_serial_no and remove batch --- erpnext/stock/report/stock_ageing/stock_ageing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 790cd8fc26..91ba463683 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -166,9 +166,9 @@ def get_fifo_queue(filters): else: fifo_queue.append([d.actual_qty, d.posting_date]) else: - if d.serial_no or d.batch_no: + if d.serial_no: if d.serial_no: - serial_no_list = d.serial_no.split("\n") + serial_no_list = get_serial_nos(d.serial_no) for serial_no in fifo_queue: if serial_no[0] in serial_no_list: fifo_queue.remove(serial_no) From a19d1d692658d7377aebd27974d76753cabaf6a4 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 23 Jul 2019 08:30:09 +0530 Subject: [PATCH 08/61] fix: Fixes in stock ageing report --- .../stock/report/stock_ageing/stock_ageing.py | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 91ba463683..83a1d7b62b 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -148,30 +148,28 @@ def get_fifo_queue(filters): if d.voucher_type == "Stock Reconciliation": d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) + serial_no_list = get_serial_nos(d.serial_no) if d.serial_no else [] + if d.actual_qty > 0: if transfered_item_details.get((d.voucher_no, d.name)): - qty_to_add = d.actual_qty batch = transfered_item_details[(d.voucher_no, d.name)][0] fifo_queue.append(batch) transfered_item_details[((d.voucher_no, d.name))].pop(0) else: - if d.serial_no: - if d.serial_no: - for no in get_serial_nos(d.serial_no): - if serial_no_batch_purchase_details.get(no): - fifo_queue.append([no, serial_no_batch_purchase_details.get(no)]) - else: - serial_no_batch_purchase_details.setdefault(no, d.posting_date) - fifo_queue.append([no, d.posting_date]) + if serial_no_list: + for serial_no in serial_no_list: + if serial_no_batch_purchase_details.get(serial_no): + fifo_queue.append([serial_no, serial_no_batch_purchase_details.get(serial_no)]) + else: + serial_no_batch_purchase_details.setdefault(serial_no, d.posting_date) + fifo_queue.append([serial_no, d.posting_date]) else: fifo_queue.append([d.actual_qty, d.posting_date]) else: - if d.serial_no: - if d.serial_no: - serial_no_list = get_serial_nos(d.serial_no) - for serial_no in fifo_queue: - if serial_no[0] in serial_no_list: - fifo_queue.remove(serial_no) + if serial_no_list: + for serial_no in fifo_queue: + if serial_no[0] in serial_no_list: + fifo_queue.remove(serial_no) else: qty_to_pop = abs(d.actual_qty) while qty_to_pop: From bcfbc792b4d99108dfc696f3f901e2a885a1690e Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 23 Jul 2019 16:05:29 +0530 Subject: [PATCH 09/61] fix: scrap item not adding while doing finished good entry --- erpnext/stock/doctype/stock_entry/stock_entry.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index f40560a57f..b5303327f6 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -802,13 +802,13 @@ class StockEntry(StockController): self.add_to_stock_entry_detail(item_dict) - if self.purpose != "Send to Subcontractor": - scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty) - for item in itervalues(scrap_item_dict): - if self.pro_doc and self.pro_doc.scrap_warehouse: - item["to_warehouse"] = self.pro_doc.scrap_warehouse + if self.purpose != "Send to Subcontractor" and self.purpose == "Manufacture": + scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty) + for item in itervalues(scrap_item_dict): + if self.pro_doc and self.pro_doc.scrap_warehouse: + item["to_warehouse"] = self.pro_doc.scrap_warehouse - self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no) + self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no) # fetch the serial_no of the first stock entry for the second stock entry if self.work_order and self.purpose == "Manufacture": From 20e1a3e1998b5c24d03d20c9bc49ed8a40e41593 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 23 Jul 2019 17:00:23 +0530 Subject: [PATCH 10/61] fix: reset issue fulfilled indicator --- erpnext/support/doctype/issue/issue.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 98d8c99809..58e2076858 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -210,6 +210,7 @@ class Issue(Document): self.service_level_agreement_creation = now_datetime() self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement) + self.agreement_fulfilled = "Ongoing" self.save() def get_expected_time_for(parameter, service_level, start_date_time): From 14600e6a3e10b1c3f6ad1500a471a482302e01d7 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 24 Jul 2019 15:18:52 +0530 Subject: [PATCH 11/61] fix(travis): Remove unnecessary commands --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a8a0d82614..ace0bfb243 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,12 +14,6 @@ services: install: # fix mongodb travis error - - sudo rm /etc/apt/sources.list.d/mongodb*.list - - pip install flake8==3.3.0 - - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics - - sudo rm /etc/apt/sources.list.d/docker.list - - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ - - sudo apt-get purge -y mysql-common mysql-server mysql-client - nvm install 10 - pip install python-coveralls - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py From b1f3e0224c8a0ef104e43901c0cee9f8d1702940 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 24 Jul 2019 21:32:55 +0530 Subject: [PATCH 12/61] fix: GSTR-1 query fix --- erpnext/regional/report/gstr_1/gstr_1.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index e8c170e721..2da1085732 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -161,8 +161,9 @@ class Gstr1Report(object): "gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]] }) - conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1 - and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers])) + if customers: + conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1 + and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers])) if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') @@ -174,11 +175,11 @@ class Gstr1Report(object): "gst_category": ["in", ["Unregistered"]] }) - if self.filters.get("type_of_business") == "B2C Large": + if self.filters.get("type_of_business") == "B2C Large" and customers: conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2) and grand_total > {0} and is_return != 1 and customer in ({1})""".\ format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers])) - elif self.filters.get("type_of_business") == "B2C Small": + elif self.filters.get("type_of_business") == "B2C Small" and customers: conditions += """ and ( SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2) or grand_total <= {0}) and is_return != 1 and customer in ({1})""".\ From f56284b0c1920fa098f458d17f0afbde53b9d815 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 25 Jul 2019 12:23:40 +0530 Subject: [PATCH 13/61] Dynamic link issue fix in Bank reconciliation statement --- .../bank_reconciliation_statement.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py index 1923f78cf8..63317c52d8 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -58,8 +58,7 @@ def get_columns(): { "fieldname": "payment_document", "label": _("Payment Document Type"), - "fieldtype": "Link", - "options": "DocType", + "fieldtype": "Data", "width": 220 }, { From 7204bcb932bc6f00b6aa041d0d3958f9f509db61 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 13:42:43 +0530 Subject: [PATCH 14/61] fix(travis): Restructure build matrix --- .travis.yml | 36 +++++++++++++++++++++++++----------- travis/run-tests.sh | 12 ------------ 2 files changed, 25 insertions(+), 23 deletions(-) delete mode 100755 travis/run-tests.sh diff --git a/.travis.yml b/.travis.yml index ace0bfb243..0660779b2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,34 @@ -language: python dist: trusty -python: - - "2.7" - - "3.6" - -env: - - TEST_TYPE="Server Side Test" - - TEST_TYPE="Patch Test" +language: python services: - mysql +jobs: + include: + - name: "Python 2.7 Server Side Test" + python: 2.7 + script: bench run-tests --app erpnext --coverage + + - name: "Python 3.6 Server Side Test" + python: 3.6 + script: bench run-tests --app erpnext --coverage + + - name: "Python 2.7 Patch Test" + python: 2.7 + before_script: + - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz + - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + script: bench migrate + + - name: "Python 3.6 Patch Test" + python: 3.6 + before_script: + - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz + - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + script: bench migrate + install: # fix mongodb travis error - nvm install 10 @@ -38,8 +55,5 @@ before_script: - bench start & - sleep 10 -script: - - bash $TRAVIS_BUILD_DIR/travis/run-tests.sh - after_script: - coveralls -b apps/erpnext -d ../../sites/.coverage diff --git a/travis/run-tests.sh b/travis/run-tests.sh deleted file mode 100755 index 7cfd64833b..0000000000 --- a/travis/run-tests.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e - -if [[ $TEST_TYPE == 'Server Side Test' ]]; then - bench run-tests --app erpnext --coverage - -elif [[ $TEST_TYPE == 'Patch Test' ]]; then - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - bench migrate -fi From 828699f26a29cd5e4af29b86b6eb10755aed2985 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:09:34 +0530 Subject: [PATCH 15/61] fix(travis): Use MariaDB 10.3 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0660779b2d..1561d6ca0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ dist: trusty language: python -services: - - mysql +addons: + mariadb: 10.3 jobs: include: From c49d45497c86e0bc16c72494c055e63d0d292e1d Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:10:06 +0530 Subject: [PATCH 16/61] fix(travis): Install coverall after tests --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1561d6ca0f..c51c6b078e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,9 +30,7 @@ jobs: script: bench migrate install: - # fix mongodb travis error - nvm install 10 - - pip install python-coveralls - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py - sudo python install.py --develop --user travis --without-bench-setup - sudo pip install -e ~/bench @@ -56,4 +54,5 @@ before_script: - sleep 10 after_script: + - pip install python-coveralls - coveralls -b apps/erpnext -d ../../sites/.coverage From 306a410b773ed9e7ffc426576630dc427dabae67 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:11:18 +0530 Subject: [PATCH 17/61] fix(travis): Do not execute install.py --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c51c6b078e..047a98640f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,11 @@ jobs: script: bench migrate install: + - cd ~ - nvm install 10 - - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py - - sudo python install.py --develop --user travis --without-bench-setup - - sudo pip install -e ~/bench + + - git clone https://github.com/frappe/bench --depth 1 + - pip install -e ./bench - rm $TRAVIS_BUILD_DIR/.git/shallow - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh From ac185989ff9b41fe9abede23757163af4d4ea79e Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:15:30 +0530 Subject: [PATCH 18/61] fix(travis): Remove travis/bench_init.sh --- .travis.yml | 5 +++-- travis/bench_init.sh | 8 -------- 2 files changed, 3 insertions(+), 10 deletions(-) delete mode 100755 travis/bench_init.sh diff --git a/.travis.yml b/.travis.yml index 047a98640f..e0a2ead3d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,9 @@ install: - git clone https://github.com/frappe/bench --depth 1 - pip install -e ./bench - - rm $TRAVIS_BUILD_DIR/.git/shallow - - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh + - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 + - bench init --frappe-path ~/frappe --python $(which python) frappe-bench + - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ before_script: diff --git a/travis/bench_init.sh b/travis/bench_init.sh deleted file mode 100755 index f96269b919..0000000000 --- a/travis/bench_init.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -cd ~/ -curl -I https://github.com/frappe/frappe/tree/$TRAVIS_BRANCH | head -n 1 | cut -d $' ' -f2 | ( - read response; - [ $response == '200' ] && branch=$TRAVIS_BRANCH || branch='develop'; - bench init frappe-bench --frappe-path https://github.com/frappe/frappe.git --frappe-branch $branch --python $(which python) -) From 06ca6f7705675752540b05481056b686bc5c4dfb Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:18:05 +0530 Subject: [PATCH 19/61] fix(travis): Remove unused files --- .travis.yml | 3 ++- {test_sites/test_site => .travis}/site_config.json | 3 +-- test_sites/apps.txt | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) rename {test_sites/test_site => .travis}/site_config.json (81%) delete mode 100644 test_sites/apps.txt diff --git a/.travis.yml b/.travis.yml index e0a2ead3d5..108df91e40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,8 @@ install: - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 - bench init --frappe-path ~/frappe --python $(which python) frappe-bench - - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ + - mkdir ~/frappe-bench/sites/test_site + - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ before_script: - mysql -u root -ptravis -e 'create database test_frappe' diff --git a/test_sites/test_site/site_config.json b/.travis/site_config.json similarity index 81% rename from test_sites/test_site/site_config.json rename to .travis/site_config.json index 7a4d106508..695f6c3517 100644 --- a/test_sites/test_site/site_config.json +++ b/.travis/site_config.json @@ -6,8 +6,7 @@ "mail_login": "test@example.com", "mail_password": "test", "admin_password": "admin", - "run_selenium_tests": 1, "root_password": "travis", - "host_name": "http://localhost:8000", + "host_name": "http://test_site:8000", "install_apps": ["erpnext"] } \ No newline at end of file diff --git a/test_sites/apps.txt b/test_sites/apps.txt deleted file mode 100644 index ee6454915c..0000000000 --- a/test_sites/apps.txt +++ /dev/null @@ -1 +0,0 @@ -erpnext \ No newline at end of file From 8005022508d9c2fb718449ceb5aa7bcc3aabaca6 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:19:30 +0530 Subject: [PATCH 20/61] fix(travis): Setup MariaDB --- .travis.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 108df91e40..5ecede08e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,9 +43,15 @@ install: - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ before_script: - - mysql -u root -ptravis -e 'create database test_frappe' - - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis - - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis + - mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'" + - mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" + + - mysql -u root -e "CREATE DATABASE test_frappe" + - mysql -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'" + - mysql -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'" + + - mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'" + - mysql -u root -e "FLUSH PRIVILEGES" - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR From 6f025e7b4fc5360febaeb09b0af8b65e44c0bfa4 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:21:19 +0530 Subject: [PATCH 21/61] fix(travis): Do not use use_site --- .travis.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ecede08e8..9840ad5e15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,31 +3,32 @@ dist: trusty language: python addons: + hosts: test_site mariadb: 10.3 jobs: include: - name: "Python 2.7 Server Side Test" python: 2.7 - script: bench run-tests --app erpnext --coverage + script: bench --site test_site run-tests --app erpnext --coverage - name: "Python 3.6 Server Side Test" python: 3.6 - script: bench run-tests --app erpnext --coverage + script: bench --site test_site run-tests --app erpnext --coverage - name: "Python 2.7 Patch Test" python: 2.7 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - script: bench migrate + script: bench --site test_site migrate - name: "Python 3.6 Patch Test" python: 3.6 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - script: bench migrate + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + script: bench --site test_site migrate install: - cd ~ @@ -55,9 +56,8 @@ before_script: - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR - - bench use test_site - - bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes - - bench scheduler disable + - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes + - bench --site test_site scheduler disable - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - sleep 10 From 6e2fa02c56bdfca84c2505abaeb4a6eaf36b1a51 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:21:54 +0530 Subject: [PATCH 22/61] fix(travis): Do not disable scheduler using CLI --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9840ad5e15..cd593a8aed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,6 @@ before_script: - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes - - bench --site test_site scheduler disable - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - sleep 10 From 97ad6352afe91febc06b5daf2d6385a8ead5cd11 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:23:24 +0530 Subject: [PATCH 23/61] fix(travis): Execute get-app and reinstall after bench start --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd593a8aed..d3581e2b8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,11 +55,11 @@ before_script: - mysql -u root -e "FLUSH PRIVILEGES" - cd ~/frappe-bench - - bench get-app erpnext $TRAVIS_BUILD_DIR - - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - sleep 10 + - bench get-app erpnext $TRAVIS_BUILD_DIR + - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes after_script: - pip install python-coveralls From 6f978d2497553ce78c89aaf701e505a8582e4233 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:23:43 +0530 Subject: [PATCH 24/61] perf(travis): Do not waste 10 seconds --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d3581e2b8d..23627f51f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,6 @@ before_script: - cd ~/frappe-bench - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - - sleep 10 - bench get-app erpnext $TRAVIS_BUILD_DIR - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes From 543996652baae9e992d21f28b63c79d397c8647f Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:25:53 +0530 Subject: [PATCH 25/61] fix(travis): Use MariaDB credentials from site_config.json --- .travis.yml | 2 +- .travis/site_config.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 23627f51f0..54d77db7c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ before_script: - sed -i 's/9000/9001/g' sites/common_site_config.json - bench start & - bench get-app erpnext $TRAVIS_BUILD_DIR - - bench --site test_site reinstall --mariadb-root-username root --mariadb-root-password travis --yes + - bench --site test_site reinstall --yes after_script: - pip install python-coveralls diff --git a/.travis/site_config.json b/.travis/site_config.json index 695f6c3517..dae80095d4 100644 --- a/.travis/site_config.json +++ b/.travis/site_config.json @@ -6,6 +6,7 @@ "mail_login": "test@example.com", "mail_password": "test", "admin_password": "admin", + "root_login": "root", "root_password": "travis", "host_name": "http://test_site:8000", "install_apps": ["erpnext"] From 13919440a7afdce366e38925e3638eab71b00d78 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:27:20 +0530 Subject: [PATCH 26/61] perf(travis): Remove unnecessary processes from Procfile --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 54d77db7c6..2637d978e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,12 @@ before_script: - mysql -u root -e "FLUSH PRIVILEGES" - cd ~/frappe-bench - - sed -i 's/9000/9001/g' sites/common_site_config.json + + - sed -i 's/watch:/# watch:/g' Procfile + - sed -i 's/schedule:/# schedule:/g' Procfile + - sed -i 's/socketio:/# socketio:/g' Procfile + - sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile + - bench start & - bench get-app erpnext $TRAVIS_BUILD_DIR - bench --site test_site reinstall --yes From 1de45877b116ed33bbdf55222c2e4e1da63ea709 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:28:15 +0530 Subject: [PATCH 27/61] perf(travis): Do not build assets --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2637d978e4..e3d432a5ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ install: - pip install -e ./bench - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 - - bench init --frappe-path ~/frappe --python $(which python) frappe-bench + - bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench - mkdir ~/frappe-bench/sites/test_site - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ From 5542af9be8af5f5397a771ad7086fcc59755de12 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:36:22 +0530 Subject: [PATCH 28/61] perf(travis): Use travis optimizations --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index e3d432a5ae..ee385d0e08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,12 @@ dist: trusty language: python +git: + depth: 1 + +cache: + - pip + addons: hosts: test_site mariadb: 10.3 From 4b680178be72dd0ce129ba5e771184c21db0c273 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:38:07 +0530 Subject: [PATCH 29/61] fix(travis): Execute get-app before bench start --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ee385d0e08..2f7637372e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,8 +67,8 @@ before_script: - sed -i 's/socketio:/# socketio:/g' Procfile - sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile - - bench start & - bench get-app erpnext $TRAVIS_BUILD_DIR + - bench start & - bench --site test_site reinstall --yes after_script: From 6002fd7820c08c7a75b1d7560ef01229ab9dd6f7 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:39:30 +0530 Subject: [PATCH 30/61] fix(travis): Merge install and before_script --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2f7637372e..fb941f3ff3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,6 @@ install: - mkdir ~/frappe-bench/sites/test_site - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/ -before_script: - mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'" - mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" From dac46ed6e1278fed1274ab14d336fbaef0091283 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:50:46 +0530 Subject: [PATCH 31/61] fix(travis): Use --site parameter --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb941f3ff3..9b51c85eca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ jobs: python: 2.7 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis script: bench --site test_site migrate - name: "Python 3.6 Patch Test" From fdb395c9776459aa7e48580f55a5bf800cb94f74 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 21:51:12 +0530 Subject: [PATCH 32/61] fix(travis): Remove redundant arguments --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9b51c85eca..53c67fe15d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,14 +26,14 @@ jobs: python: 2.7 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz script: bench --site test_site migrate - name: "Python 3.6 Patch Test" python: 3.6 before_script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz script: bench --site test_site migrate install: From a630a24040f039fae82f65741895c96b3ef09fe9 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 22:40:26 +0530 Subject: [PATCH 33/61] fix(travis): Install wkhtmltopdf --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 53c67fe15d..40afeee8d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,6 +59,11 @@ install: - mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'" - mysql -u root -e "FLUSH PRIVILEGES" + - wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz + - tar -xf /tmp/wkhtmltox.tar.xz -C /tmp + - sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf + - sudo chmod o+x /usr/local/bin/wkhtmltopdf + - cd ~/frappe-bench - sed -i 's/watch:/# watch:/g' Procfile From 6a5b7f751cd8c2cb4b335c683e69bd7cff102f2e Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 25 Jul 2019 23:37:43 +0530 Subject: [PATCH 34/61] perf(tests): Use setUpClass and tearDownClass instead of setUp and tearDown --- .../doctype/purchase_invoice/test_purchase_invoice.py | 7 +++++-- .../accounts/doctype/sales_invoice/test_sales_invoice.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index b4d584fbde..6deee38148 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -20,11 +20,13 @@ test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Templ test_ignore = ["Serial No"] class TestPurchaseInvoice(unittest.TestCase): - def setUp(self): + @classmethod + def setUpClass(self): unlink_payment_on_cancel_of_invoice() frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) - def tearDown(self): + @classmethod + def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) def test_gl_entries_without_perpetual_inventory(self): @@ -91,6 +93,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi_doc = frappe.get_doc('Purchase Invoice', pi_doc.name) self.assertRaises(frappe.LinkExistsError, pi_doc.cancel) + unlink_payment_on_cancel_of_invoice() def test_purchase_invoice_for_blocked_supplier(self): supplier = frappe.get_doc('Supplier', '_Test Supplier') diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 52470fde95..dff55947df 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -29,10 +29,12 @@ class TestSalesInvoice(unittest.TestCase): w.submit() return w - def setUp(self): + @classmethod + def setUpClass(self): unlink_payment_on_cancel_of_invoice() - def tearDown(self): + @classmethod + def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) def test_timestamp_change(self): @@ -135,6 +137,7 @@ class TestSalesInvoice(unittest.TestCase): unlink_payment_on_cancel_of_invoice(0) si = frappe.get_doc('Sales Invoice', si.name) self.assertRaises(frappe.LinkExistsError, si.cancel) + unlink_payment_on_cancel_of_invoice() def test_sales_invoice_calculation_export_currency(self): si = frappe.copy_doc(test_records[2]) From 0ae786adec215f25fd60f20b11b7ff8503322eae Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 00:38:51 +0530 Subject: [PATCH 35/61] perf(tests): Do not unnecessarily create companies --- erpnext/tests/test_notifications.py | 44 ++++++++++------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/erpnext/tests/test_notifications.py b/erpnext/tests/test_notifications.py index 596bc80dee..1fd90beef0 100644 --- a/erpnext/tests/test_notifications.py +++ b/erpnext/tests/test_notifications.py @@ -2,45 +2,31 @@ # MIT License. See license.txt from __future__ import unicode_literals +import frappe import unittest from frappe.desk import notifications from frappe.test_runner import make_test_objects class TestNotifications(unittest.TestCase): - def setUp(self): - test_records_company = [ - { - "abbr": "_TC6", - "company_name": "_Test Company 6", - "country": "India", - "default_currency": "INR", - "doctype": "Company", - "domain": "Manufacturing", - "monthly_sales_target": 2000, - "chart_of_accounts": "Standard" - }, - { - "abbr": "_TC7", - "company_name": "_Test Company 7", - "country": "United States", - "default_currency": "USD", - "doctype": "Company", - "domain": "Retail", - "monthly_sales_target": 10000, - "total_monthly_sales": 1000, - "chart_of_accounts": "Standard" - }, - ] - - make_test_objects('Company', test_records=test_records_company, reset=True) - def test_get_notifications_for_targets(self): ''' Test notification config entries for targets as percentages ''' + company = frappe.get_all("Company")[0] + frappe.db.set_value("Company", company.name, "monthly_sales_target", 10000) + frappe.db.set_value("Company", company.name, "total_monthly_sales", 1000) + config = notifications.get_notification_config() doc_target_percents = notifications.get_notifications_for_targets(config, {}) - self.assertEqual(doc_target_percents['Company']['_Test Company 7'], 10) - self.assertEqual(doc_target_percents['Company']['_Test Company 6'], 0) + + self.assertEqual(doc_target_percents['Company'][company.name], 10) + + frappe.db.set_value("Company", company.name, "monthly_sales_target", 2000) + frappe.db.set_value("Company", company.name, "total_monthly_sales", 0) + + config = notifications.get_notification_config() + doc_target_percents = notifications.get_notifications_for_targets(config, {}) + + self.assertEqual(doc_target_percents['Company'][company.name], 0) From 0f072d7d40ff820ebd237a02b96e81f629661854 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 01:09:01 +0530 Subject: [PATCH 36/61] perf(tests): Use country with lesser fixtures --- .../report/procurement_tracker/test_procurement_tracker.py | 2 +- erpnext/hr/doctype/staffing_plan/test_staffing_plan.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py index 4a13f385bb..bebf0ccec5 100644 --- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py +++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py @@ -30,7 +30,7 @@ class TestProcurementTracker(unittest.TestCase): company_name="_Test Procurement Company", abbr="_TPC", default_currency="INR", - country="India" + country="Pakistan" )).insert() warehouse = create_warehouse("_Test Procurement Warehouse", company="_Test Procurement Company") mr = make_material_request(company="_Test Procurement Company", warehouse=warehouse) diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py index 4a0ce1800a..9ba6d5e63f 100644 --- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py @@ -92,5 +92,5 @@ def make_company(): company.abbr = "_TC10" company.parent_company = "_Test Company" company.default_currency = "INR" - company.country = "India" + company.country = "Pakistan" company.insert() \ No newline at end of file From 6bc2988623a273eeb8379719c31bdf22b0164def Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 03:05:40 +0530 Subject: [PATCH 37/61] fix(stock): Fix travis builds --- .../stock/doctype/stock_reconciliation/stock_reconciliation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index d9e62c7931..98a8c59483 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -327,7 +327,8 @@ class StockReconciliation(StockController): if sl_entries: sl_entries.reverse() - self.make_sl_entries(sl_entries) + allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock") + self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock) # repost future entries for selected item_code, warehouse for entries in existing_entries: From ff79463e36cf4ebbe751dc356f7075f22265ac42 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 03:06:23 +0530 Subject: [PATCH 38/61] perf(travis): Use setUpClass instead of setUp --- .../test_stock_reconciliation.py | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index f0c71cf39a..ededc4d8b4 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -17,10 +17,11 @@ from erpnext.stock.utils import get_stock_balance, get_incoming_rate, get_availa from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos class TestStockReconciliation(unittest.TestCase): - def setUp(self): + @classmethod + def setUpClass(self): create_batch_or_serial_no_items() frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - self.insert_existing_sle() + insert_existing_sle() def test_reco_for_fifo(self): self._test_reco_sle_gle("FIFO") @@ -97,18 +98,6 @@ class TestStockReconciliation(unittest.TestCase): self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100], [items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]]) - def insert_existing_sle(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - - make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item", - target="_Test Warehouse - _TC", qty=10, basic_rate=700) - - make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", - source="_Test Warehouse - _TC", qty=15) - - make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", - target="_Test Warehouse - _TC", qty=15, basic_rate=1200) - def test_stock_reco_for_serialized_item(self): set_perpetual_inventory() @@ -218,6 +207,18 @@ class TestStockReconciliation(unittest.TestCase): for d in to_delete_records: frappe.delete_doc("Stock Reconciliation", d) +def insert_existing_sle(): + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + + make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item", + target="_Test Warehouse - _TC", qty=10, basic_rate=700) + + make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", + source="_Test Warehouse - _TC", qty=15) + + make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", + target="_Test Warehouse - _TC", qty=15, basic_rate=1200) + def create_batch_or_serial_no_items(): create_warehouse("_Test Warehouse for Stock Reco1", {"is_group": 0, "parent_warehouse": "_Test Warehouse Group - _TC"}) From 1e82638ae894da7e4b922985e476d522e6a6bb4b Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 03:51:45 +0530 Subject: [PATCH 39/61] perf(tests): Remove unnecessary tearDown code --- .../doctype/stock_settings/test_stock_settings.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.py b/erpnext/stock/doctype/stock_settings/test_stock_settings.py index 1e83ec2f49..42a78f723d 100644 --- a/erpnext/stock/doctype/stock_settings/test_stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/test_stock_settings.py @@ -8,16 +8,7 @@ import unittest class TestStockSettings(unittest.TestCase): def setUp(self): - settings = frappe.get_single('Stock Settings') - settings.clean_description_html = 0 - settings.save() - - frappe.delete_doc('Item', 'Item for description test') - - def tearDown(self): - settings = frappe.get_single('Stock Settings') - settings.clean_description_html = 1 - settings.save() + frappe.db.set_value("Stock Settings", None, "clean_description_html", 0) def test_settings(self): item = frappe.get_doc(dict( From 96eec7e2cd01885a91dbbc2fff20ae5830055e43 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Fri, 26 Jul 2019 05:06:42 +0530 Subject: [PATCH 40/61] chore: Empty commit From 0ec747f57c374811ac34bfad1425dafd7217d53c Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 26 Jul 2019 08:15:45 +0530 Subject: [PATCH 41/61] fix(Account): Pass parent currency to child currency In a scenario where Parent Company Account's Currency is different from it's default currency, the Account Currency of Child would be set from the default currency of Company which might be wrong --- erpnext/accounts/doctype/account/account.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 68efe37719..0e57b3f198 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -123,7 +123,9 @@ class Account(NestedSet): doc.flags.ignore_root_company_validation = True doc.update({ "company": company, - "account_currency": None, + # parent account's currency should be passed down to child account's curreny + # if it is None, it picks it up from default company currency, which might be unintended + "account_currency": self.account_currency, "parent_account": parent_acc_name_map[company] }) doc.save() From efd6307bc4a8faf0003a41f62bfd88ed14d52807 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 14 Jul 2019 19:28:56 +0530 Subject: [PATCH 42/61] fix: Default Accounting Dimensions in doctypes --- .../accounting_dimension/accounting_dimension.json | 9 ++++++++- erpnext/public/js/utils.js | 2 +- erpnext/public/js/utils/dimension_tree_filter.js | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 6a4dc5c34f..0fab74d522 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -9,6 +9,7 @@ "document_type", "label", "fieldname", + "default_dimension", "mandatory_for_bs", "mandatory_for_pl", "disabled" @@ -53,9 +54,15 @@ "fieldname": "mandatory_for_pl", "fieldtype": "Check", "label": "Mandatory For Profit and Loss Account" + }, + { + "fieldname": "default_dimension", + "fieldtype": "Dynamic Link", + "label": "Default Dimension", + "options": "document_type" } ], - "modified": "2019-07-14 17:25:01.307948", + "modified": "2019-07-14 19:16:25.405924", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 0252f38931..1c5e98eb7d 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -69,7 +69,7 @@ $.extend(erpnext, { return []; } let dimensions = await frappe.db.get_list('Accounting Dimension', { - fields: ['label', 'fieldname', 'document_type'], + fields: ['label', 'fieldname', 'document_type', 'default_dimension'], filters: { disabled: 0 } diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 549f95e039..4a82edda69 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -14,6 +14,9 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { onload: function(frm) { erpnext.dimension_filters.then((dimensions) => { dimensions.forEach((dimension) => { + if (dimension['default_dimension']) { + frm.set_value(dimension['fieldname'], dimension['default_dimension']); + } frappe.model.with_doctype(dimension['document_type'], () => { if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { frm.set_query(dimension['fieldname'], { From ada1ac80133c519e7afc628bb8e4794c8b3f95e4 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Wed, 17 Jul 2019 15:38:21 +0530 Subject: [PATCH 43/61] fix: Added default dimension and filter in bootinfo --- .../accounting_dimension.js | 68 +++++++++++-------- .../accounting_dimension.json | 12 ++-- .../accounting_dimension.py | 8 +++ .../accounting_dimension_detail/__init__.py | 0 .../accounting_dimension_detail.json | 47 +++++++++++++ .../accounting_dimension_detail.py | 10 +++ .../journal_entry_account.json | 4 +- .../sales_invoice_item.json | 3 +- .../accounts_payable/accounts_payable.js | 15 ++-- .../accounts_payable_summary.js | 15 ++-- .../accounts_receivable.js | 15 ++-- .../accounts_receivable_summary.js | 14 ++-- .../budget_variance_report.js | 7 +- .../report/general_ledger/general_ledger.js | 15 ++-- .../profitability_analysis.js | 7 +- .../report/sales_register/sales_register.js | 15 ++-- .../report/trial_balance/trial_balance.js | 6 +- erpnext/public/js/financial_statements.js | 14 ++-- erpnext/public/js/utils.js | 14 ---- .../public/js/utils/dimension_tree_filter.js | 41 +++++++---- erpnext/startup/boot.py | 18 +++++ 21 files changed, 219 insertions(+), 129 deletions(-) create mode 100644 erpnext/accounts/doctype/accounting_dimension_detail/__init__.py create mode 100644 erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json create mode 100644 erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index ffb6d5e597..bb4d514981 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -8,41 +8,48 @@ frappe.ui.form.on('Accounting Dimension', { frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () { frappe.set_route("List", frm.doc.document_type); }); - } - frm.set_query('document_type', () => { - return { - filters: { - name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']] - } - }; - }); - - let button = frm.doc.disabled ? "Enable" : "Disable"; - - frm.add_custom_button(__(button), function() { - - frm.set_value('disabled', 1 - frm.doc.disabled); - - frappe.call({ - method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension", - args: { - doc: frm.doc - }, - freeze: true, - callback: function(r) { - let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled"; - frm.save(); - frappe.show_alert({message:__(message), indicator:'green'}); - } + frm.set_query('document_type', () => { + return { + filters: { + name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']] + } + }; }); - }); + + let button = frm.doc.disabled ? "Enable" : "Disable"; + + frm.add_custom_button(__(button), function() { + + frm.set_value('disabled', 1 - frm.doc.disabled); + + frappe.call({ + method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension", + args: { + doc: frm.doc + }, + freeze: true, + callback: function(r) { + let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled"; + frm.save(); + frappe.show_alert({message:__(message), indicator:'green'}); + } + }); + }); + } }, document_type: function(frm) { + frm.set_value('label', frm.doc.document_type); frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type)); + if (frm.is_new()){ + let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults"); + row.reference_document = frm.doc.document_type; + frm.refresh_fields("dimension_defaults"); + } + frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => { if (r && r.document_type) { frm.set_df_property('document_type', 'description', "Document type is already set as dimension"); @@ -50,3 +57,10 @@ frappe.ui.form.on('Accounting Dimension', { }); }, }); + +frappe.ui.form.on('Accounting Dimension Detail', { + dimension_defaults_add: function(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + row.reference_document = frm.doc.document_type; + } +}) \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 0fab74d522..19fa9bf837 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -9,7 +9,7 @@ "document_type", "label", "fieldname", - "default_dimension", + "dimension_defaults", "mandatory_for_bs", "mandatory_for_pl", "disabled" @@ -56,13 +56,13 @@ "label": "Mandatory For Profit and Loss Account" }, { - "fieldname": "default_dimension", - "fieldtype": "Dynamic Link", - "label": "Default Dimension", - "options": "document_type" + "fieldname": "dimension_defaults", + "fieldtype": "Table", + "label": "Dimension Defaults", + "options": "Accounting Dimension Detail" } ], - "modified": "2019-07-14 19:16:25.405924", + "modified": "2019-07-16 18:00:11.365510", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 314849847c..218ab596e3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -144,6 +144,14 @@ def toggle_disabling(doc): frappe.clear_cache(doctype=doctype) + dimension_filters = frappe.db.sql(""" + SELECT label, fieldname, document_type + FROM `tabAccounting Dimension` + WHERE disabled = 0 + """, as_dict=1) + + return dimension_filters + def get_doctypes_with_dimensions(): doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset", "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py b/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json new file mode 100644 index 0000000000..f46a065271 --- /dev/null +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json @@ -0,0 +1,47 @@ +{ + "creation": "2019-07-16 17:53:18.718831", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "reference_document", + "default_dimension" + ], + "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "fieldname": "reference_document", + "fieldtype": "Link", + "hidden": 1, + "label": "Reference Document", + "options": "DocType", + "read_only": 1 + }, + { + "fieldname": "default_dimension", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Default Dimension", + "options": "reference_document", + "reqd": 1 + } + ], + "istable": 1, + "modified": "2019-07-16 18:54:52.202378", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Accounting Dimension Detail", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py new file mode 100644 index 0000000000..17cf549fc4 --- /dev/null +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class AccountingDimensionDetail(Document): + pass diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index e4acf5a03d..8728950286 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -258,6 +258,7 @@ "print_hide": 1 }, { + "collapsible": 1, "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", "label": "Accounting Dimensions" @@ -269,12 +270,13 @@ ], "idx": 1, "istable": 1, - "modified": "2019-05-25 22:14:02.715509", + "modified": "2019-07-16 17:12:08.238334", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", "owner": "Administrator", "permissions": [], + "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index 465df277fd..779ac4f656 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -764,6 +764,7 @@ "label": "Image" }, { + "collapsible": 1, "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", "label": "Accounting Dimensions" @@ -782,7 +783,7 @@ ], "idx": 1, "istable": 1, - "modified": "2019-06-28 17:30:12.156086", + "modified": "2019-07-16 16:36:46.527606", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index cfcc575718..5e07d080fb 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -115,13 +115,12 @@ frappe.query_reports["Accounts Payable"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index 006068a266..426de6782d 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -99,13 +99,12 @@ frappe.query_reports["Accounts Payable Summary"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index 2a45454bac..816e43898a 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -173,13 +173,12 @@ frappe.query_reports["Accounts Receivable"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index a7c0787fcd..d63af8b3f3 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -117,13 +117,11 @@ frappe.query_reports["Accounts Receivable Summary"] = { } } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index f2a33a83ee..33dc555a95 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -63,8 +63,7 @@ frappe.query_reports["Budget Variance Report"] = { ] } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); }); + diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index ea82575b80..74a1ea70ac 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -159,13 +159,12 @@ frappe.query_reports["General Ledger"] = { ] } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js index d6864b54f7..2656a7e7b5 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js @@ -105,9 +105,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "initial_depth": 3 } - erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); - }); + frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); }); + }); diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js index 442aa1262e..105f5a29c1 100644 --- a/erpnext/accounts/report/sales_register/sales_register.js +++ b/erpnext/accounts/report/sales_register/sales_register.js @@ -68,13 +68,12 @@ frappe.query_reports["Sales Register"] = { ] } -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); +frappe.boot.dimension_filters.forEach((dimension) => { + frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); + diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js index 73d2ab3898..dc6d07e2bb 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.js +++ b/erpnext/accounts/report/trial_balance/trial_balance.js @@ -94,10 +94,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "parent_field": "parent_account", "initial_depth": 3 } -}); -erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { + frappe.boot.dimension_filters.forEach((dimension) => { frappe.query_reports["Trial Balance"].filters.splice(5, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), @@ -107,3 +105,5 @@ erpnext.dimension_filters.then((dimensions) => { }); }); + + diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 89cb13d981..5feedd3e15 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -129,14 +129,12 @@ function get_filters(){ } ] - erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - filters.push({ - "fieldname": dimension["fieldname"], - "label": __(dimension["label"]), - "fieldtype": "Link", - "options": dimension["document_type"] - }); + frappe.boot.dimension_filters.forEach((dimension) => { + filters.push({ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] }); }); diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 1c5e98eb7d..0a363a04fd 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -63,20 +63,6 @@ $.extend(erpnext, { me.show_serial_batch_selector(grid_row.frm, grid_row.doc); }); }, - - get_dimension_filters: async function() { - if (!frappe.model.can_read('Accounting Dimension')) { - return []; - } - let dimensions = await frappe.db.get_list('Accounting Dimension', { - fields: ['label', 'fieldname', 'document_type', 'default_dimension'], - filters: { - disabled: 0 - } - }); - - return dimensions; - } }); diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 4a82edda69..22b4834dfb 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -7,25 +7,40 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile"]; -erpnext.dimension_filters = erpnext.get_dimension_filters(); - erpnext.doctypes_with_dimensions.forEach((doctype) => { frappe.ui.form.on(doctype, { onload: function(frm) { - erpnext.dimension_filters.then((dimensions) => { - dimensions.forEach((dimension) => { - if (dimension['default_dimension']) { - frm.set_value(dimension['fieldname'], dimension['default_dimension']); + frappe.boot.dimension_filters.forEach((dimension) => { + frappe.model.with_doctype(dimension['document_type'], () => { + if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { + frm.set_query(dimension['fieldname'], { + "is_group": 0 + }); } - frappe.model.with_doctype(dimension['document_type'], () => { - if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { - frm.set_query(dimension['fieldname'], { - "is_group": 0 - }); - } - }); }); }); + }, + + company: function(frm) { + if(frm.doc.company) { + frappe.boot.dimension_filters.forEach((dimension) => { + frm.set_value(dimension['fieldname'], frappe.boot.default_dimensions[frm.doc.company][dimension['document_type']]); + }); + } + }, + + items_add: function(frm, cdt, cdn) { + frappe.boot.dimension_filters.forEach((dimension) => { + var row = frappe.get_doc(cdt, cdn); + frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]); + }); + }, + + accounts_add: function(frm, cdt, cdn) { + frappe.boot.dimension_filters.forEach((dimension) => { + var row = frappe.get_doc(cdt, cdn); + frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]); + }); } }); }); \ No newline at end of file diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 4ca43a89b8..7d70cc2349 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -39,6 +39,8 @@ def boot_session(bootinfo): party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""") bootinfo.party_account_types = frappe._dict(party_account_types) + load_dimension_filters(bootinfo) + load_default_dimensions(bootinfo) def load_country_and_currency(bootinfo): country = frappe.db.get_default("country") @@ -49,6 +51,22 @@ def load_country_and_currency(bootinfo): number_format, smallest_currency_fraction_value, symbol from tabCurrency where enabled=1""", as_dict=1, update={"doctype":":Currency"}) +def load_dimension_filters(bootinfo): + bootinfo.dimension_filters = frappe.db.sql(""" + SELECT label, fieldname, document_type + FROM `tabAccounting Dimension` + WHERE disabled = 0 + """, as_dict=1) + +def load_default_dimensions(bootinfo): + default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension + FROM `tabAccounting Dimension Detail`""", as_dict=1) + + bootinfo.default_dimensions = {} + for dimension in default_dimensions: + bootinfo.default_dimensions.setdefault(dimension['company'], {}) + bootinfo.default_dimensions[dimension['company']][dimension['parent']] = dimension['default_dimension'] + def update_page_info(bootinfo): bootinfo.page_info.update({ "Chart of Accounts": { From 6dd5f746717433497e81832eb092490c0c5655e0 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 18 Jul 2019 08:54:15 +0530 Subject: [PATCH 44/61] fix: Remove dimensions from boot --- .../accounting_dimension.json | 18 +--------- .../accounting_dimension.py | 34 ++++++++++++++----- .../accounting_dimension_detail.json | 24 +++++++++++-- erpnext/accounts/doctype/gl_entry/gl_entry.py | 16 ++++----- .../accounts_payable/accounts_payable.js | 2 +- .../accounts_payable_summary.js | 2 +- .../accounts_receivable.js | 2 +- .../accounts_receivable_summary.js | 2 +- .../budget_variance_report.js | 2 +- .../report/general_ledger/general_ledger.js | 2 +- .../profitability_analysis.js | 2 +- .../report/sales_register/sales_register.js | 2 +- .../report/trial_balance/trial_balance.js | 2 +- erpnext/public/js/financial_statements.js | 2 +- .../public/js/utils/dimension_tree_filter.js | 18 +++++++--- erpnext/startup/boot.py | 18 ---------- 16 files changed, 79 insertions(+), 69 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 19fa9bf837..cf6dc7a8fa 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -1,6 +1,4 @@ { - "_comments": "[]", - "_liked_by": "[]", "autoname": "field:label", "creation": "2019-05-04 18:13:37.002352", "doctype": "DocType", @@ -10,8 +8,6 @@ "label", "fieldname", "dimension_defaults", - "mandatory_for_bs", - "mandatory_for_pl", "disabled" ], "fields": [ @@ -43,18 +39,6 @@ "label": "Disable", "read_only": 1 }, - { - "default": "0", - "fieldname": "mandatory_for_bs", - "fieldtype": "Check", - "label": "Mandatory For Balance Sheet" - }, - { - "default": "0", - "fieldname": "mandatory_for_pl", - "fieldtype": "Check", - "label": "Mandatory For Profit and Loss Account" - }, { "fieldname": "dimension_defaults", "fieldtype": "Table", @@ -62,7 +46,7 @@ "options": "Accounting Dimension Detail" } ], - "modified": "2019-07-16 18:00:11.365510", + "modified": "2019-07-17 16:49:31.134385", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 218ab596e3..90cc50d419 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -144,14 +144,6 @@ def toggle_disabling(doc): frappe.clear_cache(doctype=doctype) - dimension_filters = frappe.db.sql(""" - SELECT label, fieldname, document_type - FROM `tabAccounting Dimension` - WHERE disabled = 0 - """, as_dict=1) - - return dimension_filters - def get_doctypes_with_dimensions(): doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset", "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item", @@ -163,9 +155,33 @@ def get_doctypes_with_dimensions(): return doclist def get_accounting_dimensions(as_list=True): - accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "mandatory_for_pl", "mandatory_for_bs", "disabled"], filters={"disabled": 0}) + accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "disabled"]) if as_list: return [d.fieldname for d in accounting_dimensions] else: return accounting_dimensions + +def get_checks_for_pl_and_bs_accounts(): + dimensions = frappe.db.sql("""SELECT parent, company, mandatory_for_pl, mandatory_for_bs + FROM `tabAccounting Dimension Detail`""", as_dict=1) + + return dimensions + +@frappe.whitelist() +def get_dimension_filters(): + dimension_filters = frappe.db.sql(""" + SELECT label, fieldname, document_type + FROM `tabAccounting Dimension` + WHERE disabled = 0 + """, as_dict=1) + + default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension + FROM `tabAccounting Dimension Detail`""", as_dict=1) + + default_dimensions_map = {} + for dimension in default_dimensions: + default_dimensions_map.setdefault(dimension['company'], {}) + default_dimensions_map[dimension['company']][dimension['parent']] = dimension['default_dimension'] + + return dimension_filters, default_dimensions_map diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json index f46a065271..1ccef6cc7a 100644 --- a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json @@ -6,10 +6,13 @@ "field_order": [ "company", "reference_document", - "default_dimension" + "default_dimension", + "mandatory_for_bs", + "mandatory_for_pl" ], "fields": [ { + "columns": 2, "fieldname": "company", "fieldtype": "Link", "in_list_view": 1, @@ -26,16 +29,33 @@ "read_only": 1 }, { + "columns": 2, "fieldname": "default_dimension", "fieldtype": "Dynamic Link", "in_list_view": 1, "label": "Default Dimension", "options": "reference_document", "reqd": 1 + }, + { + "columns": 3, + "default": "0", + "fieldname": "mandatory_for_bs", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Mandatory For Balance Sheet" + }, + { + "columns": 3, + "default": "0", + "fieldname": "mandatory_for_pl", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Mandatory For Profit and Loss Account" } ], "istable": 1, - "modified": "2019-07-16 18:54:52.202378", + "modified": "2019-07-17 23:34:33.026883", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension Detail", diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 84276eae10..80e518644d 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -12,7 +12,7 @@ from erpnext.accounts.party import validate_party_gle_currency, validate_party_f from erpnext.accounts.utils import get_account_currency from erpnext.accounts.utils import get_fiscal_year from erpnext.exceptions import InvalidAccountCurrency -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts exclude_from_linked_with = True class GLEntry(Document): @@ -86,19 +86,19 @@ class GLEntry(Document): account_type = frappe.db.get_value("Account", self.account, "report_type") - for dimension in get_accounting_dimensions(as_list=False): + for dimension in get_checks_for_pl_and_bs_accounts(): if account_type == "Profit and Loss" \ - and dimension.mandatory_for_pl and not dimension.disabled: - if not self.get(dimension.fieldname): + and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled: + if not self.get(frappe.scrub(dimension.parent)): frappe.throw(_("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.") - .format(dimension.label, self.account)) + .format(dimension.parent, self.account)) if account_type == "Balance Sheet" \ - and dimension.mandatory_for_bs and not dimension.disabled: - if not self.get(dimension.fieldname): + and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled: + if not self.get(frappe.scrub(dimension.parent)): frappe.throw(_("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.") - .format(dimension.label, self.account)) + .format(dimension.parent, self.account)) def check_pl_account(self): diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index 5e07d080fb..8eb670de51 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -115,7 +115,7 @@ frappe.query_reports["Accounts Payable"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index 426de6782d..5f0fdc9f2c 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -99,7 +99,7 @@ frappe.query_reports["Accounts Payable Summary"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index 816e43898a..4551973ac6 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -173,7 +173,7 @@ frappe.query_reports["Accounts Receivable"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index d63af8b3f3..0120608a8f 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -117,7 +117,7 @@ frappe.query_reports["Accounts Receivable Summary"] = { } } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index 33dc555a95..24511871fd 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -63,7 +63,7 @@ frappe.query_reports["Budget Variance Report"] = { ] } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); }); diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 74a1ea70ac..4a287060b3 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -159,7 +159,7 @@ frappe.query_reports["General Ledger"] = { ] } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js index 2656a7e7b5..889ede5a82 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js @@ -105,7 +105,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "initial_depth": 3 } - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); }); diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js index 105f5a29c1..9dee656d4a 100644 --- a/erpnext/accounts/report/sales_register/sales_register.js +++ b/erpnext/accounts/report/sales_register/sales_register.js @@ -68,7 +68,7 @@ frappe.query_reports["Sales Register"] = { ] } -frappe.boot.dimension_filters.forEach((dimension) => { +erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js index dc6d07e2bb..f15b5b1a19 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.js +++ b/erpnext/accounts/report/trial_balance/trial_balance.js @@ -95,7 +95,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "initial_depth": 3 } - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { frappe.query_reports["Trial Balance"].filters.splice(5, 0 ,{ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 5feedd3e15..63e057c39d 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -129,7 +129,7 @@ function get_filters(){ } ] - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { filters.push({ "fieldname": dimension["fieldname"], "label": __(dimension["label"]), diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 22b4834dfb..9d4c435240 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -7,10 +7,18 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile"]; +frappe.call({ + method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", + callback: function(r){ + erpnext.dimension_filters = r.message[0]; + erpnext.default_dimensions = r.message[1]; + } +}); + erpnext.doctypes_with_dimensions.forEach((doctype) => { frappe.ui.form.on(doctype, { onload: function(frm) { - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { frappe.model.with_doctype(dimension['document_type'], () => { if (frappe.meta.has_field(dimension['document_type'], 'is_group')) { frm.set_query(dimension['fieldname'], { @@ -23,21 +31,21 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { company: function(frm) { if(frm.doc.company) { - frappe.boot.dimension_filters.forEach((dimension) => { - frm.set_value(dimension['fieldname'], frappe.boot.default_dimensions[frm.doc.company][dimension['document_type']]); + erpnext.dimension_filters.forEach((dimension) => { + frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); }); } }, items_add: function(frm, cdt, cdn) { - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { var row = frappe.get_doc(cdt, cdn); frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]); }); }, accounts_add: function(frm, cdt, cdn) { - frappe.boot.dimension_filters.forEach((dimension) => { + erpnext.dimension_filters.forEach((dimension) => { var row = frappe.get_doc(cdt, cdn); frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]); }); diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 7d70cc2349..4ca43a89b8 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -39,8 +39,6 @@ def boot_session(bootinfo): party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""") bootinfo.party_account_types = frappe._dict(party_account_types) - load_dimension_filters(bootinfo) - load_default_dimensions(bootinfo) def load_country_and_currency(bootinfo): country = frappe.db.get_default("country") @@ -51,22 +49,6 @@ def load_country_and_currency(bootinfo): number_format, smallest_currency_fraction_value, symbol from tabCurrency where enabled=1""", as_dict=1, update={"doctype":":Currency"}) -def load_dimension_filters(bootinfo): - bootinfo.dimension_filters = frappe.db.sql(""" - SELECT label, fieldname, document_type - FROM `tabAccounting Dimension` - WHERE disabled = 0 - """, as_dict=1) - -def load_default_dimensions(bootinfo): - default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension - FROM `tabAccounting Dimension Detail`""", as_dict=1) - - bootinfo.default_dimensions = {} - for dimension in default_dimensions: - bootinfo.default_dimensions.setdefault(dimension['company'], {}) - bootinfo.default_dimensions[dimension['company']][dimension['parent']] = dimension['default_dimension'] - def update_page_info(bootinfo): bootinfo.page_info.update({ "Chart of Accounts": { From 703fc08467cdd205262d34ca75ac3319b9d00cb6 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 18 Jul 2019 18:14:12 +0530 Subject: [PATCH 45/61] fix: Patch --- .../v12_0/update_ewaybill_field_position.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/erpnext/patches/v12_0/update_ewaybill_field_position.py b/erpnext/patches/v12_0/update_ewaybill_field_position.py index d0291d2123..c0230c4395 100644 --- a/erpnext/patches/v12_0/update_ewaybill_field_position.py +++ b/erpnext/patches/v12_0/update_ewaybill_field_position.py @@ -10,18 +10,19 @@ def execute(): field = frappe.db.get_value("Custom Field", {"dt": "Sales Invoice", "fieldname": "ewaybill"}) - ewaybill_field = frappe.get_doc("Custom Field", field) + if field: + ewaybill_field = frappe.get_doc("Custom Field", field) - ewaybill_field.flags.ignore_validate = True + ewaybill_field.flags.ignore_validate = True - ewaybill_field.update({ - 'fieldname': 'ewaybill', - 'label': 'e-Way Bill No.', - 'fieldtype': 'Data', - 'depends_on': 'eval:(doc.docstatus === 1)', - 'allow_on_submit': 1, - 'insert_after': 'tax_id', - 'translatable': 0 - }) + ewaybill_field.update({ + 'fieldname': 'ewaybill', + 'label': 'e-Way Bill No.', + 'fieldtype': 'Data', + 'depends_on': 'eval:(doc.docstatus === 1)', + 'allow_on_submit': 1, + 'insert_after': 'tax_id', + 'translatable': 0 + }) - ewaybill_field.save() \ No newline at end of file + ewaybill_field.save() \ No newline at end of file From b124aff0bb5fe430974dd80e18664a7afcfc14ff Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 18 Jul 2019 18:29:34 +0530 Subject: [PATCH 46/61] fix: Codacy Fixes --- .../doctype/accounting_dimension/accounting_dimension.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index bb4d514981..d5f39b5cd3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -63,4 +63,4 @@ frappe.ui.form.on('Accounting Dimension Detail', { let row = locals[cdt][cdn]; row.reference_document = frm.doc.document_type; } -}) \ No newline at end of file +}); \ No newline at end of file From 41a1cd954c14f7168a73f1dfe7f1d2f71ffa1ecf Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 20 Jul 2019 17:53:29 +0530 Subject: [PATCH 47/61] fix: Set query fix --- .../accounting_dimension/accounting_dimension.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index d5f39b5cd3..88b11dd678 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -4,19 +4,19 @@ frappe.ui.form.on('Accounting Dimension', { refresh: function(frm) { + frm.set_query('document_type', () => { + return { + filters: { + name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center', 'Accounting Dimension Detail']] + } + }; + }); + if (!frm.is_new()) { frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () { frappe.set_route("List", frm.doc.document_type); }); - frm.set_query('document_type', () => { - return { - filters: { - name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']] - } - }; - }); - let button = frm.doc.disabled ? "Enable" : "Disable"; frm.add_custom_button(__(button), function() { From 0ce2afc9bc7c7810b3af1d0a82ab4c7aeee614a5 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 22 Jul 2019 12:41:48 +0530 Subject: [PATCH 48/61] fix: Test Cases for accounting dimensions --- .../test_accounting_dimension.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index 527ddcc80f..7de7c108a2 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -28,11 +28,20 @@ class TestAccountingDimension(unittest.TestCase): "doctype": "Accounting Dimension", "document_type": "Location", "mandatory_for_pl": 1 - }).insert() + }) + + dimension1.append("dimension_defaults", { + "company": "_Test Company", + "reference_document": "Location", + "default_dimension": "Block 1", + "mandatory_for_pl": 1 + }) + + dimension1.insert() + dimension1.save() else: dimension1 = frappe.get_doc("Accounting Dimension", "Location") dimension1.disabled = 0 - dimension1.mandatory_for_pl = 1 dimension1.save() def test_dimension_against_sales_invoice(self): From aa92df4ddc6ab2aa6b1fb631374bb294a4c9eb05 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 23 Jul 2019 08:32:37 +0530 Subject: [PATCH 49/61] fix: Test cases for accounting dimensions --- .../doctype/accounting_dimension/test_accounting_dimension.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index 7de7c108a2..c75ba825a4 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -27,14 +27,13 @@ class TestAccountingDimension(unittest.TestCase): dimension1 = frappe.get_doc({ "doctype": "Accounting Dimension", "document_type": "Location", - "mandatory_for_pl": 1 }) dimension1.append("dimension_defaults", { "company": "_Test Company", "reference_document": "Location", "default_dimension": "Block 1", - "mandatory_for_pl": 1 + "mandatory_for_bs": 1 }) dimension1.insert() From dda6b5cd5332917ea7943438a50207d33e5c84dc Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Fri, 26 Jul 2019 09:12:30 +0530 Subject: [PATCH 50/61] fix: Add accounting dimensions to subscription and opening invoice tool --- .../accounting_dimension.py | 7 +- .../opening_invoice_creation_tool.json | 14 +- .../opening_invoice_creation_tool.py | 8 + .../opening_invoice_creation_tool_item.json | 15 +- .../doctype/subscription/subscription.json | 1099 ++++------------- .../doctype/subscription/subscription.py | 13 + .../subscription_plan/subscription_plan.json | 723 ++--------- erpnext/patches.txt | 1 + ...counting_dimensions_in_missing_doctypes.py | 38 + .../public/js/utils/dimension_tree_filter.js | 5 +- 10 files changed, 440 insertions(+), 1483 deletions(-) create mode 100644 erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 90cc50d419..61f699f6ab 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -96,13 +96,13 @@ def delete_accounting_dimension(doc): frappe.db.sql(""" DELETE FROM `tabCustom Field` - WHERE fieldname = %s + WHERE fieldname = %s AND dt IN (%s)""" % #nosec ('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist)) frappe.db.sql(""" DELETE FROM `tabProperty Setter` - WHERE field_name = %s + WHERE field_name = %s AND doc_type IN (%s)""" % #nosec ('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist)) @@ -150,7 +150,8 @@ def get_doctypes_with_dimensions(): "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule", "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", - "Travel Request", "Fees", "POS Profile"] + "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription", + "Subscription Plan"] return doclist diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json index 7d2d5a11a8..bc9241802d 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json @@ -10,7 +10,9 @@ "create_missing_party", "column_break_3", "invoice_type", + "accounting_dimensions_section", "cost_center", + "dimension_col_break", "section_break_4", "invoices" ], @@ -59,11 +61,21 @@ "fieldtype": "Link", "label": "Cost Center", "options": "Cost Center" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } ], "hide_toolbar": 1, "issingle": 1, - "modified": "2019-06-13 11:45:31.405267", + "modified": "2019-07-25 14:57:33.187689", "modified_by": "Administrator", "module": "Accounts", "name": "Opening Invoice Creation Tool", diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py index 5fa7b48c09..ce8aba75b2 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py @@ -7,6 +7,7 @@ import frappe from frappe import _, scrub from frappe.utils import flt, nowdate from frappe.model.document import Document +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions class OpeningInvoiceCreationTool(Document): @@ -173,6 +174,13 @@ class OpeningInvoiceCreationTool(Document): "currency": frappe.get_cached_value('Company', self.company, "default_currency") }) + accounting_dimension = get_accounting_dimensions() + + for dimension in accounting_dimension: + args.update({ + dimension: item.get(dimension) + }) + if self.invoice_type == "Sales": args["is_pos"] = 0 diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json index afa7229e53..4ce8cb95b1 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json @@ -15,7 +15,9 @@ "outstanding_amount", "column_break_4", "qty", - "cost_center" + "accounting_dimensions_section", + "cost_center", + "dimension_col_break" ], "fields": [ { @@ -92,10 +94,19 @@ "fieldtype": "Link", "label": "Cost Center", "options": "Cost Center" + }, + { + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } ], "istable": 1, - "modified": "2019-06-13 11:48:08.324063", + "modified": "2019-07-25 15:00:00.460695", "modified_by": "Administrator", "module": "Accounts", "name": "Opening Invoice Creation Tool Item", diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json index c9305164f0..29cb62a397 100644 --- a/erpnext/accounts/doctype/subscription/subscription.json +++ b/erpnext/accounts/doctype/subscription/subscription.json @@ -1,926 +1,245 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "ACC-SUB-.YYYY.-.#####", - "beta": 0, - "creation": "2017-07-18 17:50:43.967266", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "autoname": "ACC-SUB-.YYYY.-.#####", + "creation": "2017-07-18 17:50:43.967266", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "customer", + "cb_1", + "status", + "subscription_period", + "start", + "cancelation_date", + "trial_period_start", + "trial_period_end", + "column_break_11", + "current_invoice_start", + "current_invoice_end", + "days_until_due", + "cancel_at_period_end", + "generate_invoice_at_period_start", + "sb_4", + "plans", + "sb_1", + "tax_template", + "sb_2", + "apply_additional_discount", + "cb_2", + "additional_discount_percentage", + "additional_discount_amount", + "sb_3", + "invoices", + "accounting_dimensions_section", + "dimension_col_break" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Customer", - "length": 0, - "no_copy": 0, - "options": "Customer", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "customer", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Customer", + "options": "Customer", + "reqd": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "cb_1", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscription_period", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subscription Period", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "subscription_period", + "fieldtype": "Section Break", + "label": "Subscription Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "start", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subscription Start Date", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "start", + "fieldtype": "Date", + "label": "Subscription Start Date", + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cancelation_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Cancelation Date", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cancelation_date", + "fieldtype": "Date", + "label": "Cancelation Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "trial_period_start", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Trial Period Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "trial_period_start", + "fieldtype": "Date", + "label": "Trial Period Start Date", + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.trial_period_start", - "fieldname": "trial_period_end", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Trial Period End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.trial_period_start", + "fieldname": "trial_period_end", + "fieldtype": "Date", + "label": "Trial Period End Date", + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_invoice_start", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Current Invoice Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "current_invoice_start", + "fieldtype": "Date", + "label": "Current Invoice Start Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_invoice_end", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Current Invoice End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "current_invoice_end", + "fieldtype": "Date", + "label": "Current Invoice End Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "description": "Number of days that the subscriber has to pay invoices generated by this subscription", - "fieldname": "days_until_due", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Days Until Due", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "description": "Number of days that the subscriber has to pay invoices generated by this subscription", + "fieldname": "days_until_due", + "fieldtype": "Int", + "label": "Days Until Due" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cancel_at_period_end", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Cancel At End Of Period", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "cancel_at_period_end", + "fieldtype": "Check", + "label": "Cancel At End Of Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "generate_invoice_at_period_start", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Generate Invoice At Beginning Of Period", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "generate_invoice_at_period_start", + "fieldtype": "Check", + "label": "Generate Invoice At Beginning Of Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "sb_4", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Plans", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "sb_4", + "fieldtype": "Section Break", + "label": "Plans" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "plans", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Plans", - "length": 0, - "no_copy": 0, - "options": "Subscription Plan Detail", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "plans", + "fieldtype": "Table", + "label": "Plans", + "options": "Subscription Plan Detail", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_1", + "fieldtype": "Section Break", + "label": "Taxes" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tax_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Sales Taxes and Charges Template", - "length": 0, - "no_copy": 0, - "options": "Sales Taxes and Charges Template", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "tax_template", + "fieldtype": "Link", + "label": "Sales Taxes and Charges Template", + "options": "Sales Taxes and Charges Template" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "", - "fieldname": "sb_2", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Discounts", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_2", + "fieldtype": "Section Break", + "label": "Discounts" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "apply_additional_discount", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Apply Additional Discount On", - "length": 0, - "no_copy": 0, - "options": "\nGrand Total\nNet total", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "apply_additional_discount", + "fieldtype": "Select", + "label": "Apply Additional Discount On", + "options": "\nGrand Total\nNet total" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "cb_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_2", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "additional_discount_percentage", - "fieldtype": "Percent", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional DIscount Percentage", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "additional_discount_percentage", + "fieldtype": "Percent", + "label": "Additional DIscount Percentage" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "depends_on": "", - "fieldname": "additional_discount_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional DIscount Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "additional_discount_amount", + "fieldtype": "Currency", + "label": "Additional DIscount Amount" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "depends_on": "eval:doc.invoices", - "fieldname": "sb_3", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoices", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.invoices", + "fieldname": "sb_3", + "fieldtype": "Section Break", + "label": "Invoices" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "depends_on": "", - "fieldname": "invoices", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoices", - "length": 0, - "no_copy": 0, - "options": "Subscription Invoice", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "collapsible": 1, + "fieldname": "invoices", + "fieldtype": "Table", + "label": "Invoices", + "options": "Subscription Invoice" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-10-14 10:38:55.545540", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Subscription", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-07-25 18:45:38.579579", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Subscription", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 858359eccb..6d01897e8f 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -9,6 +9,7 @@ from frappe import _ from frappe.model.document import Document from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date, flt from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions class Subscription(Document): @@ -241,6 +242,15 @@ class Subscription(Document): invoice.posting_date = self.current_invoice_start invoice.customer = self.customer + ## Add dimesnions in invoice for subscription: + accounting_dimensions = get_accounting_dimensions() + + for dimension in accounting_dimensions: + if self.get(dimension): + invoice.update({ + dimension: self.get(dimension) + }) + # Subscription is better suited for service items. I won't update `update_stock` # for that reason items_list = self.get_items_from_plans(self.plans, prorate) @@ -280,6 +290,9 @@ class Subscription(Document): invoice.save() invoice.submit() + for dimension in accounting_dimensions: + invoice.load_from_db() + return invoice def get_items_from_plans(self, plans, prorate=0): diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json index 453521d04d..9f79066235 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json @@ -1,612 +1,163 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 1, - "autoname": "field:plan_name", - "beta": 0, - "creation": "2018-02-24 11:31:23.066506", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "allow_rename": 1, + "autoname": "field:plan_name", + "creation": "2018-02-24 11:31:23.066506", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "plan_name", + "currency", + "column_break_3", + "item", + "section_break_5", + "price_determination", + "column_break_7", + "cost", + "price_list", + "section_break_11", + "billing_interval", + "column_break_13", + "billing_interval_count", + "payment_plan_section", + "payment_plan_id", + "column_break_16", + "payment_gateway", + "accounting_dimensions_section", + "dimension_col_break" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "plan_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Plan Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "fieldname": "plan_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Plan Name", + "reqd": 1, "unique": 1 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "item", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Item", - "length": 0, - "no_copy": 0, - "options": "Item", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item", + "options": "Item", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_5", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "price_determination", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price Determination", - "length": 0, - "no_copy": 0, - "options": "\nFixed rate\nBased on price list", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price_determination", + "fieldtype": "Select", + "label": "Price Determination", + "options": "\nFixed rate\nBased on price list", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_7", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_7", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.price_determination==\"Fixed rate\"", - "fieldname": "cost", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Cost", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.price_determination==\"Fixed rate\"", + "fieldname": "cost", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Cost" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.price_determination==\"Based on price list\"", - "fieldname": "price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.price_determination==\"Based on price list\"", + "fieldname": "price_list", + "fieldtype": "Link", + "label": "Price List", + "options": "Price List" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_11", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_11", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Day", - "fieldname": "billing_interval", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Billing Interval", - "length": 0, - "no_copy": 0, - "options": "Day\nWeek\nMonth\nYear", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Day", + "fieldname": "billing_interval", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Billing Interval", + "options": "Day\nWeek\nMonth\nYear", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_13", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "description": "Number of intervals for the interval field e.g if Interval is 'Days' and Billing Interval Count is 3, invoices will be generated every 3 days", - "fieldname": "billing_interval_count", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Billing Interval Count", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "1", + "description": "Number of intervals for the interval field e.g if Interval is 'Days' and Billing Interval Count is 3, invoices will be generated every 3 days", + "fieldname": "billing_interval_count", + "fieldtype": "Int", + "label": "Billing Interval Count", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_plan_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Plan", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_plan_section", + "fieldtype": "Section Break", + "label": "Payment Plan" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_plan_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Plan", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_plan_id", + "fieldtype": "Data", + "label": "Payment Plan" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_16", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_16", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_gateway", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Gateway", - "length": 0, - "no_copy": 0, - "options": "Payment Gateway Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "payment_gateway", + "fieldtype": "Link", + "label": "Payment Gateway", + "options": "Payment Gateway Account" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-06-20 16:59:54.082358", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Subscription Plan", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-07-25 18:35:04.362556", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Subscription Plan", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 398c6020a0..33d4f55ae0 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -624,4 +624,5 @@ erpnext.patches.v11_1.update_default_supplier_in_item_defaults erpnext.patches.v12_0.update_due_date_in_gle erpnext.patches.v12_0.add_default_buying_selling_terms_in_company erpnext.patches.v12_0.update_ewaybill_field_position +erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes erpnext.patches.v11_1.set_status_for_material_request_type_manufacture diff --git a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py new file mode 100644 index 0000000000..1796c53c14 --- /dev/null +++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py @@ -0,0 +1,38 @@ +from __future__ import unicode_literals +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_field + +def execute(): + accounting_dimensions = frappe.db.sql("""select fieldname, label, document_type, disabled from + `tabAccounting Dimension`""", as_dict=1) + + if not accounting_dimensions: + return + + count = 1 + for d in accounting_dimensions: + + if count%2 == 0: + insert_after_field = 'dimension_col_break' + else: + insert_after_field = 'accounting_dimensions_section' + + for doctype in ["Subscription Plan", "Subscription", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]: + + field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname}) + + if field: + continue + + df = { + "fieldname": d.fieldname, + "label": d.label, + "fieldtype": "Link", + "options": d.document_type, + "insert_after": insert_after_field + } + + create_custom_field(doctype, df) + frappe.clear_cache(doctype=doctype) + + count += 1 \ No newline at end of file diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 9d4c435240..10855ea3e6 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -5,7 +5,7 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule", "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", - "Travel Request", "Fees", "POS Profile"]; + "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]; frappe.call({ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", @@ -25,6 +25,9 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { "is_group": 0 }); } + if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) { + frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); + } }); }); }, From a65ad10c627ea84a657066d20c176a4fb903b0bf Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 27 Jul 2019 19:06:36 +0530 Subject: [PATCH 51/61] fix: GL entry validation fix --- .../doctype/accounting_dimension/accounting_dimension.py | 5 +++-- .../accounting_dimension/test_accounting_dimension.py | 1 - erpnext/accounts/doctype/gl_entry/gl_entry.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 61f699f6ab..1f418de47b 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -164,8 +164,9 @@ def get_accounting_dimensions(as_list=True): return accounting_dimensions def get_checks_for_pl_and_bs_accounts(): - dimensions = frappe.db.sql("""SELECT parent, company, mandatory_for_pl, mandatory_for_bs - FROM `tabAccounting Dimension Detail`""", as_dict=1) + dimensions = frappe.db.sql("""SELECT p.label, p.disabled, p.fieldname, c.company, c.mandatory_for_pl, c.mandatory_for_bs + FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c + WHERE p.name = c.parent""", as_dict=1) return dimensions diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index c75ba825a4..104880f6f3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -108,7 +108,6 @@ def disable_dimension(): dimension1.save() dimension2 = frappe.get_doc("Accounting Dimension", "Location") - dimension2.mandatory_for_pl = 0 dimension2.disabled = 1 dimension2.save() diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 80e518644d..4944c8f76f 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -90,15 +90,15 @@ class GLEntry(Document): if account_type == "Profit and Loss" \ and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled: - if not self.get(frappe.scrub(dimension.parent)): + if not self.get(frappe.scrub(dimension.fieldname)): frappe.throw(_("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.") - .format(dimension.parent, self.account)) + .format(dimension.label, self.account)) if account_type == "Balance Sheet" \ and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled: - if not self.get(frappe.scrub(dimension.parent)): + if not self.get(frappe.scrub(dimension.fieldname)): frappe.throw(_("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.") - .format(dimension.parent, self.account)) + .format(dimension.label, self.account)) def check_pl_account(self): From 6a43f6718a9a1677aee417197fd8c33d7df6653f Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 28 Jul 2019 10:30:32 +0530 Subject: [PATCH 52/61] fix: Reload doc in patch --- .../v12_0/create_accounting_dimensions_in_missing_doctypes.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py index 1796c53c14..b71ea66594 100644 --- a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py +++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py @@ -3,6 +3,9 @@ import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field def execute(): + + frappe.reload_doc('accounts', 'doctype', 'accounting_dimension') + accounting_dimensions = frappe.db.sql("""select fieldname, label, document_type, disabled from `tabAccounting Dimension`""", as_dict=1) From ec421df4e490bec78018a720b2dc7489a8a62724 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 29 Jul 2019 08:58:56 +0530 Subject: [PATCH 53/61] fix: Code cleanup --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 4 ++-- erpnext/accounts/doctype/subscription/subscription.py | 3 --- erpnext/public/js/utils/dimension_tree_filter.js | 3 ++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 4944c8f76f..078e05816d 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -90,13 +90,13 @@ class GLEntry(Document): if account_type == "Profit and Loss" \ and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled: - if not self.get(frappe.scrub(dimension.fieldname)): + if not self.get(dimension.fieldname): frappe.throw(_("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.") .format(dimension.label, self.account)) if account_type == "Balance Sheet" \ and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled: - if not self.get(frappe.scrub(dimension.fieldname)): + if not self.get(dimension.fieldname): frappe.throw(_("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.") .format(dimension.label, self.account)) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 6d01897e8f..f13ca4c49e 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -290,9 +290,6 @@ class Subscription(Document): invoice.save() invoice.submit() - for dimension in accounting_dimensions: - invoice.load_from_db() - return invoice def get_items_from_plans(self, plans, prorate=0): diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 10855ea3e6..f1c92091a8 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -5,7 +5,8 @@ erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoi "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule", "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", - "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]; + "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription", + "Subscription Plan"]; frappe.call({ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", From 4c652396d010e60a4bbe1ac0f533e50de6ae2c5b Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 29 Jul 2019 14:57:33 +0530 Subject: [PATCH 54/61] fix: Opening balance not getting calculated in trail_balance_report --- erpnext/accounts/report/trial_balance/trial_balance.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index b6ddaa8e85..10e977acbf 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -123,11 +123,12 @@ def get_rootwise_opening_balances(filters, report_type): if accounting_dimensions: for dimension in accounting_dimensions: - additional_conditions += """ and {0} in (%({0})s) """.format(dimension) + if filters.get(dimension): + additional_conditions += """ and {0} in (%({0})s) """.format(dimension) - query_filters.update({ - dimension: filters.get(dimension) - }) + query_filters.update({ + dimension: filters.get(dimension) + }) gle = frappe.db.sql(""" select From f9c0ef3eb3c3755b1e892c1078e3497c3c8d59bc Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 30 Jul 2019 18:49:19 +0530 Subject: [PATCH 55/61] fix: Check zero valuation rate only for valid doctypes --- erpnext/stock/stock_ledger.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index ff5b026695..5fda2a4007 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -363,8 +363,17 @@ class update_entries_after(object): self.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.valuation_rate]) def check_if_allow_zero_valuation_rate(self, voucher_type, voucher_detail_no): - ref_item_dt = voucher_type + (" Detail" if voucher_type == "Stock Entry" else " Item") - return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate") + ref_item_dt = "" + + if voucher_type == "Stock Entry": + ref_item_dt = voucher_type + " Detail" + elif voucher_type in ["Purchase Invoice", "Sales Invoice", "Delivery Note", "Purchase Receipt"]: + ref_item_dt = voucher_type + " Item" + + if ref_item_dt: + return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate") + else: + return 0 def get_sle_before_datetime(self): """get previous stock ledger entry before current time-bucket""" From d301d26fda50b85b79fd56c6883f865d6ff65f4c Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Wed, 31 Jul 2019 15:58:19 +0530 Subject: [PATCH 56/61] fix: Enhancement in credit note (#18511) * fix: Credit note enhancement * Fix: Print format for Sales Invoice Return * fix: Zero quantity validation fix for credit note --- .../doctype/sales_invoice/sales_invoice.js | 14 +- .../sales_invoice_return/__init__.py | 0 .../sales_invoice_return.html | 129 ++++++++++++++++++ .../sales_invoice_return.json | 24 ++++ erpnext/controllers/accounts_controller.py | 4 +- erpnext/controllers/taxes_and_totals.py | 7 +- .../public/js/controllers/taxes_and_totals.js | 8 +- 7 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 erpnext/accounts/print_format/sales_invoice_return/__init__.py create mode 100644 erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html create mode 100644 erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 1fe6895601..74e9186e37 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -44,6 +44,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.frm.toggle_reqd("due_date", !this.frm.doc.is_return); + if (this.frm.doc.is_return) { + this.frm.return_print_format = "Sales Invoice Return"; + } + this.show_general_ledger(); if(doc.update_stock) this.show_stock_ledger(); @@ -148,16 +152,24 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }, set_default_print_format: function() { - // set default print format to POS type + // set default print format to POS type or Credit Note if(cur_frm.doc.is_pos) { if(cur_frm.pos_print_format) { cur_frm.meta._default_print_format = cur_frm.meta.default_print_format; cur_frm.meta.default_print_format = cur_frm.pos_print_format; } + } else if(cur_frm.doc.is_return) { + if(cur_frm.return_print_format) { + cur_frm.meta._default_print_format = cur_frm.meta.default_print_format; + cur_frm.meta.default_print_format = cur_frm.return_print_format; + } } else { if(cur_frm.meta._default_print_format) { cur_frm.meta.default_print_format = cur_frm.meta._default_print_format; cur_frm.meta._default_print_format = null; + } else if(in_list([cur_frm.pos_print_format, cur_frm.return_print_format], cur_frm.meta.default_print_format)) { + cur_frm.meta.default_print_format = null; + cur_frm.meta._default_print_format = null; } } }, diff --git a/erpnext/accounts/print_format/sales_invoice_return/__init__.py b/erpnext/accounts/print_format/sales_invoice_return/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html new file mode 100644 index 0000000000..889b7f71aa --- /dev/null +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html @@ -0,0 +1,129 @@ +{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value, fieldmeta, + get_width, get_align_class -%} + +{%- macro render_currency(df, doc) -%} +
+
+ +
+
+ {% if doc.get(df.fieldname) != None -%} + {{ frappe.utils.fmt_money((doc[df.fieldname])|int|abs, currency=doc.currency) }} + {% endif %} +
+
+{%- endmacro -%} + +{%- macro render_taxes(df, doc) -%} + {%- set data = doc.get(df.fieldname)[df.start:df.end] -%} +
+
+
+ {%- for charge in data -%} + {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%} +
+
+
+
+ {{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }} +
+
+ {%- endif -%} + {%- endfor -%} +
+
+{%- endmacro -%} + +{%- macro render_table(df, doc) -%} + {%- set table_meta = frappe.get_meta(df.options) -%} + {%- set data = doc.get(df.fieldname)[df.start:df.end] -%} + {%- if doc.print_templates and + doc.print_templates.get(df.fieldname) -%} + {% include doc.print_templates[df.fieldname] %} + {%- else -%} + {%- if data -%} + {%- set visible_columns = get_visible_columns(doc.get(df.fieldname), + table_meta, df) -%} +
+ + + + + {% for tdf in visible_columns %} + {% if (data and not data[0].flags.compact_item_print) or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %} + + {% endif %} + {% endfor %} + + + + {% for d in data %} + + + {% for tdf in visible_columns %} + {% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %} + + {% else %} +
{{ print_value(tdf, d, doc, visible_columns) }}
+ {% endif %} + {% endif %} + {% endfor %} + + {% endfor %} + +
{{ _("Sr") }} + {{ _(tdf.label) }}
{{ d.idx }} + {% if tdf.fieldtype == 'Currency' %} +
{{ frappe.utils.fmt_money((d[tdf.fieldname])|int|abs, currency=doc.currency) }}
+
+ {%- endif -%} + {%- endif -%} +{%- endmacro -%} + +{% for page in layout %} +
+
+ {{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }} +
+ + {% if print_settings.repeat_header_footer %} + + {% endif %} + + {% for section in page %} +
+ {% if section.columns.fields %} + {%- if doc._line_breaks and loop.index != 1 -%}
{%- endif -%} + {%- if doc._show_section_headings and section.label and section.has_data -%} +

{{ _(section.label) }}

+ {% endif %} + {%- endif -%} + {% for column in section.columns %} +
+ {% for df in column.fields %} + {% if df.fieldname == 'taxes' %} + {{ render_taxes(df, doc) }} + {% elif df.fieldtype == 'Currency' %} + {{ render_currency(df, doc) }} + {% elif df.fieldtype =='Table' %} + {{ render_table(df, doc)}} + {% elif doc[df.fieldname] %} + {{ render_field(df, doc) }} + {% endif %} + {% endfor %} +
+ {% endfor %} +
+ {% endfor %} +
+{% endfor %} diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json new file mode 100644 index 0000000000..352b5498e6 --- /dev/null +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json @@ -0,0 +1,24 @@ +{ + "align_labels_right": 1, + "creation": "2019-07-24 20:13:30.259953", + "custom_format": 0, + "default_print_language": "en-US", + "disabled": 0, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "html": "", + "idx": 0, + "line_breaks": 1, + "modified": "2019-07-24 20:13:30.259953", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Sales Invoice Return", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 1, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index ca59a396b8..288aa082c5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -60,7 +60,9 @@ class AccountsController(TransactionBase): def validate(self): - self.validate_qty_is_not_zero() + if not self.get('is_return'): + self.validate_qty_is_not_zero() + if self.get("_action") and self._action != "update_after_submit": self.set_missing_values(for_validate=True) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 8d24e7a316..b774037266 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -81,7 +81,12 @@ class calculate_taxes_and_totals(object): item.discount_amount = item.price_list_rate - item.rate item.net_rate = item.rate - item.amount = flt(item.rate * item.qty, item.precision("amount")) + + if not item.qty and self.doc.is_return: + item.amount = flt(-1 * item.rate, item.precision("amount")) + else: + item.amount = flt(item.rate * item.qty, item.precision("amount")) + item.net_amount = item.amount self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"]) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 91800cd9a9..7cf2181e42 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -92,7 +92,13 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ $.each(this.frm.doc["items"] || [], function(i, item) { frappe.model.round_floats_in(item); item.net_rate = item.rate; - item.amount = flt(item.rate * item.qty, precision("amount", item)); + + if ((!item.qty) && me.frm.doc.is_return) { + item.amount = flt(item.rate * -1, precision("amount", item)); + } else { + item.amount = flt(item.rate * item.qty, precision("amount", item)); + } + item.net_amount = item.amount; item.item_tax_amount = 0.0; item.total_weight = flt(item.weight_per_unit * item.stock_qty); From 8704bc6f39bc829a5ce334788ae56ffa2a6cb338 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 1 Aug 2019 13:24:48 +0530 Subject: [PATCH 57/61] fix: Payment Order link fix in bank dashboard --- erpnext/accounts/doctype/bank/bank_dashboard.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py index 432404155d..e047b9aad0 100644 --- a/erpnext/accounts/doctype/bank/bank_dashboard.py +++ b/erpnext/accounts/doctype/bank/bank_dashboard.py @@ -6,6 +6,9 @@ from frappe import _ def get_data(): return { 'fieldname': 'bank', + 'non_standard_fieldnames': { + 'Paymnet Order': 'company_bank' + }, 'transactions': [ { 'label': _('Bank Deatils'), From dc53e8ebb07ad522e01ccf6dd5de77dee5bdb17e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 2 Aug 2019 13:56:49 +0530 Subject: [PATCH 58/61] fix: task not updated issue --- erpnext/projects/doctype/task/task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 50557f1551..492eabe89e 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -145,7 +145,7 @@ class Task(NestedSet): def populate_depends_on(self): if self.parent_task: - parent = frappe.get_cached_doc('Task', self.parent_task) + parent = frappe.get_doc('Task', self.parent_task) if not self.name in [row.task for row in parent.depends_on]: parent.append("depends_on", { "doctype": "Task Depends On", From 4b3b358ac641fe962abe124fc7b8f08bb9f419ea Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 2 Aug 2019 21:46:38 +0530 Subject: [PATCH 59/61] fix: Show correct label instead of showing undefined (#18559) --- .../doctype/sales_order/sales_order.js | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 39dda92e3e..2e5f255a90 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -255,27 +255,44 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( }); return; } else { - var fields = [ - {fieldtype:'Table', fieldname: 'items', - description: __('Select BOM and Qty for Production'), - fields: [ - {fieldtype:'Read Only', fieldname:'item_code', - label: __('Item Code'), in_list_view:1}, - {fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1, - label: __('Select BOM'), in_list_view:1, get_query: function(doc) { - return {filters: {item: doc.item_code}}; - }}, - {fieldtype:'Float', fieldname:'pending_qty', reqd: 1, - label: __('Qty'), in_list_view:1}, - {fieldtype:'Data', fieldname:'sales_order_item', reqd: 1, - label: __('Sales Order Item'), hidden:1} - ], - data: r.message, - get_data: function() { - return r.message + const fields = [{ + label: 'Items', + fieldtype: 'Table', + fieldname: 'items', + description: __('Select BOM and Qty for Production'), + fields: [{ + fieldtype: 'Read Only', + fieldname: 'item_code', + label: __('Item Code'), + in_list_view: 1 + }, { + fieldtype: 'Link', + fieldname: 'bom', + options: 'BOM', + reqd: 1, + label: __('Select BOM'), + in_list_view: 1, + get_query: function (doc) { + return { filters: { item: doc.item_code } }; } + }, { + fieldtype: 'Float', + fieldname: 'pending_qty', + reqd: 1, + label: __('Qty'), + in_list_view: 1 + }, { + fieldtype: 'Data', + fieldname: 'sales_order_item', + reqd: 1, + label: __('Sales Order Item'), + hidden: 1 + }], + data: r.message, + get_data: () => { + return r.message } - ] + }] var d = new frappe.ui.Dialog({ title: __('Select Items to Manufacture'), fields: fields, From 93e46310b8ea9e61dbabf02bd3dd4b6b6748dd6e Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 3 Aug 2019 10:17:44 +0530 Subject: [PATCH 60/61] fix: Remove payment order from bank dashboard --- erpnext/accounts/doctype/bank/bank_dashboard.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py index e047b9aad0..4a1dad8952 100644 --- a/erpnext/accounts/doctype/bank/bank_dashboard.py +++ b/erpnext/accounts/doctype/bank/bank_dashboard.py @@ -6,16 +6,10 @@ from frappe import _ def get_data(): return { 'fieldname': 'bank', - 'non_standard_fieldnames': { - 'Paymnet Order': 'company_bank' - }, 'transactions': [ { 'label': _('Bank Deatils'), 'items': ['Bank Account', 'Bank Guarantee'] - }, - { - 'items': ['Payment Order'] } ] } From b6565298189416f59341efdcbcdba5cbf1c7d6a7 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 3 Aug 2019 13:40:37 +0530 Subject: [PATCH 61/61] fix: Error handling in taxes and totals --- erpnext/controllers/taxes_and_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index b774037266..d2db9d005a 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -82,7 +82,7 @@ class calculate_taxes_and_totals(object): item.net_rate = item.rate - if not item.qty and self.doc.is_return: + if not item.qty and self.doc.get("is_return"): item.amount = flt(-1 * item.rate, item.precision("amount")) else: item.amount = flt(item.rate * item.qty, item.precision("amount"))