From 49f93b347c2a7f0f1297d54a67ae540527c11aff Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 02:19:18 +0530 Subject: [PATCH 01/19] fix: Display data in tree form --- erpnext/accounts/report/gross_profit/gross_profit.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.js b/erpnext/accounts/report/gross_profit/gross_profit.js index ba17a94e8d3..c6c43251acf 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.js +++ b/erpnext/accounts/report/gross_profit/gross_profit.js @@ -36,5 +36,9 @@ frappe.query_reports["Gross Profit"] = { "options": "Invoice\nItem Code\nItem Group\nBrand\nWarehouse\nCustomer\nCustomer Group\nTerritory\nSales Person\nProject", "default": "Invoice" }, - ] + ], + "tree": true, + "name_field": "parent", + "parent_field": "parent_invoice", + "initial_depth": 2 } From 6431243ce366c3f48941ee86ae87ea2884561cc0 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 02:20:18 +0530 Subject: [PATCH 02/19] fix: Display items as descendants of invoices --- .../report/gross_profit/gross_profit.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index ef048bfc3bb..15560b45f43 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -99,6 +99,10 @@ class GrossProfitGenerator(object): self.average_buying_rate = {} self.filters = frappe._dict(filters) self.load_invoice_items() + + if filters.group_by == 'Invoice': + self.group_items_by_invoice() + self.load_stock_ledger_entries() self.load_product_bundle() self.load_non_stock_items() @@ -356,6 +360,51 @@ class GrossProfitGenerator(object): .format(conditions=conditions, sales_person_cols=sales_person_cols, sales_team_table=sales_team_table, match_cond = get_match_cond('Sales Invoice')), self.filters, as_dict=1) + def group_items_by_invoice(self): + parents = [] + + for row in self.si_list: + if row.parent not in parents: + parents.append(row.parent) + + parents_index = 0 + for index, row in enumerate(self.si_list): + if parents_index < len(parents) and row.parent == parents[parents_index]: + invoice = frappe._dict({ + 'parent_invoice': "", + 'parent': row.parent, + 'indent': 0.0, + 'posting_date': row.posting_date, + 'posting_time': row.posting_time, + 'project': row.project, + 'update_stock': row.update_stock, + 'customer': row.customer, + 'customer_group': row.customer_group, + 'customer_group': row.customer_group, + 'item_code': None, + 'item_name': None, + 'description': None, + 'warehouse': None, + 'item_group': None, + 'brand': None, + 'dn_detail': None, + 'delivery_note': None, + 'qty': 0, + 'item_row': None, + 'is_return': row.is_return, + 'cost_center': row.cost_center, + 'base_net_amount': 0 + }) + + self.si_list.insert(index, invoice) + parents_index += 1 + + else: + row.indent = 1.0 + row.parent_invoice = row.parent + row.parent = row.item_code + self.si_list[0].base_net_amount += row.base_net_amount + def load_stock_ledger_entries(self): res = frappe.db.sql("""select item_code, voucher_type, voucher_no, voucher_detail_no, stock_value, warehouse, actual_qty as qty From e676a09c185ed4f5343f690f4d7e9a6874e7c2a2 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 02:38:34 +0530 Subject: [PATCH 03/19] fix: Make Invoice row bold --- .../accounts/report/gross_profit/gross_profit.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.js b/erpnext/accounts/report/gross_profit/gross_profit.js index c6c43251acf..b3b16a8852a 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.js +++ b/erpnext/accounts/report/gross_profit/gross_profit.js @@ -40,5 +40,16 @@ frappe.query_reports["Gross Profit"] = { "tree": true, "name_field": "parent", "parent_field": "parent_invoice", - "initial_depth": 2 + "initial_depth": 2, + "formatter": function(value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + + if (data && !data.parent_invoice) { + value = $(`${value}`); + var $value = $(value).css("font-weight", "bold"); + value = $value.wrap("

").parent().html(); + } + + return value; + }, } From 7cf5dc7dab788a2534ea7cf7caf0b2ff080e16d6 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 03:54:19 +0530 Subject: [PATCH 04/19] fix: Assign indent and parent_invoice --- .../report/gross_profit/gross_profit.py | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 15560b45f43..495e4484ecb 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -46,10 +46,26 @@ def execute(filters=None): for col in group_wise_columns.get(scrub(filters.group_by)): row.append(src.get(col)) - row.append(filters.currency) - if idx == len(gross_profit_data.grouped_data)-1: - row[0] = frappe.bold("Total") - data.append(row) + for src in gross_profit_data.si_list: + row = frappe._dict() + row.indent = src.indent + row.parent_invoice = src.parent_invoice + row.currency = filters.currency + + for col in group_wise_columns.get(scrub(filters.group_by)): + row[column_names[col]] = src.get(col) + + data.append(row) + + else: + for src in gross_profit_data.grouped_data: + row = [] + row.append(filters.currency) + + for col in group_wise_columns.get(scrub(filters.group_by)): + row.append(src.get(col)) + + data.append(row) return columns, data @@ -393,7 +409,9 @@ class GrossProfitGenerator(object): 'item_row': None, 'is_return': row.is_return, 'cost_center': row.cost_center, - 'base_net_amount': 0 + 'base_net_amount': 0, + 'indent': 0.0, + 'parent_invoice': '' }) self.si_list.insert(index, invoice) @@ -403,7 +421,8 @@ class GrossProfitGenerator(object): row.indent = 1.0 row.parent_invoice = row.parent row.parent = row.item_code - self.si_list[0].base_net_amount += row.base_net_amount + # ind = parents_index-1 if parents_index > 0 else parents_index + # self.si_list[ind].base_net_amount += row.base_net_amount def load_stock_ledger_entries(self): res = frappe.db.sql("""select item_code, voucher_type, voucher_no, From e4995dc9ed96f2249e470869b4afef546307924f Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 06:06:47 +0530 Subject: [PATCH 05/19] fix: Set initial_depth to 3 --- erpnext/accounts/report/gross_profit/gross_profit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.js b/erpnext/accounts/report/gross_profit/gross_profit.js index b3b16a8852a..5a6346c1c1d 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.js +++ b/erpnext/accounts/report/gross_profit/gross_profit.js @@ -40,7 +40,7 @@ frappe.query_reports["Gross Profit"] = { "tree": true, "name_field": "parent", "parent_field": "parent_invoice", - "initial_depth": 2, + "initial_depth": 3, "formatter": function(value, row, column, data, default_formatter) { value = default_formatter(value, row, column, data); From 678960209c5010803b7079668c1107970c4d8c2c Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 06:07:53 +0530 Subject: [PATCH 06/19] fix: Add items belonging to Product Bundles as children --- .../report/gross_profit/gross_profit.py | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 495e4484ecb..5bb0e333466 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -377,6 +377,10 @@ class GrossProfitGenerator(object): sales_team_table=sales_team_table, match_cond = get_match_cond('Sales Invoice')), self.filters, as_dict=1) def group_items_by_invoice(self): + """ + Turns list of Sales Invoice Items to a tree of Sales Invoices with their Items as children. + """ + parents = [] for row in self.si_list: @@ -388,15 +392,14 @@ class GrossProfitGenerator(object): if parents_index < len(parents) and row.parent == parents[parents_index]: invoice = frappe._dict({ 'parent_invoice': "", - 'parent': row.parent, 'indent': 0.0, + 'parent': row.parent, 'posting_date': row.posting_date, 'posting_time': row.posting_time, 'project': row.project, 'update_stock': row.update_stock, 'customer': row.customer, 'customer_group': row.customer_group, - 'customer_group': row.customer_group, 'item_code': None, 'item_name': None, 'description': None, @@ -409,21 +412,60 @@ class GrossProfitGenerator(object): 'item_row': None, 'is_return': row.is_return, 'cost_center': row.cost_center, - 'base_net_amount': 0, - 'indent': 0.0, - 'parent_invoice': '' + 'base_net_amount': 0 }) self.si_list.insert(index, invoice) parents_index += 1 else: - row.indent = 1.0 - row.parent_invoice = row.parent - row.parent = row.item_code + # skipping the bundle items rows + if not row.indent: + row.indent = 1.0 + row.parent_invoice = row.parent + row.parent = row.item_code + # ind = parents_index-1 if parents_index > 0 else parents_index # self.si_list[ind].base_net_amount += row.base_net_amount + if frappe.db.exists('Product Bundle', row.item_code): + self.add_bundle_items(row, index) + + def add_bundle_items(self, product_bundle, index): + bundle_items = frappe.get_all( + 'Product Bundle Item', + filters = { + 'parent': product_bundle.item_code + }, + fields = ['item_code', 'qty'] + ) + + for i, item in enumerate(bundle_items): + bundle_item = frappe._dict({ + 'parent_invoice': product_bundle.item_code, + 'indent': product_bundle.indent + 1, + 'parent': item.item_code, + 'posting_date': product_bundle.posting_date, + 'posting_time': product_bundle.posting_time, + 'project': product_bundle.project, + 'customer': product_bundle.customer, + 'customer_group': product_bundle.customer_group, + 'item_code': item.item_code, + 'item_name': frappe.db.get_value('Item', item.item_code, 'item_name'), + 'description': frappe.db.get_value('Item', item.item_code, 'description'), + 'warehouse': product_bundle.warehouse, + 'item_group': frappe.db.get_value('Item', item.item_code, 'item_group'), + 'brand': frappe.db.get_value('Item', item.item_code, 'brand'), + 'dn_detail': product_bundle.dn_detail, + 'delivery_note': product_bundle.delivery_note, + 'qty': (product_bundle.qty * item.qty), + 'item_row': None, + 'is_return': product_bundle.is_return, + 'cost_center': product_bundle.cost_center + }) + + self.si_list.insert((index+i+1), bundle_item) + def load_stock_ledger_entries(self): res = frappe.db.sql("""select item_code, voucher_type, voucher_no, voucher_detail_no, stock_value, warehouse, actual_qty as qty From 7cc02bf861c7da2d4182b1889f1efe6adca0cb47 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 18:25:36 +0530 Subject: [PATCH 07/19] fix: Display Items in the format Item Code: Item Name --- .../accounts/report/gross_profit/gross_profit.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 5bb0e333466..952d269860f 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -46,6 +46,9 @@ def execute(filters=None): for col in group_wise_columns.get(scrub(filters.group_by)): row.append(src.get(col)) + # to display item as Item Code: Item Name + columns[0] = 'Sales Invoice:Link/Item:300' + for src in gross_profit_data.si_list: row = frappe._dict() row.indent = src.indent @@ -455,12 +458,12 @@ class GrossProfitGenerator(object): 'description': frappe.db.get_value('Item', item.item_code, 'description'), 'warehouse': product_bundle.warehouse, 'item_group': frappe.db.get_value('Item', item.item_code, 'item_group'), - 'brand': frappe.db.get_value('Item', item.item_code, 'brand'), - 'dn_detail': product_bundle.dn_detail, - 'delivery_note': product_bundle.delivery_note, - 'qty': (product_bundle.qty * item.qty), - 'item_row': None, - 'is_return': product_bundle.is_return, + 'brand': frappe.db.get_value('Item', item.item_code, 'brand'), + 'dn_detail': product_bundle.dn_detail, + 'delivery_note': product_bundle.delivery_note, + 'qty': (product_bundle.qty * item.qty), + 'item_row': None, + 'is_return': product_bundle.is_return, 'cost_center': product_bundle.cost_center }) From dd7b02ad7d57e1c1521b717dcb9f0a46e70dee21 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 20 Aug 2021 18:26:17 +0530 Subject: [PATCH 08/19] fix: Remove Item Code and Item Name columns --- erpnext/accounts/report/gross_profit/gross_profit.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 952d269860f..5a4b21de827 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -48,6 +48,8 @@ def execute(filters=None): # to display item as Item Code: Item Name columns[0] = 'Sales Invoice:Link/Item:300' + # removing Item Code and Item Name columns + del columns[4:6] for src in gross_profit_data.si_list: row = frappe._dict() From 452c613974d45e796a56c9b4a1c40ca5ced15f40 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 23 Aug 2021 21:17:32 +0530 Subject: [PATCH 09/19] fix: Calculate total buying_amount and gross profit for each invoice --- .../report/gross_profit/gross_profit.py | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 5a4b21de827..ba58d617b74 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -137,7 +137,12 @@ class GrossProfitGenerator(object): self.currency_precision = cint(frappe.db.get_default("currency_precision")) or 3 self.float_precision = cint(frappe.db.get_default("float_precision")) or 2 - for row in self.si_list: + grouped_by_invoice = True if self.filters.get("group_by") == "Invoice" else False + + if grouped_by_invoice: + buying_amount = 0 + + for row in reversed(self.si_list): if self.skip_row(row, self.product_bundles): continue @@ -159,6 +164,13 @@ class GrossProfitGenerator(object): row.buying_amount = flt(self.get_buying_amount(row, row.item_code), self.currency_precision) + if grouped_by_invoice: + if row.indent == 1.0: + buying_amount = row.buying_amount + elif row.indent == 0.0: + row.buying_amount = buying_amount + buying_amount = 0 + # get buying rate if row.qty: row.buying_rate = flt(row.buying_amount / row.qty, self.float_precision) @@ -430,12 +442,36 @@ class GrossProfitGenerator(object): row.parent_invoice = row.parent row.parent = row.item_code - # ind = parents_index-1 if parents_index > 0 else parents_index - # self.si_list[ind].base_net_amount += row.base_net_amount + # if not self.si_list[parents_index-1].base_net_amount: + # self.si_list[parents_index-1].base_net_amount = 0 + + # self.si_list[parents_index-1].base_net_amount += row.base_net_amount + + # print("\n\n\n\n\nRow Details: ", index, ". ", row.parent, ": ", row.base_net_amount) + # print("Ind details: ", parents_index-1, ": ", self.si_list[parents_index-1].base_net_amount, "\n\n\n") if frappe.db.exists('Product Bundle', row.item_code): self.add_bundle_items(row, index) + base_net_amount = 0 + for row in reversed(self.si_list): + if row.indent == 1.0: + base_net_amount += row.get('base_net_amount') + + elif row.indent == 0.0: + row.base_net_amount = base_net_amount + base_net_amount = 0 + + # print("\n"*10) + # for index, row in enumerate(self.si_list): + # if row.indent == 0.0: + # print(index, ". ", row.parent, ": ", row.base_net_amount) + # elif row.indent == 1.0: + # print("\t", index, ". ", row.parent, ": ", row.base_net_amount) + # elif row.indent == 2.0: + # print("\t\t", index, ". ", row.parent, ": ", row.base_net_amount) + # print("") + def add_bundle_items(self, product_bundle, index): bundle_items = frappe.get_all( 'Product Bundle Item', From 391bf86e0ac37341cf534759d9d4400ec0d5e21f Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 24 Aug 2021 23:32:19 +0530 Subject: [PATCH 10/19] fix: Fetch base_net_total for each Invoice --- erpnext/accounts/report/gross_profit/gross_profit.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index ba58d617b74..74ce108bcb3 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -429,7 +429,8 @@ class GrossProfitGenerator(object): 'item_row': None, 'is_return': row.is_return, 'cost_center': row.cost_center, - 'base_net_amount': 0 + 'base_net_amount': frappe.db.get_value('Sales Invoice', row.parent, 'base_net_total'), + 'base_rate': None }) self.si_list.insert(index, invoice) @@ -444,7 +445,7 @@ class GrossProfitGenerator(object): # if not self.si_list[parents_index-1].base_net_amount: # self.si_list[parents_index-1].base_net_amount = 0 - + # self.si_list[parents_index-1].base_net_amount += row.base_net_amount # print("\n\n\n\n\nRow Details: ", index, ". ", row.parent, ": ", row.base_net_amount) @@ -459,7 +460,7 @@ class GrossProfitGenerator(object): base_net_amount += row.get('base_net_amount') elif row.indent == 0.0: - row.base_net_amount = base_net_amount + row.base_net_amount = base_net_amount base_net_amount = 0 # print("\n"*10) @@ -471,7 +472,7 @@ class GrossProfitGenerator(object): # elif row.indent == 2.0: # print("\t\t", index, ". ", row.parent, ": ", row.base_net_amount) # print("") - + def add_bundle_items(self, product_bundle, index): bundle_items = frappe.get_all( 'Product Bundle Item', From de660bf9c4a0be2cf940e81575fc097a0099163a Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 24 Aug 2021 23:38:24 +0530 Subject: [PATCH 11/19] fix: Fetch bundle item details --- .../report/gross_profit/gross_profit.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 74ce108bcb3..87a663e630c 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -483,6 +483,8 @@ class GrossProfitGenerator(object): ) for i, item in enumerate(bundle_items): + item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code) + bundle_item = frappe._dict({ 'parent_invoice': product_bundle.item_code, 'indent': product_bundle.indent + 1, @@ -493,14 +495,14 @@ class GrossProfitGenerator(object): 'customer': product_bundle.customer, 'customer_group': product_bundle.customer_group, 'item_code': item.item_code, - 'item_name': frappe.db.get_value('Item', item.item_code, 'item_name'), - 'description': frappe.db.get_value('Item', item.item_code, 'description'), + 'item_name': item_name, + 'description': description, 'warehouse': product_bundle.warehouse, - 'item_group': frappe.db.get_value('Item', item.item_code, 'item_group'), - 'brand': frappe.db.get_value('Item', item.item_code, 'brand'), + 'item_group': item_group, + 'brand': brand, 'dn_detail': product_bundle.dn_detail, 'delivery_note': product_bundle.delivery_note, - 'qty': (product_bundle.qty * item.qty), + 'qty': (flt(product_bundle.qty) * flt(item.qty)), 'item_row': None, 'is_return': product_bundle.is_return, 'cost_center': product_bundle.cost_center @@ -508,6 +510,13 @@ class GrossProfitGenerator(object): self.si_list.insert((index+i+1), bundle_item) + def get_bundle_item_details(self, item_code): + return frappe.db.get_value( + 'Item', + item_code, + ['item_name', 'description', 'item_group', 'brand'] + ) + def load_stock_ledger_entries(self): res = frappe.db.sql("""select item_code, voucher_type, voucher_no, voucher_detail_no, stock_value, warehouse, actual_qty as qty From 4aede0ea3f7f18d387391358837121e507b942d9 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 00:09:07 +0530 Subject: [PATCH 12/19] fix: Calculate total buying_amount for each invoice --- erpnext/accounts/report/gross_profit/gross_profit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 87a663e630c..fa8441a79a6 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -166,7 +166,7 @@ class GrossProfitGenerator(object): if grouped_by_invoice: if row.indent == 1.0: - buying_amount = row.buying_amount + buying_amount += row.buying_amount elif row.indent == 0.0: row.buying_amount = buying_amount buying_amount = 0 From 6fdf4dd03eb701c306147d1cfb128fb55d4ef047 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 00:33:55 +0530 Subject: [PATCH 13/19] fix: Remove base_rate and buying_rate for Invoice rows --- .../accounts/report/gross_profit/gross_profit.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index fa8441a79a6..c91fcbc70db 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -176,7 +176,8 @@ class GrossProfitGenerator(object): row.buying_rate = flt(row.buying_amount / row.qty, self.float_precision) row.base_rate = flt(row.base_amount / row.qty, self.float_precision) else: - row.buying_rate, row.base_rate = 0.0, 0.0 + if self.is_not_invoice_row(row): + row.buying_rate, row.base_rate = 0.0, 0.0 # calculate gross profit row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision) @@ -222,14 +223,17 @@ class GrossProfitGenerator(object): for returned_item_row in returned_item_rows: row.qty += returned_item_row.qty row.base_amount += flt(returned_item_row.base_amount, self.currency_precision) - row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision) - if row.qty or row.base_amount: + row.buying_amount = flt(flt(row.qty) * flt(row.buying_rate), self.currency_precision) + if (flt(row.qty) or row.base_amount) and self.is_not_invoice_row(row): row = self.set_average_rate(row) self.grouped_data.append(row) self.add_to_totals(row) self.set_average_gross_profit(self.totals) self.grouped_data.append(self.totals) + def is_not_invoice_row(self, row): + return (self.filters.get("group_by") == "Invoice" and row.indent != 0.0) or self.filters.get("group_by") != "Invoice" + def set_average_rate(self, new_row): self.set_average_gross_profit(new_row) new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0 @@ -429,8 +433,7 @@ class GrossProfitGenerator(object): 'item_row': None, 'is_return': row.is_return, 'cost_center': row.cost_center, - 'base_net_amount': frappe.db.get_value('Sales Invoice', row.parent, 'base_net_total'), - 'base_rate': None + 'base_net_amount': frappe.db.get_value('Sales Invoice', row.parent, 'base_net_total') }) self.si_list.insert(index, invoice) From ae6e69ebd4c4f65fc31ef94f781ef6f143dcf976 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 02:49:14 +0530 Subject: [PATCH 14/19] fix: Display only the Invoice rows in bold --- erpnext/accounts/report/gross_profit/gross_profit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.js b/erpnext/accounts/report/gross_profit/gross_profit.js index 5a6346c1c1d..856b97d1645 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.js +++ b/erpnext/accounts/report/gross_profit/gross_profit.js @@ -44,7 +44,7 @@ frappe.query_reports["Gross Profit"] = { "formatter": function(value, row, column, data, default_formatter) { value = default_formatter(value, row, column, data); - if (data && !data.parent_invoice) { + if (data && data.indent == 0.0) { value = $(`${value}`); var $value = $(value).css("font-weight", "bold"); value = $value.wrap("

").parent().html(); From 70244cee8960414cec17284be3230714228fb1ec Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 02:52:18 +0530 Subject: [PATCH 15/19] fix: Get data when grouped by invoice and otherwise --- .../report/gross_profit/gross_profit.py | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index c91fcbc70db..0a96d98e75e 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -41,38 +41,43 @@ def execute(filters=None): columns = get_columns(group_wise_columns, filters) + if filters.group_by == 'Invoice': + get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_wise_columns, data) + + else: + get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_columns, data) + + return columns, data + +def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_wise_columns, data): + column_names = get_column_names() + + # to display item as Item Code: Item Name + columns[0] = 'Sales Invoice:Link/Item:300' + # removing Item Code and Item Name columns + del columns[4:6] + + for src in gross_profit_data.si_list: + row = frappe._dict() + row.indent = src.indent + row.parent_invoice = src.parent_invoice + row.currency = filters.currency + + for col in group_wise_columns.get(scrub(filters.group_by)): + row[column_names[col]] = src.get(col) + + data.append(row) + +def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_columns, data): for idx, src in enumerate(gross_profit_data.grouped_data): row = [] for col in group_wise_columns.get(scrub(filters.group_by)): row.append(src.get(col)) - # to display item as Item Code: Item Name - columns[0] = 'Sales Invoice:Link/Item:300' - # removing Item Code and Item Name columns - del columns[4:6] - - for src in gross_profit_data.si_list: - row = frappe._dict() - row.indent = src.indent - row.parent_invoice = src.parent_invoice - row.currency = filters.currency - - for col in group_wise_columns.get(scrub(filters.group_by)): - row[column_names[col]] = src.get(col) - - data.append(row) - - else: - for src in gross_profit_data.grouped_data: - row = [] - row.append(filters.currency) - - for col in group_wise_columns.get(scrub(filters.group_by)): - row.append(src.get(col)) - - data.append(row) - - return columns, data + row.append(filters.currency) + if idx == len(gross_profit_data.grouped_data)-1: + row[0] = frappe.bold("Total") + data.append(row) def get_columns(group_wise_columns, filters): columns = [] From e2e751e26f2dd1d3d923946a9216ecf790415dd7 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 15:20:27 +0530 Subject: [PATCH 16/19] fix: Remove comments --- .../report/gross_profit/gross_profit.py | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 0a96d98e75e..3349a2ae54f 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -451,35 +451,8 @@ class GrossProfitGenerator(object): row.parent_invoice = row.parent row.parent = row.item_code - # if not self.si_list[parents_index-1].base_net_amount: - # self.si_list[parents_index-1].base_net_amount = 0 - - # self.si_list[parents_index-1].base_net_amount += row.base_net_amount - - # print("\n\n\n\n\nRow Details: ", index, ". ", row.parent, ": ", row.base_net_amount) - # print("Ind details: ", parents_index-1, ": ", self.si_list[parents_index-1].base_net_amount, "\n\n\n") - - if frappe.db.exists('Product Bundle', row.item_code): - self.add_bundle_items(row, index) - - base_net_amount = 0 - for row in reversed(self.si_list): - if row.indent == 1.0: - base_net_amount += row.get('base_net_amount') - - elif row.indent == 0.0: - row.base_net_amount = base_net_amount - base_net_amount = 0 - - # print("\n"*10) - # for index, row in enumerate(self.si_list): - # if row.indent == 0.0: - # print(index, ". ", row.parent, ": ", row.base_net_amount) - # elif row.indent == 1.0: - # print("\t", index, ". ", row.parent, ": ", row.base_net_amount) - # elif row.indent == 2.0: - # print("\t\t", index, ". ", row.parent, ": ", row.base_net_amount) - # print("") + if frappe.db.exists('Product Bundle', row.item_code): + self.add_bundle_items(row, index) def add_bundle_items(self, product_bundle, index): bundle_items = frappe.get_all( From 94162e013922fc34eb5483ad2ccf3ad9bd4d307a Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 15:33:53 +0530 Subject: [PATCH 17/19] fix: Get Bundle Items --- .../report/gross_profit/gross_profit.py | 89 +++++++++++++------ 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 3349a2ae54f..d38156ac040 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -416,31 +416,7 @@ class GrossProfitGenerator(object): parents_index = 0 for index, row in enumerate(self.si_list): if parents_index < len(parents) and row.parent == parents[parents_index]: - invoice = frappe._dict({ - 'parent_invoice': "", - 'indent': 0.0, - 'parent': row.parent, - 'posting_date': row.posting_date, - 'posting_time': row.posting_time, - 'project': row.project, - 'update_stock': row.update_stock, - 'customer': row.customer, - 'customer_group': row.customer_group, - 'item_code': None, - 'item_name': None, - 'description': None, - 'warehouse': None, - 'item_group': None, - 'brand': None, - 'dn_detail': None, - 'delivery_note': None, - 'qty': 0, - 'item_row': None, - 'is_return': row.is_return, - 'cost_center': row.cost_center, - 'base_net_amount': frappe.db.get_value('Sales Invoice', row.parent, 'base_net_total') - }) - + invoice = self.get_invoice_row(row) self.si_list.insert(index, invoice) parents_index += 1 @@ -454,8 +430,41 @@ class GrossProfitGenerator(object): if frappe.db.exists('Product Bundle', row.item_code): self.add_bundle_items(row, index) + def get_invoice_row(self, row): + return frappe._dict({ + 'parent_invoice': "", + 'indent': 0.0, + 'parent': row.parent, + 'posting_date': row.posting_date, + 'posting_time': row.posting_time, + 'project': row.project, + 'update_stock': row.update_stock, + 'customer': row.customer, + 'customer_group': row.customer_group, + 'item_code': None, + 'item_name': None, + 'description': None, + 'warehouse': None, + 'item_group': None, + 'brand': None, + 'dn_detail': None, + 'delivery_note': None, + 'qty': None, + 'item_row': None, + 'is_return': row.is_return, + 'cost_center': row.cost_center, + 'base_net_amount': frappe.db.get_value('Sales Invoice', row.parent, 'base_net_total') + }) + def add_bundle_items(self, product_bundle, index): - bundle_items = frappe.get_all( + bundle_items = self.get_bundle_items(product_bundle) + + for i, item in enumerate(bundle_items): + bundle_item = self.get_bundle_item_row(product_bundle, item) + self.si_list.insert((index+i+1), bundle_item) + + def get_bundle_items(self, product_bundle): + return frappe.get_all( 'Product Bundle Item', filters = { 'parent': product_bundle.item_code @@ -463,6 +472,7 @@ class GrossProfitGenerator(object): fields = ['item_code', 'qty'] ) +<<<<<<< HEAD for i, item in enumerate(bundle_items): item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code) @@ -490,6 +500,33 @@ class GrossProfitGenerator(object): }) self.si_list.insert((index+i+1), bundle_item) +======= + def get_bundle_item_row(self, product_bundle, item): + item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code) + + return frappe._dict({ + 'parent_invoice': product_bundle.item_code, + 'indent': product_bundle.indent + 1, + 'parent': item.item_code, + 'posting_date': product_bundle.posting_date, + 'posting_time': product_bundle.posting_time, + 'project': product_bundle.project, + 'customer': product_bundle.customer, + 'customer_group': product_bundle.customer_group, + 'item_code': item.item_code, + 'item_name': item_name, + 'description': description, + 'warehouse': product_bundle.warehouse, + 'item_group': item_group, + 'brand': brand, + 'dn_detail': product_bundle.dn_detail, + 'delivery_note': product_bundle.delivery_note, + 'qty': (flt(product_bundle.qty) * flt(item.qty)), + 'item_row': None, + 'is_return': product_bundle.is_return, + 'cost_center': product_bundle.cost_center + }) +>>>>>>> 3135d6dc6a (fix: Get Bundle Items) def get_bundle_item_details(self, item_code): return frappe.db.get_value( From 5bc7d63646fe1893ead67c3c890647178c70edbe Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 25 Aug 2021 15:33:53 +0530 Subject: [PATCH 18/19] fix: Get Bundle Items --- .../report/gross_profit/gross_profit.py | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index d38156ac040..8d30af3964e 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -472,35 +472,6 @@ class GrossProfitGenerator(object): fields = ['item_code', 'qty'] ) -<<<<<<< HEAD - for i, item in enumerate(bundle_items): - item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code) - - bundle_item = frappe._dict({ - 'parent_invoice': product_bundle.item_code, - 'indent': product_bundle.indent + 1, - 'parent': item.item_code, - 'posting_date': product_bundle.posting_date, - 'posting_time': product_bundle.posting_time, - 'project': product_bundle.project, - 'customer': product_bundle.customer, - 'customer_group': product_bundle.customer_group, - 'item_code': item.item_code, - 'item_name': item_name, - 'description': description, - 'warehouse': product_bundle.warehouse, - 'item_group': item_group, - 'brand': brand, - 'dn_detail': product_bundle.dn_detail, - 'delivery_note': product_bundle.delivery_note, - 'qty': (flt(product_bundle.qty) * flt(item.qty)), - 'item_row': None, - 'is_return': product_bundle.is_return, - 'cost_center': product_bundle.cost_center - }) - - self.si_list.insert((index+i+1), bundle_item) -======= def get_bundle_item_row(self, product_bundle, item): item_name, description, item_group, brand = self.get_bundle_item_details(item.item_code) @@ -526,7 +497,6 @@ class GrossProfitGenerator(object): 'is_return': product_bundle.is_return, 'cost_center': product_bundle.cost_center }) ->>>>>>> 3135d6dc6a (fix: Get Bundle Items) def get_bundle_item_details(self, item_code): return frappe.db.get_value( From 5f2819c9b1f244c68deb4f1cb4ca0e7bfaa5b73b Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 25 Oct 2021 02:24:19 +0530 Subject: [PATCH 19/19] fix: Add column names --- .../report/gross_profit/gross_profit.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 8d30af3964e..a9323df8098 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -119,6 +119,28 @@ def get_columns(group_wise_columns, filters): return columns +def get_column_names(): + return frappe._dict({ + 'parent': 'sales_invoice', + 'customer': 'customer', + 'customer_group': 'customer_group', + 'posting_date': 'posting_date', + 'item_code': 'item_code', + 'item_name': 'item_name', + 'item_group': 'item_group', + 'brand': 'brand', + 'description': 'description', + 'warehouse': 'warehouse', + 'qty': 'qty', + 'base_rate': 'avg._selling_rate', + 'buying_rate': 'valuation_rate', + 'base_amount': 'selling_amount', + 'buying_amount': 'buying_amount', + 'gross_profit': 'gross_profit', + 'gross_profit_percent': 'gross_profit_%', + 'project': 'project' + }) + class GrossProfitGenerator(object): def __init__(self, filters=None): self.data = []