From a275f4144e46c0bac2e7d5aae469c6b143fff323 Mon Sep 17 00:00:00 2001 From: Ali <010109ali@gmail.com> Date: Mon, 15 Jun 2026 16:00:11 +0000 Subject: [PATCH] fix(amas): priority queue + connecting tick + drop role column MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- invoice_az/amas_api.py | 19 +++++++++++++++++-- invoice_az/client/employee.js | 7 ++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/invoice_az/amas_api.py b/invoice_az/amas_api.py index 967fc4e..5fe37e3 100644 --- a/invoice_az/amas_api.py +++ b/invoice_az/amas_api.py @@ -2731,10 +2731,15 @@ def on_delete_employee(doc, method): @frappe.whitelist() -def import_bulk_employees(asan_login_name, employees_data, company, create_designation=0): +def import_bulk_employees(asan_login_name, employees_data, company, create_designation=0, queue="default"): """Enqueue bulk employee import as a background job with realtime progress via Socket.IO. Refuses to enqueue if an import for the same Asan Login is already running. + + ``queue`` lets callers pick a less-contended RQ queue. The setup wizard passes + "short" so the import isn't stuck behind the pile of post-setup jobs on the + default queue (a single `bench worker` drains queues short→default→long, so + "short" jumps the line and starts as soon as the worker frees). """ if isinstance(employees_data, str): employees_data = json.loads(employees_data) @@ -2774,7 +2779,7 @@ def import_bulk_employees(asan_login_name, employees_data, company, create_desig company=company, create_designation=create_designation, user=user, - queue="default", + queue=queue or "default", timeout=1200, ) @@ -2948,6 +2953,16 @@ def _process_bulk_employees_import(asan_login_name, employees, company, create_d updated_count = 0 errors = [] + # First tick the instant the worker picks up the job: flips the bar from the + # "queued" seed to "connecting" so the user can tell the job actually started + # (vs. still waiting in the queue) even before the first detail fetch lands. + _set_import_progress(asan_login_name, 0, total, "connecting", None, 1) + frappe.publish_realtime( + "amas_import_progress", + {"current": 0, "total": total, "phase": "connecting", "percent": 1}, + user=user, + ) + try: # Refresh the plaintext CSRF token from /core.dashboard once before going # parallel. The DB may have a stale (or previously-corrupted) token; the diff --git a/invoice_az/client/employee.js b/invoice_az/client/employee.js index 5216bb8..b7a5e32 100644 --- a/invoice_az/client/employee.js +++ b/invoice_az/client/employee.js @@ -730,6 +730,8 @@ function attach_amas_import_listeners(listview, asan_login_name, total_hint) { const phaseLabel = function(phase) { if (phase === 'save') return __('Saving employees'); if (phase === 'fetch') return __('Fetching details'); + if (phase === 'connecting') return __('Connecting to ƏMAS...'); + if (phase === 'queued') return __('Waiting to start...'); return __('Preparing import...'); }; @@ -754,7 +756,7 @@ function attach_amas_import_listeners(listview, asan_login_name, total_hint) { const label = phaseLabel(phase); let detail; - if (phase === 'queued' || !(total > 0)) { + if (phase === 'queued' || phase === 'connecting' || !(total > 0)) { detail = label; } else if (employee_name) { detail = label + ': ' + employee_name + ' (' + current + '/' + total + ')'; @@ -1461,7 +1463,7 @@ function show_amas_accounts_dialog(asan_login_name, accounts, retry_callback) { // Build accounts table let table_html = '
'; table_html += ''; - table_html += ''; + table_html += ''; table_html += ''; accounts.forEach(function(account, index) { @@ -1473,7 +1475,6 @@ function show_amas_accounts_dialog(asan_login_name, accounts, retry_callback) { table_html += ` -
Organization NameVOENRoleAction
Organization NameVOENAction
${frappe.utils.escape_html(name)} ${frappe.utils.escape_html(voen)}${frappe.utils.escape_html(role)}