feat(property-tax-gov): rework property_tax_gov client script; add RU architecture doc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6d6ff50afe
commit
d370d74e32
|
|
@ -0,0 +1,218 @@
|
|||
# Property Tax Gov — полный разбор
|
||||
|
||||
## Назначение
|
||||
|
||||
Это доктайп для формирования **декларации по налогу на имущество** (Əmlak vergisinin
|
||||
bəyannaməsi) для азербайджанской системы E-Taxes. Он берёт данные об основных средствах
|
||||
(Asset) из ERPNext, агрегирует их, рассчитывает налог по формулам, извлечённым из самого
|
||||
кабинета new.e-taxes.gov.az, и экспортирует результат в XML для подачи.
|
||||
|
||||
Это часть пилота **Property Tax Gov** — нового семейства доктайпов с расчётом «по странице,
|
||||
без авторизации», заменяющего старые `property_tax_return_ai`.
|
||||
|
||||
## Файлы доктайпа
|
||||
|
||||
| Файл | Роль |
|
||||
|------|------|
|
||||
| `property_tax_gov.json` | Определение полей: 3 таба, ~8 дочерних таблиц |
|
||||
| `property_tax_gov.py` | Бэкенд: агрегация Asset → строки таблиц + мост к Node-калькулятору |
|
||||
| `property_tax_gov.js` | Клиент: автозаполнение, расчёт формул, валидация, XML-экспорт |
|
||||
| `gns_property_calc.bundle.js` | Извлечённый из кабинета ГНС `useCalculation` (эталон формул) |
|
||||
| `gns_property_calc_cli.js` | stdin/stdout-обёртка Node для bundle |
|
||||
|
||||
---
|
||||
|
||||
## 1. Структура формы (JSON)
|
||||
|
||||
Три основных таба:
|
||||
|
||||
1. **Ümumi məlumat** (Общая информация) — шапка декларации: налоговый орган
|
||||
(`vergiorqanı` — большой Select со всеми территориальными управлениями), год (`il`),
|
||||
ВОЕН, ФИО/название плательщика, тип плательщика (Hüquqi/Fiziki), вид деклараций и т.д.
|
||||
|
||||
2. **Əmlak vergisinin hesablanması** (Расчёт налога на имущество) — 8 «cədvəl»
|
||||
(расчётных таблиц):
|
||||
- `vergi_hesab_1ci` / `vergi_hesab_1ci_1` — остаток на начало года (501) / на дату создания (503)
|
||||
- `vergi_hesab_2ci` — остаток на конец года (504)
|
||||
- `vergi_hesab_3cu` — сверхзастрахованные ОС (505)
|
||||
- `vergi_hesab_4cu` — ставка налога (506), `vergi_hesab_4cu_1` — кол-во месяцев (507)
|
||||
- `vergi_hesab_5ci` — рассчитанный налог (509/510)
|
||||
- `vergi_hesab_6ci` — сумма к уплате в бюджет (511)
|
||||
|
||||
3. **Əlavə 1** (`elave_1`) и **Əlavə 2** (`elave_2`) — два приложения, **источники данных**:
|
||||
- **Əlavə 1** — имущество, **освобождённое** от налога, сгруппированное по статьям НК
|
||||
(199.1, 199.4.1, 207.3 …). Ключевое поле строки — `azadolmasəbəbi` (основание освобождения).
|
||||
- **Əlavə 2** — имущество, **подлежащее** налогообложению, по категориям (Binalar,
|
||||
Mənzillər, Nəqliyyat vasitələri …). Ключевое поле — `vergiyəcəlbolunanəmlaklarınkateqoriyası`.
|
||||
|
||||
### Ключевая развилка: два режима
|
||||
|
||||
Два взаимоисключающих чекбокса в шапке управляют всей логикой:
|
||||
|
||||
- **`tam_il`** (Tam İl) — компания работала **полный год**.
|
||||
- **`il_erzinde`** (İl Ərzində) — компания **создана в течение года** (неполный период).
|
||||
|
||||
Клиентский код (`setup_checkbox_exclusivity`, обработчики `tam_il`/`il_erzinde`) гарантирует,
|
||||
что ровно один из них всегда включён.
|
||||
|
||||
---
|
||||
|
||||
## 2. Автозаполнение из Asset (Python-бэкенд)
|
||||
|
||||
Когда выбран год и режим, JS вызывает `reload_property_tax_data()` → серверный
|
||||
`populate_property_tax_tables()`.
|
||||
|
||||
**Поток данных:**
|
||||
|
||||
```
|
||||
tabAsset (docstatus=1, company, purchase_date<=to_date)
|
||||
│
|
||||
├─ taxable_asset_type заполнен ──→ get_taxable_assets_aggregated() ──→ Əlavə 2
|
||||
└─ industrial/tax_exempt_tax_article ─→ get_tax_exempt_assets_aggregated() ─→ Əlavə 1
|
||||
```
|
||||
|
||||
Сердце расчёта — `get_asset_balances_using_standard_logic()`. Это **точная репликация
|
||||
стандартного отчёта ERPNext «Asset Depreciations and Balances»**:
|
||||
|
||||
- `get_asset_cost_details` — валовая стоимость (на начало периода, новые покупки,
|
||||
проданные/списанные/капитализированные);
|
||||
- `get_asset_depreciation_details` — накопленная амортизация из GL Entry
|
||||
(через `tabAsset Category Account`);
|
||||
- `get_asset_value_adjustments` — переоценки.
|
||||
|
||||
Из них считается `net_asset_value_as_on_from_date/to_date` (остаточная стоимость).
|
||||
Плюс `insurance_value` = (застрахованная сумма − валовая стоимость), если объект
|
||||
застрахован выше стоимости.
|
||||
|
||||
**Версионная совместимость:** код проверяет колонки таблицы Asset и сам выбирает
|
||||
`gross_purchase_amount` / `net_purchase_amount` / `purchase_amount`, потому что ERPNext v15
|
||||
переименовал поле (`gross_purchase_amount` → `net_purchase_amount`).
|
||||
|
||||
**Сопоставление со строками таблиц** — нечёткое (fuzzy):
|
||||
- `extract_article_number()` достаёт «199.1» из «Vergi Məcəlləsinin 199.1-ci maddəsinə əsasən»
|
||||
регуляркой;
|
||||
- `find_matching_azadolma_sebeb()` ищет строку Əlavə 1, чей `azadolmasəbəbi` содержит этот номер;
|
||||
- `find_matching_category()` сопоставляет `taxable_asset_type` со строкой Əlavə 2 по частичному
|
||||
вхождению («Mənzillər» ↔ «1.5 Mənzillər»).
|
||||
|
||||
**Бизнес-правило для İl Ərzində:** если у компании, созданной в течение года, нет новых покупок
|
||||
(`value_of_new_purchase < 0.01`), все поля строки обнуляются. Также в зависимости от режима
|
||||
данные кладутся в разные колонки: в `tam_il` — в «остаток на начало года» (501),
|
||||
в `il_erzinde` — в «принято на учёт в течение года» (503).
|
||||
|
||||
Сервер возвращает не строки, а **карты `{ключ_строки: {поле: значение}}`**, а уже клиент
|
||||
применяет их к существующим строкам через `update_child_table_values()`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Расчётный движок (клиент)
|
||||
|
||||
Здесь самое тонкое место. Файл содержит **два поколения кода расчёта**, и работает только второе.
|
||||
|
||||
### Старый код (строки 269–919)
|
||||
Ручные функции: `calculate_509_1`, `calculate_509_2`, `calculate_binalar_totals`,
|
||||
`calculate_elave_*_totals`, `calculate_vergi_hesab_3cu_totals`. Они напрямую считали формулы:
|
||||
- `509.1 = ((501.1 + 504.1) / 2) * 1% + 505.1 * 1%` (полный год);
|
||||
- `509.2 = ((503.1 + 504.1) / 24 * 507) * 1% + 505.1 * 1%` (неполный год, 507 = число месяцев).
|
||||
|
||||
### Новый код (строки 1042–1264) — **активный**
|
||||
|
||||
В конце файла все шесть `calculate_*` **переопределены заново** как тонкие делегаторы:
|
||||
|
||||
```js
|
||||
function calculate_509_1(frm) { gns_property_recalc(frm); }
|
||||
// ... и т.д.
|
||||
```
|
||||
|
||||
Это работает за счёт **hoisting функций в JS: последнее объявление побеждает**. То есть все
|
||||
старые триггеры (обработчики дочерних таблиц на строках 924–1040) теперь незаметно вызывают
|
||||
новый единый движок `gns_property_recalc()`. Старые тела функций мертвы, но оставлены.
|
||||
|
||||
**Как считает новый движок** (`_gns_property_recalc_now`):
|
||||
|
||||
1. `ptgov_sum()` суммирует строки `elave_1` → объект `a1` (приложение 1, освобождённые),
|
||||
`elave_2` → `a2` (облагаемые). При суммировании Əlavə 2 исключаются «итоговые» строки —
|
||||
родитель «1. Binalar» и «CƏMİ» (`ptgov_is_excluded_e2`).
|
||||
2. `full = !il_erzinde`, `months` берётся из строки 507.
|
||||
3. `ptgov_calc_byArticle()` строит карту `{номер_статьи: значение}` — те же формулы, что и в
|
||||
старом коде, но в одном месте, с округлением half-up до 2 знаков (`ptgov_round2`). Облагается
|
||||
**только** Əlavə 2; 511 (к уплате) = 509.
|
||||
4. Результаты разносятся по всем выходным cədvəl-таблицам: по номеру статьи (`ptgov_article`
|
||||
парсит «509.1» из метки `göstəricilər`) в поле `manatla`; ставка 506 → `faizlə = 1`.
|
||||
|
||||
**Защита от рекурсии:** флаг `frm.__ptgov_writing` ставится перед записью значений, чтобы наши же
|
||||
`set_value` не зациклили обработчики `manatla`. Плюс debounce 250 мс (`_ptgov_timer`).
|
||||
|
||||
### Про Node-мост (`compute_via_gns` + bundle)
|
||||
По задумке предполагалось гонять **родной калькулятор кабинета** (`useCalculation`, извлечённый
|
||||
в `gns_property_calc.bundle.js`) офлайн через Node-subprocess. Сейчас же, как явно сказано в
|
||||
комментарии (строки 1103–1107), **формулы переписаны нативно в JS**, а bundle и
|
||||
`compute_via_gns` остаются в репо как **эталонный источник**, из которого формулы выведены и
|
||||
сверены. То есть в рантайме Node не вызывается — всё считается в браузере.
|
||||
|
||||
---
|
||||
|
||||
## 4. Условная логика отображения
|
||||
|
||||
`apply_conditional_table_logic()` показывает/прячет таблицы под режим:
|
||||
- `tam_il` → видна `vergi_hesab_1ci` (501); строки 509.1/511.1 в 5-й/6-й таблицах;
|
||||
- `il_erzinde` → видны `vergi_hesab_1ci_1` (503) и `vergi_hesab_4cu_1` (месяцы); строки
|
||||
509.2/511.2; колонки 501.x скрываются (`toggle_field_readonly`).
|
||||
|
||||
Строки 5-й/6-й таблиц **полностью пересоздаются** под режим (`filter_vergi_hesab_5ci_rows`),
|
||||
при этом старые значения сохраняются в `window.property_tax_saved_values` и восстанавливаются.
|
||||
|
||||
`calculate_months_for_vergi_hesab_4cu_1()` (Python) находит самый ранний Asset по
|
||||
`available_for_use_date` в году и считает число месяцев до конца года для формулы 509.2.
|
||||
|
||||
---
|
||||
|
||||
## 5. Валидация
|
||||
|
||||
`validate_minimum_asset_value()` — только в режиме `il_erzinde`: стоимость ОС в колонках
|
||||
503.1/503.2 не может быть **< 500 манат** (но > 0). При нарушении:
|
||||
- блокирует сохранение (`frm.validated = false`);
|
||||
- подсвечивает ячейки красным (`highlight_invalid_cells`);
|
||||
- показывает HTML-предупреждение и ставит 🔴 в заголовок таба (`update_tab_title`).
|
||||
|
||||
---
|
||||
|
||||
## 6. Шаблонные строки и кнопки
|
||||
|
||||
- `ptgov_ensure_rows()` — при `refresh` заполняет пустые дочерние таблицы каноническими наборами
|
||||
строк (`PTGOV_E1_ROWS` — 23 статьи освобождения, `PTGOV_E2_ROWS` — 12 категорий, cədvəl-таблицы
|
||||
— из `options` поля `göstəricilər`).
|
||||
- `ptgov_set_readonly()` — делает вычисляемые колонки (`manatla`, `faizlə`) read-only.
|
||||
- Кнопки: **«Şablon sətirləri yarat»** (создать шаблонные строки), **«ГНС ilə hesabla»**
|
||||
(пересчитать вручную), **«Export XML»** (через `xml_mapping_tool.generate_xml`).
|
||||
|
||||
---
|
||||
|
||||
## Сводный поток работы
|
||||
|
||||
```
|
||||
Пользователь: выбирает год + режим (Tam İl / İl Ərzində)
|
||||
↓
|
||||
JS reload_property_tax_data → Python populate_property_tax_tables
|
||||
↓
|
||||
tabAsset → агрегация (ERPNext balance-логика) → карты {строка: значения}
|
||||
↓
|
||||
JS раскладывает по Əlavə 1 / Əlavə 2
|
||||
↓
|
||||
любое изменение строки → gns_property_recalc (debounce 250ms)
|
||||
↓
|
||||
ptgov_sum → ptgov_calc_byArticle → разнос по cədvəl (501→511)
|
||||
↓
|
||||
валидация (min 500 ман.) → Export XML → подача в E-Taxes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Главное при правках этого файла
|
||||
|
||||
1. Активен только **второй** блок расчёта (делегаторы внизу). Старые `calculate_509_*` —
|
||||
мёртвый код, переопределён hoisting'ом. Правь `ptgov_calc_byArticle`, а не их.
|
||||
2. Сопоставление Asset ↔ строки таблиц — **нечёткое по подстроке**, легко ломается при
|
||||
изменении меток строк.
|
||||
3. Поля имеют азербайджанские имена с диакритикой (`göstəricilər`, `manatla`) — копируй точно.
|
||||
4. Node-мост (`compute_via_gns`) сейчас не в рантайме, а как эталон формул.
|
||||
|
|
@ -1097,64 +1097,76 @@ function gns_property_recalc(frm) {
|
|||
_ptgov_timer = setTimeout(function () { _gns_property_recalc_now(frm); }, 250);
|
||||
}
|
||||
|
||||
// half-up rounding to 2 decimals (matches the cabinet's decimal rounding)
|
||||
function ptgov_round2(x) { return Math.round((flt(x) + Number.EPSILON) * 100) / 100; }
|
||||
|
||||
// LOCAL implementation of the property-tax formulas. The formulas/logic were extracted &
|
||||
// verified from the GNS cabinet (new.e-taxes.gov.az) — see .etaxes_notes/scratch/calc_extract.
|
||||
// Only the +,-,*,/ run here (locally, offline). The cabinet is the SOURCE of the formulas,
|
||||
// not a runtime dependency; compute_via_gns + the extracted bundle stay in the repo as the
|
||||
// reference from which these were derived.
|
||||
// a1 = appendix1 (taxFree) totals, a2 = appendix2 (taxable) totals, full = Tam İl
|
||||
function ptgov_calc_byArticle(a1, a2, full, months) {
|
||||
const RATE = 0.01; // 506 taxDegree = 1% for legal entities
|
||||
const by = {};
|
||||
if (full) {
|
||||
// 501 prePeriod (beginning of year): total = taxable + tax-exempt
|
||||
by['501.1'] = a2.periodStart; // taxable residual
|
||||
by['501.2'] = a1.periodStart; // tax-exempt residual
|
||||
by['501'] = a2.periodStart + a1.periodStart;
|
||||
} else {
|
||||
// 503 createDate (newly established during the year)
|
||||
by['503.1'] = a2.onCreate;
|
||||
by['503.2'] = a1.created;
|
||||
by['503'] = a2.onCreate + a1.created;
|
||||
}
|
||||
// 504 endYear
|
||||
by['504.1'] = a2.periodEnd;
|
||||
by['504.2'] = a1.endYear;
|
||||
by['504'] = a2.periodEnd + a1.endYear;
|
||||
// 505 excess-insured
|
||||
by['505.1'] = a2.excess;
|
||||
by['505.2'] = a1.over;
|
||||
by['505'] = a2.excess + a1.over;
|
||||
// 509 calculated tax — only taxable (appendix2) is taxed; 511 shouldBePaid mirrors it
|
||||
let tax;
|
||||
if (full) {
|
||||
tax = ptgov_round2((a2.periodStart + a2.periodEnd) / 2 * RATE + a2.excess * RATE);
|
||||
by['509.1'] = tax; by['511.1'] = tax;
|
||||
} else {
|
||||
tax = ptgov_round2((a2.onCreate + a2.periodEnd) / 24 * flt(months) * RATE + a2.excess * RATE);
|
||||
by['509.2'] = tax; by['511.2'] = tax;
|
||||
}
|
||||
return by;
|
||||
}
|
||||
|
||||
function _gns_property_recalc_now(frm) {
|
||||
const e1 = ptgov_sum(frm.doc.elave_1, PTGOV_E1);
|
||||
const e2 = ptgov_sum(frm.doc.elave_2, PTGOV_E2, ptgov_is_excluded_e2);
|
||||
|
||||
const activity = frm.doc.il_erzinde ? 'OBJECT_ESTABLISHED' : 'OBJECT_FULL_ACTIVITY';
|
||||
|
||||
// months (507): read from the 4cu cedvel 1 (ayla) row, used only for OBJECT_ESTABLISHED
|
||||
let months = null;
|
||||
const a1 = ptgov_sum(frm.doc.elave_1, PTGOV_E1);
|
||||
const a2 = ptgov_sum(frm.doc.elave_2, PTGOV_E2, ptgov_is_excluded_e2);
|
||||
const full = !frm.doc.il_erzinde;
|
||||
let months = 0;
|
||||
(frm.doc.vergi_hesab_4cu_1 || []).forEach(function (r) {
|
||||
if (ptgov_article(r.göstəricilər) === '507') months = flt(r.ayla);
|
||||
});
|
||||
const byArt = ptgov_calc_byArticle(a1, a2, full, months);
|
||||
|
||||
const payload = {
|
||||
objectActivity: activity,
|
||||
calculation: {
|
||||
monthCountFromStartPeriod: activity === 'OBJECT_ESTABLISHED' ? months : null,
|
||||
monthCountToLiquidation: null,
|
||||
},
|
||||
appendix1: {
|
||||
periodStartTotal: e1.periodStart, createdTotal: e1.created,
|
||||
removedTotal: e1.removed, endYearTotal: e1.endYear, overTotal: e1.over,
|
||||
},
|
||||
appendix2: {
|
||||
periodStartTotal: e2.periodStart, onCreateDateTotal: e2.onCreate,
|
||||
onCancelDateTotal: e2.onCancel, periodEndTotal: e2.periodEnd,
|
||||
excessInsuredTotal: e2.excess,
|
||||
},
|
||||
};
|
||||
|
||||
frappe.call({
|
||||
method: 'taxes_az.taxes_az.doctype.property_tax_gov.property_tax_gov.compute_via_gns',
|
||||
args: { payload: JSON.stringify(payload) },
|
||||
callback: function (r) {
|
||||
if (!r.message || !r.message.byArticle) return;
|
||||
const byArt = r.message.byArticle;
|
||||
frm.__ptgov_writing = true; // guard: our set_value writes retrigger manatla handlers
|
||||
try {
|
||||
// write computed values into the calculation cedvel rows (manatla) by article number
|
||||
PTGOV_OUT_TABLES.forEach(function (tbl) {
|
||||
(frm.doc[tbl] || []).forEach(function (row) {
|
||||
const art = ptgov_article(row.göstəricilər);
|
||||
if (art != null && byArt[art] != null) {
|
||||
frappe.model.set_value(row.doctype, row.name, 'manatla', flt(byArt[art]));
|
||||
}
|
||||
});
|
||||
});
|
||||
// tax rate (506) is the constant 1% for legal entities
|
||||
(frm.doc.vergi_hesab_4cu || []).forEach(function (row) {
|
||||
if (ptgov_article(row.göstəricilər) === '506') {
|
||||
frappe.model.set_value(row.doctype, row.name, 'faizlə', 1);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
PTGOV_OUT_TABLES.concat(['vergi_hesab_4cu']).forEach(function (t) { frm.refresh_field(t); });
|
||||
setTimeout(function () { frm.__ptgov_writing = false; }, 0); // release after sync triggers flush
|
||||
frm.__ptgov_writing = true; // guard: our set_value writes retrigger manatla handlers
|
||||
try {
|
||||
PTGOV_OUT_TABLES.forEach(function (tbl) {
|
||||
(frm.doc[tbl] || []).forEach(function (row) {
|
||||
const art = ptgov_article(row.göstəricilər);
|
||||
frappe.model.set_value(row.doctype, row.name, 'manatla', flt(byArt[art] || 0));
|
||||
});
|
||||
});
|
||||
(frm.doc.vergi_hesab_4cu || []).forEach(function (row) {
|
||||
if (ptgov_article(row.göstəricilər) === '506') {
|
||||
frappe.model.set_value(row.doctype, row.name, 'faizlə', 1);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
PTGOV_OUT_TABLES.concat(['vergi_hesab_4cu']).forEach(function (t) { frm.refresh_field(t); });
|
||||
setTimeout(function () { frm.__ptgov_writing = false; }, 0); // release after sync triggers flush
|
||||
}
|
||||
}
|
||||
|
||||
// ---- delegators: override the old hand-coded calc (hoisting: these win) ----
|
||||
|
|
@ -1165,41 +1177,85 @@ function calculate_vergi_hesab_3cu_totals(frm) { gns_property_recalc(frm); }
|
|||
function calculate_509_1(frm) { gns_property_recalc(frm); }
|
||||
function calculate_509_2(frm) { gns_property_recalc(frm); }
|
||||
|
||||
// ---- template rows: create one row per Select option for empty tables ----
|
||||
// (the form shipped without default rows for elave_1/2 and most cedvel tables;
|
||||
// autofill matches asset data to these rows and the calc writes results into them)
|
||||
const PTGOV_ROW_TEMPLATES = [
|
||||
['elave_1', 'azadolmasəbəbi'],
|
||||
['elave_2', 'vergiyəcəlbolunanəmlaklarınkateqoriyası'],
|
||||
['vergi_hesab_1ci', 'göstəricilər'],
|
||||
['vergi_hesab_1ci_1', 'göstəricilər'],
|
||||
['vergi_hesab_2ci', 'göstəricilər'],
|
||||
['vergi_hesab_3cu', 'göstəricilər'],
|
||||
['vergi_hesab_4cu', 'göstəricilər'],
|
||||
['vergi_hesab_4cu_1', 'göstəricilər'],
|
||||
['vergi_hesab_5ci', 'göstəricilər'],
|
||||
['vergi_hesab_6ci', 'göstəricilər'],
|
||||
// ---- template rows: identical to the original doctype's Default Client Scripts ----
|
||||
// elave_1/elave_2 use the exact curated row sets; cedvel tables use their göstərici options.
|
||||
const PTGOV_E1_ROWS = [
|
||||
"Vergi Məcəlləsinin 199.1-ci maddəsinə əsasən azaldılmalı əmlak vergisinin məbləği",
|
||||
"Vergi Məcəlləsinin 199.4.1-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.4.2-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.4.3-cü maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.4.4-cü maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.4.1-1-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.5-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.7-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.8-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.9-cu maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.11-cu maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.14-cu maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.15-cu maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.16-cı maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.17-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.18-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.19-cu maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 199.20-ci maddəsinə əsasən:",
|
||||
"Vergi Məcəlləsinin 227.1-ci maddəsinə əsasən:",
|
||||
"Qanunla təsdiq olunmuş hasilatın pay bölgüsü haqqında, əsas boru kəməri haqqında və digər bu qəbildən olan sazişlərdə və ya qanunlarda, o cümlədən neft və qaz haqqında, ixrac məqsədli neft-qaz fəaliyyəti üzrə:",
|
||||
"Xüsusi iqtisadi zonalar haqqında qanunlarda nəzərdə tutulan əmlaklar üzrə:",
|
||||
"Azərbaycan Respublikasının tərəfdar çıxdığı beynəlxalq müqavilələr üzrə:",
|
||||
"Vergidən azad olunan əmlakın CƏMİ dəyəri:",
|
||||
];
|
||||
const PTGOV_E2_ROWS = [
|
||||
"1. Binalar, tikililər və qurğular",
|
||||
"1.1 Çoxmərtəbəli (çoxmənzilli) yaşayış binaları",
|
||||
"1.2 Qeyri-yaşayış binaları (sahələri)",
|
||||
"1.3 Əmlak kompleksi kimi müəssisələr",
|
||||
"1.4 Qurğular",
|
||||
"1.5 Mənzillər",
|
||||
"1.6 Fərdi yaşayış və bağ evləri",
|
||||
"2 Maşınlar və avadanlıqlar",
|
||||
"3 Yüksək texnologiyalar məhsulu olan hesablama texnikası",
|
||||
"4 Nəqliyyat vasitələri",
|
||||
"5 Digər əsas vəsaitlər",
|
||||
"Vergiyə cəlb olunan əmlakın CƏMİ dəyəri:",
|
||||
];
|
||||
const PTGOV_CEDVEL_TABLES = ['vergi_hesab_1ci', 'vergi_hesab_1ci_1', 'vergi_hesab_2ci', 'vergi_hesab_3cu',
|
||||
'vergi_hesab_4cu', 'vergi_hesab_4cu_1', 'vergi_hesab_5ci', 'vergi_hesab_6ci'];
|
||||
|
||||
function ptgov_ensure_rows(frm) {
|
||||
let added = false;
|
||||
PTGOV_ROW_TEMPLATES.forEach(function (pair) {
|
||||
const tbl = pair[0], fld = pair[1];
|
||||
if ((frm.doc[tbl] || []).length) return; // already has rows -> skip
|
||||
function fill(tbl, fld, vals) {
|
||||
if ((frm.doc[tbl] || []).length) return; // already has rows -> skip
|
||||
vals.forEach(function (v) { frm.add_child(tbl)[fld] = v; });
|
||||
if (vals.length) { frm.refresh_field(tbl); added = true; }
|
||||
}
|
||||
fill('elave_1', 'azadolmasəbəbi', PTGOV_E1_ROWS);
|
||||
fill('elave_2', 'vergiyəcəlbolunanəmlaklarınkateqoriyası', PTGOV_E2_ROWS);
|
||||
PTGOV_CEDVEL_TABLES.forEach(function (tbl) {
|
||||
const field = frm.get_field(tbl);
|
||||
if (!field) return;
|
||||
const childDt = field.df.options;
|
||||
const df = frappe.meta.get_docfield(childDt, fld);
|
||||
const df = frappe.meta.get_docfield(field.df.options, 'göstəricilər');
|
||||
const opts = ((df && df.options) || '').split('\n').filter(function (x) { return x.trim(); });
|
||||
opts.forEach(function (opt) { frm.add_child(tbl)[fld] = opt; });
|
||||
if (opts.length) { frm.refresh_field(tbl); added = true; }
|
||||
fill(tbl, 'göstəricilər', opts);
|
||||
});
|
||||
return added;
|
||||
}
|
||||
|
||||
// make computed output columns read-only (the cedvel manatla/faizlə are calc results)
|
||||
function ptgov_set_readonly(frm) {
|
||||
const cols = [['vergi_hesab_1ci', 'manatla'], ['vergi_hesab_1ci_1', 'manatla'], ['vergi_hesab_2ci', 'manatla'],
|
||||
['vergi_hesab_3cu', 'manatla'], ['vergi_hesab_5ci', 'manatla'], ['vergi_hesab_6ci', 'manatla'],
|
||||
['vergi_hesab_4cu', 'faizlə']];
|
||||
cols.forEach(function (pair) {
|
||||
const f = frm.get_field(pair[0]);
|
||||
if (f && f.grid) f.grid.update_docfield_property(pair[1], 'read_only', 1);
|
||||
});
|
||||
}
|
||||
|
||||
// manual recalc button (autofill runs automatically on İl / Tam İl / İl Ərzində change)
|
||||
frappe.ui.form.on('Property Tax Gov', {
|
||||
refresh: function (frm) {
|
||||
ptgov_ensure_rows(frm); // populate empty child tables with their template rows
|
||||
ptgov_ensure_rows(frm); // populate empty child tables with their template rows
|
||||
ptgov_set_readonly(frm); // lock computed cedvel columns
|
||||
frm.add_custom_button('Şablon sətirləri yarat', function () {
|
||||
if (ptgov_ensure_rows(frm)) frappe.show_alert({ message: 'Şablon sətirləri yaradıldı', indicator: 'green' });
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue