From 8cba58ba02e0b2313d848a4755717bbb21fd1218 Mon Sep 17 00:00:00 2001 From: kurogeek Date: Thu, 17 Sep 2026 10:02:23 +0000 Subject: [PATCH] feat: default Shipping Rule per Thai company "Shipping Charges - ": Selling, Fixed, posting to a "Shipping Charges" income account under Direct Income (created if the chart lacks it) with the default cost center. Shipping Rule is named by its label, so the company abbreviation keeps one rule per company, as ERPNext names its tax templates. Created on Company save, after install, and by a patch for existing companies. The amount is entered on the transaction, not the rule: ERPNext re-applies the rule on every recalculation and would reset the charge row to the rule's fixed amount. ThaiShippingRule overrides the doctype class so a Fixed rule with no amount only seeds the row and leaves the entered amount alone. --- default_thai_company/hooks.py | 10 ++- default_thai_company/patches.txt | 1 + .../patches/create_shipping_rules.py | 5 ++ default_thai_company/shipping.py | 66 +++++++++++++++++++ .../tests/test_tax_withholding.py | 33 ++++++++++ 5 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 default_thai_company/patches/create_shipping_rules.py create mode 100644 default_thai_company/shipping.py diff --git a/default_thai_company/hooks.py b/default_thai_company/hooks.py index fb3b862..a647b72 100644 --- a/default_thai_company/hooks.py +++ b/default_thai_company/hooks.py @@ -139,8 +139,12 @@ fixtures = [ # ------------ # before_install = "default_thai_company.install.before_install" -# Fixtures are synced before this runs; VAT schemes for companies that already exist. -after_install = "default_thai_company.vat.setup_companies" +# Fixtures are synced before this runs; VAT schemes and Shipping Rules for companies +# that already exist. +after_install = [ + "default_thai_company.vat.setup_companies", + "default_thai_company.shipping.setup_companies", +] # Fixture import re-inserts the Location tree; restore lft/rgt for user-added nodes. after_migrate = "default_thai_company.assets.rebuild_locations" @@ -191,6 +195,7 @@ after_migrate = "default_thai_company.assets.rebuild_locations" override_doctype_class = { "Sales Invoice": "default_thai_company.tax_withholding.ThaiSalesInvoice", "Payment Entry": "default_thai_company.tax_withholding.ThaiPaymentEntry", + "Shipping Rule": "default_thai_company.shipping.ThaiShippingRule", } # Document Events @@ -213,6 +218,7 @@ doc_events = { "default_thai_company.tax_withholding.setup_company", "default_thai_company.vat.setup_company", "default_thai_company.assets.setup_company", + "default_thai_company.shipping.setup_company", ], }, "Payment Entry": { diff --git a/default_thai_company/patches.txt b/default_thai_company/patches.txt index e8da871..e1ea1ce 100644 --- a/default_thai_company/patches.txt +++ b/default_thai_company/patches.txt @@ -6,3 +6,4 @@ # Patches added in this section will be executed after doctypes are migrated default_thai_company.patches.create_vat_accounts default_thai_company.patches.create_vat_templates +default_thai_company.patches.create_shipping_rules diff --git a/default_thai_company/patches/create_shipping_rules.py b/default_thai_company/patches/create_shipping_rules.py new file mode 100644 index 0000000..aa7a05c --- /dev/null +++ b/default_thai_company/patches/create_shipping_rules.py @@ -0,0 +1,5 @@ +from default_thai_company.shipping import setup_companies + + +def execute(): + setup_companies() diff --git a/default_thai_company/shipping.py b/default_thai_company/shipping.py new file mode 100644 index 0000000..212d2d0 --- /dev/null +++ b/default_thai_company/shipping.py @@ -0,0 +1,66 @@ +import erpnext +import frappe +from erpnext.accounts.doctype.shipping_rule.shipping_rule import ShippingRule + +from default_thai_company.tax_withholding import company_ready, get_or_create_account, thai_companies + +# Shipping Rule is named by its label (site-wide unique) but bound to one company, +# so each Thai company gets "