diff --git a/jey_wizard/__init__.py b/jey_wizard/__init__.py
index f3b4574..970659c 100644
--- a/jey_wizard/__init__.py
+++ b/jey_wizard/__init__.py
@@ -1 +1 @@
-__version__ = "0.1.15"
+__version__ = "0.1.16"
diff --git a/jey_wizard/etaxes.py b/jey_wizard/etaxes.py
index ec6da82..a5a73f6 100644
--- a/jey_wizard/etaxes.py
+++ b/jey_wizard/etaxes.py
@@ -1103,24 +1103,22 @@ def _find_default_warehouse(company):
def _drop_alert_messages():
- """Remove every entry from frappe.local.message_log that was queued via
- frappe.msgprint(alert=True) (a.k.a. toast). Keeps non-alert msgprints so
- the user still sees real warnings.
+ """Wipe everything in frappe.local.message_log that piled up during the
+ setup_complete request. We need the entire log gone, not just alerts:
+ besides the az_locale rename toasts (alert=True), HRMS Salary Component
+ warnings ("Hesablar təyin edilməyib") and Frappe's own user-creation
+ notes ("Employee Self Service rolu silindi") come through plain
+ msgprints — and they're noise for an automated setup. Genuine failures
+ would have raised an exception and been handled separately, so blanket
+ clearing is safe here.
"""
try:
- log = list(getattr(frappe.local, "message_log", []) or [])
+ frappe.clear_messages()
except Exception:
- return
- if not log:
- return
- def _is_alert(m):
try:
- if isinstance(m, dict):
- return bool(m.get("alert"))
- return bool(getattr(m, "alert", 0))
+ frappe.local.message_log = []
except Exception:
- return False
- frappe.local.message_log = [m for m in log if not _is_alert(m)]
+ pass
def _only_admin():
diff --git a/jey_wizard/public/js/jey_setup.js b/jey_wizard/public/js/jey_setup.js
index fc3db77..627e7b3 100644
--- a/jey_wizard/public/js/jey_setup.js
+++ b/jey_wizard/public/js/jey_setup.js
@@ -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.1.15";
+const JEY_WIZARD_VERSION = "0.1.16";
// 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.
@@ -415,11 +415,11 @@ frappe.setup.SetupWizard = class JeySetupWizard {
-
+
-
+
${__("Default: current calendar year (Jan 1 – Dec 31).")}
@@ -443,8 +443,25 @@ frappe.setup.SetupWizard = class JeySetupWizard {
`);
$body.find(".jey-company-name").val(this.data.company_name);
- $body.find(".jey-fy-start").val(this.data.fy_start_date);
- $body.find(".jey-fy-end").val(this.data.fy_end_date);
+
+ // Mount native Frappe Date controls (Flatpickr-styled) into the
+ // jey-fy-start / jey-fy-end placeholders. Plain
+ // looks dated and inconsistent with the rest of Frappe's UI. The
+ // controls expose set_value / get_value; we wire those into the
+ // usual data dict.
+ this.fy_start_ctrl = frappe.ui.form.make_control({
+ df: { fieldtype: "Date", fieldname: "fy_start_date", placeholder: "" },
+ parent: $body.find(".jey-fy-start")[0],
+ render_input: true,
+ });
+ this.fy_start_ctrl.set_value(this.data.fy_start_date || "");
+ this.fy_end_ctrl = frappe.ui.form.make_control({
+ df: { fieldtype: "Date", fieldname: "fy_end_date", placeholder: "" },
+ parent: $body.find(".jey-fy-end")[0],
+ render_input: true,
+ });
+ this.fy_end_ctrl.set_value(this.data.fy_end_date || "");
+
$body.find(".jey-valuation-method").val(this.data.valuation_method || "FIFO");
$body.find(".jey-accounting-method").val(this.data.accounting_method || "Hesablama metodu");
// Show why the default landed where it did, only when the auto-pick
@@ -676,8 +693,10 @@ frappe.setup.SetupWizard = class JeySetupWizard {
return false;
}
this.data.company_abbr = abbr;
- const fyStart = (this.$wrap.find(".jey-fy-start").val() || "").trim();
- const fyEnd = (this.$wrap.find(".jey-fy-end").val() || "").trim();
+ // Frappe Date controls return the value as YYYY-MM-DD or "" when
+ // blank. Mirrors the previous .val() contract on .
+ const fyStart = String((this.fy_start_ctrl && this.fy_start_ctrl.get_value()) || "").trim();
+ const fyEnd = String((this.fy_end_ctrl && this.fy_end_ctrl.get_value()) || "").trim();
if (!fyStart || !fyEnd) {
this.$wrap.find(".jey-status").text(__("Fiscal year start and end dates are required"));
return false;
@@ -1322,35 +1341,75 @@ frappe.setup.SetupWizard = class JeySetupWizard {
}
finalize() {
- this.$wrap.find(".jey-body").html(
- `
${__("Setting up your system. This can take a minute...")}
`
- );
+ // Render an inline progress UI in place of the wizard form. We don't
+ // pass freeze:true to frappe.call — the freeze overlay would dim and
+ // hide the bar. process_setup_stages publishes realtime "setup_task"
+ // events with {progress: [idx, total], stage_status: "..."}; we
+ // subscribe and translate those into bar width + status text.
+ this.$wrap.find(".jey-body").html(`
+
${__("Setting up your system")}
+
${__("Starting...")}
+
+
+
+
5%
+ `);
this.$wrap.find(".jey-nav").empty();
this.$wrap.find(".jey-status").empty();
+ const setProgress = (pct, status) => {
+ pct = Math.max(0, Math.min(100, Math.round(pct)));
+ this.$wrap.find(".jey-finalize-bar").css("width", pct + "%");
+ this.$wrap.find(".jey-finalize-pct").text(pct + "%");
+ if (status) this.$wrap.find(".jey-finalize-status").text(status);
+ };
+
+ // Realtime subscription. Each "setup_task" event carries either a
+ // progress tuple or a final status. Cap displayed pct at 95% during
+ // the run so the bar visibly completes when the HTTP response lands.
+ const onSetupTask = (data) => {
+ if (!data) return;
+ if (Array.isArray(data.progress)) {
+ const [done, total] = data.progress;
+ if (total > 0) {
+ const ratio = Math.min(done / total, 0.95);
+ setProgress(5 + ratio * 90, data.stage_status || __("Working..."));
+ }
+ }
+ if (data.status === "fail") {
+ this.show_error(
+ data.fail_msg || __("Setup failed"),
+ data.exc || data.exception || __("(check server logs)")
+ );
+ }
+ };
+ frappe.realtime.on("setup_task", onSetupTask);
+ const cleanup = () => frappe.realtime.off("setup_task", onSetupTask);
+
const values = this.build_setup_args();
frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.setup_complete",
args: { args: values },
- freeze: true,
callback: (r) => {
const m = r.message || {};
if (m.status === "ok") {
- this.$wrap.find(".jey-body").html(
- `