From e8e20da78eeece6b5fad895c6aa6f50f57e561e4 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Thu, 19 Jan 2023 09:39:43 +0000 Subject: [PATCH 1/8] fix(gp): fetch buying amount from dn related to so --- .../report/gross_profit/gross_profit.py | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 130b7150fba..6990c5b0ddc 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -655,10 +655,36 @@ class GrossProfitGenerator(object): return self.calculate_buying_amount_from_sle( row, my_sle, parenttype, parent, item_row, item_code ) + elif row.sales_order and row.so_detail: + incoming_amount = self.get_buying_amount_from_so_dn(row.sales_order, row.so_detail, item_code) + if incoming_amount: + return incoming_amount else: return flt(row.qty) * self.get_average_buying_rate(row, item_code) - return 0.0 + return flt(row.qty) * self.get_average_buying_rate(row, item_code) + + def get_buying_amount_from_so_dn(self, sales_order, so_detail, item_code): + from frappe.query_builder.functions import Sum + delivery_note = frappe.qb.DocType("Delivery Note") + delivery_note_item = frappe.qb.DocType("Delivery Note Item") + + query = ( + frappe.qb.from_(delivery_note) + .inner_join(delivery_note_item) + .on(delivery_note.name == delivery_note_item.parent) + .select( + Sum(delivery_note_item.incoming_rate * delivery_note_item.stock_qty) + ) + .where(delivery_note.docstatus == 1) + .where(delivery_note_item.item_code == item_code) + .where(delivery_note_item.against_sales_order == sales_order) + .where(delivery_note_item.so_detail == so_detail) + .groupby(delivery_note_item.item_code) + ) + + incoming_amount = query.run() + return flt(incoming_amount[0][0]) if incoming_amount else 0 def get_average_buying_rate(self, row, item_code): args = row @@ -760,7 +786,8 @@ class GrossProfitGenerator(object): `tabSales Invoice`.territory, `tabSales Invoice Item`.item_code, `tabSales Invoice Item`.item_name, `tabSales Invoice Item`.description, `tabSales Invoice Item`.warehouse, `tabSales Invoice Item`.item_group, - `tabSales Invoice Item`.brand, `tabSales Invoice Item`.dn_detail, + `tabSales Invoice Item`.brand, `tabSales Invoice Item`.so_detail, + `tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.dn_detail, `tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.stock_qty as qty, `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, `tabSales Invoice Item`.name as "item_row", `tabSales Invoice`.is_return, From ef90e249312dce414c6dbe088b8880c47403b3cc Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Thu, 19 Jan 2023 10:25:05 +0000 Subject: [PATCH 2/8] chore: linting issue --- erpnext/accounts/report/gross_profit/gross_profit.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 6990c5b0ddc..25e7891a499 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -666,6 +666,7 @@ class GrossProfitGenerator(object): def get_buying_amount_from_so_dn(self, sales_order, so_detail, item_code): from frappe.query_builder.functions import Sum + delivery_note = frappe.qb.DocType("Delivery Note") delivery_note_item = frappe.qb.DocType("Delivery Note Item") @@ -673,9 +674,7 @@ class GrossProfitGenerator(object): frappe.qb.from_(delivery_note) .inner_join(delivery_note_item) .on(delivery_note.name == delivery_note_item.parent) - .select( - Sum(delivery_note_item.incoming_rate * delivery_note_item.stock_qty) - ) + .select(Sum(delivery_note_item.incoming_rate * delivery_note_item.stock_qty)) .where(delivery_note.docstatus == 1) .where(delivery_note_item.item_code == item_code) .where(delivery_note_item.against_sales_order == sales_order) From 1f6ab86a659d9745fa8971656a54c19bc784de2b Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 30 Jan 2023 10:35:43 +0000 Subject: [PATCH 3/8] feat(gp): test for inv and dn related via so --- .../report/gross_profit/test_gross_profit.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index fa11a41df4a..332be8ef54e 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -302,3 +302,79 @@ class TestGrossProfit(FrappeTestCase): columns, data = execute(filters=filters) self.assertGreater(len(data), 0) + + def test_order_connected_dn_and_inv(self): + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order + """ + Test gp calculation when invoice and delivery note aren't directly connected. + SO -- INV + | + DN + """ + se = make_stock_entry( + company=self.company, + item_code=self.item, + target=self.warehouse, + qty=3, + basic_rate=100, + do_not_submit=True, + ) + item = se.items[0] + se.append( + "items", + { + "item_code": item.item_code, + "s_warehouse": item.s_warehouse, + "t_warehouse": item.t_warehouse, + "qty": 10, + "basic_rate": 200, + "conversion_factor": item.conversion_factor or 1.0, + "transfer_qty": flt(item.qty) * (flt(item.conversion_factor) or 1.0), + "serial_no": item.serial_no, + "batch_no": item.batch_no, + "cost_center": item.cost_center, + "expense_account": item.expense_account, + }, + ) + se = se.save().submit() + + so = make_sales_order( + customer=self.customer, + company=self.company, + warehouse=self.warehouse, + item=self.item, + qty=4, + do_not_save=False, + do_not_submit=False, + ) + + from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice + make_delivery_note(so.name).submit() + sinv = make_sales_invoice(so.name).submit() + + filters = frappe._dict( + company=self.company, from_date=nowdate(), to_date=nowdate(), group_by="Invoice" + ) + + columns, data = execute(filters=filters) + + # Without Delivery Note, buying rate should be 150 + expected_entry = { + "parent_invoice": sinv.name, + "currency": "INR", + "sales_invoice": self.item, + "customer": self.customer, + "posting_date": frappe.utils.datetime.date.fromisoformat(nowdate()), + "item_code": self.item, + "item_name": self.item, + "warehouse": "Stores - _GP", + "qty": 4.0, + "avg._selling_rate": 100.0, + "valuation_rate": 125.0, + "selling_amount": 400.0, + "buying_amount": 500.0, + "gross_profit": -100.0, + "gross_profit_%": -25.0, + } + gp_entry = [x for x in data if x.parent_invoice == sinv.name] + self.assertDictContainsSubset(expected_entry, gp_entry[0]) \ No newline at end of file From d69c8393692fa8ecc08ff7f10ca66a1c5a9f3b0f Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 30 Jan 2023 10:45:08 +0000 Subject: [PATCH 4/8] chore: linting issues --- .../accounts/report/gross_profit/test_gross_profit.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index 332be8ef54e..21681bef5b5 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -305,6 +305,7 @@ class TestGrossProfit(FrappeTestCase): def test_order_connected_dn_and_inv(self): from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order + """ Test gp calculation when invoice and delivery note aren't directly connected. SO -- INV @@ -348,7 +349,11 @@ class TestGrossProfit(FrappeTestCase): do_not_submit=False, ) - from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice + from erpnext.selling.doctype.sales_order.sales_order import ( + make_delivery_note, + make_sales_invoice, + ) + make_delivery_note(so.name).submit() sinv = make_sales_invoice(so.name).submit() @@ -357,8 +362,6 @@ class TestGrossProfit(FrappeTestCase): ) columns, data = execute(filters=filters) - - # Without Delivery Note, buying rate should be 150 expected_entry = { "parent_invoice": sinv.name, "currency": "INR", @@ -377,4 +380,4 @@ class TestGrossProfit(FrappeTestCase): "gross_profit_%": -25.0, } gp_entry = [x for x in data if x.parent_invoice == sinv.name] - self.assertDictContainsSubset(expected_entry, gp_entry[0]) \ No newline at end of file + self.assertDictContainsSubset(expected_entry, gp_entry[0]) From 2bad86d8d8220f4eb729c3a918ce0002f6b87693 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 30 Jan 2023 19:58:23 +0530 Subject: [PATCH 5/8] ci: bump isort to 5.12.0 (#33875) [skip ci] --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 73aae33e936..d70977c07e2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,8 +32,8 @@ repos: - id: black additional_dependencies: ['click==8.0.4'] - - repo: https://github.com/timothycrosley/isort - rev: 5.9.1 + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 hooks: - id: isort exclude: ".*setup.py$" From f487660a7c32c5f81950eb72d379876f9ec422a6 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 30 Jan 2023 21:33:43 +0530 Subject: [PATCH 6/8] fix: disposal_was_made_on_original_schedule_date --- erpnext/assets/doctype/asset/depreciation.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 5337fd64eea..17d40784bed 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -4,7 +4,17 @@ import frappe from frappe import _ -from frappe.utils import add_months, cint, flt, get_link_to_form, getdate, nowdate, today +from frappe.utils import ( + add_months, + cint, + flt, + get_last_day, + get_link_to_form, + getdate, + is_last_day_of_the_month, + nowdate, + today, +) from frappe.utils.user import get_users_with_role from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( @@ -400,6 +410,9 @@ def disposal_was_made_on_original_schedule_date(schedule_idx, row, posting_date_ row.depreciation_start_date, schedule_idx * cint(row.frequency_of_depreciation) ) + if is_last_day_of_the_month(row.depreciation_start_date): + orginal_schedule_date = get_last_day(orginal_schedule_date) + if orginal_schedule_date == posting_date_of_disposal: return True From 11d165c274ffe17b6f403bf30d86b4430976518b Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 30 Jan 2023 19:33:58 +0100 Subject: [PATCH 7/8] fix(Fixed Asset Register): error when selecting more than one fiscal year --- .../fixed_asset_register/fixed_asset_register.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index faffd1134d3..d41069c1c9f 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -126,16 +126,18 @@ def get_asset_value(asset, finance_book=None): if not asset.calculate_depreciation: return flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation) - finance_book_filter = ["finance_book", "is", "not set"] - if finance_book: - finance_book_filter = ["finance_book", "=", finance_book] - - return frappe.db.get_value( + result = frappe.get_all( doctype="Asset Finance Book", - filters=[["parent", "=", asset.asset_id], finance_book_filter], - fieldname="value_after_depreciation", + filters={ + "parent": asset.asset_id, + "finance_book": finance_book or ("is", "not set"), + }, + pluck="value_after_depreciation", + limit=1, ) + return result[0] if result else 0.0 + def prepare_chart_data(data, filters): labels_values_map = {} From b3dc22de29821ee46f59bf1223dfbb1df6dbb493 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 31 Jan 2023 09:33:33 +0530 Subject: [PATCH 8/8] fix: Fetch commission rate from sales partner (#33851) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 4729d9c3db9..2f4e45e6187 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -1776,6 +1776,8 @@ "width": "50%" }, { + "fetch_from": "sales_partner.commission_rate", + "fetch_if_empty": 1, "fieldname": "commission_rate", "fieldtype": "Float", "hide_days": 1, @@ -2141,7 +2143,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2022-12-12 18:34:33.409895", + "modified": "2023-01-28 19:45:47.538163", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice",