Auto-import all fetched ƏMAS employees; apply default language on boot
- Remove the manual employee selection UI. After loading, the wizard caches every record returned by emasValidEmploymentContractOnline and lands on the done sub-state. import_bulk_employees updates existing records on FIN match, so running on a populated site is safe. - On constructor, if the booted session lang differs from the wizard's default (az), trigger load_messages so the UI renders in that language without the user having to re-pick it from the dropdown.
This commit is contained in:
parent
3f62fea6e6
commit
e166da49cc
|
|
@ -1 +1 @@
|
|||
__version__ = "0.0.7"
|
||||
__version__ = "0.0.8"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ frappe.provide("jey_wizard");
|
|||
// Bump this string in every commit that changes wizard code. Displayed in the badge so
|
||||
// we can tell at a glance which version is actually running on a given machine. Kept in
|
||||
// sync with __version__ in jey_wizard/__init__.py.
|
||||
const JEY_WIZARD_VERSION = "0.0.7";
|
||||
const JEY_WIZARD_VERSION = "0.0.8";
|
||||
|
||||
// Wipe Frappe + ERPNext default slides so their `before_load`/`after_load` listeners
|
||||
// don't try to mutate a wizard that isn't slide-based anymore.
|
||||
|
|
@ -72,6 +72,15 @@ frappe.setup.SetupWizard = class JeySetupWizard {
|
|||
this.current_step = 0;
|
||||
this.steps = ["language", "asan", "employees", "company", "confirm"];
|
||||
this.render();
|
||||
|
||||
// Session arrives in whatever language Frappe booted in (usually English for
|
||||
// the first-run Administrator). Pull the default language's translations
|
||||
// immediately so every subsequent render runs in that language without the
|
||||
// user having to re-pick it.
|
||||
const bootLang = (frappe.boot.lang || "en").split("-")[0];
|
||||
if (bootLang !== this.data.language) {
|
||||
this.change_language(this.data.language, /* force */ true);
|
||||
}
|
||||
}
|
||||
|
||||
// Frappe's on_page_show calls frappe.wizard.show_slide — no-op for us.
|
||||
|
|
@ -334,71 +343,20 @@ frappe.setup.SetupWizard = class JeySetupWizard {
|
|||
<div style="color:#666">${__("Fetching from ƏMAS...")}</div>
|
||||
</div>
|
||||
`);
|
||||
} else if (this.amas_state === "select") {
|
||||
const emps = this.amas_employees || [];
|
||||
const existing = this.amas_existing_map || {};
|
||||
const newCount = emps.filter((e) => !existing[e.identification_number]).length;
|
||||
const existingCount = emps.length - newCount;
|
||||
|
||||
const rows = emps.map((e, i) => {
|
||||
const fin = e.identification_number || "";
|
||||
const existingId = existing[fin];
|
||||
const statusCell = existingId
|
||||
? `<span class="indicator-pill green" style="font-size:11px">${frappe.utils.escape_html(existingId)}</span>`
|
||||
: "";
|
||||
return `
|
||||
<tr>
|
||||
<td style="padding:6px"><input type="checkbox" class="jey-emp-pick" data-idx="${i}" ${existingId ? "" : "checked"}></td>
|
||||
<td style="padding:6px">${frappe.utils.escape_html(e.full_name || "")}</td>
|
||||
<td style="padding:6px;font-family:monospace">${frappe.utils.escape_html(fin)}</td>
|
||||
<td style="padding:6px">${frappe.utils.escape_html(e.work_position_text || "")}</td>
|
||||
<td style="padding:6px;text-align:right">${frappe.utils.escape_html(String(e.monthly_salary || ""))}</td>
|
||||
<td style="padding:6px">${frappe.utils.escape_html(e.contract_status || "")}</td>
|
||||
<td style="padding:6px">${statusCell}</td>
|
||||
</tr>
|
||||
`;
|
||||
}).join("");
|
||||
|
||||
$body.html(`
|
||||
<h3 style="margin-bottom:12px">${__("Select employees from ƏMAS")}</h3>
|
||||
<div style="margin-bottom:10px;padding:10px;background:#e3f2fd;border-radius:4px">
|
||||
${__("Organization:")} <b>${frappe.utils.escape_html(this.data.amas_organization_name || "")}</b><br>
|
||||
${__("Employees found:")} <b>${emps.length}</b>
|
||||
(${__("new")}: <b>${newCount}</b>, ${__("already in system")}: <b>${existingCount}</b>)
|
||||
</div>
|
||||
<label style="display:block;margin-bottom:10px">
|
||||
<input type="checkbox" class="jey-emp-create-desig" ${this.data.amas_create_designation ? "checked" : ""}>
|
||||
${__("Create Designation if not found")}
|
||||
</label>
|
||||
<div style="max-height:400px;overflow-y:auto;border:1px solid #eee;border-radius:4px">
|
||||
<table style="width:100%;border-collapse:collapse;font-size:13px">
|
||||
<thead style="position:sticky;top:0;background:#fafafa">
|
||||
<tr>
|
||||
<th style="padding:8px;text-align:left"><input type="checkbox" class="jey-emp-all"></th>
|
||||
<th style="padding:8px;text-align:left">${__("Full Name")}</th>
|
||||
<th style="padding:8px;text-align:left">${__("FIN")}</th>
|
||||
<th style="padding:8px;text-align:left">${__("Position")}</th>
|
||||
<th style="padding:8px;text-align:right">${__("Salary")}</th>
|
||||
<th style="padding:8px;text-align:left">${__("Status")}</th>
|
||||
<th style="padding:8px;text-align:left">${__("In System")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>${rows}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`);
|
||||
|
||||
$body.find(".jey-emp-all").on("change", (e) => {
|
||||
const checked = $(e.currentTarget).prop("checked");
|
||||
$body.find(".jey-emp-pick").prop("checked", checked);
|
||||
});
|
||||
} else if (this.amas_state === "done") {
|
||||
const n = (this.data.amas_selected_employees || []).length;
|
||||
const existingCount = Object.keys(this.amas_existing_map || {}).length;
|
||||
const newCount = n - existingCount;
|
||||
$body.html(`
|
||||
<h3 style="margin-bottom:16px;color:#080">✓ ${__("Employees selected")}</h3>
|
||||
<p>${__("Selected {0} employee(s). They will be imported into ƏMAS Employees and the standard Employee doctype after the wizard finishes.", [n])}</p>
|
||||
<h3 style="margin-bottom:16px;color:#080">✓ ${__("Employees ready to import")}</h3>
|
||||
<div style="padding:12px;background:#e8f5e9;border-radius:4px;margin-bottom:12px">
|
||||
${__("Organization:")} <b>${frappe.utils.escape_html(this.data.amas_organization_name || "")}</b><br>
|
||||
${__("Employees found:")} <b>${n}</b>
|
||||
(${__("new")}: <b>${newCount < 0 ? n : newCount}</b>, ${__("already in system")}: <b>${existingCount}</b>)
|
||||
</div>
|
||||
<p style="color:#666">${__("All employees will be imported into ƏMAS Employees and the standard Employee doctype after the wizard finishes.")}</p>
|
||||
<div style="margin-top:16px">
|
||||
<button class="btn btn-default jey-amas-back-intro">${__("Change selection")}</button>
|
||||
<button class="btn btn-default jey-amas-back-intro">${__("Reload from ƏMAS")}</button>
|
||||
</div>
|
||||
`);
|
||||
$body.find(".jey-amas-back-intro").on("click", () => {
|
||||
|
|
@ -479,13 +437,6 @@ frappe.setup.SetupWizard = class JeySetupWizard {
|
|||
// surfaces a standard Next.
|
||||
showStdNext = this.asan_state === "done";
|
||||
} else if (step === "employees") {
|
||||
if (this.amas_state === "select") {
|
||||
// Commit selection instead of plain Next.
|
||||
$(`<button class="btn btn-primary jey-emp-commit">${__("Next")}</button>`)
|
||||
.appendTo($nav)
|
||||
.on("click", () => this.amas_commit_selection());
|
||||
return;
|
||||
}
|
||||
// On intro the user uses explicit Skip / Load buttons, not Next.
|
||||
// Only the "done" sub-state surfaces a standard Next to move on.
|
||||
showStdNext = this.amas_state === "done";
|
||||
|
|
@ -565,8 +516,9 @@ frappe.setup.SetupWizard = class JeySetupWizard {
|
|||
|
||||
// ---------- language ----------
|
||||
|
||||
change_language(code) {
|
||||
if (!code || code === this.data.language) return;
|
||||
change_language(code, force = false) {
|
||||
if (!code) return;
|
||||
if (!force && code === this.data.language) return;
|
||||
const langName = LANG_NAME[code] || "English";
|
||||
frappe._messages = {};
|
||||
frappe.call({
|
||||
|
|
@ -943,21 +895,22 @@ frappe.setup.SetupWizard = class JeySetupWizard {
|
|||
this.show_current_step();
|
||||
return;
|
||||
}
|
||||
this.amas_employees = m.employees || [];
|
||||
if (this.amas_employees.length === 0) {
|
||||
const employees = m.employees || [];
|
||||
if (employees.length === 0) {
|
||||
this.$wrap.find(".jey-status").text(__("No employees found in ƏMAS for this organization."));
|
||||
this.amas_state = "intro";
|
||||
this.show_current_step();
|
||||
return;
|
||||
}
|
||||
// Check which FINs are already in the Employee doctype.
|
||||
const fins = this.amas_employees
|
||||
this.amas_employees = employees;
|
||||
// Populate existing_map purely for the summary UI; the actual import
|
||||
// updates existing records rather than skipping them, so no filtering.
|
||||
const fins = employees
|
||||
.map((e) => e.identification_number)
|
||||
.filter(Boolean);
|
||||
if (fins.length === 0) {
|
||||
this.amas_existing_map = {};
|
||||
this.amas_state = "select";
|
||||
this.show_current_step();
|
||||
this.amas_commit_selection();
|
||||
return;
|
||||
}
|
||||
frappe.call({
|
||||
|
|
@ -974,43 +927,44 @@ frappe.setup.SetupWizard = class JeySetupWizard {
|
|||
if (emp.passport_number) map[emp.passport_number] = emp.name;
|
||||
});
|
||||
this.amas_existing_map = map;
|
||||
this.amas_state = "select";
|
||||
this.show_current_step();
|
||||
this.amas_commit_selection();
|
||||
},
|
||||
error: () => {
|
||||
this.amas_existing_map = {};
|
||||
this.amas_commit_selection();
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Caches the full fetched list (user requested: import every active contract the
|
||||
// report returned, no manual selection). Runs right after amas_load_employees.
|
||||
amas_commit_selection() {
|
||||
const $body = this.$wrap.find(".jey-body");
|
||||
const selected = [];
|
||||
$body.find(".jey-emp-pick:checked").each((i, el) => {
|
||||
const idx = parseInt($(el).attr("data-idx"), 10);
|
||||
if (!isNaN(idx)) selected.push(this.amas_employees[idx]);
|
||||
});
|
||||
if (selected.length === 0) {
|
||||
this.$wrap.find(".jey-status").text(__("Select at least one employee, or go back and skip this step."));
|
||||
const all = this.amas_employees || [];
|
||||
if (all.length === 0) {
|
||||
this.amas_state = "intro";
|
||||
this.show_current_step();
|
||||
return;
|
||||
}
|
||||
const createDesignation = $body.find(".jey-emp-create-desig").is(":checked") ? 1 : 0;
|
||||
const createDesignation = 1;
|
||||
this.data.amas_create_designation = createDesignation;
|
||||
|
||||
frappe.call({
|
||||
method: "jey_wizard.amas.cache_selected_employees",
|
||||
args: {
|
||||
employees_json: JSON.stringify(selected),
|
||||
employees_json: JSON.stringify(all),
|
||||
create_designation: createDesignation,
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Saving selection..."),
|
||||
callback: (r) => {
|
||||
const m = r.message || {};
|
||||
if (!m.ok) {
|
||||
this.$wrap.find(".jey-status").text(__("Failed to cache selection."));
|
||||
this.amas_state = "intro";
|
||||
this.show_current_step();
|
||||
return;
|
||||
}
|
||||
this.data.amas_selected_employees = selected;
|
||||
this.data.amas_selected_employees = all;
|
||||
this.data.amas_skipped = false;
|
||||
this.amas_state = "done";
|
||||
this.show_current_step();
|
||||
|
|
|
|||
Loading…
Reference in New Issue