feat: auto-populate hissə_2 with compensation data from payroll

Refactored payroll data fetch into shared fetch_payroll_data() used by
both hissə_1 and hissə_2. hissə_2 shows employees with məzuniyyət
kompensasiyası, with il from date_of_joining year.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali 2026-04-01 15:02:56 +04:00
parent cf3f1f46de
commit 572564fd0d
2 changed files with 48 additions and 10 deletions

View File

@ -88,6 +88,7 @@ function reload_hisse_1_data(frm) {
if (r.message && r.message.success) { if (r.message && r.message.success) {
populate_hisse_1(frm, r.message.hisse_1_data || []); populate_hisse_1(frm, r.message.hisse_1_data || []);
populate_child_table(frm, 'hissə_2', r.message.hisse_2_data || []);
populate_child_table(frm, 'hissə_3', r.message.hisse_3_data || []); populate_child_table(frm, 'hissə_3', r.message.hisse_3_data || []);
frm.dirty(); frm.dirty();
frm.refresh_fields(); frm.refresh_fields();

View File

@ -3,7 +3,7 @@
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import flt from frappe.utils import flt, getdate
from taxes_az.taxes_az.report.employee_payroll_register.employee_payroll_register import ( from taxes_az.taxes_az.report.employee_payroll_register.employee_payroll_register import (
DEDUCTION_TYPES, DEDUCTION_TYPES,
@ -27,6 +27,7 @@ _ISSIZLIK_ISCI = frappe.scrub("İşsizlikdən sığorta haqqı (işçi 0,5%)")
_ISSIZLIK_SIRKET = frappe.scrub("İşsizlikdən sığorta haqqı (şirkət 0,5%)") _ISSIZLIK_SIRKET = frappe.scrub("İşsizlikdən sığorta haqqı (şirkət 0,5%)")
_ITS_ISCI = frappe.scrub("İcbari tibbi sığorta (işçi 2%)") _ITS_ISCI = frappe.scrub("İcbari tibbi sığorta (işçi 2%)")
_ITS_SIRKET = frappe.scrub("İcbari tibbi sığorta (şirkət 2%)") _ITS_SIRKET = frappe.scrub("İcbari tibbi sığorta (şirkət 2%)")
_KOMPENSASIYA = frappe.scrub("Məzuniyyət Kompensasiyası")
class Singledeclarationrelatedtosalariedandnonsalariedwork(Document): class Singledeclarationrelatedtosalariedandnonsalariedwork(Document):
@ -47,10 +48,9 @@ def get_company_defaults(company):
@frappe.whitelist() @frappe.whitelist()
def populate_declaration_tables(company, year, quarter): def populate_declaration_tables(company, year, quarter):
"""Populate child tables from Employee Payroll Register data. """Populate child tables from payroll and absence data.
Returns dict with data for each child table. Returns dict with data for each child table.
Designed for extensibility: future tables add their key to the result dict.
""" """
try: try:
year = int(year) year = int(year)
@ -61,12 +61,16 @@ def populate_declaration_tables(company, year, quarter):
from_date = f"{year}-{start_suffix}" from_date = f"{year}-{start_suffix}"
to_date = f"{year}-{end_suffix}" to_date = f"{year}-{end_suffix}"
hisse_1_data = get_aggregated_employee_data(company, from_date, to_date) # Fetch payroll data once, build hissə_1 and hissə_2 from it
payroll = fetch_payroll_data(company, from_date, to_date)
hisse_1_data = build_hisse_1(payroll)
hisse_2_data = build_hisse_2(payroll)
hisse_3_data = get_absence_data(company, from_date, to_date) hisse_3_data = get_absence_data(company, from_date, to_date)
return { return {
"success": True, "success": True,
"hisse_1_data": hisse_1_data, "hisse_1_data": hisse_1_data,
"hisse_2_data": hisse_2_data,
"hisse_3_data": hisse_3_data, "hisse_3_data": hisse_3_data,
} }
@ -78,8 +82,8 @@ def populate_declaration_tables(company, year, quarter):
return {"success": False, "error": str(e)} return {"success": False, "error": str(e)}
def get_aggregated_employee_data(company, from_date, to_date): def fetch_payroll_data(company, from_date, to_date):
"""Fetch salary slip data and aggregate per employee for hissə_1.""" """Fetch and aggregate salary slip data per employee. Shared by hissə_1 and hissə_2."""
import erpnext import erpnext
company_currency = erpnext.get_company_currency(company) company_currency = erpnext.get_company_currency(company)
@ -95,15 +99,13 @@ def get_aggregated_employee_data(company, from_date, to_date):
salary_slips = get_salary_slips(filters, company_currency) salary_slips = get_salary_slips(filters, company_currency)
if not salary_slips: if not salary_slips:
return [] return {"employee_map": {}, "fin_map": {}, "doj_map": {}}
ss_earning_map = get_salary_slip_details(salary_slips, currency, company_currency, "earnings") 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") ss_ded_map = get_salary_slip_details(salary_slips, currency, company_currency, "deductions")
doj_map = get_employee_doj_map() doj_map = get_employee_doj_map()
# Scrubbed keys for summing
all_scrubbed_keys = [frappe.scrub(e) for e in EARNING_TYPES] + [frappe.scrub(d) for d in DEDUCTION_TYPES] all_scrubbed_keys = [frappe.scrub(e) for e in EARNING_TYPES] + [frappe.scrub(d) for d in DEDUCTION_TYPES]
sum_fields = ["gross_pay", "total_deduction", "net_pay"] + all_scrubbed_keys sum_fields = ["gross_pay", "total_deduction", "net_pay"] + all_scrubbed_keys
employee_map = {} employee_map = {}
@ -146,7 +148,14 @@ def get_aggregated_employee_data(company, from_date, to_date):
fin_data = frappe.get_all("Employee", filters={"name": ["in", employee_ids]}, fields=["name", "passport_number"]) 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} fin_map = {d.name: d.passport_number for d in fin_data}
# Build child table rows with original fieldnames return {"employee_map": employee_map, "fin_map": fin_map, "doj_map": doj_map}
def build_hisse_1(payroll):
"""Build hissə_1 rows from aggregated payroll data."""
employee_map = payroll["employee_map"]
fin_map = payroll["fin_map"]
result = [] result = []
for agg in employee_map.values(): for agg in employee_map.values():
child_row = { child_row = {
@ -164,6 +173,34 @@ def get_aggregated_employee_data(company, from_date, to_date):
return result return result
def build_hisse_2(payroll):
"""Build hissə_2 rows from aggregated payroll data. Only employees with compensation."""
employee_map = payroll["employee_map"]
fin_map = payroll["fin_map"]
doj_map = payroll["doj_map"]
result = []
for agg in employee_map.values():
compensation = flt(agg.get(_KOMPENSASIYA, 0))
if not compensation:
continue
emp = agg["employee"]
doj = doj_map.get(emp)
doj_year = str(getdate(doj).year) if doj else ""
child_row = {
"işçininsığortaolunanınsoyadıadıatasınınadı": agg["employee_name"],
"fin": fin_map.get(emp, ""),
"il": doj_year,
"kompensasiyaməbləği": compensation,
}
result.append(child_row)
result.sort(key=lambda x: x.get("işçininsığortaolunanınsoyadıadıatasınınadı", ""))
return result
def get_absence_data(company, from_date, to_date): def get_absence_data(company, from_date, to_date):
"""Fetch absence data from Monthly Absence Report for hissə_3.""" """Fetch absence data from Monthly Absence Report for hissə_3."""
from taxes_az.taxes_az.report.monthly_absence_report.monthly_absence_report import get_data from taxes_az.taxes_az.report.monthly_absence_report.monthly_absence_report import get_data