feat(vat): auto-fill new Əlavə 1 tables and page totals
Fill the second Əlavə 1 tab (əlavə1_yeni) from the Purchase VAT offset report (Cədvəl 22), whose columns map one-to-one onto the table and whose vat_offset_line_code shares the 308/314/316 options of sətirkodu. The report gained a posting_date key so the tarix column can be filled; its visible columns are unchanged. Also fill three summary targets that were left to manual entry: - əlavə_1_2 totals over Əlavə 1 - əlavə1_2_yeni totals per line code - sertifikat...səhifəsicəmi page total of Əlavə 8 Tablo 2 The two summary tables already carry rows created by a client script, so they are filled in place — fill_first_row and fill_rows_by_code never add or remove rows. Rows are matched on the leading line code because the stored sətirkodu carries a long description after it. Widen the Int money fields to Float: paid VAT is proportional and was truncating (106.78 -> 107). Invoice number becomes Data, matching the report where it is a free-form string. Note: the generated Formula Editor client script still writes əlavə_1_2 and əlavə1_2_yeni row 0 from report() grand totals. Those 6 formula blocks are to be removed by hand; the Formula Editor record itself no longer defines them, so they will not be regenerated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1aba387f87
commit
4e4a6517c9
|
|
@ -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];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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ə 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,
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue