auto-populate hissə_1 from Employee Payroll Register on year/quarter change
Redesign Single Declaration-Elave1_Hisse1 child table with all report columns (26 fields), add server-side aggregation per employee with insurance formula (işçi + şirkət) × 3, and client-side triggers on il/hesabatdövrü fields. Also fix backtick escaping for Unicode field names in frappe.db.get_value. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4addeb8a05
commit
63e9ec5ee4
|
|
@ -6,60 +6,194 @@
|
|||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"soyadadataad\u0131",
|
||||
"fin",
|
||||
"g\u0259lirl\u0259rc\u0259mi",
|
||||
"vergim\u0259bl\u0259\u011fi",
|
||||
"employee",
|
||||
"employeename",
|
||||
"dateofjoining",
|
||||
"branch",
|
||||
"department",
|
||||
"designation",
|
||||
"leavewithoutpay",
|
||||
"absentdays",
|
||||
"paymentdays",
|
||||
"\u0259sas\u0259m\u0259khaqq\u0131",
|
||||
"m\u0259zuniyy\u0259tkompensasiyas\u0131",
|
||||
"dsmfx\u0259rc\u015firk\u0259t",
|
||||
"icbaritibbis\u0131\u011fortax\u0259rc\u015firk\u0259t2",
|
||||
"i\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131x\u0259rc\u015firk\u0259t05",
|
||||
"grosspay",
|
||||
"dsmfi\u015f\u00e7i",
|
||||
"dsmf\u015firk\u0259t",
|
||||
"icbaritibbis\u0131\u011fortai\u015f\u00e7i2",
|
||||
"icbaritibbis\u0131\u011forta\u015firk\u0259t2",
|
||||
"i\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131i\u015f\u00e7i05",
|
||||
"i\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131\u015firk\u0259t05",
|
||||
"totaldeduction",
|
||||
"netpay",
|
||||
"hesablanm\u0131\u015fmdsshaqq\u0131",
|
||||
"hesablanm\u0131\u015fi\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131",
|
||||
"hesablanm\u0131\u015ficbaritibbis\u0131\u011fortahaqq\u0131"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "soyadadataad\u0131",
|
||||
"fieldtype": "Data",
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Soyad, ad, ata ad\u0131",
|
||||
"label": "Employee",
|
||||
"options": "Employee",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "fin",
|
||||
"fieldname": "employeename",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "F\u0130N",
|
||||
"label": "Employee Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "g\u0259lirl\u0259rc\u0259mi",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u0259lirl\u0259r c\u0259mi",
|
||||
"fieldname": "dateofjoining",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date of Joining",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "vergim\u0259bl\u0259\u011fi",
|
||||
"fieldname": "branch",
|
||||
"fieldtype": "Data",
|
||||
"label": "Branch",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Data",
|
||||
"label": "Department",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "designation",
|
||||
"fieldtype": "Data",
|
||||
"label": "Designation",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "leavewithoutpay",
|
||||
"fieldtype": "Float",
|
||||
"label": "Leave Without Pay",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "absentdays",
|
||||
"fieldtype": "Float",
|
||||
"label": "Absent Days",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "paymentdays",
|
||||
"fieldtype": "Float",
|
||||
"label": "Payment Days",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "\u0259sas\u0259m\u0259khaqq\u0131",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u018esas \u0259m\u0259k haqq\u0131",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "m\u0259zuniyy\u0259tkompensasiyas\u0131",
|
||||
"fieldtype": "Currency",
|
||||
"label": "M\u0259zuniyy\u0259t Kompensasiyas\u0131",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "dsmfx\u0259rc\u015firk\u0259t",
|
||||
"fieldtype": "Currency",
|
||||
"label": "DSMF (x\u0259rc \u015firk\u0259t)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "icbaritibbis\u0131\u011fortax\u0259rc\u015firk\u0259t2",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u0130cbari tibbi s\u0131\u011forta (x\u0259rc \u015firk\u0259t 2%)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131x\u0259rc\u015firk\u0259t05",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u0130\u015fsizlikd\u0259n s\u0131\u011forta haqq\u0131 (x\u0259rc \u015firk\u0259t 0,5%)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "grosspay",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Vergi m\u0259bl\u0259\u011fi",
|
||||
"label": "Gross Pay",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "dsmfi\u015f\u00e7i",
|
||||
"fieldtype": "Currency",
|
||||
"label": "DSMF (i\u015f\u00e7i)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "dsmf\u015firk\u0259t",
|
||||
"fieldtype": "Currency",
|
||||
"label": "DSMF (\u015firk\u0259t)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "icbaritibbis\u0131\u011fortai\u015f\u00e7i2",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u0130cbari tibbi s\u0131\u011forta (i\u015f\u00e7i 2%)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "icbaritibbis\u0131\u011forta\u015firk\u0259t2",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u0130cbari tibbi s\u0131\u011forta (\u015firk\u0259t 2%)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131i\u015f\u00e7i05",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u0130\u015fsizlikd\u0259n s\u0131\u011forta haqq\u0131 (i\u015f\u00e7i 0,5%)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "i\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131\u015firk\u0259t05",
|
||||
"fieldtype": "Currency",
|
||||
"label": "\u0130\u015fsizlikd\u0259n s\u0131\u011forta haqq\u0131 (\u015firk\u0259t 0,5%)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "totaldeduction",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Deduction",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "netpay",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Net Pay",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hesablanm\u0131\u015fmdsshaqq\u0131",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesablanm\u0131\u015f MDSS haqq\u0131",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hesablanm\u0131\u015fi\u015fsizlikd\u0259ns\u0131\u011fortahaqq\u0131",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesablanm\u0131\u015f i\u015fsizlikd\u0259n s\u0131\u011forta haqq\u0131",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hesablanm\u0131\u015ficbaritibbis\u0131\u011fortahaqq\u0131",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesablanm\u0131\u015f icbari tibbi s\u0131\u011forta haqq\u0131",
|
||||
"read_only": 1
|
||||
|
|
@ -68,8 +202,8 @@
|
|||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-03-26 18:02:10.219887",
|
||||
"modified_by": "nihad_m@jeysoft.az",
|
||||
"modified": "2026-03-30 12:00:00.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Single Declaration-Elave1_Hisse1",
|
||||
"owner": "Administrator",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ function fillFromCompanyDefaults(frm) {
|
|||
frappe.db.get_value(
|
||||
'Company',
|
||||
company,
|
||||
['mdssüzrə', 'icbaritibbisığortaüzrə', 'işsizlikdənsığortaüzrə', 'main_activity']
|
||||
['`mdssüzrə`', '`icbaritibbisığortaüzrə`', '`işsizlikdənsığortaüzrə`', '`main_activity`']
|
||||
).then(r => {
|
||||
if (!r || !r.message) return;
|
||||
const v = r.message;
|
||||
|
|
@ -25,23 +25,24 @@ frappe.ui.form.on('Single declaration related to salaried and non-salaried work'
|
|||
|
||||
il: function(frm) {
|
||||
fillFromCompanyDefaults(frm);
|
||||
}
|
||||
});
|
||||
reload_hisse_1_data(frm);
|
||||
},
|
||||
|
||||
hesabatdövrü: function(frm) {
|
||||
reload_hisse_1_data(frm);
|
||||
},
|
||||
|
||||
// Код для экспорта XML
|
||||
frappe.ui.form.on('Single declaration related to salaried and non-salaried work', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Export XML'), function() {
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.xml_mapping_tool.xml_mapping_tool.generate_xml',
|
||||
args: {
|
||||
mapping_tool: 'Single declaration related to salaried and non-salaried work', // Замените на имя вашего документа XML Mapping Tool
|
||||
doctype: 'Single declaration related to salaried and non-salaried work', // Замените на имя DocType
|
||||
mapping_tool: 'Single declaration related to salaried and non-salaried work',
|
||||
doctype: 'Single declaration related to salaried and non-salaried work',
|
||||
docname: frm.docname
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
// Создаем временный элемент для скачивания
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/xml;charset=utf-8,' + encodeURIComponent(r.message));
|
||||
element.setAttribute('download', frm.docname + '.xml');
|
||||
|
|
@ -59,5 +60,71 @@ frappe.ui.form.on('Single declaration related to salaried and non-salaried work'
|
|||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
});
|
||||
|
||||
function reload_hisse_1_data(frm) {
|
||||
if (!frm.doc.il || !frm.doc.hesabatdövrü) {
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
const company = frappe.defaults.get_user_default('Company')
|
||||
|| frappe.defaults.get_default('Company');
|
||||
if (!company) {
|
||||
frappe.msgprint(__('Company not found in user defaults'));
|
||||
return;
|
||||
}
|
||||
|
||||
frappe.dom.freeze(__('Loading payroll data...'));
|
||||
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.single_declaration_related_to_salaried_and_non_salaried_work.single_declaration_related_to_salaried_and_non_salaried_work.populate_declaration_tables',
|
||||
args: {
|
||||
company: company,
|
||||
year: frm.doc.il,
|
||||
quarter: frm.doc.hesabatdövrü
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.dom.unfreeze();
|
||||
|
||||
if (r.message && r.message.success) {
|
||||
populate_hisse_1(frm, r.message.hisse_1_data || []);
|
||||
frm.dirty();
|
||||
frm.refresh_fields();
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('Payroll data loaded successfully'),
|
||||
indicator: 'green'
|
||||
});
|
||||
} else {
|
||||
frappe.msgprint({
|
||||
title: __('Error'),
|
||||
message: r.message ? r.message.error : __('Failed to load data'),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
frappe.dom.unfreeze();
|
||||
frappe.msgprint({
|
||||
title: __('Error'),
|
||||
message: __('Server error while loading payroll data'),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function populate_hisse_1(frm, data) {
|
||||
frm.clear_table('hissə_1');
|
||||
|
||||
data.forEach(function(emp_data) {
|
||||
let row = frm.add_child('hissə_1');
|
||||
Object.keys(emp_data).forEach(function(field) {
|
||||
if (emp_data[field] !== null && emp_data[field] !== undefined) {
|
||||
row[field] = emp_data[field];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
frm.refresh_field('hissə_1');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,206 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
from taxes_az.taxes_az.report.employee_payroll_register.employee_payroll_register import (
|
||||
DEDUCTION_TYPES,
|
||||
EARNING_TYPES,
|
||||
get_employee_doj_map,
|
||||
get_salary_slip_details,
|
||||
get_salary_slips,
|
||||
)
|
||||
|
||||
QUARTER_DATE_RANGES = {
|
||||
"1. Rüb": ("01-01", "03-31"),
|
||||
"2. Rüb": ("04-01", "06-30"),
|
||||
"3. Rüb": ("07-01", "09-30"),
|
||||
"4. Rüb": ("10-01", "12-31"),
|
||||
}
|
||||
|
||||
# Mapping from frappe.scrub(salary_component_name) to child table fieldnames.
|
||||
# Uses frappe.scrub() at module level to handle İ→i̇ Unicode correctly.
|
||||
REPORT_KEY_TO_FIELDNAME = {
|
||||
# Earnings
|
||||
frappe.scrub("DSMF (xərc şirkət)"): "dsmfxərcşirkət",
|
||||
frappe.scrub("Məzuniyyət Kompensasiyası"): "məzuniyyətkompensasiyası",
|
||||
frappe.scrub("İcbari tibbi sığorta (xərc şirkət 2%)"): "icbaritibbisığortaxərcşirkət2",
|
||||
frappe.scrub("İşsizlikdən sığorta haqqı (xərc şirkət 0,5%)"): "işsizlikdənsığortahaqqıxərcşirkət05",
|
||||
frappe.scrub("Əsas əmək haqqı"): "əsasəməkhaqqı",
|
||||
# Deductions
|
||||
frappe.scrub("DSMF (işçi)"): "dsmfişçi",
|
||||
frappe.scrub("DSMF (şirkət)"): "dsmfşirkət",
|
||||
frappe.scrub("İcbari tibbi sığorta (işçi 2%)"): "icbaritibbisığortaişçi2",
|
||||
frappe.scrub("İcbari tibbi sığorta (şirkət 2%)"): "icbaritibbisığortaşirkət2",
|
||||
frappe.scrub("İşsizlikdən sığorta haqqı (işçi 0,5%)"): "işsizlikdənsığortahaqqıişçi05",
|
||||
frappe.scrub("İşsizlikdən sığorta haqqı (şirkət 0,5%)"): "işsizlikdənsığortahaqqışirkət05",
|
||||
}
|
||||
|
||||
# Scrubbed keys for insurance formula calculation
|
||||
_DSMF_ISCI = frappe.scrub("DSMF (işçi)")
|
||||
_DSMF_SIRKET = frappe.scrub("DSMF (şirkət)")
|
||||
_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%)")
|
||||
|
||||
|
||||
class Singledeclarationrelatedtosalariedandnonsalariedwork(Document):
|
||||
pass
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def populate_declaration_tables(company, year, quarter):
|
||||
"""Populate child tables from Employee Payroll Register 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)
|
||||
if quarter not in QUARTER_DATE_RANGES:
|
||||
return {"success": False, "error": f"Invalid quarter: {quarter}"}
|
||||
|
||||
start_suffix, end_suffix = QUARTER_DATE_RANGES[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)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"hisse_1_data": hisse_1_data,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(
|
||||
f"Error in populate_declaration_tables: {str(e)}",
|
||||
"Single Declaration",
|
||||
)
|
||||
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."""
|
||||
import erpnext
|
||||
|
||||
company_currency = erpnext.get_company_currency(company)
|
||||
currency = "AZN"
|
||||
|
||||
filters = {
|
||||
"company": company,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"currency": currency,
|
||||
"docstatus": "Submitted",
|
||||
}
|
||||
|
||||
salary_slips = get_salary_slips(filters, company_currency)
|
||||
if not salary_slips:
|
||||
return []
|
||||
|
||||
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()
|
||||
|
||||
# Build per-slip rows (same logic as report's execute())
|
||||
all_scrubbed_keys = []
|
||||
for e in EARNING_TYPES:
|
||||
all_scrubbed_keys.append(frappe.scrub(e))
|
||||
for d in DEDUCTION_TYPES:
|
||||
all_scrubbed_keys.append(frappe.scrub(d))
|
||||
|
||||
sum_fields = [
|
||||
"leave_without_pay",
|
||||
"absent_days",
|
||||
"payment_days",
|
||||
"gross_pay",
|
||||
"total_deduction",
|
||||
"net_pay",
|
||||
] + all_scrubbed_keys
|
||||
|
||||
employee_map = {}
|
||||
|
||||
for ss in salary_slips:
|
||||
emp = ss.employee
|
||||
|
||||
if emp not in employee_map:
|
||||
employee_map[emp] = {
|
||||
"employee": emp,
|
||||
"employee_name": ss.employee_name,
|
||||
"date_of_joining": doj_map.get(emp),
|
||||
"branch": ss.branch,
|
||||
"department": ss.department,
|
||||
"designation": ss.designation,
|
||||
}
|
||||
for field in sum_fields:
|
||||
employee_map[emp][field] = 0.0
|
||||
|
||||
agg = employee_map[emp]
|
||||
|
||||
# Earnings
|
||||
for e in EARNING_TYPES:
|
||||
key = frappe.scrub(e)
|
||||
agg[key] += flt(ss_earning_map.get(ss.name, {}).get(e, 0))
|
||||
|
||||
# Gross pay
|
||||
if currency == company_currency:
|
||||
agg["gross_pay"] += flt(ss.gross_pay) * flt(ss.exchange_rate)
|
||||
else:
|
||||
agg["gross_pay"] += flt(ss.gross_pay)
|
||||
|
||||
# Deductions
|
||||
for d in DEDUCTION_TYPES:
|
||||
key = frappe.scrub(d)
|
||||
agg[key] += flt(ss_ded_map.get(ss.name, {}).get(d, 0))
|
||||
|
||||
# Totals
|
||||
if currency == company_currency:
|
||||
agg["total_deduction"] += flt(ss.total_deduction) * flt(ss.exchange_rate)
|
||||
agg["net_pay"] += flt(ss.net_pay) * flt(ss.exchange_rate)
|
||||
else:
|
||||
agg["total_deduction"] += flt(ss.total_deduction)
|
||||
agg["net_pay"] += flt(ss.net_pay)
|
||||
|
||||
# Days
|
||||
agg["leave_without_pay"] += flt(ss.leave_without_pay)
|
||||
agg["absent_days"] += flt(ss.absent_days)
|
||||
agg["payment_days"] += flt(ss.payment_days)
|
||||
|
||||
# Convert to child table format with clean fieldnames
|
||||
result = []
|
||||
for agg in employee_map.values():
|
||||
child_row = {
|
||||
"employee": agg["employee"],
|
||||
"employeename": agg["employee_name"],
|
||||
"dateofjoining": str(agg["date_of_joining"]) if agg["date_of_joining"] else None,
|
||||
"branch": agg.get("branch"),
|
||||
"department": agg.get("department"),
|
||||
"designation": agg.get("designation"),
|
||||
"leavewithoutpay": agg["leave_without_pay"],
|
||||
"absentdays": agg["absent_days"],
|
||||
"paymentdays": agg["payment_days"],
|
||||
"grosspay": agg["gross_pay"],
|
||||
"totaldeduction": agg["total_deduction"],
|
||||
"netpay": agg["net_pay"],
|
||||
}
|
||||
|
||||
# Map scrubbed report keys to clean child table fieldnames
|
||||
for report_key, child_fieldname in REPORT_KEY_TO_FIELDNAME.items():
|
||||
child_row[child_fieldname] = agg.get(report_key, 0.0)
|
||||
|
||||
# Calculate insurance fields: (işçi + şirkət) × 3
|
||||
child_row["hesablanmışmdsshaqqı"] = (flt(agg.get(_DSMF_ISCI, 0)) + flt(agg.get(_DSMF_SIRKET, 0))) * 3
|
||||
child_row["hesablanmışişsizlikdənsığortahaqqı"] = (
|
||||
flt(agg.get(_ISSIZLIK_ISCI, 0)) + flt(agg.get(_ISSIZLIK_SIRKET, 0))
|
||||
) * 3
|
||||
child_row["hesablanmışicbaritibbisığortahaqqı"] = (
|
||||
flt(agg.get(_ITS_ISCI, 0)) + flt(agg.get(_ITS_SIRKET, 0))
|
||||
) * 3
|
||||
|
||||
result.append(child_row)
|
||||
|
||||
result.sort(key=lambda x: x.get("employeename", ""))
|
||||
return result
|
||||
|
|
|
|||
Loading…
Reference in New Issue