diff --git a/default_thai_company/patches.txt b/default_thai_company/patches.txt index f15c3a9..4c363e9 100644 --- a/default_thai_company/patches.txt +++ b/default_thai_company/patches.txt @@ -3,4 +3,5 @@ # Read docs to understand patches: https://frappeframework.com/docs/v14/user/en/database-migrations [post_model_sync] -# Patches added in this section will be executed after doctypes are migrated \ No newline at end of file +# Patches added in this section will be executed after doctypes are migrated +default_thai_company.patches.create_vat_accounts diff --git a/default_thai_company/patches/__init__.py b/default_thai_company/patches/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/default_thai_company/patches/create_vat_accounts.py b/default_thai_company/patches/create_vat_accounts.py new file mode 100644 index 0000000..acfc89c --- /dev/null +++ b/default_thai_company/patches/create_vat_accounts.py @@ -0,0 +1,8 @@ +from default_thai_company.tax_withholding import ensure_company_accounts, thai_companies + + +def execute(): + """Output VAT / Input VAT were added to COMPANY_ACCOUNTS; Company.on_update + only runs on save, so give existing Thai companies the pair.""" + for company in thai_companies(): + ensure_company_accounts(company) diff --git a/default_thai_company/tax_withholding.py b/default_thai_company/tax_withholding.py index a287e49..83155e8 100644 --- a/default_thai_company/tax_withholding.py +++ b/default_thai_company/tax_withholding.py @@ -12,10 +12,23 @@ from frappe.utils import cint, flt from default_thai_company.utils import money_in_words -# Liability: tax we withhold from suppliers and remit on P.N.D.3/53 (linked on every category). -# Asset: tax customers withhold from us, creditable against corporate income tax. +# Tax accounts every Thai company gets (Company.on_update, fixture import, and the +# create_vat_accounts patch for companies that predate the VAT pair). +# Withholding: liability = tax we withhold from suppliers, remitted on P.N.D.3/53 +# (linked on every category); asset = tax customers withhold from us, creditable +# against corporate income tax. +# VAT: output (ภาษีขาย) collected on sales is payable, input (ภาษีซื้อ) paid on +# purchases is recoverable; the P.P.30 return nets the two, so they are kept apart. LIABILITY_ACCOUNT = "Withholding Tax Payable" ASSET_ACCOUNT = "Withholding Tax Receivable" +OUTPUT_VAT_ACCOUNT = "Output VAT" +INPUT_VAT_ACCOUNT = "Input VAT" +COMPANY_ACCOUNTS = ( + (LIABILITY_ACCOUNT, "Liability"), + (ASSET_ACCOUNT, "Asset"), + (OUTPUT_VAT_ACCOUNT, "Liability"), + (INPUT_VAT_ACCOUNT, "Asset"), +) # Preferred parent groups by root type; first match wins, else the root account. PARENT_GROUPS = { @@ -67,9 +80,10 @@ def find_parent_group(company, root_type): def ensure_company_accounts(company): - """Create both withholding accounts for `company`; return the liability account name.""" - get_or_create_account(company, ASSET_ACCOUNT, "Asset") - return get_or_create_account(company, LIABILITY_ACCOUNT, "Liability") + """Create every account in COMPANY_ACCOUNTS for `company`; return the + withholding liability account name (the one Tax Withholding Categories link).""" + accounts = {name: get_or_create_account(company, name, root_type) for name, root_type in COMPANY_ACCOUNTS} + return accounts[LIABILITY_ACCOUNT] def link_company(category, company, account): @@ -105,7 +119,7 @@ def prepare_fixture_accounts(doc, method=None): def setup_company(doc, method=None): - """Company.on_update: create withholding accounts and link every WHT category.""" + """Company.on_update: create the tax accounts and link every WHT category.""" if doc.country != "Thailand" or not frappe.db.exists("Account", {"company": doc.name}): return diff --git a/default_thai_company/tests/test_tax_withholding.py b/default_thai_company/tests/test_tax_withholding.py index f9ad2dc..b7e442e 100644 --- a/default_thai_company/tests/test_tax_withholding.py +++ b/default_thai_company/tests/test_tax_withholding.py @@ -8,7 +8,9 @@ from frappe.utils import nowdate from default_thai_company.tax_withholding import ( ASSET_ACCOUNT, + INPUT_VAT_ACCOUNT, LIABILITY_ACCOUNT, + OUTPUT_VAT_ACCOUNT, get_payment_entry, thai_companies, ) @@ -44,16 +46,7 @@ class TestTaxWithholding(FrappeTestCase): ).insert() cls.payable = f"{LIABILITY_ACCOUNT} - {ABBR}" cls.receivable = f"{ASSET_ACCOUNT} - {ABBR}" - - cls.vat = frappe.get_doc( - { - "doctype": "Account", - "company": COMPANY, - "account_name": "Output VAT", - "parent_account": f"Duties and Taxes - {ABBR}", - "account_type": "Tax", - } - ).insert() + cls.vat = frappe.get_doc("Account", f"{OUTPUT_VAT_ACCOUNT} - {ABBR}") frappe.get_doc( { @@ -137,14 +130,17 @@ class TestTaxWithholding(FrappeTestCase): def test_company_creation_adds_accounts_and_links_categories(self): self.assertIn(COMPANY, thai_companies()) - self.assertEqual( - frappe.db.get_value("Account", self.payable, ["root_type", "parent_account"]), - ("Liability", f"Duties and Taxes - {ABBR}"), - ) - self.assertEqual( - frappe.db.get_value("Account", self.receivable, ["root_type", "parent_account"]), - ("Asset", f"Tax Assets - {ABBR}"), - ) + for account, expected in ( + (self.payable, ("Liability", f"Duties and Taxes - {ABBR}", "Tax")), + (self.receivable, ("Asset", f"Tax Assets - {ABBR}", "Tax")), + (f"{OUTPUT_VAT_ACCOUNT} - {ABBR}", ("Liability", f"Duties and Taxes - {ABBR}", "Tax")), + (f"{INPUT_VAT_ACCOUNT} - {ABBR}", ("Asset", f"Tax Assets - {ABBR}", "Tax")), + ): + self.assertEqual( + frappe.db.get_value("Account", account, ["root_type", "parent_account", "account_type"]), + expected, + account, + ) categories = frappe.get_all( "Tax Withholding Category", filters={"name": ("like", "WHT %")}, pluck="name" diff --git a/default_thai_company/translations/th.csv b/default_thai_company/translations/th.csv index a50b695..9ec2920 100644 --- a/default_thai_company/translations/th.csv +++ b/default_thai_company/translations/th.csv @@ -53,3 +53,7 @@ Grand Total,ยอดรวมทั้งสิ้น Rounded Total,ยอดรวมปัดเศษ Terms and Conditions Details,รายละเอียดข้อตกลงและเงื่อนไข Page {0} of {1},หน้า {0} จาก {1} +Withholding Tax Payable,ภาษีหัก ณ ที่จ่ายค้างจ่าย +Withholding Tax Receivable,ภาษีถูกหัก ณ ที่จ่าย +Output VAT,ภาษีขาย +Input VAT,ภาษีซื้อ