From 2ec119e561cdfdb9f0d1f987348fa62171697992 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Thu, 11 Dec 2025 12:57:08 +0530 Subject: [PATCH 1/2] fix(accounts): handle drop ship in company linked address validation --- erpnext/controllers/accounts_controller.py | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 58c0b8a5dd1..cc4d6592da2 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -315,13 +315,30 @@ class AccountsController(TransactionBase): def validate_company_linked_addresses(self): address_fields = [] - if self.doctype in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice"): + sales_doctypes = ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice") + purchase_doctypes = ("Purchase Order", "Purchase Receipt", "Purchase Invoice", "Supplier Quotation") + + if self.doctype in sales_doctypes: address_fields = ["dispatch_address_name", "company_address"] - elif self.doctype in ("Purchase Order", "Purchase Receipt", "Purchase Invoice", "Supplier Quotation"): + elif self.doctype in purchase_doctypes: address_fields = ["billing_address", "shipping_address"] + if not address_fields: + return + + # Determine if drop ship applies + is_drop_ship = self.doctype in { + "Purchase Order", + "Sales Order", + "Sales Invoice", + } and self.is_drop_ship(self.items) + for field in address_fields: address = self.get(field) + + if (field in ["dispatch_address_name", "shipping_address"]) and is_drop_ship: + continue + if address and not frappe.db.exists( "Dynamic Link", { @@ -332,11 +349,15 @@ class AccountsController(TransactionBase): }, ): frappe.throw( - _("{0} does not belong to the {1}.").format( + _("{0} does not belong to the Company {1}.").format( _(self.meta.get_label(field)), bold(self.company) ) ) + @staticmethod + def is_drop_ship(items): + return any(item.delivered_by_supplier for item in items) + def set_default_letter_head(self): if hasattr(self, "letter_head") and not self.letter_head: self.letter_head = frappe.db.get_value("Company", self.company, "default_letter_head") From f6a96e5563340236c5672e9b11c38c105f410630 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Thu, 11 Dec 2025 13:01:53 +0530 Subject: [PATCH 2/2] test(accounts): add validation test for dispatch address with drop ship enabled --- .../controllers/tests/test_accounts_controller.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 08ffa636329..44e3d6a7bf4 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -2438,6 +2438,7 @@ class TestAccountsController(IntegrationTestCase): def test_company_linked_address(self): from erpnext.crm.doctype.prospect.test_prospect import make_address + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order company_address = make_address( address_title="Company", address_type="Shipping", address_line1="100", city="Mumbai" @@ -2466,3 +2467,16 @@ class TestAccountsController(IntegrationTestCase): po.billing_address = company_address.name po.reload() po.save() + + si = make_sales_order(do_not_save=1, do_not_submit=1) + si.dispatch_address_name = supplier_billing.name + self.assertRaises(frappe.ValidationError, si.save) + si.items[0].delivered_by_supplier = 1 + si.items[0].supplier = "_Test Supplier" + si.save() + + po = create_purchase_order(do_not_save=True) + po.shipping_address = customer_shipping.name + self.assertRaises(frappe.ValidationError, po.save) + po.items[0].delivered_by_supplier = 1 + po.save()