chore(property-tax): remove Property Tax Gov pilot doctypes
The Property Tax Gov family (parent + 10 child tables) was a duplicate of Property tax return, used as a pilot for page-based declaration calc. It is no longer needed; the original Property tax return is untouched and remains the only property-tax declaration. Both tables were empty (0 documents). `bench migrate` drops the orphaned DocTypes; the empty `tabProperty Tax Gov*` tables were dropped manually since migrate leaves them behind. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
94c25e19e2
commit
682902a828
|
|
@ -1,218 +0,0 @@
|
|||
# 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`) сейчас не в рантайме, а как эталон формул.
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,12 +0,0 @@
|
|||
// CLI: stdin JSON model -> stdout JSON of computed {path: value}. Used by property_tax_gov.py.
|
||||
const { calc } = require('./gns_property_calc.bundle.js');
|
||||
let d = '';
|
||||
process.stdin.on('data', (c) => (d += c));
|
||||
process.stdin.on('end', () => {
|
||||
try {
|
||||
process.stdout.write(JSON.stringify(calc(JSON.parse(d || '{}'))));
|
||||
} catch (e) {
|
||||
process.stderr.write(String((e && e.stack) || e));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,385 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 14:18:26.085350",
|
||||
"default_view": "List",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"\u00fcmumi_m\u0259lumat_tab",
|
||||
"html_pegz",
|
||||
"idar\u0259",
|
||||
"vergiorqan\u0131",
|
||||
"vergid\u00f6vr\u00fc",
|
||||
"il",
|
||||
"tam_il",
|
||||
"il_erzinde",
|
||||
"\u015f\u0259xsi",
|
||||
"v\u00f6en",
|
||||
"soyad\u0131",
|
||||
"atas\u0131n\u0131nad\u0131",
|
||||
"mobn\u00f6mr\u02591",
|
||||
"mobn\u00f6mr\u02592",
|
||||
"column_break_yjgp",
|
||||
"\u00f6d\u0259yicitipi",
|
||||
"ad\u0131",
|
||||
"\u015f\u0259h\u0259rn\u00f6mr\u0259si1",
|
||||
"\u015f\u0259h\u0259rn\u00f6mr\u0259si2",
|
||||
"section_break_pcfz",
|
||||
"\u0259sasf\u0259aliyy\u0259tn\u00f6v\u00fcn\u00fcnkodu",
|
||||
"t\u0259qdimolunmu\u015f\u0259lav\u0259l\u0259rinsay\u0131",
|
||||
"b\u0259yannam\u0259ninn\u00f6v\u00fc",
|
||||
"d\u0259qiql\u0259\u015fdirilmi\u015fb\u0259yannam\u0259nint\u0259qdimedilm\u0259sibar\u0259d\u0259bildiri\u015f",
|
||||
"column_break_xcxz",
|
||||
"section_break_vfvd",
|
||||
"b\u0259yan_edil\u0259c\u0259k_m\u0259lumat\u0131m_yoxdur",
|
||||
"section_break_wnwr",
|
||||
"column_break_dblg",
|
||||
"s\u0259tirl\u0259rd\u0259nbirinise\u00e7in",
|
||||
"\u0259mlak_vergisinin_hesablanmas\u0131_tab",
|
||||
"html_ikbb",
|
||||
"vergi_hesab_1ci",
|
||||
"html_uhqz",
|
||||
"vergi_hesab_1ci_1",
|
||||
"section_break_bhtd",
|
||||
"html_umxi",
|
||||
"vergi_hesab_2ci",
|
||||
"section_break_fugy",
|
||||
"html_exjg",
|
||||
"vergi_hesab_3cu",
|
||||
"section_break_bhet",
|
||||
"html_tuak",
|
||||
"vergi_hesab_4cu",
|
||||
"vergi_hesab_4cu_1",
|
||||
"section_break_cnpg",
|
||||
"html_mxir",
|
||||
"vergi_hesab_5ci",
|
||||
"section_break_klzd",
|
||||
"html_ctml",
|
||||
"vergi_hesab_6ci",
|
||||
"\u0259lav\u0259_1_tab",
|
||||
"html_hken",
|
||||
"warning_elave_1_html",
|
||||
"elave_1",
|
||||
"\u0259lav\u0259_2_tab",
|
||||
"html_ybie",
|
||||
"elave_2"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "\u00fcmumi_m\u0259lumat_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "\u00dcmumi m\u0259lumat"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_pegz",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 20px;font-weight: bold;color: blue;\"> \u018fmlak vergisinin b\u0259yannam\u0259si</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergiorqan\u0131",
|
||||
"fieldtype": "Select",
|
||||
"label": "Vergi orqan\u0131",
|
||||
"options": "2 sayl\u0131 \u018frazi Vergil\u0259r Ba\u015f idar\u0259si\tSumqay\u0131t\t02\n3 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\tQuba\t03\n4 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\t\u015eamax\u0131\t04\n5 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\t\u015eirvan\t05\n6 sayl\u0131 \u018frazi Vergil\u0259r Ba\u015f \u0130dar\u0259si\tL\u0259nk\u0259ran\t06\nQaraba\u011f \u018frazi Vergil\u0259r Ba\u015f \u0130dar\u0259si\tA\u011fdam, F\u00fczuli, \u015eu\u015fa, Xocal\u0131, Xocav\u0259nd\t07\n8 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\tBeyl\u0259qan\t08\n9 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\tG\u00f6y\u00e7ay\t09\n10 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\tQ\u0259b\u0259l\u0259\t10\n11 sayl\u0131 \u018frazi Vergil\u0259r Ba\u015f \u0130dar\u0259si\tYevlax\t11\n12 sayl\u0131 \u018frazi Vergil\u0259r Ba\u015f \u0130dar\u0259si\tG\u0259nc\u0259\t12\n13 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\tZaqatala\t13\n14 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si\t\u015e\u0259mkir\t14\nD\u00f6vl\u0259t Vergi xidm\u0259tinin Milli G\u0259lirl\u0259r Ba\u015f idar\u0259si\tBak\u0131\t16\nD\u00f6vl\u0259t Vergi xidm\u0259tinin Bak\u0131 \u015f\u0259h\u0259ri Lokal G\u0259lirl\u0259r Ba\u015f idar\u0259si\tBak\u0131\t19\nD\u00f6vl\u0259t Vergi xidm\u0259tinin Bak\u0131 \u015f\u0259h\u0259ri Ki\u00e7ik Sahibkarl\u0131qla \u0130\u015f \u00fczr\u0259 Ba\u015f idar\u0259si\tBak\u0131\t39\nNax\u00e7\u0131van \u015f\u0259h\u0259ri \u00fczr\u0259 Vergil\u0259r \u0130dar\u0259si\tNax\u00e7\u0131van\t27\n2 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si (Nax\u00e7\u0131van MR)\t\u015e\u0259rur, S\u0259d\u0259r\u0259k, K\u0259ng\u0259rli\t30\n3 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si (Nax\u00e7\u0131van MR)\t\u015eahbuz, Bab\u0259k\t26\n4 sayl\u0131 \u018frazi Vergil\u0259r \u0130dar\u0259si (Nax\u00e7\u0131van MR)\tCulfa, Ordubad\t24\n\u015e\u0259rqi Z\u0259ng\u0259zur \u018frazi Vergil\u0259r \u0130dar\u0259si\tC\u0259bray\u0131l, K\u0259lb\u0259c\u0259r, La\u00e7\u0131n, Qubadl\u0131, Z\u0259ngilan\t55"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergid\u00f6vr\u00fc",
|
||||
"fieldtype": "Select",
|
||||
"label": "Vergi d\u00f6vr\u00fc",
|
||||
"options": "\u0130llik"
|
||||
},
|
||||
{
|
||||
"fieldname": "il",
|
||||
"fieldtype": "Int",
|
||||
"label": "\u0130l",
|
||||
"length": 4
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "tam_il",
|
||||
"fieldtype": "Check",
|
||||
"label": "Tam \u0130l"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "il_erzinde",
|
||||
"fieldtype": "Check",
|
||||
"label": "\u0130l \u018frzind\u0259"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u015f\u0259xsi",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "\u015e\u0259xsi"
|
||||
},
|
||||
{
|
||||
"fieldname": "v\u00f6en",
|
||||
"fieldtype": "Int",
|
||||
"label": "V\u00d6EN"
|
||||
},
|
||||
{
|
||||
"fieldname": "soyad\u0131",
|
||||
"fieldtype": "Data",
|
||||
"label": "Soyad\u0131"
|
||||
},
|
||||
{
|
||||
"fieldname": "atas\u0131n\u0131nad\u0131",
|
||||
"fieldtype": "Data",
|
||||
"label": "Atas\u0131n\u0131n ad\u0131"
|
||||
},
|
||||
{
|
||||
"fieldname": "mobn\u00f6mr\u02591",
|
||||
"fieldtype": "Int",
|
||||
"label": "Mob n\u00f6mr\u0259 1"
|
||||
},
|
||||
{
|
||||
"fieldname": "mobn\u00f6mr\u02592",
|
||||
"fieldtype": "Int",
|
||||
"label": "Mob n\u00f6mr\u0259 2"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_yjgp",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u00f6d\u0259yicitipi",
|
||||
"fieldtype": "Select",
|
||||
"label": "\u00d6d\u0259yici tipi",
|
||||
"options": "H\u00fcquqi\nFiziki"
|
||||
},
|
||||
{
|
||||
"fieldname": "ad\u0131",
|
||||
"fieldtype": "Data",
|
||||
"label": "Ad\u0131"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u015f\u0259h\u0259rn\u00f6mr\u0259si1",
|
||||
"fieldtype": "Int",
|
||||
"label": "\u015e\u0259h\u0259r n\u00f6mr\u0259si 1"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u015f\u0259h\u0259rn\u00f6mr\u0259si2",
|
||||
"fieldtype": "Int",
|
||||
"label": "\u015e\u0259h\u0259r n\u00f6mr\u0259si 2"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_pcfz",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u0259sasf\u0259aliyy\u0259tn\u00f6v\u00fcn\u00fcnkodu",
|
||||
"fieldtype": "Int",
|
||||
"label": "\u018fsas f\u0259aliyy\u0259t n\u00f6v\u00fcn\u00fcn kodu"
|
||||
},
|
||||
{
|
||||
"fieldname": "t\u0259qdimolunmu\u015f\u0259lav\u0259l\u0259rinsay\u0131",
|
||||
"fieldtype": "Int",
|
||||
"label": "T\u0259qdim olunmu\u015f \u0259lav\u0259l\u0259rin say\u0131"
|
||||
},
|
||||
{
|
||||
"fieldname": "b\u0259yannam\u0259ninn\u00f6v\u00fc",
|
||||
"fieldtype": "Select",
|
||||
"label": "B\u0259yannam\u0259nin n\u00f6v\u00fc",
|
||||
"options": "Cari\nD\u0259qiql\u0259\u015fdirilmi\u015f\nL\u0259\u011fv olma\nL\u0259\u011fvin d\u0259qiql\u0259\u015fdirilmi\u015fi\nAnaloji\nK\u00f6n\u00fcll\u00fc a\u00e7\u0131qlama"
|
||||
},
|
||||
{
|
||||
"fieldname": "d\u0259qiql\u0259\u015fdirilmi\u015fb\u0259yannam\u0259nint\u0259qdimedilm\u0259sibar\u0259d\u0259bildiri\u015f",
|
||||
"fieldtype": "Float",
|
||||
"label": "D\u0259qiql\u0259\u015fdirilmi\u015f b\u0259yannam\u0259nin t\u0259qdim edilm\u0259si bar\u0259d\u0259 bildiri\u015fin n\u00f6mr\u0259si",
|
||||
"precision": "2"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_xcxz",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_vfvd",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "b\u0259yan_edil\u0259c\u0259k_m\u0259lumat\u0131m_yoxdur",
|
||||
"fieldtype": "Check",
|
||||
"label": "B\u0259yan edil\u0259c\u0259k m\u0259lumat\u0131m yoxdur"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_ikbb",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> Hesabat ilinin \u0259vv\u0259lin\u0259</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u0259lav\u0259_1_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"js_parent_subtab": "Verginin hesablanmas\u0131",
|
||||
"label": "\u018flav\u0259 1"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_ctml",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> B\u00fcdc\u0259y\u0259 \u00f6d\u0259nilm\u0259li verginin m\u0259bl\u0259\u011fi </p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_hken",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> Vergid\u0259n azad olunan \u0259mlak\u0131n d\u0259y\u0259ri haqq\u0131nda m\u0259lumat</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_ybie",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> Vergiy\u0259 c\u0259lb olunan \u0259sas v\u0259saitin d\u0259y\u0259ri haqq\u0131nda m\u0259lumat</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "warning_elave_1_html",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "\u0259mlak_vergisinin_hesablanmas\u0131_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "\u018fmlak vergisinin hesablanmas\u0131"
|
||||
},
|
||||
{
|
||||
"fieldname": "\u0259lav\u0259_2_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"js_parent_subtab": "Verginin hesablanmas\u0131",
|
||||
"label": "\u018flav\u0259 2"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_fugy",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_exjg",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> Art\u0131q qiym\u0259t\u0259 s\u0131\u011fortalanan \u0259sas v\u0259saitl\u0259r</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_bhet",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_tuak",
|
||||
"fieldtype": "HTML"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_bhtd",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_umxi",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> Hesabat ilinin sonuna</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_cnpg",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_mxir",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> Hesablanm\u0131\u015f verginin m\u0259bl\u0259\u011fi</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "idar\u0259",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "\u0130dar\u0259"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_klzd",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_1ci",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 1ci cedvel"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_2ci",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 2ci cedvel"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_3cu",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 3cu cedvel"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_4cu",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 4cu cedvel"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_5ci",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 5ci cedvel"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_6ci",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 6ci cedvel"
|
||||
},
|
||||
{
|
||||
"fieldname": "elave_1",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Elave 1"
|
||||
},
|
||||
{
|
||||
"fieldname": "elave_2",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Elave 2"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_wnwr",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "M\u00fc\u0259ssis\u0259 il \u0259rzind\u0259 tam f\u0259aliyy\u0259t g\u00f6st\u0259rdiyi halda",
|
||||
"fieldname": "s\u0259tirl\u0259rd\u0259nbirinise\u00e7in",
|
||||
"fieldtype": "Select",
|
||||
"label": "S\u0259tirl\u0259rd\u0259n birini se\u00e7in",
|
||||
"options": "M\u00fc\u0259ssis\u0259 il \u0259rzind\u0259 yarand\u0131\u011f\u0131 halda\nM\u00fc\u0259ssis\u0259 il \u0259rzind\u0259 tam f\u0259aliyy\u0259t g\u00f6st\u0259rdiyi halda"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_dblg",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "html_uhqz",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<p style=\"text-align: center;font-size: 15px;font-weight: bold;color: black;\"> M\u00fc\u0259ssis\u0259nin yaranma v\u0259 ya \u0259mlak vergisinin \u00f6d\u0259yicisi olma tarixin\u0259</p>"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_1ci_1",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 1ci cedvel 1"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergi_hesab_4cu_1",
|
||||
"fieldtype": "Table",
|
||||
"options": "Property Tax Gov Emlak vergi hesablamasi 4cu cedvel 1"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-12-29 18:27:42.028445",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,886 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt, add_days
|
||||
import re
|
||||
import json
|
||||
|
||||
|
||||
class PropertyTaxGov(Document):
|
||||
pass
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# GNS calc bridge — runs the cabinet's OWN calculation code (useCalculation,
|
||||
# extracted from new.e-taxes.gov.az declaration bundle) offline via Node.
|
||||
# No authorization / no network: the calc is pure functions over the model.
|
||||
# Bundle: gns_property_calc.bundle.js + gns_property_calc_cli.js (this dir).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _node_bin():
|
||||
import shutil, glob
|
||||
n = shutil.which("node")
|
||||
if n:
|
||||
return n
|
||||
cands = sorted(glob.glob("/home/frappe/.nvm/versions/node/*/bin/node"))
|
||||
return cands[-1] if cands else "node"
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def compute_via_gns(payload):
|
||||
"""Compute property-tax indicators with the GNS cabinet's own JS calc.
|
||||
|
||||
payload: dict (or JSON string) shaped as
|
||||
{
|
||||
"objectActivity": "OBJECT_FULL_ACTIVITY" | "OBJECT_ESTABLISHED" | "LIQUIDATION",
|
||||
"calculation": {"monthCountFromStartPeriod": int, "monthCountToLiquidation": int, ...},
|
||||
"appendix1": {"periodStartTotal","endYearTotal","overTotal","removedTotal","createdTotal"},
|
||||
"appendix2": {"periodStartTotal","periodEndTotal","excessInsuredTotal","onCreateDateTotal","onCancelDateTotal"}
|
||||
}
|
||||
Returns dict {"<step>.<group>.<indicatorCode>": value, ...} exactly as the cabinet computes.
|
||||
"""
|
||||
import os, subprocess
|
||||
|
||||
if isinstance(payload, str):
|
||||
payload = json.loads(payload)
|
||||
|
||||
cli = os.path.join(os.path.dirname(os.path.abspath(__file__)), "gns_property_calc_cli.js")
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
[_node_bin(), cli],
|
||||
input=json.dumps(payload),
|
||||
capture_output=True, text=True, timeout=30,
|
||||
)
|
||||
except Exception as e:
|
||||
frappe.throw(f"GNS calc invocation failed: {e}")
|
||||
|
||||
if proc.returncode != 0:
|
||||
frappe.throw(f"GNS calc error: {(proc.stderr or '')[:800]}")
|
||||
return json.loads(proc.stdout or "{}")
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def populate_property_tax_tables(company, year, from_date, to_date, calculation_mode, existing_elave_1, existing_elave_2):
|
||||
"""
|
||||
Main method to populate Property Tax Gov child tables from Asset data
|
||||
|
||||
Args:
|
||||
company: Company name
|
||||
year: Tax year (integer)
|
||||
from_date: Start date (YYYY-MM-DD)
|
||||
to_date: End date (YYYY-MM-DD)
|
||||
calculation_mode: 'tam_il' or 'il_erzinde'
|
||||
existing_elave_1: Existing Əlavə 1 rows (JSON array)
|
||||
existing_elave_2: Existing Əlavə 2 rows (JSON array)
|
||||
|
||||
Returns:
|
||||
Dictionary with elave_1_data and elave_2_data mappings
|
||||
"""
|
||||
try:
|
||||
# Parse JSON if needed
|
||||
if isinstance(existing_elave_1, str):
|
||||
existing_elave_1 = json.loads(existing_elave_1)
|
||||
if isinstance(existing_elave_2, str):
|
||||
existing_elave_2 = json.loads(existing_elave_2)
|
||||
|
||||
# Get aggregated asset data
|
||||
taxable_aggregated = get_taxable_assets_aggregated(company, from_date, to_date)
|
||||
tax_exempt_aggregated = get_tax_exempt_assets_aggregated(company, from_date, to_date)
|
||||
|
||||
# Map to rows with proper field names based on calculation_mode
|
||||
# Use fuzzy matching for Əlavə 2 (Taxable Assets)
|
||||
elave_2_data = {}
|
||||
for category, data in taxable_aggregated.items():
|
||||
# Find matching row by partial match (e.g., "Mənzillər" matches "1.5 Mənzillər")
|
||||
matching_key = find_matching_category(category, existing_elave_2)
|
||||
|
||||
if matching_key:
|
||||
if calculation_mode == 'tam_il':
|
||||
elave_2_data[matching_key] = {
|
||||
'hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyəri': data['value_as_on_from_date'],
|
||||
'hesabatilinsonunaəsasvəsaitlərinqalıqdəyəri': data['net_asset_value_as_on_to_date'],
|
||||
'hesabatilierzindeuçotaalınan': 0,
|
||||
'artıqqiymətəəsasvəsaitlərindəyəri505': data['insurance_value']
|
||||
}
|
||||
else: # il_erzinde
|
||||
# Бизнес-правило: Для компаний, созданных в течение года (İl Ərzində),
|
||||
# если нет новых покупок (value_of_new_purchase < 0.01), то все поля = 0
|
||||
if flt(data.get('value_of_new_purchase', 0)) >= 0.01:
|
||||
elave_2_data[matching_key] = {
|
||||
'hesabatilierzindeuçotaalınan': data['value_of_new_purchase'],
|
||||
'hesabatilinsonunaəsasvəsaitlərinqalıqdəyəri': data['net_asset_value_as_on_to_date'],
|
||||
'hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyəri': 0,
|
||||
'artıqqiymətəəsasvəsaitlərindəyəri505': data['insurance_value']
|
||||
}
|
||||
else:
|
||||
# Нет новых покупок - очистить все поля
|
||||
elave_2_data[matching_key] = {
|
||||
'hesabatilierzindeuçotaalınan': 0,
|
||||
'hesabatilinsonunaəsasvəsaitlərinqalıqdəyəri': 0,
|
||||
'hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyəri': 0,
|
||||
'artıqqiymətəəsasvəsaitlərindəyəri505': 0
|
||||
}
|
||||
|
||||
# Map to rows with fuzzy matching for Əlavə 1 (Tax Exempt Assets)
|
||||
elave_1_data = {}
|
||||
for article_number, data in tax_exempt_aggregated.items():
|
||||
# Find matching row by article number in "Azadolma səbəbi"
|
||||
matching_key = find_matching_azadolma_sebeb(article_number, existing_elave_1)
|
||||
|
||||
if matching_key:
|
||||
if calculation_mode == 'tam_il':
|
||||
elave_1_data[matching_key] = {
|
||||
'hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyərimanatla5012': data['value_as_on_from_date'],
|
||||
'ilinsonunaəsasvəsaitlərinqalıqdəyəri': data['net_asset_value_as_on_to_date'],
|
||||
'hesabatiliərzindəəsasvəsaitlərinqalıqdəyəri': 0,
|
||||
'artıqqiymətəəsasvəsaitlərindəyəri': data['insurance_value']
|
||||
}
|
||||
else: # il_erzinde
|
||||
# Бизнес-правило: Для компаний, созданных в течение года (İl Ərzində),
|
||||
# если нет новых покупок (value_of_new_purchase < 0.01), то все поля = 0
|
||||
if flt(data.get('value_of_new_purchase', 0)) >= 0.01:
|
||||
elave_1_data[matching_key] = {
|
||||
'hesabatiliərzindəəsasvəsaitlərinqalıqdəyəri': data['value_of_new_purchase'],
|
||||
'ilinsonunaəsasvəsaitlərinqalıqdəyəri': data['net_asset_value_as_on_to_date'],
|
||||
'hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyərimanatla5012': 0,
|
||||
'artıqqiymətəəsasvəsaitlərindəyəri': data['insurance_value']
|
||||
}
|
||||
else:
|
||||
# Нет новых покупок - очистить все поля
|
||||
elave_1_data[matching_key] = {
|
||||
'hesabatiliərzindəəsasvəsaitlərinqalıqdəyəri': 0,
|
||||
'ilinsonunaəsasvəsaitlərinqalıqdəyəri': 0,
|
||||
'hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyərimanatla5012': 0,
|
||||
'artıqqiymətəəsasvəsaitlərindəyəri': 0
|
||||
}
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'elave_1_data': elave_1_data,
|
||||
'elave_2_data': elave_2_data
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(f"Error in populate_property_tax_tables: {str(e)}", "Property Tax Gov")
|
||||
return {
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}
|
||||
|
||||
|
||||
def get_taxable_assets_aggregated(company, from_date, to_date):
|
||||
"""
|
||||
Get aggregated data for taxable assets grouped by taxable_asset_type
|
||||
|
||||
Returns:
|
||||
Dictionary: {
|
||||
'taxable_asset_type_value': {
|
||||
'value_as_on_from_date': float,
|
||||
'value_of_new_purchase': float,
|
||||
'net_asset_value_as_on_to_date': float
|
||||
}
|
||||
}
|
||||
"""
|
||||
# Get all assets with taxable_asset_type populated
|
||||
assets_with_taxable_type = frappe.db.sql("""
|
||||
SELECT
|
||||
name,
|
||||
taxable_asset_type
|
||||
FROM
|
||||
`tabAsset`
|
||||
WHERE
|
||||
docstatus = 1
|
||||
AND company = %(company)s
|
||||
AND taxable_asset_type IS NOT NULL
|
||||
AND taxable_asset_type != ''
|
||||
AND purchase_date <= %(to_date)s
|
||||
""", {
|
||||
'company': company,
|
||||
'to_date': to_date
|
||||
}, as_dict=True)
|
||||
|
||||
if not assets_with_taxable_type:
|
||||
return {}
|
||||
|
||||
# Get asset balances
|
||||
asset_names = [asset['name'] for asset in assets_with_taxable_type]
|
||||
asset_balances = get_asset_balances_using_standard_logic(company, from_date, to_date, asset_names)
|
||||
|
||||
# Aggregate by taxable_asset_type
|
||||
aggregated = {}
|
||||
|
||||
for asset in assets_with_taxable_type:
|
||||
asset_type = asset['taxable_asset_type']
|
||||
|
||||
# Find balance for this asset
|
||||
balance = next(
|
||||
(b for b in asset_balances if b['asset'] == asset['name']),
|
||||
{}
|
||||
)
|
||||
|
||||
# Initialize if not exists
|
||||
if asset_type not in aggregated:
|
||||
aggregated[asset_type] = {
|
||||
'value_as_on_from_date': 0.0,
|
||||
'value_of_new_purchase': 0.0,
|
||||
'net_asset_value_as_on_to_date': 0.0,
|
||||
'insurance_value': 0.0
|
||||
}
|
||||
|
||||
# Accumulate values
|
||||
aggregated[asset_type]['value_as_on_from_date'] += flt(balance.get('value_as_on_from_date', 0))
|
||||
aggregated[asset_type]['value_of_new_purchase'] += flt(balance.get('value_of_new_purchase', 0))
|
||||
aggregated[asset_type]['net_asset_value_as_on_to_date'] += flt(balance.get('net_asset_value_as_on_to_date', 0))
|
||||
aggregated[asset_type]['insurance_value'] += flt(balance.get('insurance_value', 0))
|
||||
|
||||
return aggregated
|
||||
|
||||
|
||||
def get_tax_exempt_assets_aggregated(company, from_date, to_date):
|
||||
"""
|
||||
Get aggregated data for tax exempt assets grouped by tax article
|
||||
|
||||
Returns:
|
||||
Dictionary: {
|
||||
'tax_article_number': { # e.g., '199.1', '207.3'
|
||||
'value_as_on_from_date': float,
|
||||
'value_of_new_purchase': float,
|
||||
'net_asset_value_as_on_to_date': float
|
||||
}
|
||||
}
|
||||
"""
|
||||
# Get all assets with industrial_tax_article or tax_exempt_tax_article
|
||||
# Exclude agricultural_tax_article as per requirements
|
||||
assets_with_tax_articles = frappe.db.sql("""
|
||||
SELECT
|
||||
a.name,
|
||||
a.industrial_tax_article,
|
||||
a.tax_exempt_tax_article,
|
||||
COALESCE(NULLIF(a.industrial_tax_article, ''), a.tax_exempt_tax_article) as tax_article
|
||||
FROM
|
||||
`tabAsset` a
|
||||
WHERE
|
||||
a.docstatus = 1
|
||||
AND a.company = %(company)s
|
||||
AND (
|
||||
(a.industrial_tax_article IS NOT NULL AND a.industrial_tax_article != '')
|
||||
OR (a.tax_exempt_tax_article IS NOT NULL AND a.tax_exempt_tax_article != '')
|
||||
)
|
||||
AND a.purchase_date <= %(to_date)s
|
||||
""", {
|
||||
'company': company,
|
||||
'to_date': to_date
|
||||
}, as_dict=True)
|
||||
|
||||
if not assets_with_tax_articles:
|
||||
return {}
|
||||
|
||||
# Get asset balances
|
||||
asset_names = [asset['name'] for asset in assets_with_tax_articles]
|
||||
asset_balances = get_asset_balances_using_standard_logic(company, from_date, to_date, asset_names)
|
||||
|
||||
# Aggregate by tax article number
|
||||
aggregated = {}
|
||||
|
||||
for asset in assets_with_tax_articles:
|
||||
# Extract article number from Tax Article name
|
||||
tax_article_full = asset['tax_article']
|
||||
article_number = extract_article_number(tax_article_full)
|
||||
|
||||
if not article_number:
|
||||
continue
|
||||
|
||||
# Find balance for this asset
|
||||
balance = next(
|
||||
(b for b in asset_balances if b['asset'] == asset['name']),
|
||||
{}
|
||||
)
|
||||
|
||||
# Initialize if not exists
|
||||
if article_number not in aggregated:
|
||||
aggregated[article_number] = {
|
||||
'value_as_on_from_date': 0.0,
|
||||
'value_of_new_purchase': 0.0,
|
||||
'net_asset_value_as_on_to_date': 0.0,
|
||||
'insurance_value': 0.0
|
||||
}
|
||||
|
||||
# Accumulate values
|
||||
aggregated[article_number]['value_as_on_from_date'] += flt(balance.get('value_as_on_from_date', 0))
|
||||
aggregated[article_number]['value_of_new_purchase'] += flt(balance.get('value_of_new_purchase', 0))
|
||||
aggregated[article_number]['net_asset_value_as_on_to_date'] += flt(balance.get('net_asset_value_as_on_to_date', 0))
|
||||
aggregated[article_number]['insurance_value'] += flt(balance.get('insurance_value', 0))
|
||||
|
||||
return aggregated
|
||||
|
||||
|
||||
def extract_article_number(tax_article_name):
|
||||
"""
|
||||
Extract article number from Tax Article name
|
||||
|
||||
Examples:
|
||||
"Vergi Məcəlləsinin 199.1-ci maddəsinə əsasən" → "199.1"
|
||||
"Vergi Məcəlləsinin 207.3-cü maddəsinə əsasən" → "207.3"
|
||||
"Vergi Məcəlləsinin 199.4.1-ci maddəsinə əsasən" → "199.4.1"
|
||||
|
||||
Returns:
|
||||
String: Article number or None if not found
|
||||
"""
|
||||
if not tax_article_name:
|
||||
return None
|
||||
|
||||
# Pattern to match article numbers like 199.1, 207.3, 199.4.1-1, 227.1
|
||||
pattern = r'(\d+(?:\.\d+)*(?:-\d+)?)'
|
||||
match = re.search(pattern, tax_article_name)
|
||||
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_matching_azadolma_sebeb(article_number, existing_rows):
|
||||
"""
|
||||
Find the "Azadolma səbəbi" value that contains the given article number
|
||||
|
||||
Args:
|
||||
article_number: String like "199.1" or "207.3"
|
||||
existing_rows: List of existing Əlavə 1 rows
|
||||
|
||||
Returns:
|
||||
The matching "Azadolma səbəbi" value or None
|
||||
"""
|
||||
if not article_number:
|
||||
return None
|
||||
|
||||
for row in existing_rows:
|
||||
azadolma_sebeb = row.get('azadolmasəbəbi', '')
|
||||
if article_number in azadolma_sebeb:
|
||||
return azadolma_sebeb
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_matching_category(asset_category, existing_rows):
|
||||
"""
|
||||
Find matching category in Əlavə 2 rows using partial match
|
||||
|
||||
Examples:
|
||||
Asset has: "Mənzillər"
|
||||
Row has: "1.5 Mənzillər"
|
||||
Result: Match found
|
||||
|
||||
Asset has: "Qeyri-yaşayış binaları (sahələri)"
|
||||
Row has: "1.2 Qeyri-yaşayış binaları (sahələri)"
|
||||
Result: Match found
|
||||
|
||||
Args:
|
||||
asset_category: Category from Asset's taxable_asset_type field
|
||||
existing_rows: List of existing Əlavə 2 rows
|
||||
|
||||
Returns:
|
||||
The matching "Vergiyə cəlb olunan əmlakların kateqoriyası" value or None
|
||||
"""
|
||||
if not asset_category:
|
||||
return None
|
||||
|
||||
for row in existing_rows:
|
||||
row_category = row.get('vergiyəcəlbolunanəmlaklarınkateqoriyası', '')
|
||||
|
||||
# Check if asset_category is contained in row_category (e.g., "Mənzillər" in "1.5 Mənzillər")
|
||||
if asset_category in row_category:
|
||||
return row_category
|
||||
|
||||
# Also check reverse - if row_category is contained in asset_category
|
||||
# (in case asset has full name with prefix)
|
||||
if row_category in asset_category:
|
||||
return row_category
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_asset_balances_using_standard_logic(company, from_date, to_date, asset_names):
|
||||
"""
|
||||
Calculate asset balances using ERPNext's Asset Depreciations and Balances report logic
|
||||
|
||||
Returns:
|
||||
List of dictionaries with asset balances
|
||||
"""
|
||||
if not asset_names:
|
||||
return []
|
||||
|
||||
# Check ERPNext version for field compatibility
|
||||
version_info = check_erpnext_version()
|
||||
purchase_amount_field = version_info['purchase_amount_field']
|
||||
has_capitalization = version_info['has_capitalization']
|
||||
|
||||
# Get asset details (gross values)
|
||||
asset_details = get_asset_cost_details(
|
||||
company, from_date, to_date, asset_names,
|
||||
purchase_amount_field, has_capitalization
|
||||
)
|
||||
|
||||
# Get depreciation details
|
||||
asset_depreciation = get_asset_depreciation_details(
|
||||
company, from_date, to_date, asset_names
|
||||
)
|
||||
|
||||
# Get value adjustments
|
||||
asset_adjustments = get_asset_value_adjustments(
|
||||
company, from_date, to_date, asset_names
|
||||
)
|
||||
|
||||
# Combine and calculate net values
|
||||
result = []
|
||||
|
||||
for asset_detail in asset_details:
|
||||
asset_name = asset_detail.get('name')
|
||||
|
||||
# Find depreciation
|
||||
depreciation = next(
|
||||
(dep for dep in asset_depreciation if dep['asset'] == asset_name),
|
||||
{}
|
||||
)
|
||||
|
||||
# Find adjustments
|
||||
adjustments = asset_adjustments.get(asset_name, {
|
||||
'adjustment_before_from_date': 0.0,
|
||||
'adjustment_till_to_date': 0.0
|
||||
})
|
||||
|
||||
# Calculate values following ERPNext standard report logic
|
||||
value_as_on_from_date = flt(asset_detail.get('cost_as_on_from_date', 0))
|
||||
value_as_on_from_date += adjustments['adjustment_before_from_date']
|
||||
|
||||
value_of_new_purchase = flt(asset_detail.get('cost_of_new_purchase', 0))
|
||||
|
||||
adjustment_during_period = (
|
||||
adjustments['adjustment_till_to_date'] -
|
||||
adjustments['adjustment_before_from_date']
|
||||
)
|
||||
|
||||
value_as_on_to_date = (
|
||||
value_as_on_from_date +
|
||||
value_of_new_purchase -
|
||||
flt(asset_detail.get('cost_of_sold_asset', 0)) -
|
||||
flt(asset_detail.get('cost_of_scrapped_asset', 0)) -
|
||||
flt(asset_detail.get('cost_of_capitalized_asset', 0)) +
|
||||
adjustment_during_period
|
||||
)
|
||||
|
||||
accumulated_depreciation_as_on_from_date = flt(
|
||||
depreciation.get('accumulated_depreciation_as_on_from_date', 0)
|
||||
)
|
||||
|
||||
accumulated_depreciation_as_on_to_date = (
|
||||
accumulated_depreciation_as_on_from_date +
|
||||
flt(depreciation.get('depreciation_amount_during_the_period', 0)) -
|
||||
flt(depreciation.get('depreciation_eliminated_during_the_period', 0)) -
|
||||
flt(depreciation.get('depreciation_eliminated_via_reversal', 0))
|
||||
)
|
||||
|
||||
net_asset_value_as_on_from_date = (
|
||||
value_as_on_from_date - accumulated_depreciation_as_on_from_date
|
||||
)
|
||||
|
||||
net_asset_value_as_on_to_date = (
|
||||
value_as_on_to_date - accumulated_depreciation_as_on_to_date
|
||||
)
|
||||
|
||||
# Calculate insurance value (Insured value - Gross Purchase Amount)
|
||||
# Version-compat: ERPNext v15 renamed Asset.gross_purchase_amount -> net_purchase_amount
|
||||
# (patch v15_0/rename_gross_purchase_amount_to_net_purchase_amount). Use the same field
|
||||
# the rest of this cost logic uses (purchase_amount_field), with explicit fallback.
|
||||
_asset_cols = frappe.db.get_table_columns('Asset')
|
||||
if 'gross_purchase_amount' in _asset_cols:
|
||||
_gross_field = 'gross_purchase_amount'
|
||||
elif 'net_purchase_amount' in _asset_cols:
|
||||
_gross_field = 'net_purchase_amount'
|
||||
else:
|
||||
_gross_field = 'purchase_amount'
|
||||
insured_value = flt(frappe.db.get_value('Asset', asset_name, 'insured_value') or 0)
|
||||
gross_purchase_amount = flt(frappe.db.get_value('Asset', asset_name, _gross_field) or 0)
|
||||
# Only calculate difference if insured_value is actually set (> 0)
|
||||
insurance_difference = (insured_value - gross_purchase_amount) if insured_value > 0 else 0
|
||||
|
||||
balance_result = {
|
||||
'asset': asset_name,
|
||||
'value_as_on_from_date': value_as_on_from_date,
|
||||
'value_of_new_purchase': value_of_new_purchase,
|
||||
'net_asset_value_as_on_from_date': net_asset_value_as_on_from_date,
|
||||
'net_asset_value_as_on_to_date': net_asset_value_as_on_to_date,
|
||||
'insurance_value': insurance_difference
|
||||
}
|
||||
result.append(balance_result)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def check_erpnext_version():
|
||||
"""Check ERPNext version for field compatibility"""
|
||||
columns = frappe.db.get_table_columns("Asset")
|
||||
has_net_purchase_amount = "net_purchase_amount" in columns
|
||||
has_capitalization = "Asset Capitalization" in frappe.get_all("DocType", pluck="name")
|
||||
|
||||
return {
|
||||
"purchase_amount_field": "net_purchase_amount" if has_net_purchase_amount else "gross_purchase_amount",
|
||||
"has_capitalization": has_capitalization
|
||||
}
|
||||
|
||||
|
||||
def get_asset_cost_details(company, from_date, to_date, asset_names, purchase_amount_field, has_capitalization):
|
||||
"""Get asset cost details (mimics ERPNext standard report)"""
|
||||
|
||||
asset_placeholders = ", ".join(["%s"] * len(asset_names))
|
||||
|
||||
capitalization_check = ""
|
||||
if has_capitalization:
|
||||
capitalization_check = """
|
||||
AND NOT EXISTS(
|
||||
SELECT 1 FROM `tabAsset Capitalization Asset Item` acai
|
||||
JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name
|
||||
WHERE acai.asset = a.name
|
||||
AND ac.posting_date < %s
|
||||
AND ac.docstatus = 1
|
||||
)
|
||||
"""
|
||||
else:
|
||||
# В версии 15 просто исключаем активы где есть запись в Asset Capitalization Asset Item
|
||||
capitalization_check = " AND NOT EXISTS(SELECT name FROM `tabAsset Capitalization Asset Item` WHERE asset = a.name)"
|
||||
|
||||
query = f"""
|
||||
SELECT
|
||||
a.name,
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN a.purchase_date < %s THEN
|
||||
CASE
|
||||
WHEN IFNULL(a.disposal_date, 0) = 0 OR a.disposal_date >= %s
|
||||
THEN a.{purchase_amount_field}
|
||||
ELSE 0
|
||||
END
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as cost_as_on_from_date,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN a.purchase_date >= %s
|
||||
THEN a.{purchase_amount_field}
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as cost_of_new_purchase,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN IFNULL(a.disposal_date, 0) != 0
|
||||
AND a.disposal_date >= %s
|
||||
AND a.disposal_date <= %s
|
||||
THEN
|
||||
CASE WHEN a.status = 'Sold' THEN a.{purchase_amount_field} ELSE 0 END
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as cost_of_sold_asset,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN IFNULL(a.disposal_date, 0) != 0
|
||||
AND a.disposal_date >= %s
|
||||
AND a.disposal_date <= %s
|
||||
THEN
|
||||
CASE WHEN a.status = 'Scrapped' THEN a.{purchase_amount_field} ELSE 0 END
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as cost_of_scrapped_asset,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN IFNULL(a.disposal_date, 0) != 0
|
||||
AND a.disposal_date >= %s
|
||||
AND a.disposal_date <= %s
|
||||
THEN
|
||||
CASE WHEN a.status = 'Capitalized' THEN a.{purchase_amount_field} ELSE 0 END
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as cost_of_capitalized_asset
|
||||
FROM
|
||||
`tabAsset` a
|
||||
WHERE
|
||||
a.docstatus = 1
|
||||
AND a.company = %s
|
||||
AND a.purchase_date <= %s
|
||||
AND a.name IN ({asset_placeholders})
|
||||
{capitalization_check}
|
||||
GROUP BY a.name
|
||||
"""
|
||||
|
||||
values = [
|
||||
from_date, # cost_as_on_from_date condition 1
|
||||
from_date, # cost_as_on_from_date condition 2
|
||||
from_date, # cost_of_new_purchase
|
||||
from_date, # cost_of_sold_asset condition 1
|
||||
to_date, # cost_of_sold_asset condition 2
|
||||
from_date, # cost_of_scrapped_asset condition 1
|
||||
to_date, # cost_of_scrapped_asset condition 2
|
||||
from_date, # cost_of_capitalized_asset condition 1
|
||||
to_date, # cost_of_capitalized_asset condition 2
|
||||
company, # company filter
|
||||
to_date, # purchase_date filter
|
||||
*asset_names # asset names for IN clause
|
||||
]
|
||||
|
||||
if has_capitalization:
|
||||
values.append(from_date)
|
||||
|
||||
return frappe.db.sql(query, values, as_dict=True)
|
||||
|
||||
|
||||
def get_asset_depreciation_details(company, from_date, to_date, asset_names):
|
||||
"""Get asset depreciation details (mimics ERPNext standard report)"""
|
||||
|
||||
asset_placeholders = ", ".join(["%s"] * len(asset_names))
|
||||
|
||||
query = f"""
|
||||
SELECT
|
||||
results.name as asset,
|
||||
SUM(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
|
||||
SUM(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
|
||||
SUM(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period,
|
||||
SUM(results.depreciation_eliminated_via_reversal) as depreciation_eliminated_via_reversal
|
||||
FROM (
|
||||
SELECT
|
||||
a.name as name,
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN gle.posting_date < %s
|
||||
AND (IFNULL(a.disposal_date, 0) = 0 OR a.disposal_date >= %s)
|
||||
THEN gle.debit
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as accumulated_depreciation_as_on_from_date,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN gle.posting_date <= %s
|
||||
AND IFNULL(a.disposal_date, 0) = 0
|
||||
THEN gle.credit
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as depreciation_eliminated_via_reversal,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN IFNULL(a.disposal_date, 0) != 0
|
||||
AND a.disposal_date >= %s
|
||||
AND a.disposal_date <= %s
|
||||
AND gle.posting_date <= a.disposal_date
|
||||
THEN gle.debit
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as depreciation_eliminated_during_the_period,
|
||||
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN gle.posting_date >= %s
|
||||
AND gle.posting_date <= %s
|
||||
AND (IFNULL(a.disposal_date, 0) = 0 OR gle.posting_date <= a.disposal_date)
|
||||
THEN gle.debit
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as depreciation_amount_during_the_period
|
||||
FROM
|
||||
`tabGL Entry` gle
|
||||
JOIN
|
||||
`tabAsset` a ON gle.against_voucher = a.name
|
||||
JOIN
|
||||
`tabAsset Category Account` aca ON aca.parent = a.asset_category
|
||||
AND aca.company_name = %s
|
||||
JOIN
|
||||
`tabCompany` company ON company.name = %s
|
||||
WHERE
|
||||
a.docstatus = 1
|
||||
AND a.company = %s
|
||||
AND a.purchase_date <= %s
|
||||
AND gle.is_cancelled = 0
|
||||
AND gle.account = IFNULL(aca.depreciation_expense_account, company.depreciation_expense_account)
|
||||
AND a.name IN ({asset_placeholders})
|
||||
GROUP BY a.name
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
a.name as name,
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN IFNULL(a.disposal_date, 0) != 0
|
||||
AND a.disposal_date < %s
|
||||
THEN 0
|
||||
ELSE a.opening_accumulated_depreciation
|
||||
END
|
||||
), 0) as accumulated_depreciation_as_on_from_date,
|
||||
0 as depreciation_eliminated_via_reversal,
|
||||
IFNULL(SUM(
|
||||
CASE
|
||||
WHEN a.disposal_date >= %s
|
||||
AND a.disposal_date <= %s
|
||||
THEN a.opening_accumulated_depreciation
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as depreciation_eliminated_during_the_period,
|
||||
0 as depreciation_amount_during_the_period
|
||||
FROM
|
||||
`tabAsset` a
|
||||
WHERE
|
||||
a.docstatus = 1
|
||||
AND a.company = %s
|
||||
AND a.purchase_date <= %s
|
||||
AND a.name IN ({asset_placeholders})
|
||||
GROUP BY a.name
|
||||
) as results
|
||||
GROUP BY results.name
|
||||
"""
|
||||
|
||||
values = [
|
||||
from_date, # accumulated_depreciation_as_on_from_date condition 1
|
||||
from_date, # accumulated_depreciation_as_on_from_date condition 2
|
||||
to_date, # depreciation_eliminated_via_reversal
|
||||
from_date, # depreciation_eliminated_during_the_period condition 1
|
||||
to_date, # depreciation_eliminated_during_the_period condition 2
|
||||
from_date, # depreciation_amount_during_the_period condition 1
|
||||
to_date, # depreciation_amount_during_the_period condition 2
|
||||
company, # aca.company_name
|
||||
company, # company.name
|
||||
company, # a.company
|
||||
to_date, # a.purchase_date
|
||||
*asset_names, # asset names for IN clause (first SELECT)
|
||||
from_date, # disposal_date condition (second SELECT)
|
||||
from_date, # disposal_date condition (second SELECT)
|
||||
to_date, # disposal_date condition (second SELECT)
|
||||
company, # a.company (second SELECT)
|
||||
to_date, # a.purchase_date (second SELECT)
|
||||
*asset_names # asset names for IN clause (second SELECT)
|
||||
]
|
||||
|
||||
return frappe.db.sql(query, values, as_dict=True)
|
||||
|
||||
|
||||
def get_asset_value_adjustments(company, from_date, to_date, asset_names):
|
||||
"""Get asset value adjustments (mimics ERPNext standard report)"""
|
||||
|
||||
asset_placeholders = ", ".join(["%s"] * len(asset_names))
|
||||
|
||||
query = f"""
|
||||
SELECT
|
||||
a.name AS asset,
|
||||
IFNULL(
|
||||
SUM(
|
||||
CASE
|
||||
WHEN gle.posting_date < %s
|
||||
AND (a.disposal_date IS NULL OR a.disposal_date >= %s)
|
||||
THEN gle.debit - gle.credit
|
||||
ELSE 0
|
||||
END
|
||||
),
|
||||
0) AS value_adjustment_before_from_date,
|
||||
IFNULL(
|
||||
SUM(
|
||||
CASE
|
||||
WHEN gle.posting_date <= %s
|
||||
AND (a.disposal_date IS NULL OR a.disposal_date >= %s)
|
||||
THEN gle.debit - gle.credit
|
||||
ELSE 0
|
||||
END
|
||||
),
|
||||
0) AS value_adjustment_till_to_date
|
||||
FROM
|
||||
`tabGL Entry` gle
|
||||
JOIN
|
||||
`tabAsset` a ON gle.against_voucher = a.name
|
||||
JOIN
|
||||
`tabAsset Category Account` aca ON aca.parent = a.asset_category
|
||||
AND aca.company_name = %s
|
||||
WHERE
|
||||
gle.is_cancelled = 0
|
||||
AND a.docstatus = 1
|
||||
AND a.company = %s
|
||||
AND a.purchase_date <= %s
|
||||
AND gle.account = aca.fixed_asset_account
|
||||
AND a.name IN ({asset_placeholders})
|
||||
GROUP BY a.name
|
||||
"""
|
||||
|
||||
values = [
|
||||
from_date, # value_adjustment_before_from_date condition 1
|
||||
from_date, # value_adjustment_before_from_date condition 2
|
||||
to_date, # value_adjustment_till_to_date condition 1
|
||||
to_date, # value_adjustment_till_to_date condition 2
|
||||
company, # aca.company_name
|
||||
company, # a.company
|
||||
to_date, # a.purchase_date
|
||||
*asset_names # asset names for IN clause
|
||||
]
|
||||
|
||||
result = frappe.db.sql(query, values, as_dict=True)
|
||||
|
||||
# Convert to dictionary
|
||||
adjustment_map = {}
|
||||
for r in result:
|
||||
adjustment_map[r['asset']] = {
|
||||
'adjustment_before_from_date': flt(r.get('value_adjustment_before_from_date', 0)),
|
||||
'adjustment_till_to_date': flt(r.get('value_adjustment_till_to_date', 0))
|
||||
}
|
||||
|
||||
return adjustment_map
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def calculate_months_for_vergi_hesab_4cu_1(company, year):
|
||||
"""
|
||||
Находит самый ранний Asset по available_for_use_date в указанном году
|
||||
и возвращает количество месяцев от этого месяца до конца года (включительно)
|
||||
|
||||
Args:
|
||||
company: Название компании
|
||||
year: Год для поиска (integer)
|
||||
|
||||
Returns:
|
||||
Integer: Количество месяцев (1-12) или 0 если нет Assets
|
||||
"""
|
||||
try:
|
||||
# Найти самый ранний Asset в году
|
||||
# docstatus = 1 означает статус "Submitted" (не Draft и не Cancelled)
|
||||
earliest_asset = frappe.db.sql("""
|
||||
SELECT MIN(available_for_use_date) as earliest_date
|
||||
FROM `tabAsset`
|
||||
WHERE company = %(company)s
|
||||
AND docstatus = 1
|
||||
AND available_for_use_date IS NOT NULL
|
||||
AND YEAR(available_for_use_date) = %(year)s
|
||||
""", {
|
||||
'company': company,
|
||||
'year': year
|
||||
}, as_dict=True)
|
||||
|
||||
if not earliest_asset or not earliest_asset[0].get('earliest_date'):
|
||||
return 0
|
||||
|
||||
earliest_date = earliest_asset[0]['earliest_date']
|
||||
|
||||
# Получить номер месяца (1-12)
|
||||
from datetime import datetime
|
||||
if isinstance(earliest_date, str):
|
||||
earliest_date = datetime.strptime(earliest_date, '%Y-%m-%d')
|
||||
|
||||
month = earliest_date.month
|
||||
|
||||
# Вычислить количество месяцев от этого месяца до конца года (не включая этот месяц)
|
||||
# Январь (1) → 12-1=11 месяцев, Март (3) → 12-3=9 месяцев, Сентябрь (9) → 12-9=3 месяца
|
||||
months_count = 12 - month
|
||||
|
||||
return months_count
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(f"Error in calculate_months_for_vergi_hesab_4cu_1: {str(e)}", "Property Tax Gov")
|
||||
return 0
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
|
||||
|
||||
class TestPropertyTaxGov(FrappeTestCase):
|
||||
pass
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 15:04:47.107017",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"azadolmasəbəbi",
|
||||
"hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyərimanatla5012",
|
||||
"ləğvolunmatarixinəəsasvəsaitlərinqalıqdəyəri",
|
||||
"hesabatiliərzindəəsasvəsaitlərinqalıqdəyəri",
|
||||
"ilinsonunaəsasvəsaitlərinqalıqdəyəri",
|
||||
"artıqqiymətəəsasvəsaitlərindəyəri"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "azadolmasəbəbi",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Azadolma səbəbi",
|
||||
"options": "Vergi Məcəlləsinin 199.1-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.4.1-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.4.2-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.4.3-cü maddəsinə əsasən:\nVergi Məcəlləsinin 199.4.4-cü maddəsinə əsasən:\nVergi Məcəlləsinin 199.4.1-1-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.5-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.7-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.8-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.9-cu maddəsinə əsasən:\nVergi Məcəlləsinin 199.11-cu maddəsinə əsasən:\nVergi Məcəlləsinin 199.14-cu maddəsinə əsasən:\nVergi Məcəlləsinin 199.15-cu maddəsinə əsasən:\nVergi Məcəlləsinin 199.16-cı maddəsinə əsasən:\nVergi Məcəlləsinin 199.17-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.18-ci maddəsinə əsasən:\nVergi Məcəlləsinin 199.19-cu maddəsinə əsasən:\nVergi Məcəlləsinin 227.1-ci maddəsinə əsasən:\nQanunla 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ə:\nXüsusi iqtisadi zonalar haqqında qanunlarda nəzərdə tutulan əmlaklar üzrə:\nAzərbaycan Respublikasının tərəfdar çıxdığı beynəlxalq müqavilələr üzrə:\nVergidən azad olunan əmlakın CƏMİ dəyəri:",
|
||||
"read_only": 1,
|
||||
"length": 255
|
||||
},
|
||||
{
|
||||
"fieldname": "hesabatiliərzindəəsasvəsaitlərinqalıqdəyəri",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Yeni yaradıldığı (uçota alındığı) və ya əmlak vergisi ödəyicisi olma tarixinə əsas vəsaitlərin qalıq dəyəri (manatla) (503.2)\t",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "ləğvolunmatarixinəəsasvəsaitlərinqalıqdəyəri",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Vergi ödəyicisinin ləğv olunma və ya uçotdan çıxarılma tarixinə əsas vəsaitlərin qalıq dəyəri (manatla) (502.2)",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "ilinsonunaəsasvəsaitlərinqalıqdəyəri",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Vergi ödəyicisinin ilin sonuna əsas vəsaitlərinin qalıq dəyəri (manatla) (504.2)"
|
||||
},
|
||||
{
|
||||
"fieldname": "artıqqiymətəəsasvəsaitlərindəyəri",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Artıq qiymətə sığortalanan əsas vəsaitlərin dəyəri (manatla) (505.2)"
|
||||
},
|
||||
{
|
||||
"fieldname": "hesabatilininəvvəlinəəsasvəsaitlərinqalıqdəyərimanatla5012",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesabat ilinin əvvəlinə əsas vəsaitlərin qalıq dəyəri (manatla) (501.2)"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-05 14:25:59.341379",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Elave 1",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovElave1(Document):
|
||||
pass
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 16:36:30.780093",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"vergiy\u0259c\u0259lbolunan\u0259mlaklar\u0131nkateqoriyas\u0131",
|
||||
"hesabatilinin\u0259vv\u0259lin\u0259\u0259sasv\u0259saitl\u0259rinqal\u0131qd\u0259y\u0259ri",
|
||||
"l\u0259\u011fvolunmatarixin\u0259\u0259sasv\u0259saitl\u0259rinqal\u0131qd\u0259y\u0259ri",
|
||||
"hesabatilierzindeu\u00e7otaal\u0131nan",
|
||||
"hesabatilinsonuna\u0259sasv\u0259saitl\u0259rinqal\u0131qd\u0259y\u0259ri",
|
||||
"art\u0131qqiym\u0259t\u0259\u0259sasv\u0259saitl\u0259rind\u0259y\u0259ri505"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "l\u0259\u011fvolunmatarixin\u0259\u0259sasv\u0259saitl\u0259rinqal\u0131qd\u0259y\u0259ri",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Vergi \u00f6d\u0259yicisinin l\u0259\u011fv olunma v\u0259 ya u\u00e7otdan \u00e7\u0131xar\u0131lma tarixin\u0259 \u0259sas v\u0259saitl\u0259rin qal\u0131q d\u0259y\u0259ri (manatla) (502.1)",
|
||||
"precision": "2"
|
||||
},
|
||||
{
|
||||
"fieldname": "vergiy\u0259c\u0259lbolunan\u0259mlaklar\u0131nkateqoriyas\u0131",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Vergiy\u0259 c\u0259lb olunan \u0259mlaklar\u0131n kateqoriyas\u0131",
|
||||
"options": "1. Binalar, tikilil\u0259r v\u0259 qur\u011fular\n1.1 \u00c7oxm\u0259rt\u0259b\u0259li (\u00e7oxm\u0259nzilli) ya\u015fay\u0131\u015f binalar\u0131\n1.2 Qeyri-ya\u015fay\u0131\u015f binalar\u0131 (sah\u0259l\u0259ri)\n1.3 \u018fmlak kompleksi kimi m\u00fc\u0259ssis\u0259l\u0259r\n1.4 Qur\u011fular\n1.5 M\u0259nzill\u0259r\n1.6 F\u0259rdi ya\u015fay\u0131\u015f v\u0259 ba\u011f evl\u0259ri\n2 Ma\u015f\u0131nlar v\u0259 avadanl\u0131qlar\n3 Y\u00fcks\u0259k texnologiyalar m\u0259hsulu olan hesablama texnikas\u0131\n4 N\u0259qliyyat vasit\u0259l\u0259ri\n5 Dig\u0259r \u0259sas v\u0259saitl\u0259r\nVergiy\u0259 c\u0259lb olunan \u0259mlak\u0131n C\u018fM\u0130 d\u0259y\u0259ri:",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hesabatilinin\u0259vv\u0259lin\u0259\u0259sasv\u0259saitl\u0259rinqal\u0131qd\u0259y\u0259ri",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesabat ilinin \u0259vv\u0259lin\u0259 \u0259sas v\u0259saitl\u0259rin qal\u0131q d\u0259y\u0259ri (manatla) (501.1)",
|
||||
"precision": "2"
|
||||
},
|
||||
{
|
||||
"fieldname": "hesabatilierzindeu\u00e7otaal\u0131nan",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesabat ili \u0259rzind\u0259 yarand\u0131\u011f\u0131 (u\u00e7ota al\u0131nd\u0131\u011f\u0131) v\u0259 ya \u0259mlak vergisi \u00f6d\u0259yicisi olma tarixin\u0259 \u0259sas v\u0259saitl\u0259rin qal\u0131q d\u0259y\u0259ri (manatla) (503.1)",
|
||||
"precision": "2",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hesabatilinsonuna\u0259sasv\u0259saitl\u0259rinqal\u0131qd\u0259y\u0259ri",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Hesabat ilinin sonuna \u0259sas v\u0259saitl\u0259rinin qal\u0131q d\u0259y\u0259ri (manatla) (504.1)",
|
||||
"precision": "2"
|
||||
},
|
||||
{
|
||||
"fieldname": "art\u0131qqiym\u0259t\u0259\u0259sasv\u0259saitl\u0259rind\u0259y\u0259ri505",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Art\u0131q qiym\u0259t\u0259 s\u0131\u011fotalanan \u0259sas v\u0259saitl\u0259rin d\u0259y\u0259ri (manatla) (505.1)",
|
||||
"precision": "2"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-01-08 18:48:57.656460",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Elave 2",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovElave2(Document):
|
||||
pass
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 14:28:57.994528",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"manatla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "501. \u018fmlak\u0131n \u00fcmumi qal\u0131q d\u0259y\u0259ri\n501.1 Vergiy\u0259 c\u0259lb olunan \u0259mlak\u0131n qal\u0131q d\u0259y\u0259ri\n501.1.1 Qeyri-kommersiya f\u0259aliyy\u0259tind\u0259 istifad\u0259 olunan \u0259mlak\u0131n qal\u0131q d\u0259y\u0259ri\n501.2 Vergid\u0259n azad olunan \u0259mlak\u0131n qal\u0131q d\u0259y\u0259ri",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "manatla",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Manatla"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 19:47:26.620548",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 1ci cedvel",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi1cicedvel(Document):
|
||||
pass
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-08-04 12:02:18.835114",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"manatla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "503. \u018fmlak\u0131n \u00fcmumi d\u0259y\u0259ri\n503.1 Vergiy\u0259 c\u0259lb olunan \u0259mlak\u0131n d\u0259y\u0259ri\n503.1.1 Qeyri-kommersiya f\u0259aliyy\u0259tind\u0259 istifad\u0259 olunan \u0259mlak\u0131n d\u0259y\u0259ri\n503.2 Vergid\u0259n azad olunan \u0259mlak\u0131n d\u0259y\u0259ri",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "manatla",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Manatla"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 19:38:26.382915",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 1ci cedvel 1",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi1cicedvel1(Document):
|
||||
pass
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 14:36:20.467665",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"manatla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "504. \u018fmlak\u0131n \u00fcmumi qal\u0131q d\u0259y\u0259ri\n504.1 Vergiy\u0259 c\u0259lb olunan \u0259mlak\u0131n qal\u0131q d\u0259y\u0259ri\n504.1.1 Qeyri-kommersiya f\u0259aliyy\u0259tind\u0259 istifad\u0259 olunan \u0259mlak\u0131n qal\u0131q d\u0259y\u0259ri\n504.2 Vergid\u0259n azad olunan \u0259mlak\u0131n qal\u0131q d\u0259y\u0259ri",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "manatla",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Manatla"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 12:00:07.915973",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 2ci cedvel",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi2cicedvel(Document):
|
||||
pass
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 14:35:10.099838",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"manatla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "505 Art\u0131q qiym\u0259t\u0259 s\u0131\u011fortalanan \u0259mlak\u0131n d\u0259y\u0259ri\n505.1 Vergiy\u0259 c\u0259lb olunan art\u0131q qiym\u0259t\u0259 s\u0131\u011fortalanan \u0259mlak\u0131n d\u0259y\u0259ri\n505.2 Vergid\u0259n azad olunan art\u0131q qiym\u0259t\u0259 s\u0131\u011fortalanan \u0259mlak\u0131n d\u0259y\u0259ri",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "manatla",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Manatla"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 12:00:44.910640",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 3cu cedvel",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi3cucedvel(Document):
|
||||
pass
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 14:36:07.154586",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"faizl\u0259"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "506 Verginin d\u0259r\u0259c\u0259si",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "faizl\u0259",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Faizl\u0259 %",
|
||||
"precision": "2",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-12-29 18:09:10.263087",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 4cu cedvel",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi4cucedvel(Document):
|
||||
pass
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-08-04 19:40:22.377464",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"ayla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "507 M\u00fc\u0259ssis\u0259 yarand\u0131\u011f\u0131 aydan sonra ilin sonuna q\u0259d\u0259r olan aylar\u0131n say\u0131",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "ayla",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Ayla"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 19:41:48.738524",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 4cu cedvel 1",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi4cucedvel1(Document):
|
||||
pass
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-01-13 15:00:15.158446",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"manatla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "509.1 Vergi \u00f6d\u0259yicisi il \u0259rzind\u0259 tam f\u0259aliyy\u0259t g\u00f6st\u0259rdiyi halda:\n509.2 Hesabat ili \u0259rzind\u0259 yarad\u0131ld\u0131\u011f\u0131 (u\u00e7ota al\u0131nd\u0131\u011f\u0131) v\u0259 ya \u0259mlak vergisi \u00f6d\u0259yicisi oldu\u011fu halda:\n510 Vergi m\u0259c\u0259ll\u0259sinin 199.21-ci madd\u0259sin\u0259 \u0259sas\u0259n azald\u0131lmal\u0131 \u0259mlak vergisinin m\u0259bl\u0259\u011fi"
|
||||
},
|
||||
{
|
||||
"fieldname": "manatla",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Manatla",
|
||||
"precision": "2"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-01-07 14:25:22.271312",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 5ci cedvel",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi5cicedvel(Document):
|
||||
pass
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-08-04 14:47:33.216880",
|
||||
"default_view": "List",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"g\u00f6st\u0259ricil\u0259r",
|
||||
"manatla"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "g\u00f6st\u0259ricil\u0259r",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "G\u00f6st\u0259ricil\u0259r",
|
||||
"options": "511.1 M\u00fc\u0259ssis\u0259 il \u0259rzind\u0259 tam f\u0259aliyy\u0259t g\u00f6st\u0259rdiyi halda\n511.2 M\u00fc\u0259ssis\u0259 il \u0259rzind\u0259 yarand\u0131\u011f\u0131 halda",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "manatla",
|
||||
"fieldtype": "Float",
|
||||
"precision": "2",
|
||||
"in_list_view": 1,
|
||||
"label": "Manatla",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 21:25:48.999866",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Taxes Az",
|
||||
"name": "Property Tax Gov Emlak vergi hesablamasi 6ci cedvel",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2025, Jey Soft and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PropertyTaxGovEmlakvergihesablamasi6cicedvel(Document):
|
||||
pass
|
||||
Loading…
Reference in New Issue