Commit Graph

393 Commits

Author SHA1 Message Date
Ali afd65ce302 fix(fno): run declaration calculations once per Dövr pick
Picking a period fired every recalculation twice. `frm.set_value()` schedules the
field's handlers asynchronously (frappe.model.set_value -> run_serially), so by
the time the first trigger ran, both `ay`/`rüb` and `il` were already set in
frm.doc — and each field's handler then did a full pass. In VAT that also meant
`populate_vat_tables` was called twice per pick.

Five declarations were affected, all of them via Formula_Editor_Script_* which
bind a handler to every field a formula depends on: Declaration of value added
tax, Declaration of mining tax, Road tax 2, Tax return withheld at source of
payment, Single declaration related to salaried and non-salaried work.

Those scripts are generated, so they can't be patched — the fix has to live in
the picker. Instead of two set_value() calls, write the fields directly, do what
set_value would have done (refresh_field, refresh_dependency, dirty) and fire the
handlers exactly once.

Firing only `il` is safe: for every affected declaration the period handler and
the `il` handler have byte-identical bodies once the trigger-field argument is
normalized (VAT 2750 lines each, single declaration 1202, mining tax 484, road
tax 2 128, tax withheld 4 — differing only in a comment), and
calculate_table_row_field() never reads its triggerField argument. A runtime
fallback triggers the period field instead when no `il` handler is bound.

Note this cannot be done with set_value("il", year) alone: frappe.model.set_value
skips both the trigger and dirty() when the value is unchanged, so changing only
the month within the same year would silently recalculate nothing.

Verified headless: one call per pick on both VAT (month) and Single declaration
(quarter), including a second pick within the same year.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 12:10:08 +00:00
Ali fd389d7b37 feat(fno): unified Dövr period picker across all declarations
Every declaration used to expose its reporting period as raw `ay` (month or
quarter Select), `il` (Int year) and/or `rüb` (quarter Select) fields, scattered
across the form. This adds a single `Dövr` field to all 23 declarations that
have a period, and hides the legacy fields.

Clicking `Dövr` opens an inline air-datepicker popup (the same widget Frappe
uses for Date fields, not a modal), restricted per declaration:

  month       -> month grid with Azerbaijani month names + year nav
  quarter_*   -> 2x2 grid of "1. Rüb".."4. Rüb"
  annual      -> year grid

The selection is written back into the hidden `ay`/`il`/`rüb` in their exact
original formats, so all downstream code (VAT appendix auto-fill, property tax
asset loading, single declaration, reports) keeps working untouched.

`dövr` deliberately carries no `read_only` docfield flag: with the site setting
`hide_empty_read_only_fields` enabled, Frappe hides empty read-only fields, which
made the picker invisible (and unopenable) on new documents. Keyboard input is
blocked from JS instead.

Also restores `ay` + `il` (hidden) on Declaration of value added tax: they were
deleted upstream while declaration_of_value_added_tax.{js,py} still read them,
which had silently broken the Əlavə auto-fill from reports.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 11:35:33 +00:00
Ali 682902a828 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>
2026-07-09 11:35:18 +00:00
Ali 94c25e19e2 push from mvp 2026-07-09 11:02:04 +00:00
Ali 7cfae04159 feat(vat): Certificate VAT Report (Cədvəl 23) + auto-fill Əlavə 8
- New Script Report "Certificate VAT Report": one row per sales-invoice item
  certificate (cert no, VÖEN, taxpayer, value), full item amount per certificate
  with no splitting; filters company + date range, submitted invoices only.
- Auto-fill VAT declaration Əlavə 8 Table 2 (müəssisə_malın_dəyəri) from that
  report inside populate_vat_tables; split cert_no into series (letters, max 3)
  and number (digits).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:46:54 +00:00
