diff --git a/taxes_az/taxes_az/doctype/single_declaration_elave4_icbari_tibbi_sigorta/single_declaration_elave4_icbari_tibbi_sigorta.json b/taxes_az/taxes_az/doctype/single_declaration_elave4_icbari_tibbi_sigorta/single_declaration_elave4_icbari_tibbi_sigorta.json index cd99b87..c100a18 100644 --- a/taxes_az/taxes_az/doctype/single_declaration_elave4_icbari_tibbi_sigorta/single_declaration_elave4_icbari_tibbi_sigorta.json +++ b/taxes_az/taxes_az/doctype/single_declaration_elave4_icbari_tibbi_sigorta/single_declaration_elave4_icbari_tibbi_sigorta.json @@ -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", diff --git a/taxes_az/taxes_az/doctype/single_declaration_elave4_issizlikden_sigorta/single_declaration_elave4_issizlikden_sigorta.json b/taxes_az/taxes_az/doctype/single_declaration_elave4_issizlikden_sigorta/single_declaration_elave4_issizlikden_sigorta.json index 179a06d..e60f031 100644 --- a/taxes_az/taxes_az/doctype/single_declaration_elave4_issizlikden_sigorta/single_declaration_elave4_issizlikden_sigorta.json +++ b/taxes_az/taxes_az/doctype/single_declaration_elave4_issizlikden_sigorta/single_declaration_elave4_issizlikden_sigorta.json @@ -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", diff --git a/taxes_az/taxes_az/doctype/single_declaration_elave4_mdss/single_declaration_elave4_mdss.json b/taxes_az/taxes_az/doctype/single_declaration_elave4_mdss/single_declaration_elave4_mdss.json index 40ac7e3..a27cd2e 100644 --- a/taxes_az/taxes_az/doctype/single_declaration_elave4_mdss/single_declaration_elave4_mdss.json +++ b/taxes_az/taxes_az/doctype/single_declaration_elave4_mdss/single_declaration_elave4_mdss.json @@ -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", diff --git a/taxes_az/taxes_az/doctype/single_declaration_elave4_vergi/single_declaration_elave4_vergi.json b/taxes_az/taxes_az/doctype/single_declaration_elave4_vergi/single_declaration_elave4_vergi.json index 25af519..53dc5ae 100644 --- a/taxes_az/taxes_az/doctype/single_declaration_elave4_vergi/single_declaration_elave4_vergi.json +++ b/taxes_az/taxes_az/doctype/single_declaration_elave4_vergi/single_declaration_elave4_vergi.json @@ -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", diff --git a/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.js b/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.js index a023660..89841fa 100644 --- a/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.js +++ b/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.js @@ -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(); diff --git a/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.py b/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.py index 51fbaad..311e8f7 100644 --- a/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.py +++ b/taxes_az/taxes_az/doctype/single_declaration_related_to_salaried_and_non_salaried_work/single_declaration_related_to_salaried_and_non_salaried_work.py @@ -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