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) {
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 || []);
frm.dirty();
frm.refresh_fields();

View File

@ -3,7 +3,7 @@
import frappe
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 (
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%)")
_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ı")
class Singledeclarationrelatedtosalariedandnonsalariedwork(Document):
@ -47,10 +48,9 @@ def get_company_defaults(company):
@frappe.whitelist()
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.
Designed for extensibility: future tables add their key to the result dict.
"""
try:
year = int(year)
@ -61,12 +61,16 @@ def populate_declaration_tables(company, year, quarter):
from_date = f"{year}-{start_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)
return {
"success": True,
"hisse_1_data": hisse_1_data,
"hisse_2_data": hisse_2_data,
"hisse_3_data": hisse_3_data,
}
@ -78,8 +82,8 @@ def populate_declaration_tables(company, year, quarter):
return {"success": False, "error": str(e)}
def get_aggregated_employee_data(company, from_date, to_date):
"""Fetch salary slip data and aggregate per employee for hissə_1."""
def fetch_payroll_data(company, from_date, to_date):
"""Fetch and aggregate salary slip data per employee. Shared by hissə_1 and hissə_2."""
import erpnext
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)
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_ded_map = get_salary_slip_details(salary_slips, currency, company_currency, "deductions")
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]
sum_fields = ["gross_pay", "total_deduction", "net_pay"] + all_scrubbed_keys
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_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 = []
for agg in employee_map.values():
child_row = {
@ -164,6 +173,34 @@ def get_aggregated_employee_data(company, from_date, to_date):
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):
"""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