perf(vat): drive the post-fill recompute off actual call completion, no timer

Instead of waiting a fixed delay after selecting dövr, wrap frappe.call to track
the fill calls (populate_vat_tables + formula_editor run_reports_batch): suppress
the per-write recompute while any is in flight and run it exactly once the moment
the last one resolves (deferred a tick so the apply lands first). User edits
recompute instantly. Robust regardless of how long the reports take.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali 2026-07-15 15:52:37 +00:00
parent f45414e5ac
commit 9e8732a676
1 changed files with 35 additions and 21 deletions

View File

@ -284,31 +284,45 @@ function vc_recompute(frm) {
frm.refresh_field("sertifikathesabatdövründəmalındəyərininsəhifəsicəmi"); frm.refresh_field("sertifikathesabatdövründəmalındəyərininsəhifəsicəmi");
} }
// --- Suppress the per-write recompute during the report-fill storm (populate_vat_tables / // --- Recompute exactly when the report-fill finishes — event-driven, no timer. Picking a
// formula_editor write hundreds of cells via set_value; recomputing on each would freeze // period fires populate_vat_tables + formula_editor (run_reports_batch) via frappe.call,
// the UI). "Fill mode" starts on period change and re-arms on every programmatic write. // each writing many cells; recomputing per write would freeze the form. We wrap
// 3s after the fill settles it runs the recompute ONCE, so roll-ups / passthrough // frappe.call to track those specific calls: the per-write recompute is suppressed while
// (e.g. 301.1 = Σ children, turnover ← appendices) fill in from the report data. // any is in flight, and runs ONCE when the last one resolves (deferred one tick so the
// User edits (outside fill mode) are debounced. --- // response's synchronous apply lands first). No timer, so it waits exactly as long as
var vc_fill_mode = false, vc_fill_timer = null, vc_frm = null; // the reports actually take. ---
function vc_mark_fill(frm) { var VC = (frappe.__vc = frappe.__vc || { mode: false, n: 0 });
if (frm) vc_frm = frm; VC.recompute = vc_recompute; // always the current load's recompute
vc_fill_mode = true; VC.re = /populate_vat_tables|run_reports_batch/;
if (vc_fill_timer) clearTimeout(vc_fill_timer); if (!frappe.__vc_call_wrapped) {
vc_fill_timer = setTimeout(function () { frappe.__vc_call_wrapped = true;
vc_fill_mode = false; var _vc_call = frappe.call;
if (vc_frm) vc_recompute(vc_frm); // one recompute after the report-fill burst settles frappe.call = function (opts) {
}, 400); var m = (opts && opts.method) || (typeof opts === "string" ? opts : "");
var fill = VC.re.test(m || "");
if (fill) { VC.n++; VC.mode = true; }
var ret = _vc_call.apply(this, arguments);
if (fill && ret && typeof ret.then === "function") {
var done = function () {
if (--VC.n > 0) return; // other fill calls still running
VC.n = 0;
setTimeout(function () { // let this response's set_values apply first
VC.mode = false;
if (cur_frm && cur_frm.doctype === "Declaration of value added tax" && VC.recompute) {
VC.recompute(cur_frm);
}
}, 0);
};
ret.then(done, done);
}
return ret;
};
} }
function vc_onchange(frm) { function vc_onchange(frm) {
vc_frm = frm; if (frappe.__vc.mode) return; // report-fill running: recompute once when the last fill call resolves
if (vc_fill_mode) { vc_mark_fill(frm); return; } // during report-fill: don't recompute per write (would freeze) vc_recompute(frm); // user edit: instant
vc_recompute(frm); // user edit: recompute instantly
} }
// period change (dövr picker writes ay/il) starts the fill window
frappe.ui.form.on("Declaration of value added tax", { ay: vc_mark_fill, il: vc_mark_fill, "dövr": vc_mark_fill });
// recompute on input changes in each child table // recompute on input changes in each child table
[ [
["Declaration of value added tax Elave 2 Hisse 1", [A2H1AMT]], ["Declaration of value added tax Elave 2 Hisse 1", [A2H1AMT]],