diff --git a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.js b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.js index 6c1552d..78eb0f7 100644 --- a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.js +++ b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.js @@ -10,8 +10,8 @@ frappe.ui.form.on("Declaration of value added tax", { }, }); -// Pull Əlavə 1 / Əlavə 2 Hissə 1 / Əlavə 2 Hissə 2 from the three source -// reports once both the year (İl) and month (Ay) are selected. +// Pull the appendix tables from their source reports once both the year (İl) +// and month (Ay) are selected. function fill_from_reports(frm) { if (!frm.doc.il || !frm.doc.ay) { return; @@ -31,8 +31,19 @@ function fill_from_reports(frm) { set_table(frm, "əlavə_1", r.message.elave_1); set_table(frm, "əlavə_2", r.message.elave_2); set_table(frm, "əlavə_2_2", r.message.elave_2_2); + set_table(frm, "əlavə1_yeni", r.message.elave_1_yeni); set_table(frm, "müəssisə_malın_dəyəri", r.message.elave_8_2); + // Summary tables ship with their rows already created by a client + // script, so fill them in place instead of rebuilding. + fill_first_row(frm, "əlavə_1_2", r.message.elave_1_2); + fill_rows_by_code(frm, "əlavə1_2_yeni", "sətirkodu", r.message.elave_1_2_yeni); + + frm.set_value( + "sertifikathesabatdövründəmalındəyərininsəhifəsicəmi", + r.message.elave_8_total + ); + frm.refresh_fields(); frappe.show_alert({ message: __("Əlavələr hesabatlardan dolduruldu"), indicator: "green" }); }, @@ -44,10 +55,45 @@ function set_table(frm, fieldname, rows) { frm.clear_table(fieldname); (rows || []).forEach(function (data) { const child = frm.add_child(fieldname); - Object.keys(data).forEach(function (key) { - if (data[key] !== null && data[key] !== undefined) { - child[key] = data[key]; - } - }); + assign(child, data); + }); + frm.refresh_field(fieldname); +} + +// Fill the single summary row of a table without creating or deleting rows. +function fill_first_row(frm, fieldname, values) { + const rows = frm.doc[fieldname] || []; + if (!rows.length || !values) { + return; + } + assign(rows[0], values); + frm.refresh_field(fieldname); +} + +// Fill pre-created summary rows, matching each row by the leading line code of +// `codefield`. The stored value carries a long description after the code, so +// only the first whitespace-delimited token is compared. Rows are never added +// or removed — a code with no data keeps the zeroed totals from the server. +function fill_rows_by_code(frm, fieldname, codefield, values_by_code) { + const rows = frm.doc[fieldname] || []; + if (!rows.length || !values_by_code) { + return; + } + rows.forEach(function (row) { + const code = String(row[codefield] || "").trim().split(/\s+/)[0]; + const values = values_by_code[code]; + if (values) { + assign(row, values); + } + }); + frm.refresh_field(fieldname); +} + +// Copy the supplied values onto a row, skipping keys the server left empty. +function assign(row, data) { + Object.keys(data).forEach(function (key) { + if (data[key] !== null && data[key] !== undefined) { + row[key] = data[key]; + } }); } diff --git a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.json b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.json index 775237f..bebfb9e 100644 --- a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.json +++ b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.json @@ -373,7 +373,7 @@ }, { "fieldname": "sertifikathesabatd\u00f6vr\u00fcnd\u0259mal\u0131nd\u0259y\u0259rinins\u0259hif\u0259sic\u0259mi", - "fieldtype": "Int", + "fieldtype": "Float", "label": "Sertifikat \u00fczr\u0259 hesabat d\u00f6vr\u00fcnd\u0259 t\u0259qdim edilmi\u015f mal\u0131n (g\u00f6r\u00fclm\u00fc\u015f i\u015fin, g\u00f6st\u0259rilmi\u015f xidm\u0259tin) d\u0259y\u0259rinin bu s\u0259hif\u0259si \u00fczr\u0259 C\u018fM\u0130", "precision": "2" }, @@ -604,7 +604,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2026-07-06 21:26:56.777547", + "modified": "2026-07-10 10:00:00.000000", "modified_by": "nihad_m@jeysoft.az", "module": "Taxes Az", "name": "Declaration of value added tax", diff --git a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.py b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.py index 53f2578..d9bfb6e 100644 --- a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.py +++ b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax/declaration_of_value_added_tax.py @@ -40,14 +40,29 @@ def _period_filters(year, month): return {"company": company, "from_date": from_date, "to_date": to_date} +# Line codes of the new Əlavə 1 summary table (əlavə1_2_yeni). The stored +# `sətirkodu` values carry a long description after the code, so rows are +# matched on this prefix rather than on the full option string. +VAT_OFFSET_LINE_CODES = ["308", "314", "316"] + + @frappe.whitelist() def populate_vat_tables(year, month): - """Build the VAT declaration appendix rows from the three source reports. + """Build the VAT declaration appendix rows from the source reports. Returns row dicts for: - - Əlavə 1 (əlavə_1) <- Purchase YGB VAT report - - Əlavə 2 Hissə 1 (əlavə_2) <- Purchase invoice info report - - Əlavə 2 Hissə 2 (əlavə_2_2) <- Agricultural goods stock report + - Əlavə 1 (əlavə_1) <- Purchase YGB VAT report + - Əlavə 1 cəmi (əlavə_1_2) <- totals over Əlavə 1 + - Əlavə 1 yeni (əlavə1_yeni) <- Purchase VAT offset report + - Əlavə 1 yeni cəmi (əlavə1_2_yeni) <- totals per line code + - Əlavə 2 Hissə 1 (əlavə_2) <- Purchase invoice info report + - Əlavə 2 Hissə 2 (əlavə_2_2) <- Agricultural goods stock report + - Əlavə 8 Tablo 2 (müəssisə_malın_dəyəri) <- Certificate VAT report + - Əlavə 8 cəmi (elave_8_total) <- total of the Əlavə 8 values + + The two summary tables already carry their rows (created by a client + script), so only values are returned — the caller fills existing rows + instead of rebuilding them. """ from taxes_az.taxes_az.report.purchase_ygb_vat_report.purchase_ygb_vat_report import ( get_data as ygb_get_data, @@ -61,6 +76,9 @@ def populate_vat_tables(year, month): from taxes_az.taxes_az.report.certificate_vat_report.certificate_vat_report import ( get_data as certificate_get_data, ) + from taxes_az.taxes_az.report.purchase_vat_offset_report.purchase_vat_offset_report import ( + get_data as vat_offset_get_data, + ) if not month or not year: return {"success": False, "error": "Year and month are required"} @@ -78,6 +96,47 @@ def populate_vat_tables(year, month): "ygbüzrəalınmışmalınədvməbləğimanatla": r.get("vat_amount"), }) + # Əlavə 1 cəmi — the single pre-created summary row over Əlavə 1. + elave_1_2 = { + "malınədvsizümumidəyəri": sum(flt(r["ygbüzrəalınmışmalınədvsizdəyərimanatla"]) for r in elave_1), + "malınədvməbləği": sum(flt(r["ygbüzrəalınmışmalınədvməbləğimanatla"]) for r in elave_1), + } + + # Əlavə 1 (yeni) — one row per VAT-offset purchase invoice. + elave_1_yeni = [] + for r in (vat_offset_get_data(filters) or []): + elave_1_yeni.append({ + "sətirkodu": r.get("line_code"), + "tarix": r.get("posting_date"), + "vöenadı": r.get("voen_name"), + "qaiməninseriyası": r.get("invoice_series"), + "qaiməninnömrəsi": r.get("invoice_number"), + "ümumiməbləğmanatla": r.get("total_amount"), + "ədvməbləğimanatla": r.get("vat_amount"), + "ödənilmişümumiməbləğmanatla": r.get("paid_total"), + "ödənilmişədvməbləğimanatla": r.get("paid_vat"), + }) + + # Əlavə 1 (yeni) cəmi — totals per line code, keyed by the bare code. Every + # code is present so a code that lost its rows is zeroed rather than stale. + elave_1_2_yeni = { + code: { + "ümumiməbləğmanatla": 0.0, + "ədvməbləğimanatla": 0.0, + "ödənilmişümumiməbləğmanatla": 0.0, + "ödənilmişədvməbləğimanatla": 0.0, + } + for code in VAT_OFFSET_LINE_CODES + } + for r in elave_1_yeni: + bucket = elave_1_2_yeni.get(str(r["sətirkodu"] or "").strip()) + if not bucket: + continue + bucket["ümumiməbləğmanatla"] += flt(r["ümumiməbləğmanatla"]) + bucket["ədvməbləğimanatla"] += flt(r["ədvməbləğimanatla"]) + bucket["ödənilmişümumiməbləğmanatla"] += flt(r["ödənilmişümumiməbləğmanatla"]) + bucket["ödənilmişədvməbləğimanatla"] += flt(r["ödənilmişədvməbləğimanatla"]) + # Əlavə 2 Hissə 1 — one row per agricultural purchase document. elave_2 = [] for r in (purchase_info_get_data(filters) or []): @@ -113,11 +172,20 @@ def populate_vat_tables(year, month): "sertifikataltındatəqdimolunanmallarınişlərinxidmətlərindəyəri": r.get("value"), }) + # Əlavə 8 — page total of the values listed in Tablo 2. + elave_8_total = sum( + flt(r["sertifikataltındatəqdimolunanmallarınişlərinxidmətlərindəyəri"]) for r in elave_8_2 + ) + return { "success": True, "elave_1": elave_1, + "elave_1_2": elave_1_2, + "elave_1_yeni": elave_1_yeni, + "elave_1_2_yeni": elave_1_2_yeni, "elave_2": elave_2, "elave_2_2": elave_2_2, "elave_8_2": elave_8_2, + "elave_8_total": elave_8_total, "period": filters, } \ No newline at end of file diff --git a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1/declaration_of_value_added_tax_yeni_elave_1.json b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1/declaration_of_value_added_tax_yeni_elave_1.json index 61f1fc2..9c2ba6a 100644 --- a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1/declaration_of_value_added_tax_yeni_elave_1.json +++ b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1/declaration_of_value_added_tax_yeni_elave_1.json @@ -33,21 +33,21 @@ }, { "fieldname": "qaim\u0259ninn\u00f6mr\u0259si", - "fieldtype": "Int", + "fieldtype": "Data", "in_list_view": 1, "label": "Qaim\u0259nin n\u00f6mr\u0259si", "precision": "2" }, { "fieldname": "\u00fcmumim\u0259bl\u0259\u011fmanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u00dcmumi m\u0259bl\u0259\u011f,manatla", "precision": "2" }, { "fieldname": "\u0259dvm\u0259bl\u0259\u011fimanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u018fDV m\u0259bl\u0259\u011fi,manatla", "precision": "2" @@ -68,14 +68,14 @@ }, { "fieldname": "\u00f6d\u0259nilmi\u015f\u00fcmumim\u0259bl\u0259\u011fmanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u00d6d\u0259nilmi\u015f \u00fcmumi m\u0259bl\u0259\u011f,manatla", "precision": "2" }, { "fieldname": "\u00f6d\u0259nilmi\u015f\u0259dvm\u0259bl\u0259\u011fimanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u00d6d\u0259nilmi\u015f \u018fDV m\u0259bl\u0259\u011fi,manatla", "precision": "2" @@ -84,7 +84,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-02-04 18:48:15.462987", + "modified": "2026-07-10 10:00:00.000000", "modified_by": "Administrator", "module": "Taxes Az", "name": "Declaration of value added tax yeni elave 1", diff --git a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1_2/declaration_of_value_added_tax_yeni_elave_1_2.json b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1_2/declaration_of_value_added_tax_yeni_elave_1_2.json index a80c849..b510b82 100644 --- a/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1_2/declaration_of_value_added_tax_yeni_elave_1_2.json +++ b/taxes_az/taxes_az/doctype/declaration_of_value_added_tax_yeni_elave_1_2/declaration_of_value_added_tax_yeni_elave_1_2.json @@ -22,28 +22,28 @@ }, { "fieldname": "\u00fcmumim\u0259bl\u0259\u011fmanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u00dcmumi m\u0259bl\u0259\u011f,manatla", "precision": "2" }, { "fieldname": "\u0259dvm\u0259bl\u0259\u011fimanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u018fDV m\u0259bl\u0259\u011fi,manatla", "precision": "2" }, { "fieldname": "\u00f6d\u0259nilmi\u015f\u00fcmumim\u0259bl\u0259\u011fmanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u00d6d\u0259nilmi\u015f \u00fcmumi m\u0259bl\u0259\u011f,manatla", "precision": "2" }, { "fieldname": "\u00f6d\u0259nilmi\u015f\u0259dvm\u0259bl\u0259\u011fimanatla", - "fieldtype": "Int", + "fieldtype": "Float", "in_list_view": 1, "label": "\u00d6d\u0259nilmi\u015f \u018fDV m\u0259bl\u0259\u011fi,manatla", "precision": "2" @@ -52,7 +52,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-02-04 18:50:57.540374", + "modified": "2026-07-10 10:00:00.000000", "modified_by": "Administrator", "module": "Taxes Az", "name": "Declaration of value added tax yeni elave 1_2", diff --git a/taxes_az/taxes_az/report/purchase_vat_offset_report/purchase_vat_offset_report.py b/taxes_az/taxes_az/report/purchase_vat_offset_report/purchase_vat_offset_report.py index f11aed1..b406867 100644 --- a/taxes_az/taxes_az/report/purchase_vat_offset_report/purchase_vat_offset_report.py +++ b/taxes_az/taxes_az/report/purchase_vat_offset_report/purchase_vat_offset_report.py @@ -110,6 +110,7 @@ def get_data(filters=None): rows = frappe.db.sql(f""" SELECT pi.name AS purchase_invoice, + pi.posting_date, pi.vat_offset_line_code AS line_code, pi.supplier_name, sup.tax_id, @@ -145,6 +146,7 @@ def get_data(filters=None): data.append({ "purchase_invoice": r.purchase_invoice, + "posting_date": r.posting_date, "line_code": r.line_code, "voen_name": f"{(r.tax_id or '').strip()} / {(r.supplier_name or '').strip()}", "invoice_series": r.etaxes_invoice_series,