From b901cfdbe25e53b80f53391560a58e6acfdc104c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 11 Aug 2023 09:50:43 +0530 Subject: [PATCH 1/3] fix: disallow mulitple SO with same PO No (cherry picked from commit dbd3fdbb415e032d738c0055288c41a12e4cd9b4) --- .../doctype/sales_order/sales_order.py | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index da838d1b7952..485ac60e7440 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -95,18 +95,26 @@ def validate_po(self): and customer = %s", (self.po_no, self.name, self.customer), ) - if ( - so - and so[0][0] - and not cint( + if so and so[0][0]: + if cint( frappe.db.get_single_value("Selling Settings", "allow_against_multiple_purchase_orders") - ) - ): - frappe.msgprint( - _("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format( - so[0][0], self.po_no + ): + frappe.msgprint( + _("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format( + frappe.bold(so[0][0]), frappe.bold(self.po_no) + ) + ) + else: + frappe.throw( + _( + "Sales Order {0} already exists against Customer's Purchase Order {1}. To allow multiple Sales Orders, Enable {2} in {3}" + ).format( + frappe.bold(so[0][0]), + frappe.bold(self.po_no), + frappe.bold(_("'Allow Multiple Sales Orders Against a Customer's Purchase Order'")), + get_link_to_form("Selling Settings", "Selling Settings"), + ) ) - ) def validate_for_items(self): for d in self.get("items"): From c83f10f63823f1b0fc33e04d5d014ba565a2e0e5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 11 Aug 2023 10:45:42 +0530 Subject: [PATCH 2/3] refactor(test): don't set po_no by default (cherry picked from commit 64614cd9152c54fe8a0b59416a0621f9992d41d4) # Conflicts: # erpnext/stock/doctype/delivery_note/test_delivery_note.py --- .../doctype/sales_order/test_sales_order.py | 2 +- .../delivery_note/test_delivery_note.py | 59 +++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index ced1ac62729a..608e23a82680 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -2023,7 +2023,7 @@ def make_sales_order(**args): so.company = args.company or "_Test Company" so.customer = args.customer or "_Test Customer" so.currency = args.currency or "INR" - so.po_no = args.po_no or "12345" + so.po_no = args.po_no or "" if args.selling_price_list: so.selling_price_list = args.selling_price_list diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 5d8efd5d9dc7..4b41692d90cc 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -728,7 +728,7 @@ def test_closed_delivery_note(self): def test_dn_billing_status_case1(self): # SO -> DN -> SI - so = make_sales_order() + so = make_sales_order(po_no="12345") dn = create_dn_against_so(so.name, delivered_qty=2) self.assertEqual(dn.status, "To Bill") @@ -755,7 +755,7 @@ def test_dn_billing_status_case2(self): make_sales_invoice, ) - so = make_sales_order() + so = make_sales_order(po_no="12345") si = make_sales_invoice(so.name) si.get("items")[0].qty = 5 @@ -799,7 +799,7 @@ def test_dn_billing_status_case3(self): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - so = make_sales_order() + so = make_sales_order(po_no="12345") dn1 = make_delivery_note(so.name) dn1.get("items")[0].qty = 2 @@ -845,7 +845,7 @@ def test_dn_billing_status_case4(self): from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice - so = make_sales_order() + so = make_sales_order(po_no="12345") si = make_sales_invoice(so.name) si.submit() @@ -1211,6 +1211,57 @@ def test_batch_expiry_for_delivery_note(self): self.assertTrue(return_dn.docstatus == 1) +<<<<<<< HEAD +======= + def test_reserve_qty_on_sales_return(self): + frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0) + self.reserved_qty_check() + + def test_dont_reserve_qty_on_sales_return(self): + frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 1) + self.reserved_qty_check() + + def reserved_qty_check(self): + from erpnext.controllers.sales_and_purchase_return import make_return_doc + from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note + from erpnext.stock.stock_balance import get_reserved_qty + + dont_reserve_qty = frappe.db.get_single_value( + "Selling Settings", "dont_reserve_sales_order_qty_on_sales_return" + ) + + item = make_item().name + warehouse = "_Test Warehouse - _TC" + qty_to_reserve = 5 + + so = make_sales_order(item_code=item, qty=qty_to_reserve) + + # Make qty avl for test. + make_stock_entry(item_code=item, to_warehouse=warehouse, qty=10, basic_rate=100) + + # Test that item qty has been reserved on submit of sales order. + self.assertEqual(get_reserved_qty(item, warehouse), qty_to_reserve) + + dn = make_delivery_note(so.name) + dn.save().submit() + + # Test that item qty is no longer reserved since qty has been delivered. + self.assertEqual(get_reserved_qty(item, warehouse), 0) + + dn_return = make_return_doc("Delivery Note", dn.name) + dn_return.save().submit() + + returned = frappe.get_doc("Delivery Note", dn_return.name) + returned.update_prevdoc_status() + + # Test that item qty is not reserved on sales return, if selling setting don't reserve qty is checked. + self.assertEqual(get_reserved_qty(item, warehouse), 0 if dont_reserve_qty else qty_to_reserve) + + def tearDown(self): + frappe.db.rollback() + frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0) + +>>>>>>> 64614cd915 (refactor(test): don't set po_no by default) def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") From 21d3fb06250c587b7a2708a45243ea9ba678b65b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 13 Aug 2023 08:24:01 +0530 Subject: [PATCH 3/3] chore: resolve merge conflict --- .../delivery_note/test_delivery_note.py | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 4b41692d90cc..2565d1b76d19 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1211,57 +1211,10 @@ def test_batch_expiry_for_delivery_note(self): self.assertTrue(return_dn.docstatus == 1) -<<<<<<< HEAD -======= - def test_reserve_qty_on_sales_return(self): - frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0) - self.reserved_qty_check() - - def test_dont_reserve_qty_on_sales_return(self): - frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 1) - self.reserved_qty_check() - - def reserved_qty_check(self): - from erpnext.controllers.sales_and_purchase_return import make_return_doc - from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note - from erpnext.stock.stock_balance import get_reserved_qty - - dont_reserve_qty = frappe.db.get_single_value( - "Selling Settings", "dont_reserve_sales_order_qty_on_sales_return" - ) - - item = make_item().name - warehouse = "_Test Warehouse - _TC" - qty_to_reserve = 5 - - so = make_sales_order(item_code=item, qty=qty_to_reserve) - - # Make qty avl for test. - make_stock_entry(item_code=item, to_warehouse=warehouse, qty=10, basic_rate=100) - - # Test that item qty has been reserved on submit of sales order. - self.assertEqual(get_reserved_qty(item, warehouse), qty_to_reserve) - - dn = make_delivery_note(so.name) - dn.save().submit() - - # Test that item qty is no longer reserved since qty has been delivered. - self.assertEqual(get_reserved_qty(item, warehouse), 0) - - dn_return = make_return_doc("Delivery Note", dn.name) - dn_return.save().submit() - - returned = frappe.get_doc("Delivery Note", dn_return.name) - returned.update_prevdoc_status() - - # Test that item qty is not reserved on sales return, if selling setting don't reserve qty is checked. - self.assertEqual(get_reserved_qty(item, warehouse), 0 if dont_reserve_qty else qty_to_reserve) - def tearDown(self): frappe.db.rollback() frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0) ->>>>>>> 64614cd915 (refactor(test): don't set po_no by default) def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note")