feat: an account on every Salary Component for every Thai company
Payroll Entry refuses to post a component without an account for its company. Link every Thai company on every Salary Component: on Salary Component.validate (covers the components HRMS seeds with the first company and the ones users add) and on Company.on_update, with the install hooks, the daily scheduler and a patch for existing sites. Earnings expense to "Salary" (Standard chart, Indirect Expenses). The income tax component is tax withheld from employees, remitted on P.N.D.1; Thai books carry it as ภาษีหัก ณ ที่จ่ายค้างจ่าย, split by return form when split at all, so it gets "Withholding Tax Payable (P.N.D.1)" beside the P.N.D.3/53 account the Tax Withholding Categories post to. Other deductions are held in "Salary Deductions" (Current Liabilities) until remitted. Statistical components never post and get none.
This commit is contained in:
1 parent
c8fb983749
commit
035ab2fc7f
5 files changed
+71
-7
No files matched your search
@@ -236,6 +236,10 @@ doc_events = {
|
||||
"default_thai_company.payroll.setup_company",
|
||||
],
|
||||
},
|
||||
# HRMS doctype; the hook only fires on sites that have it.
|
||||
"Salary Component": {
|
||||
"validate": "default_thai_company.payroll.set_component_accounts",
|
||||
},
|
||||
"Payment Entry": {
|
||||
"validate": "default_thai_company.tax_withholding.set_customer_withholding",
|
||||
},
|
||||
|
||||
@@ -8,3 +8,4 @@ default_thai_company.patches.create_vat_accounts
|
||||
default_thai_company.patches.create_vat_templates
|
||||
default_thai_company.patches.create_shipping_rules
|
||||
default_thai_company.patches.create_payroll_periods
|
||||
default_thai_company.patches.setup_salary_components
|
||||
@@ -0,0 +1,5 @@
|
||||
from default_thai_company.payroll import setup_companies
|
||||
|
||||
|
||||
def execute():
|
||||
setup_companies()
|
||||
@@ -1,18 +1,67 @@
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
|
||||
from default_thai_company.tax_withholding import thai_companies
|
||||
from default_thai_company.tax_withholding import get_or_create_account, thai_companies
|
||||
|
||||
# Thai personal income tax (P.N.D.1/91) is assessed per calendar year whatever
|
||||
# the company's fiscal year, so the Payroll Period is January to December.
|
||||
# Payroll Period is named by prompt (site-wide unique) but bound to one company,
|
||||
# so each Thai company gets "<year> - <abbr>", like the Shipping Rule.
|
||||
#
|
||||
# Payroll Entry refuses to post a component without an account for its company,
|
||||
# so every Salary Component gets one for every Thai company (Salary
|
||||
# Component.validate for the components HRMS seeds with the first company and
|
||||
# the ones users add; Company.on_update for companies added later).
|
||||
# Earnings expense to "Salary" (Standard chart, Indirect Expenses). The income
|
||||
# tax component is tax withheld from employees, remitted on P.N.D.1; Thai books
|
||||
# carry it as ภาษีหัก ณ ที่จ่ายค้างจ่าย, split by return form when split at all,
|
||||
# so it gets its own withholding account beside the P.N.D.3/53 one the Tax
|
||||
# Withholding Categories post to. Other deductions (social security, loans)
|
||||
# are held in "Salary Deductions" (Current Liabilities) until remitted.
|
||||
EARNING_ACCOUNT = "Salary"
|
||||
EARNING_ACCOUNT_GROUPS = ("Indirect Expenses", "Expenses")
|
||||
INCOME_TAX_ACCOUNT = "Withholding Tax Payable (P.N.D.1)"
|
||||
DEDUCTION_ACCOUNT = "Salary Deductions"
|
||||
DEDUCTION_ACCOUNT_GROUPS = ("Current Liabilities",)
|
||||
|
||||
|
||||
|
||||
def hrms_installed():
|
||||
return "hrms" in frappe.get_installed_apps()
|
||||
|
||||
|
||||
def salary_component_account(company, component):
|
||||
if component.type == "Earning":
|
||||
return get_or_create_account(company, EARNING_ACCOUNT, "Expense", "", EARNING_ACCOUNT_GROUPS)
|
||||
if component.is_income_tax_component:
|
||||
return get_or_create_account(company, INCOME_TAX_ACCOUNT, "Liability")
|
||||
return get_or_create_account(company, DEDUCTION_ACCOUNT, "Liability", "", DEDUCTION_ACCOUNT_GROUPS)
|
||||
|
||||
|
||||
def link_company(component, company):
|
||||
"""Append the company's account row to the component if missing. Statistical
|
||||
components never post, so they get none."""
|
||||
if component.statistical_component or any(row.company == company for row in component.accounts):
|
||||
return False
|
||||
component.append(
|
||||
"accounts", {"company": company, "account": salary_component_account(company, component)}
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def set_component_accounts(doc, method=None):
|
||||
"""Salary Component.validate: an account for every Thai company."""
|
||||
for company in thai_companies():
|
||||
link_company(doc, company)
|
||||
|
||||
|
||||
def ensure_component_accounts(company):
|
||||
for name in frappe.get_all("Salary Component", pluck="name"):
|
||||
component = frappe.get_doc("Salary Component", name)
|
||||
if link_company(component, company):
|
||||
component.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def payroll_period_name(company, year):
|
||||
abbr = frappe.get_cached_value("Company", company, "abbr")
|
||||
return f"{year} - {abbr}"
|
||||
@@ -39,24 +88,27 @@ def ensure_payroll_period(company, year):
|
||||
|
||||
|
||||
def setup_company(doc, method=None):
|
||||
"""Company.on_update: this year's Payroll Period for a Thai company."""
|
||||
"""Company.on_update: this year's Payroll Period and the Salary Component
|
||||
accounts for a Thai company."""
|
||||
if doc.country == "Thailand" and hrms_installed():
|
||||
ensure_payroll_period(doc.name, getdate().year)
|
||||
ensure_component_accounts(doc.name)
|
||||
|
||||
|
||||
def setup_companies():
|
||||
"""after_install, the daily scheduler, and the create_payroll_periods patch:
|
||||
this year's Payroll Period for every Thai company. The scheduler rolls the
|
||||
default over on 1 January."""
|
||||
"""after_install, the daily scheduler, and the setup_salary_components
|
||||
patch: this year's Payroll Period and the Salary Component accounts for
|
||||
every Thai company. The scheduler rolls the Payroll Period over on 1 January."""
|
||||
if not hrms_installed():
|
||||
return
|
||||
year = getdate().year
|
||||
for company in thai_companies():
|
||||
ensure_payroll_period(company, year)
|
||||
ensure_component_accounts(company)
|
||||
|
||||
|
||||
def after_app_install(app_name):
|
||||
"""Payroll Period only exists once hrms is installed; catch companies that
|
||||
were created before it."""
|
||||
"""Payroll Period and Salary Component accounts only exist once hrms is
|
||||
installed; catch companies that were created before it."""
|
||||
if app_name == "hrms":
|
||||
setup_companies()
|
||||
@@ -74,6 +74,8 @@ Rounded Total,ยอดรวมปัดเศษ
|
||||
Terms and Conditions Details,รายละเอียดข้อตกลงและเงื่อนไข
|
||||
Page {0} of {1},หน้า {0} จาก {1}
|
||||
Withholding Tax Payable,ภาษีหัก ณ ที่จ่ายค้างจ่าย
|
||||
Withholding Tax Payable (P.N.D.1),ภาษีหัก ณ ที่จ่ายค้างจ่าย (ภ.ง.ด.1)
|
||||
Salary Deductions,รายการหักจากเงินเดือน
|
||||
Withholding Tax Receivable,ภาษีถูกหัก ณ ที่จ่าย
|
||||
Output VAT,ภาษีขาย
|
||||
Input VAT,ภาษีซื้อ
|
||||
|
||||
|
Reference in new issue
Block a user