Split list-view code (frappe.listview_settings) out of the form client
scripts into dedicated *_list.js files. The form files were registered
under both doctype_js and doctype_list_js, so frappe.ui.form.on handlers
were registered twice and form events (e.g. validate) fired twice,
duplicating msgprint messages.
- New: purchase_invoice_list.js, purchase_order_list.js,
sales_order_list.js, sales_invoice_list.js, employee_list.js
- doctype_list_js now points to the *_list.js files; journal_entry.js
(list-only) removed from doctype_js
- purchase_invoice.js: drop toggle_purchase_fields_visibility and the
grid hidden/visible_columns hacks; tax_type is always visible and its
mandatory state is driven by mandatory_depends_on. validate and tax
calc now also honor agricultural_goods (equal trigger to purchase_type)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Raise purchase/sales/VAT bulk-import job timeout 1200s -> 7200s (2h), matching
the reference/items/units loaders. AMAS and Company are unchanged.
- Add utils.exceeds_one_year() (parses both 'YYYY-MM-DD' and 'DD-MM-YYYY HH:MM')
and reject date ranges spanning over one year on every e-taxes load except
Company data: server-side in the reference/items/units/VAT entry points, and
client-side in all 7 load dialogs for immediate feedback.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The find.outbox endpoint accepts maxCount=200 (verified live: 50->50, 200->200),
same as the invoice endpoints, but the VAT fetch was hardcoded to 50 — ~4x more
round-trips than necessary. Bump the client page size and the backend defaults
to 200; the pagination loop is size-agnostic so logic is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the per-page progress/cancel UI from the e-taxes list views, journal
entry, purchase/sales order and sales invoice loaders, and the settings
reference loader; progress and cancellation are now shown by the global
Background Tasks widget via realtime events.
- import_bulk_employees gains a `queue` arg so callers can route the job
off the contended default queue. The bar that hangs on "Preparing
import..." for ~a minute post-setup is queue wait: a single `bench
worker` drains short→default→long, so the import sat behind the
post-setup backlog. The wizard now enqueues on "short".
- Emit a "connecting" progress tick the instant the worker starts, so the
bar leaves the "queued" seed and shows it's actually running (vs still
waiting) before the first detail fetch.
- Org selection: drop the Role column ("Hüquqi şəxs" for every row) — the
name + VÖEN are enough. The role value is still sent to the API.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bar refilled 0->100% once per phase: the parallel fetch phase (the
slow, network-bound one) reported 0..N, then the sequential save phase
reported 0..N again. The client's monotonic guard then pinned the bar at
100% for the whole save phase, so real per-employee progress (with names)
was only visible at the very end, and the bar looked stuck at 0% during
the long fetch.
Report one overall 0-100 percent across both phases (fetch = 0-50, save =
50-100) from the worker and drive the bar from it; show per-phase "N of M"
+ a clear phase label ("Fetching details" / "Saving employees") in the
detail line. Poll every 1s for snappier updates. Bar now advances
continuously and is meaningful from the first tick.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the alarming "Reconnecting to import in progress..." fallback with
"Importing employees, please wait...". It showed whenever the bar had no
count yet — briefly before the first tick, and for the whole run when the
server returns no progress (e.g. a worker still on old code). The wording
made a working import look broken.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Employee list-view import bar relied solely on transient
publish_realtime("amas_import_progress") events. After the setup wizard
redirects to /app and the list reattaches, those in-flight events are
already gone — so the bar froze at "Reconnecting..." (0%) and employees
appeared all at once on the final refresh.
Persist each progress tick to Redis (_set_import_progress, exposed via
get_amas_import_status) and add a 2s polling fallback in employee.js that
drives the bar monotonically and detects completion even when the
realtime amas_import_complete is missed. Closing the bar still never
cancels the enqueued worker job.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "select records to import" dialogs (VAT operations, sales/purchase invoices,
AMAS employees) wasted vertical space: a fixed 500px table plus a context alert
pinned to the bottom forced scrolling to reach the content and the buttons.
Rework them to the journal_entry pattern: the records table is now the single
scroll area sized to the viewport (max-height: calc(100vh - 360px)) with a
sticky header, and the top count alert + bottom context alert are merged into
one compact header row. Affects journal_entry, sales_order, purchase_order,
sales_invoice and employee (AMAS) selection dialogs. No logic/handler changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under jey_theme/Bootstrap, soft .hide() / frappe.hide_progress() does NOT
reliably remove a modal — it sticks and the next dialog stacks on top of it
(e.g. the ASAN auth "success" message stayed under the date/org picker).
The loading-spinner Cancel button only changed its label, never closing.
- dialogs.hide(): force modal('hide') + remove() + orphaned-backdrop cleanup
(guarded by .modal:visible); no longer resets cancelLoading there so in-flight
pagination callbacks still see the cancel and bail out
- Cancel button now actually closes the spinner
- add import._closeProgress() and route every frappe.hide_progress() through a
robust force-close: purchase/sales order, sales invoice, journal entry,
employee/AMAS (closeAmasProgress), and the E-Taxes unit list
- E-Taxes list-view loading dialogs (items/customers/suppliers/units) and their
success paths force-close the same way
Applies the fix uniformly across all ETaxes JS modules and list views.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Realtime import progress modal could hang when a late 'progress' event
arrived after 'complete' (hide_progress nulls cur_progress, show_progress
then recreates an unmanaged modal). Guard every handler with an
importFinished flag and force-close via modal('hide')+remove()+backdrop
cleanup across company/employee/journal_entry/purchase_order/sales_*.
Also: show VAT operation İzahat (explanation) column in the selection
table and on the Journal Entry list; auto-create missing "Classification
code" records from taxCodeInfo so the Link field always resolves.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drops the obl-pact-list integration entirely: the doctype directory,
loader/bulk-loader entries, REFERENCE_SECTIONS row, reference-list
allow-list entry, and the existence-check guard on Presented
Certificate's sazis_code. sazis_code is now a plain Data field —
no Link target to validate against.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces "Azeri" / "Azerbaijani" / "Azerbaijan" with the native form
"Azərbaycan" in labels, descriptions, comments and docs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Convert add_menu_item to add_inner_button on E-Taxes Customer/Supplier/
Item/Unit lists, Purchase Order, Sales Order, and Journal Entry list
views so the load/import actions are visible directly instead of being
hidden under the "..." menu.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bulk import is now two-phase:
Phase A — parallel network. Up to BULK_IMPORT_PARALLELISM (=10)
ThreadPoolExecutor workers call get_employee_detail() concurrently.
Workers run in stateless mode via the new _post_amas helper and the
_state= parameter threaded through make_amas_request and the seven
detail helpers (get_edit_form_data, get_staff_data, get_person_data,
get_address_data, get_doc_main_data, get_contract_attachments,
download_contract_file). They share an in-memory snapshot of the
ƏMAS session/csrf/cookies and never touch the DB. If any worker is
rejected with HTTP 419 or a response-level CSRF code the whole
import aborts cleanly with a hint to lower BULK_IMPORT_PARALLELISM.
Phase B — sequential DB writes. create_single_employee_from_amas
takes a new prefetched_detail kwarg; the worker loop passes the
Phase-A payload through so the per-employee 7-call fetch is skipped.
Frappe ORM is not thread-safe, so writes stay sequential — that's
where the previous flow spent most of its time anyway.
Concurrency control:
- Asan Login picks up two new hidden Check fields,
amas_import_running and amas_import_cancel_requested.
- import_bulk_employees refuses to enqueue if the running flag is
already set, returning {success: False, already_running: True,
message}. The flag is set BEFORE frappe.enqueue (atomic guard
against fast double-clicks) and cleared in the worker's finally
block no matter how it exits.
- New whitelisted endpoints get_amas_import_status and
cancel_amas_import expose the flag to the UI. The worker checks
the cancel flag between Phase A futures and between Phase B
iterations.
Realtime events upgraded:
- amas_import_progress now carries phase: "fetch" | "save".
- amas_import_complete carries cancelled and aborted flags.
Frontend (employee.js):
- Bootstrap-4.6 stacked-modal fix re-applies modal-open class on
body when a nested modal closes (cancel-confirm over progress)
so the underlying backdrop isn't orphaned.
- reattach_amas_import_if_running re-binds the realtime listeners
on listview onload by polling get_connected_asan_logins +
get_amas_import_status, so refreshing /app/employee while an
import is in flight still shows the progress bar + Cancel button.
Plus the side fixes from the same session: connect_amas now opens
the org-picker dialog on success, error humanizer for common ƏMAS
codes, skip the dashboard prefetch when the cached CSRF is still
good. Schema changes need bench migrate.
- Always show "Select ƏMAS Organization" dialog after MyGovID re-auth in
the Employee → Load from AMAS flow. Previously auto-picked the first
cert, which on multi-cert users was the personal cert without rights
to the employee report — caused permission_error.
- humanize_amas_error() translates raw codes ('permission_error',
unknown) into user-facing messages. Permission failures return
permission_error: True so the frontend can offer a Reconnect button
that runs full re-auth + org selection.
- make_amas_request: drop the eager /core.dashboard fetch before every
call. Use the cached CSRF token + cookies (already updated from
Set-Cookie on each response). On real CSRF rejection (HTTP 419 or
response code CSRF/TOKENS_ARE_NOT_SAME/CSRF_TOKEN_MISMATCH), refresh
once and retry. Same simplification in get_amas_accounts.
- _process_bulk_employees_import: commit once after the loop instead of
per row, per CLAUDE.md guidance.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a "Data Loading" dialog on Company form that pulls 6 types of
taxpayer reference data from E-Taxes into dedicated doctypes, plus
in-form summary tables inside the Tax Policy tab.
New DocTypes (all with company link, Accounts User read-only,
System Manager full CRUD):
- E-Taxes Object (taxpayer registered locations)
- E-Taxes Cash Register (kassa aparatları with object FK)
- E-Taxes POS Terminal (with auto-derived object from registration number)
- E-Taxes Bank Account
- E-Taxes Obligation Pact (sazişlər / oil fields)
- E-Taxes Presented Certificate (with sazis_code FK to Obligation Pact)
Backend (invoice_az/company_api.py):
- 6 per-doctype loaders + shared _auth_headers / _etaxes_request helpers
implementing CLAUDE.md §10 401-retry-once pattern
- Cash Register / POS Terminal loaders walk the hasMore pagination
- load_company_data_bulk enqueues a background job that runs selected
loaders sequentially and streams progress over Socket.IO
(company_data_loading_progress / _complete events)
- get_company_reference_list exposes first N rows per doctype for the
Tax Policy tab tables
Frontend (invoice_az/client/company.js):
- Full ETaxes auth module inlined (CLAUDE.md §2) so ASAN Imza re-auth
works from Company form without relying on other forms' state
- "Data Loading" button opens a dialog of checkboxes (DATA_LOADERS
declarative array) — one bulk call, one floating show_progress bar
- Six reference tables rendered inside Tax Policy tab sections,
pattern copied from e-taxes_settings (card-section + Refresh +
"View All" only when total > rows)
CLAUDE.md:
- Rewrote §3 backend template with 401 retry + explicit commit
- Added §10–§16: 401 auto-refresh, two response shapes,
db.commit() standard, log title convention, frontend unauthorized
handling, field naming for reference vs fixture doctypes,
Socket.IO background job pattern
hooks.py:
- Register client/company.js under doctype_js["Company"]
.gitignore:
- Exclude *.har (may contain Bearer tokens / PII)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>