Ali 71d9e303ce feat(report): add Purchase VAT offset report (Cədvəl 22)
Lists submitted Purchase Invoices flagged for VAT offset that have a VAT
offset line code: line code, VOEN/Name, e-taxes invoice series/number,
total, VAT (only the 521.3 ƏDV tax account), paid total (Grand Total -
Outstanding, Purchase Register logic) and proportional paid VAT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 12:56:25 +00:00
Ali 93d7be9ee1 fix(vat): fill YGB date in Əlavə 1 (change field to Date)
ygbnintarixi was a Float field, so the YGB date could not be stored.
Change it to Date and map posting_date from the YGB report.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 14:56:50 +00:00
Ali d6488a68cf feat(vat): auto-fill VAT declaration appendices from reports
On selecting İl + Ay, the Declaration of value added tax fills three
appendices from the source reports' get_data:
- Əlavə 1            <- Purchase YGB VAT report
- Əlavə 2 Hissə 1    <- Purchase invoice info report (act_type mapped to AZ)
- Əlavə 2 Hissə 2    <- Agricultural goods stock report

Adds a whitelisted populate_vat_tables method + form trigger, and a
company filter to the purchase invoice info report.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 11:10:30 +00:00
Ali 8a430ae1b0 push from mvp 2026-06-26 11:09:32 +00:00
Ali 260205fd95 Reapply "chore(report): remove temporary source-document tracing"
This reverts commit b70a5bb371.
2026-06-25 11:03:42 +00:00
Ali b70a5bb371 Revert "chore(report): remove temporary source-document tracing"
This reverts commit 7505f286bd.
2026-06-25 10:49:07 +00:00
Ali 7505f286bd chore(report): remove temporary source-document tracing
Drop the temporary Source type / Source document columns and the per-voucher
detail rows used for tracing; the report returns the single summary row again.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 10:13:45 +00:00
Ali 70cb6da547 fix(report): count sale price only for stock-moving agricultural sales
Sold in period (sale price) now sums Sales Invoice items only when the
sale produced an outgoing Stock Ledger entry, so it stays consistent with
COGS/closing. A sale that does not update stock contributes 0 instead of
inflating the sale figure with no matching cost.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 10:04:07 +00:00
Ali bd61196c84 feat(report): add temporary source-document rows to agricultural stock report
Append detail rows listing the Stock Ledger entries (with a clickable link
to each source voucher) and sale prices behind opening/purchased/COGS/
closing, for tracing. The summary stays the first row. Also decide stock
direction by stock_value_difference so opening-stock reconciliations
(actual_qty = 0) are counted correctly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 09:31:18 +00:00
Ali beec3f4416 fix(report): Purchase YGB VAT report only lists documents with YGB
Replace the purchase_type/agricultural_goods gate with a YGB-presence
filter: a Purchase Invoice is included only when at least one of its YGB
fields (ygb / line_code) is filled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 09:19:10 +00:00
Ali 2d743f2878 refactor(report): source agricultural stock report from Stock Ledger
Rebuild the report on Stock Ledger Entry instead of custom FIFO over
invoices. Opening/closing balances and COGS now come from ERPNext's stock
valuation (which already applies the company's method and includes opening
stock entered via Stock Reconciliation); sale price still comes from Sales
Invoices. Filtering is now item-level (Item.agricultural_goods) and all
amounts are net of VAT, so the trade-markup VAT is not double-counted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 08:43:09 +00:00
Ali f906536b7f fix(report): cost-based opening balance in agricultural stock report
Opening balance now subtracts sales before the period at their COGS
(via the company's FIFO/Moving Average method) instead of at sale price.
This keeps it consistent with the cost-based closing balance, so each
period's opening equals the previous period's closing and the value can
no longer go negative while stock remains.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 17:27:26 +00:00
Ali 18e55b7421 feat(report): add trade markup and its VAT to agricultural stock report
Closing balance is now cost-based (opening + purchased - COGS) so the
trade-markup identity holds. Adds two columns:
- Trade markup on goods sold = sold(sale) - (opening + purchased - closing)
- VAT on trade markup = trade markup * 18%

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 16:52:23 +00:00
Ali 72f8292bfe feat(report): add Purchase YGB VAT report
Per-document purchase report (Cədvəl 21 — ƏDV - YGB hesabat). A Purchase
Invoice qualifies when submitted and at least one of purchase_type /
agricultural_goods is set (items are not filtered). Columns: document,
date, line code, YGB, amount without VAT (net_total) and VAT amount.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:24:41 +00:00
Ali 97b8b4ed56 feat(report): item-level agricultural filter, FIFO/Average COGS column
Agricultural goods stock report now filters by the per-item agricultural
flag (only agro items inside agro documents count) and grosses up rows to
include VAT. Adds a single "Sold in period (purchase price)" column whose
costing method follows the company's Default Stock Valuation Method
(Moving Average -> weighted average, otherwise FIFO).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 14:45:00 +00:00
Ali 878d2bac83 feat(report): add Agricultural goods stock report
Period-based VAT agricultural goods movement report (Cədvəl 18(1)):
opening balance, purchased (Purchase Invoices), sold (Sales Invoices)
and closing balance for agricultural_goods documents. Amounts incl. VAT
(grand_total); closing = opening + purchased - sold. Formula-editor
friendly with Company/From/To filters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:52:28 +00:00
Ali cd34b4ca87 fix(report): filter Purchase invoice info report by agricultural_goods
Switch the inclusion condition from purchase_type=1 to the newly added
agricultural_goods=1 flag on Purchase Invoice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 10:41:37 +00:00
Ali 5d2a218087 feat(report): add Purchase invoice info report
New Script Report grouping purchase-type Purchase Invoices by Act Type,
showing counterparty (ФИО/company/country), VOEN/FIN, and amount.
Includes a link column to the source Purchase Invoice and optional
date-range filters; formula-editor friendly (no total row).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 09:47:04 +00:00
Ali aaa352098c push from mvp 2026-06-23 09:09:16 +00:00
Ali 19f82f7f8e refactor(company): drop dead E-Taxes profile/auth code from company.js
Remove the now-unreachable profile-fetch and Asan inline-auth machinery
(checkAuthAndFetchProfile, showProfileDialog, startInlineAuthentication,
poll/complete/select cert, profile parsing/formatting helpers and the
dictionary cache) left orphaned after the E-Taxes buttons were removed.
Keeps gambling-activity handling, declaration defaults and tax wizards.
1797 -> 313 lines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:37:14 +00:00
Ali 1fff9d13a1 feat(company): remove E-Taxes profile and Set Main Activity buttons
Drop the "Get E-Taxes Profile" and "Set Main Activity" custom buttons
from the Company form. main_activity stays read-only (Custom Field
read_only=1) and can no longer be overridden via the dialog.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:34:19 +00:00
Ali d370d74e32 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>
2026-06-10 17:52:03 +00:00
Ali 6d6ff50afe feat(vat-allocation-report): add Əlavə 3 tax articles to the report
Add the 45 new tax articles to VAT Allocation Tax Articles Report, following
the report's hardcoded mapping standard:
- 36 from "ƏDV tutulan dövriyyə barədə məlumat" (301.x)
- 9 from "ƏDV tutulan əməliyyat sayılmayan dövriyyə" (328–336)
extending both get_tax_articles_mapping() and get_field_to_label_mapping().

Resolve the 301.1 vs 301-1 key collision (both -> vm_301_1 under the
separator->underscore convention): dash codes stay vm_301_N (consistent with
existing 302/303), the CƏMİ total line 301.1 -> vm_301_1_cemi.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 17:39:51 +00:00
Ali 4c566a1a00 feat(tax-article): split legacy mixed-VAT group into two Əlavə 3 groups
Add the two Əlavə 3 declaration tables as prefixed Tax Article groups:
- "ƏDV tutulan dövriyyə barədə məlumat" (301.x, 36 articles)
- "ƏDV tutulan əməliyyat sayılmayan dövriyyə barədə məlumat" (328–336, 9)
mirroring the client scripts that populate Declaration of value added tax Əlavə 3.

Remove the legacy "ƏDV tutulan və tutulmayan əməliyyatlar" group (6 unused,
unprefixed articles) from the fixture, and add a post_model_sync patch to delete
it on other sites before fixtures import (fixture import never deletes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 12:44:38 +00:00
Ali 0187a86f5a push from ali 2026-06-08 11:18:28 +00:00
Ali dda35f6f75 push from mvp 2026-06-08 10:36:43 +00:00
Ali af9d1322ab refactor(property-tax): replace property_tax_return_ai doctypes with property_tax_gov
Rename/retire the property_tax_return_ai doctype family in favour of the
property_tax_gov pilot (page-based, no-auth calc), and update property_tax_return.py
accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 11:15:30 +00:00
Ali 129a87711f feat(vat-allocation): group SI rows by customer+template with multi tax articles
Sales Invoice moved its single tax_article (Link) to a multi-select child table,
which inflated VAT Allocation: one line citing N articles produced N rows of the
full amount (e.g. 1500 -> 6000), so a 1500 payment only covered one article.

Group sales-invoice rows by (customer, item_tax_template) and union the cited
articles into a JSON tax_articles list, summing the amount once (the article
aggregation is computed separately so the JOIN can no longer multiply amounts).
The tax-articles report parses the list and replicates each row's amount/odenis
into every cited maddE column (same turnover under several articles, as on e-taxes).

The grid shows a translatable "N articles" cell that opens a read-only pill popup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 11:15:15 +00:00
Ali 7478d4d66c feat(reports): tax articles via SI child-table join; drop Tax Article Items Report
Revenue and VAT-allocation reports now resolve tax articles by JOINing the
Sales Invoice Tax Article child table (each article carries the full line
amount) instead of the single sii.tax_article; add 302.x/303.x mappings.
Remove the obsolete Tax Article Items Report doctype.

Also stop tracking .etaxes_notes/cabinet_internals.md (contains live
secrets) and broaden .gitignore to the whole .etaxes_notes/ folder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 12:25:24 +00:00
Ali 7f772fcb34 feat(property-tax-return-ai-fill): autofill elavə 1/2 + 507 from Asset accounting
Adds two parallel DocType families that don't touch the existing
`Property tax return` family:

- Property Tax Return AI (parent + 10 children): cabinet-verified port
  of the property-tax formulas (501/503/504 mirrors, 506=1, 509.1/509.2,
  511.x) with parity 3/3 vs. the original.

- Property Tax Return AI Fill (parent + 10 children): same formulas plus
  auto-fill from ERPNext Asset records. On form open the seeded grid is
  populated from the single Company's Assets, routed by
  `taxable_asset_type` (→ elavə 2 rows 1.1–1.6, 2–5) and
  `tax_exempt_tax_article` (→ elavə 1 rows by article-code regex).
  Residuals at year boundaries come from Depreciation Schedule;
  Company.date_of_establishment drives 507 ayla when il_erzinde=1.

Coverage: 16/16 smoke (seeding + formulas + 11 autofill scenarios) and
3/3 parity vs. original Property tax return pass.

Also adds .etaxes_notes/cabinet_internals.md (sanitised cabinet probe
notes) and gitignores .etaxes_notes/scratch/ which holds live JWTs and
HAR-like dumps.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 11:36:43 +00:00
Ali d90e56eb29 feat(tax-article): add 0% and VAT-exempt declaration articles (302.x/303.x)
Add 8 articles under "ƏDV-yə 0% dərəcə ilə tutulan əməliyyatlar" (302.x)
and 6 under "ƏDV-dən azad olunan əməliyyatlar" (303.x), sourced from the
Declaration of value added tax client scripts (Elave 4 / Elave 5).

Keep declaration-code prefixes in article_name to avoid docname collisions
between the 0% and exempt sections (e.g. 302.12 vs 303.42 share identical text).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 11:19:40 +00:00
Ali bdbe0b9dc1 push from mvp 2026-06-01 08:21:44 +00:00
Ali d11d15220c added new folder locale 2026-05-25 12:11:27 +00:00
Ali cd74b2ba85 feat(vat-allocation-report): split each tax article into amount + ödəniş columns
Per-article column now shows invoice amount; a paired Ödəniş column shows
allocated_amount from VAT allocation sales invoice. Row filter widened to
include unpaid lines (amount > 0 OR allocated_amount > 0).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 10:39:24 +00:00
Ali ae162adc0c fix(tax-article): clean curly quotes at the source instead of every migrate
The tax_article.json fixture itself contained typographic curly quotes (“ ”),
so every migrate the fixture import wrote dirty data and the after_migrate
hook normalize_on_migrate() cleaned it back — a permanent ping-pong ("4 curly
quotes fixed" in every migrate log).

Fix the source: straighten the quotes in the fixture file once. The
normalize_on_migrate hook, the normalize_tax_articles.py module and its doc
are now redundant — removed. Existing databases need a one-time cleanup of
already-imported dirty rows (rename_doc on the affected names).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:35:29 +00:00
Ali b963422bca fix(master-data): drop file-hash fast-path so sync always reconciles DB
The hash fast-path compared the JSON file hash to a stored value and exited
early when unchanged. But it only tracked the *file*, not the *table*: if rows
went missing from the DB (manual delete, restore from an older dump) while the
JSON stayed the same, the sync skipped entirely and never restored them — so
`bench migrate` silently failed to recreate missing master-data rows.

Always run the full diff now. It costs one SELECT plus an in-memory compare —
measured at ~0.1s for 13k rows — so there's no reason to skip it. The diff is
driven by DB state, making the sync self-healing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:14:50 +00:00
Ali 34adb643ee perf(master-data): sync Item Groups via hash-diff instead of after_migrate loop
create_item_groups() ran a 26-record exists-check loop on every migrate
(the "Группа X уже существует, пропускаем" spam in migrate logs). Replace
with the master_data hash-diff sync: fast-paths via stored file hash, applies
only the delta otherwise.

Item Group is a tree doctype shared with ERPNext/user groups, so the sync
gains two options: is_tree=True (insert via db_insert, rebuild lft/rgt once
at the end) and manage_deletes=False (never delete rows absent from the JSON,
since the JSON is only the AZ tax-specific subset).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 15:30:03 +00:00
Ali 1f43e8e037 feat(master-data): make Main type of activity read-only
This doctype is now populated exclusively from master_data JSON via the
hash-diff sync, so block create/write/delete in the UI and API by dropping
those permissions. The sync writes at the DB level so it is unaffected.
Also marks option_name read_only and drops allow_rename.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 14:23:47 +00:00
Ali eb392640cd push from mvp 2026-05-20 10:05:43 +00:00
Ali 29a40a7dc6 push from mvp 2026-05-20 09:59:40 +00:00
Ali a5fbff78eb perf(master-data): remove zombie fixture file and add bulk-insert fast path
The previous commit moved Main type of activity data to master_data/ but left
the original fixture file in place — Frappe's sync_fixtures reads every .json
in app/fixtures/ regardless of the hooks.py fixtures list, so the file was
still being imported on every migrate (3499 DELETE+INSERTs). Delete it.

Also adds a bulk-insert fast path (db_insert chunks of 500) to sync_master_data
for the large first-run case on fresh sites, so the new sync is faster than
the legacy fixture import even when populating an empty table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:48:42 +00:00
Ali 7e372f6f36 perf(master-data): sync Main type of activity via hash-diff instead of fixture
Fixture import does DELETE+INSERT for every row on every migrate (force=True
in frappe's import_doc), so 3499 rows of Main type of activity added minutes
to each migrate. Replace with a hash-diff sync that fast-paths via stored
file hash and otherwise applies only the delta (insert new, update changed,
smart-delete removed with disabled-fallback).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:44:06 +00:00
Ali 4a0c1519db push from mvp 2026-05-18 20:52:56 +00:00
Ali 0bdd885719 chore: use native Azərbaycan spelling in user-facing strings
Replaces "Azerbaijan" with "Azərbaycan" in app description, README, and
the descriptions of the Tax Period Closing Settings fields. Country
master Link values (e.g. country_of_origin: Azerbaijan in item fixtures)
are kept as-is to preserve references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:57:14 +00:00
Ali 8389e8502a fix(employee-payroll-register): base "cəlb edilən gəlirdən" columns on ƏH
Bookkeeper clarified the contribution net-of-exemption columns should be
computed from Əsas əmək haqqı minus the exemption amount, not from
gross_pay. With no exemption the column equals the existing (ƏH) column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:48:39 +00:00