From f4dc9ee2aa57d82a0be747a89e1ca573940da959 Mon Sep 17 00:00:00 2001 From: Marica Date: Thu, 26 Aug 2021 13:12:51 +0530 Subject: [PATCH] fix: Don't create inward SLE against SI unless is internal customer enabled (#27086) * fix: Dont create inward SLE against SI unless is internal customer enabled - Check if is internal customer enabled apart from target warehouse - Test to check if inward SLE is made if target warehouse is accidentally set but customer is not internal * test: Use internal customer for delivery of bundle items to target warehouse - created `create_internal_customer` util - reused it in delivery note and sales invoice tests - use internal customer for target warehouse test in delivery note --- .../sales_invoice/test_sales_invoice.py | 56 +++++++++++++------ erpnext/controllers/selling_controller.py | 2 +- .../selling/doctype/customer/test_customer.py | 25 +++++++++ .../delivery_note/test_delivery_note.py | 25 +++++++-- 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 5a19426eb0..43a5f5e2f6 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -151,7 +151,7 @@ class TestSalesInvoice(unittest.TestCase): si1 = create_sales_invoice(rate=1000) si2 = create_sales_invoice(rate=300) si3 = create_sales_invoice(qty=-1, rate=300, is_return=1) - + pe = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Bank - _TC") pe.append('references', { @@ -1828,23 +1828,12 @@ class TestSalesInvoice(unittest.TestCase): acc_settings.save() def test_inter_company_transaction(self): + from erpnext.selling.doctype.customer.test_customer import create_internal_customer - if not frappe.db.exists("Customer", "_Test Internal Customer"): - customer = frappe.get_doc({ - "customer_group": "_Test Customer Group", - "customer_name": "_Test Internal Customer", - "customer_type": "Individual", - "doctype": "Customer", - "territory": "_Test Territory", - "is_internal_customer": 1, - "represents_company": "_Test Company 1" - }) - - customer.append("companies", { - "company": "Wind Power LLC" - }) - - customer.insert() + create_internal_customer( + customer_name="_Test Internal Customer", + represents_company="_Test Company 1" + ) if not frappe.db.exists("Supplier", "_Test Internal Supplier"): supplier = frappe.get_doc({ @@ -1970,6 +1959,39 @@ class TestSalesInvoice(unittest.TestCase): frappe.local.enable_perpetual_inventory['_Test Company 1'] = old_perpetual_inventory frappe.db.set_value("Stock Settings", None, "allow_negative_stock", old_negative_stock) + def test_sle_if_target_warehouse_exists_accidentally(self): + """ + Check if inward entry exists if Target Warehouse accidentally exists + but Customer is not an internal customer. + """ + se = make_stock_entry( + item_code="138-CMS Shoe", + target="Finished Goods - _TC", + company = "_Test Company", + qty=1, + basic_rate=500 + ) + + si = frappe.copy_doc(test_records[0]) + si.update_stock = 1 + si.set_warehouse = "Finished Goods - _TC" + si.set_target_warehouse = "Stores - _TC" + si.get("items")[0].warehouse = "Finished Goods - _TC" + si.get("items")[0].target_warehouse = "Stores - _TC" + si.insert() + si.submit() + + sles = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": si.name}, + fields=["name", "actual_qty"]) + + # check if only one SLE for outward entry is created + self.assertEqual(len(sles), 1) + self.assertEqual(sles[0].actual_qty, -1) + + # tear down + si.cancel() + se.cancel() + def test_internal_transfer_gl_entry(self): ## Create internal transfer account account = create_account(account_name="Unrealized Profit", diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 4ea0e114b4..844c40c8a6 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -423,7 +423,7 @@ class SellingController(StockController): or (cint(self.is_return) and self.docstatus==2)): sl_entries.append(self.get_sle_for_source_warehouse(d)) - if d.target_warehouse: + if d.target_warehouse and self.get("is_internal_customer"): sl_entries.append(self.get_sle_for_target_warehouse(d)) if d.warehouse and ((not cint(self.is_return) and self.docstatus==2) diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index b1a5b52f96..908ba270b0 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -352,3 +352,28 @@ def set_credit_limit(customer, company, credit_limit): 'credit_limit': credit_limit }) customer.credit_limits[-1].db_insert() + +def create_internal_customer(**args): + args = frappe._dict(args) + + customer_name = args.get("customer_name") or "_Test Internal Customer" + + if not frappe.db.exists("Customer", customer_name): + customer = frappe.get_doc({ + "doctype": "Customer", + "customer_group": args.customer_group or "_Test Customer Group", + "customer_name": customer_name, + "customer_type": args.customer_type or "Individual", + "territory": args.territory or "_Test Territory", + "is_internal_customer": 1, + "represents_company": args.represents_company or "_Test Company with perpetual inventory" + }) + + customer.append("companies", { + "company": args.allowed_company or "Wind Power LLC" + }) + customer.insert() + + return customer + else: + return frappe.get_cached_doc("Customer", customer_name) \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 91e7c006ee..dffc73020d 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -430,12 +430,18 @@ class TestDeliveryNote(unittest.TestCase): }) def test_delivery_of_bundled_items_to_target_warehouse(self): + from erpnext.selling.doctype.customer.test_customer import create_internal_customer + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') + customer = create_internal_customer( + customer_name="_Test Internal Customer 2", + allowed_company="_Test Company with perpetual inventory" + ) set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") - target_warehouse=get_warehouse(company=company, abbr="TCP1", + target_warehouse = get_warehouse(company=company, abbr="TCP1", warehouse_name="_Test Customer Warehouse").name for warehouse in ("Stores - TCP1", target_warehouse): @@ -444,10 +450,16 @@ class TestDeliveryNote(unittest.TestCase): create_stock_reconciliation(item_code="_Test Item Home Desktop 100", company = company, expense_account = "Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100) - dn = create_delivery_note(item_code="_Test Product Bundle Item", - company='_Test Company with perpetual inventory', cost_center = 'Main - TCP1', - expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, qty=5, rate=500, - warehouse="Stores - TCP1", target_warehouse=target_warehouse) + dn = create_delivery_note( + item_code="_Test Product Bundle Item", + company="_Test Company with perpetual inventory", + customer=customer.name, + cost_center = 'Main - TCP1', + expense_account = "Cost of Goods Sold - TCP1", + do_not_submit=True, + qty=5, rate=500, + warehouse="Stores - TCP1", + target_warehouse=target_warehouse) dn.submit() @@ -487,6 +499,9 @@ class TestDeliveryNote(unittest.TestCase): for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) + # tear down + frappe.db.rollback() + def test_closed_delivery_note(self): from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status