From b73422e4eef790334e22234f0875f4e18f695cf8 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 18 Apr 2023 18:38:28 +0530 Subject: [PATCH 1/4] fix: internal Purchase Receipt GL Entries (cherry picked from commit 6fca9adcd4a881b09630f5e0ad875df136e1d6e0) --- .../doctype/purchase_receipt/purchase_receipt.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 0384c24503a..28bff671f62 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -370,7 +370,19 @@ class PurchaseReceipt(BuyingController): outgoing_amount = d.base_net_amount if self.is_internal_supplier and d.valuation_rate: - outgoing_amount = d.valuation_rate * d.stock_qty + outgoing_amount = abs( + frappe.db.get_value( + "Stock Ledger Entry", + { + "voucher_type": "Purchase Receipt", + "voucher_no": self.name, + "voucher_detail_no": d.name, + "warehouse": d.from_warehouse, + "is_cancelled": 0, + }, + "stock_value_difference", + ) + ) credit_amount = outgoing_amount if credit_amount: From 046bf64fa322f11cc61bcd08e841cc53e0f92c66 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 18 Apr 2023 21:03:23 +0530 Subject: [PATCH 2/4] test: add test case for internal PR GL Entries (cherry picked from commit c86c543fbfaa46c45f06a745a0841e821e14e712) # Conflicts: # erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py --- .../purchase_receipt/test_purchase_receipt.py | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 2457c8e80ab..8539aae8560 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -1707,6 +1707,201 @@ class TestPurchaseReceipt(FrappeTestCase): self.assertTrue(return_pi.docstatus == 1) +<<<<<<< HEAD +======= + def test_disable_last_purchase_rate(self): + from erpnext.stock.get_item_details import get_item_details + + item = make_item( + "_Test Disable Last Purchase Rate", + {"is_purchase_item": 1, "is_stock_item": 1}, + ) + + frappe.db.set_single_value("Buying Settings", "disable_last_purchase_rate", 1) + + pr = make_purchase_receipt( + qty=1, + rate=100, + item_code=item.name, + ) + + args = pr.items[0].as_dict() + args.update( + { + "supplier": pr.supplier, + "doctype": pr.doctype, + "conversion_rate": pr.conversion_rate, + "currency": pr.currency, + "company": pr.company, + "posting_date": pr.posting_date, + "posting_time": pr.posting_time, + } + ) + + res = get_item_details(args) + self.assertEqual(res.get("last_purchase_rate"), 0) + + frappe.db.set_single_value("Buying Settings", "disable_last_purchase_rate", 0) + + pr = make_purchase_receipt( + qty=1, + rate=100, + item_code=item.name, + ) + + res = get_item_details(args) + self.assertEqual(res.get("last_purchase_rate"), 100) + + def test_validate_received_qty_for_internal_pr(self): + prepare_data_for_internal_transfer() + customer = "_Test Internal Customer 2" + company = "_Test Company with perpetual inventory" + from_warehouse = create_warehouse("_Test Internal From Warehouse New", company=company) + target_warehouse = create_warehouse("_Test Internal GIT Warehouse New", company=company) + to_warehouse = create_warehouse("_Test Internal To Warehouse New", company=company) + + # Step 1: Create Item + item = make_item(properties={"is_stock_item": 1, "valuation_rate": 100}) + + # Step 2: Create Stock Entry (Material Receipt) + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + + make_stock_entry( + purpose="Material Receipt", + item_code=item.name, + qty=15, + company=company, + to_warehouse=from_warehouse, + ) + + # Step 3: Create Delivery Note with Internal Customer + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + + dn = create_delivery_note( + item_code=item.name, + company=company, + customer=customer, + cost_center="Main - TCP1", + expense_account="Cost of Goods Sold - TCP1", + qty=10, + rate=100, + warehouse=from_warehouse, + target_warehouse=target_warehouse, + ) + + # Step 4: Create Internal Purchase Receipt + from erpnext.controllers.status_updater import OverAllowanceError + from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt + + pr = make_inter_company_purchase_receipt(dn.name) + pr.items[0].qty = 15 + pr.items[0].from_warehouse = target_warehouse + pr.items[0].warehouse = to_warehouse + pr.items[0].rejected_warehouse = from_warehouse + pr.save() + + self.assertRaises(OverAllowanceError, pr.submit) + + # Step 5: Test Over Receipt Allowance + frappe.db.set_single_value("Stock Settings", "over_delivery_receipt_allowance", 50) + + make_stock_entry( + purpose="Material Transfer", + item_code=item.name, + qty=5, + company=company, + from_warehouse=from_warehouse, + to_warehouse=target_warehouse, + ) + + pr.submit() + + frappe.db.set_single_value("Stock Settings", "over_delivery_receipt_allowance", 0) + + def test_internal_pr_gl_entries(self): + from erpnext.stock import get_warehouse_account_map + from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_stock_reconciliation, + ) + + prepare_data_for_internal_transfer() + customer = "_Test Internal Customer 2" + company = "_Test Company with perpetual inventory" + from_warehouse = create_warehouse("_Test Internal From Warehouse New", company=company) + target_warehouse = create_warehouse("_Test Internal GIT Warehouse New", company=company) + to_warehouse = create_warehouse("_Test Internal To Warehouse New", company=company) + + item = make_item(properties={"is_stock_item": 1, "valuation_rate": 100}) + make_stock_entry( + purpose="Material Receipt", + item_code=item.name, + qty=10, + company=company, + to_warehouse=from_warehouse, + posting_date=add_days(today(), -3), + ) + + # Step - 1: Create Delivery Note with Internal Customer + dn = create_delivery_note( + item_code=item.name, + company=company, + customer=customer, + cost_center="Main - TCP1", + expense_account="Cost of Goods Sold - TCP1", + qty=10, + rate=100, + warehouse=from_warehouse, + target_warehouse=target_warehouse, + posting_date=add_days(today(), -2), + ) + + # Step - 2: Create Internal Purchase Receipt + pr = make_inter_company_purchase_receipt(dn.name) + pr.items[0].qty = 10 + pr.items[0].from_warehouse = target_warehouse + pr.items[0].warehouse = to_warehouse + pr.items[0].rejected_warehouse = from_warehouse + pr.save() + pr.submit() + + # Step - 3: Create back-date Stock Reconciliation [After DN and Before PR] + create_stock_reconciliation( + item_code=item, + warehouse=target_warehouse, + qty=10, + rate=50, + company=company, + posting_date=add_days(today(), -1), + ) + + warehouse_account = get_warehouse_account_map(company) + stock_account_value = frappe.db.get_value( + "GL Entry", + { + "account": warehouse_account[target_warehouse]["account"], + "voucher_type": "Purchase Receipt", + "voucher_no": pr.name, + "is_cancelled": 0, + }, + fieldname=["credit"], + ) + stock_diff = frappe.db.get_value( + "Stock Ledger Entry", + { + "voucher_type": "Purchase Receipt", + "voucher_no": pr.name, + "is_cancelled": 0, + }, + fieldname=["sum(stock_value_difference)"], + ) + + # Value of Stock Account should be equal to the sum of Stock Value Difference + self.assertEqual(stock_account_value, stock_diff) + +>>>>>>> c86c543fbf (test: add test case for internal PR GL Entries) def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier From d010b048dc73251742b5cecd4fa4611e0077f7ea Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 19 Apr 2023 16:01:45 +0530 Subject: [PATCH 3/4] fix(test): `test_backdated_stock_reco_cancellation_future_negative_stock` (cherry picked from commit 11c8503180cda70b1aebce3711def05eec840133) --- .../doctype/stock_reconciliation/test_stock_reconciliation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index a7f5f4a8ae2..a09ad946155 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -529,7 +529,9 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin): # check if cancellation of stock reco is blocked self.assertRaises(NegativeStockError, sr.cancel) - repost_exists = bool(frappe.db.exists("Repost Item Valuation", {"voucher_no": sr.name})) + repost_exists = bool( + frappe.db.exists("Repost Item Valuation", {"voucher_no": sr.name, "status": "Queued"}) + ) self.assertFalse(repost_exists, msg="Negative stock validation not working on reco cancellation") def test_intermediate_sr_bin_update(self): From 102ac9f74d7450bb397bd339361072ab00169a48 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 20 Apr 2023 16:20:25 +0530 Subject: [PATCH 4/4] chore: `conflicts` --- .../purchase_receipt/test_purchase_receipt.py | 115 +----------------- 1 file changed, 2 insertions(+), 113 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 8539aae8560..91755e61697 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -1707,117 +1707,6 @@ class TestPurchaseReceipt(FrappeTestCase): self.assertTrue(return_pi.docstatus == 1) -<<<<<<< HEAD -======= - def test_disable_last_purchase_rate(self): - from erpnext.stock.get_item_details import get_item_details - - item = make_item( - "_Test Disable Last Purchase Rate", - {"is_purchase_item": 1, "is_stock_item": 1}, - ) - - frappe.db.set_single_value("Buying Settings", "disable_last_purchase_rate", 1) - - pr = make_purchase_receipt( - qty=1, - rate=100, - item_code=item.name, - ) - - args = pr.items[0].as_dict() - args.update( - { - "supplier": pr.supplier, - "doctype": pr.doctype, - "conversion_rate": pr.conversion_rate, - "currency": pr.currency, - "company": pr.company, - "posting_date": pr.posting_date, - "posting_time": pr.posting_time, - } - ) - - res = get_item_details(args) - self.assertEqual(res.get("last_purchase_rate"), 0) - - frappe.db.set_single_value("Buying Settings", "disable_last_purchase_rate", 0) - - pr = make_purchase_receipt( - qty=1, - rate=100, - item_code=item.name, - ) - - res = get_item_details(args) - self.assertEqual(res.get("last_purchase_rate"), 100) - - def test_validate_received_qty_for_internal_pr(self): - prepare_data_for_internal_transfer() - customer = "_Test Internal Customer 2" - company = "_Test Company with perpetual inventory" - from_warehouse = create_warehouse("_Test Internal From Warehouse New", company=company) - target_warehouse = create_warehouse("_Test Internal GIT Warehouse New", company=company) - to_warehouse = create_warehouse("_Test Internal To Warehouse New", company=company) - - # Step 1: Create Item - item = make_item(properties={"is_stock_item": 1, "valuation_rate": 100}) - - # Step 2: Create Stock Entry (Material Receipt) - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - - make_stock_entry( - purpose="Material Receipt", - item_code=item.name, - qty=15, - company=company, - to_warehouse=from_warehouse, - ) - - # Step 3: Create Delivery Note with Internal Customer - from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note - - dn = create_delivery_note( - item_code=item.name, - company=company, - customer=customer, - cost_center="Main - TCP1", - expense_account="Cost of Goods Sold - TCP1", - qty=10, - rate=100, - warehouse=from_warehouse, - target_warehouse=target_warehouse, - ) - - # Step 4: Create Internal Purchase Receipt - from erpnext.controllers.status_updater import OverAllowanceError - from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt - - pr = make_inter_company_purchase_receipt(dn.name) - pr.items[0].qty = 15 - pr.items[0].from_warehouse = target_warehouse - pr.items[0].warehouse = to_warehouse - pr.items[0].rejected_warehouse = from_warehouse - pr.save() - - self.assertRaises(OverAllowanceError, pr.submit) - - # Step 5: Test Over Receipt Allowance - frappe.db.set_single_value("Stock Settings", "over_delivery_receipt_allowance", 50) - - make_stock_entry( - purpose="Material Transfer", - item_code=item.name, - qty=5, - company=company, - from_warehouse=from_warehouse, - to_warehouse=target_warehouse, - ) - - pr.submit() - - frappe.db.set_single_value("Stock Settings", "over_delivery_receipt_allowance", 0) - def test_internal_pr_gl_entries(self): from erpnext.stock import get_warehouse_account_map from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt @@ -1869,12 +1758,13 @@ class TestPurchaseReceipt(FrappeTestCase): # Step - 3: Create back-date Stock Reconciliation [After DN and Before PR] create_stock_reconciliation( - item_code=item, + item_code=item.name, warehouse=target_warehouse, qty=10, rate=50, company=company, posting_date=add_days(today(), -1), + expense_account="Stock Adjustment - TCP1", ) warehouse_account = get_warehouse_account_map(company) @@ -1901,7 +1791,6 @@ class TestPurchaseReceipt(FrappeTestCase): # Value of Stock Account should be equal to the sum of Stock Value Difference self.assertEqual(stock_account_value, stock_diff) ->>>>>>> c86c543fbf (test: add test case for internal PR GL Entries) def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier