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)}