diff --git a/default_thai_company/hooks.py b/default_thai_company/hooks.py index a647b72..3be319a 100644 --- a/default_thai_company/hooks.py +++ b/default_thai_company/hooks.py @@ -144,6 +144,7 @@ fixtures = [ after_install = [ "default_thai_company.vat.setup_companies", "default_thai_company.shipping.setup_companies", + "default_thai_company.payroll.setup_companies", ] # Fixture import re-inserts the Location tree; restore lft/rgt for user-added nodes. after_migrate = "default_thai_company.assets.rebuild_locations" @@ -160,7 +161,8 @@ after_migrate = "default_thai_company.assets.rebuild_locations" # Name of the app being installed is passed as an argument # before_app_install = "default_thai_company.utils.before_app_install" -# after_app_install = "default_thai_company.utils.after_app_install" +# Payroll Period for companies created before hrms was installed. +after_app_install = "default_thai_company.payroll.after_app_install" # Integration Cleanup # ------------------- @@ -219,6 +221,7 @@ doc_events = { "default_thai_company.vat.setup_company", "default_thai_company.assets.setup_company", "default_thai_company.shipping.setup_company", + "default_thai_company.payroll.setup_company", ], }, "Payment Entry": { @@ -229,23 +232,10 @@ doc_events = { # Scheduled Tasks # --------------- -# scheduler_events = { -# "all": [ -# "default_thai_company.tasks.all" -# ], -# "daily": [ -# "default_thai_company.tasks.daily" -# ], -# "hourly": [ -# "default_thai_company.tasks.hourly" -# ], -# "weekly": [ -# "default_thai_company.tasks.weekly" -# ], -# "monthly": [ -# "default_thai_company.tasks.monthly" -# ], -# } +# Payroll Period is per calendar year; roll the default over on 1 January. +scheduler_events = { + "daily": ["default_thai_company.payroll.setup_companies"], +} # Testing # ------- diff --git a/default_thai_company/patches.txt b/default_thai_company/patches.txt index e1ea1ce..5ebeec5 100644 --- a/default_thai_company/patches.txt +++ b/default_thai_company/patches.txt @@ -7,3 +7,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 diff --git a/default_thai_company/patches/create_payroll_periods.py b/default_thai_company/patches/create_payroll_periods.py new file mode 100644 index 0000000..873a011 --- /dev/null +++ b/default_thai_company/patches/create_payroll_periods.py @@ -0,0 +1,5 @@ +from default_thai_company.payroll import setup_companies + + +def execute(): + setup_companies() diff --git a/default_thai_company/payroll.py b/default_thai_company/payroll.py new file mode 100644 index 0000000..e9422fa --- /dev/null +++ b/default_thai_company/payroll.py @@ -0,0 +1,62 @@ +import frappe +from frappe.utils import getdate + +from default_thai_company.tax_withholding import 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 " - ", like the Shipping Rule. + + +def hrms_installed(): + return "hrms" in frappe.get_installed_apps() + + +def payroll_period_name(company, year): + abbr = frappe.get_cached_value("Company", company, "abbr") + return f"{year} - {abbr}" + + +def ensure_payroll_period(company, year): + """Calendar-year Payroll Period for `company`. No-op when any period of the + company touches the year: an existing one covers it, or the company runs its + own scheme and a second period would only fail the overlap check.""" + start, end = f"{year}-01-01", f"{year}-12-31" + if frappe.db.exists( + "Payroll Period", {"company": company, "start_date": ("<=", end), "end_date": (">=", start)} + ): + return + frappe.get_doc( + { + "doctype": "Payroll Period", + "name": payroll_period_name(company, year), + "company": company, + "start_date": start, + "end_date": end, + } + ).insert(ignore_permissions=True) + + +def setup_company(doc, method=None): + """Company.on_update: this year's Payroll Period for a Thai company.""" + if doc.country == "Thailand" and hrms_installed(): + ensure_payroll_period(doc.name, getdate().year) + + +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.""" + if not hrms_installed(): + return + year = getdate().year + for company in thai_companies(): + ensure_payroll_period(company, year) + + +def after_app_install(app_name): + """Payroll Period only exists once hrms is installed; catch companies that + were created before it.""" + if app_name == "hrms": + setup_companies()