feat(single-declaration): auto-fill elave4 deduction tables from payroll
Group salary slips by tax-free indicator over the quarter and populate vergi_, mdss_, issizlik, its child tables on il/rüb change. Convert the göstəricilər field in those four child doctypes from Select to a Link to Tax Free Indicator so values match what payroll already stores. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
02973690aa
commit
4ba9ea385f
|
|
@ -13,9 +13,10 @@
|
|||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r"
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "Tax Free Indicator"
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015f\u00e7il\u0259rinsay\u0131n\u0259f\u0259rl\u0259",
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r"
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "Tax Free Indicator"
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015f\u00e7il\u0259rinsay\u0131n\u0259f\u0259rl\u0259",
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r"
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "Tax Free Indicator"
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015f\u00e7il\u0259rinsay\u0131n\u0259f\u0259rl\u0259",
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r"
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "Tax Free Indicator"
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015f\u00e7il\u0259rinsay\u0131n\u0259f\u0259rl\u0259",
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ function reload_hisse_1_data(frm) {
|
|||
populate_child_table(frm, 'hissə_2', r.message.hisse_2_data || []);
|
||||
populate_child_table(frm, 'hissə_3', r.message.hisse_3_data || []);
|
||||
update_existing_rows(frm, 'bolme2_hisse1', r.message.bolme2_hisse1_data || {});
|
||||
populate_child_table(frm, 'vergi_', r.message.vergi_data || []);
|
||||
populate_child_table(frm, 'mdss_', r.message.mdss_data || []);
|
||||
populate_child_table(frm, 'issizlik', r.message.issizlik_data || []);
|
||||
populate_child_table(frm, 'its', r.message.its_data || []);
|
||||
frm.dirty();
|
||||
frm.refresh_fields();
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,34 @@ _ITS_ISCI = frappe.scrub("İcbari tibbi sığorta (işçi 2%)")
|
|||
_ITS_SIRKET = frappe.scrub("İcbari tibbi sığorta (şirkət 2%)")
|
||||
_KOMPENSASIYA = frappe.scrub("Məzuniyyət Kompensasiyası")
|
||||
|
||||
# Maps Salary Slip tax-free indicator/amount fields to elave4 child table rows.
|
||||
ELAVE4_SPECS = [
|
||||
{
|
||||
"key": "vergi_data",
|
||||
"indicator_field": "custom_vergi_indicator",
|
||||
"amount_field": "custom_vergi_amount",
|
||||
"row_amount_field": "gəlirvergisindənazadolanməbləğmanatla",
|
||||
},
|
||||
{
|
||||
"key": "mdss_data",
|
||||
"indicator_field": "custom_mdss_indicator",
|
||||
"amount_field": "custom_mdss_amount",
|
||||
"row_amount_field": "cəlbolunmayangəlirlərmanatla",
|
||||
},
|
||||
{
|
||||
"key": "issizlik_data",
|
||||
"indicator_field": "custom_unemployment_insurance_indicator",
|
||||
"amount_field": "custom_unemployment_insurance_amount",
|
||||
"row_amount_field": "cəlbolunmayangəlirlərmanatla",
|
||||
},
|
||||
{
|
||||
"key": "its_data",
|
||||
"indicator_field": "custom_medical_insurance_indicator",
|
||||
"amount_field": "custom_medical_insurance_amount",
|
||||
"row_amount_field": "cəlbolunmayangəlirlərmanatla",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class Singledeclarationrelatedtosalariedandnonsalariedwork(Document):
|
||||
pass
|
||||
|
|
@ -69,6 +97,7 @@ def populate_declaration_tables(company, year, quarter):
|
|||
hisse_2_data = build_hisse_2(payroll)
|
||||
hisse_3_data = get_absence_data(company, from_date, to_date)
|
||||
bolme2_hisse1_data = get_bolme2_hisse1_data(company, year, quarter)
|
||||
elave4_data = build_elave4_tables(payroll)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
|
|
@ -76,6 +105,7 @@ def populate_declaration_tables(company, year, quarter):
|
|||
"hisse_2_data": hisse_2_data,
|
||||
"hisse_3_data": hisse_3_data,
|
||||
"bolme2_hisse1_data": bolme2_hisse1_data,
|
||||
**elave4_data,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -103,7 +133,14 @@ def fetch_payroll_data(company, from_date, to_date):
|
|||
|
||||
salary_slips = get_salary_slips(filters, company_currency)
|
||||
if not salary_slips:
|
||||
return {"employee_map": {}, "fin_map": {}, "doj_map": {}}
|
||||
return {
|
||||
"employee_map": {},
|
||||
"fin_map": {},
|
||||
"doj_map": {},
|
||||
"salary_slips": [],
|
||||
"currency": currency,
|
||||
"company_currency": company_currency,
|
||||
}
|
||||
|
||||
ss_earning_map = get_salary_slip_details(salary_slips, currency, company_currency, "earnings")
|
||||
ss_ded_map = get_salary_slip_details(salary_slips, currency, company_currency, "deductions")
|
||||
|
|
@ -152,7 +189,14 @@ def fetch_payroll_data(company, from_date, to_date):
|
|||
fin_data = frappe.get_all("Employee", filters={"name": ["in", employee_ids]}, fields=["name", "passport_number"])
|
||||
fin_map = {d.name: d.passport_number for d in fin_data}
|
||||
|
||||
return {"employee_map": employee_map, "fin_map": fin_map, "doj_map": doj_map}
|
||||
return {
|
||||
"employee_map": employee_map,
|
||||
"fin_map": fin_map,
|
||||
"doj_map": doj_map,
|
||||
"salary_slips": salary_slips,
|
||||
"currency": currency,
|
||||
"company_currency": company_currency,
|
||||
}
|
||||
|
||||
|
||||
def build_hisse_1(payroll):
|
||||
|
|
@ -205,6 +249,42 @@ def build_hisse_2(payroll):
|
|||
return result
|
||||
|
||||
|
||||
def build_elave4_tables(payroll):
|
||||
"""Group salary slips by tax-free indicator into elave4 child tables.
|
||||
|
||||
One row per (table, indicator): count of distinct employees and the summed
|
||||
exempt amount over the quarter. Slips without an indicator are skipped.
|
||||
"""
|
||||
salary_slips = payroll["salary_slips"]
|
||||
currency = payroll["currency"]
|
||||
company_currency = payroll["company_currency"]
|
||||
|
||||
output = {}
|
||||
for spec in ELAVE4_SPECS:
|
||||
groups = {}
|
||||
for ss in salary_slips:
|
||||
indicator = ss.get(spec["indicator_field"])
|
||||
if not indicator:
|
||||
continue
|
||||
amount = flt(ss.get(spec["amount_field"]))
|
||||
if currency == company_currency:
|
||||
amount *= flt(ss.exchange_rate)
|
||||
entry = groups.setdefault(indicator, {"employees": set(), "amount": 0.0})
|
||||
entry["employees"].add(ss.employee)
|
||||
entry["amount"] += amount
|
||||
|
||||
rows = []
|
||||
for indicator, agg in groups.items():
|
||||
rows.append({
|
||||
"göstəricilər": indicator,
|
||||
"işçilərinsayınəfərlə": len(agg["employees"]),
|
||||
spec["row_amount_field"]: agg["amount"],
|
||||
})
|
||||
rows.sort(key=lambda x: x.get("göstəricilər", ""))
|
||||
output[spec["key"]] = rows
|
||||
return output
|
||||
|
||||
|
||||
def get_bolme2_hisse1_data(company, year, quarter):
|
||||
"""Build data for bolme2_hisse1: employee counts per month of quarter."""
|
||||
quarter_num = int(quarter[0]) # "1. Rüb" -> 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue