Allow independent dates while ARR field reviews are pending
This commit is contained in:
1 parent
fe8735aac2
commit
fb07580c0c
15 files changed
+316
-16
No files matched your search
+76
-7
@@ -24,6 +24,7 @@
|
||||
arrDownloadStorageKey: "",
|
||||
arrDownloadUsername: "",
|
||||
arrDownloadContextId: "",
|
||||
arrDownloadPendingReviews: [],
|
||||
arrDataReview: null,
|
||||
arrDataReviewRequestId: "",
|
||||
arrDataReviewLoading: false,
|
||||
@@ -31,6 +32,7 @@
|
||||
arrDataReviewDisconnected: false,
|
||||
arrDataReviewFinalizing: false,
|
||||
arrDataReviewDrafts: {},
|
||||
arrDataReviewDraftsByRequest: {},
|
||||
arrDataReviewMessage: "",
|
||||
arrDataReviewMessageError: false,
|
||||
companySourceFile: null,
|
||||
@@ -322,6 +324,53 @@
|
||||
return state.arrDownloadTask?.status === "needs_data_review";
|
||||
}
|
||||
|
||||
function selectedARRDateNeedsDataReview() {
|
||||
return arrDownloadNeedsDataReview() && $("#arr-download-date").value === state.arrDownloadTask.report_date;
|
||||
}
|
||||
|
||||
function rememberARRPendingReview(task) {
|
||||
state.arrDownloadPendingReviews = state.arrDownloadPendingReviews.filter((item) => item.request_id !== task.request_id);
|
||||
if (task.status === "needs_data_review") state.arrDownloadPendingReviews.push(task);
|
||||
state.arrDownloadPendingReviews.sort((a, b) => b.report_date.localeCompare(a.report_date) || a.request_id.localeCompare(b.request_id));
|
||||
}
|
||||
|
||||
function renderARRPendingReviews() {
|
||||
const panel = $("#arr-download-pending");
|
||||
panel.hidden = !state.arrDownloadPendingReviews.length;
|
||||
$("#arr-download-pending-title").textContent = I18N.t("arr_download.pending_dates");
|
||||
const locked = state.arrDownloadBusy || state.arrDownloadLoading || state.arrDataReviewLoading || state.arrDataReviewMutating
|
||||
|| state.arrDataReviewFinalizing || arrDownloadActive() || arrDownloadNeedsReconciliation();
|
||||
$("#arr-download-pending-list").innerHTML = state.arrDownloadPendingReviews.map((task) =>
|
||||
`<button type="button" data-arr-pending-review="${escapeHtml(task.request_id)}" aria-pressed="${state.arrDownloadTask?.request_id === task.request_id}" ${locked ? "disabled" : ""}>${escapeHtml(task.report_date)} · ${escapeHtml(I18N.t("arr_download.pending_date"))}</button>`).join("");
|
||||
}
|
||||
|
||||
async function selectARRPendingReview(requestId) {
|
||||
if (!state.arrDownloadPendingReviews.some((task) => task.request_id === requestId)
|
||||
|| state.arrDownloadBusy || state.arrDownloadLoading || state.arrDataReviewLoading || state.arrDataReviewMutating
|
||||
|| state.arrDataReviewFinalizing || arrDownloadActive() || arrDownloadNeedsReconciliation()) return;
|
||||
const contextId = state.arrDownloadContextId;
|
||||
state.arrDownloadBusy = true;
|
||||
renderARRDownload();
|
||||
try {
|
||||
const task = await api(`/api/arr-downloads/${encodeURIComponent(requestId)}`);
|
||||
if (state.arrDownloadContextId !== contextId) return;
|
||||
state.arrDownloadDateEdited = false;
|
||||
$("#arr-download-date").value = task.report_date;
|
||||
await acceptARRDownloadTask(task, { sync: false });
|
||||
if (arrDownloadNeedsDataReview()) {
|
||||
$("#arr-data-review-panel").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
$("#arr-data-review-panel").focus({ preventScroll: true });
|
||||
}
|
||||
} catch (error) {
|
||||
showToast(error.message, true);
|
||||
} finally {
|
||||
state.arrDownloadBusy = false;
|
||||
renderARRDataReview();
|
||||
renderARRDownload();
|
||||
scheduleARRDownloadPoll();
|
||||
}
|
||||
}
|
||||
|
||||
function handleARRDownloadDateChange() {
|
||||
state.arrDownloadDateEdited = true;
|
||||
// Choosing the next report date must not abandon a running or uncertain request.
|
||||
@@ -347,6 +396,7 @@
|
||||
$("#arr-date-toggle").setAttribute("aria-label", I18N.t("arr_download.choose_date"));
|
||||
$("#arr-download-help").textContent = I18N.t(locked ? "arr_download.submitting"
|
||||
: arrDownloadActive() ? "arr_download.date_next"
|
||||
: arrDownloadNeedsDataReview() ? "arr_download.date_independent"
|
||||
: reconciling ? "arr_download.date_resume" : "arr_download.help",
|
||||
{ date: state.arrDownloadIntent?.report_date });
|
||||
if (locked) closeARRCalendar();
|
||||
@@ -358,7 +408,7 @@
|
||||
if (state.arrDownloadBusy) label = "arr_download.submitting";
|
||||
else if (arrDownloadActive()) label = "arr_download.running";
|
||||
else if (pending || state.arrDownloadDisconnected) label = "arr_download.check";
|
||||
else if (arrDownloadNeedsDataReview()) label = "arr_download.complete_data";
|
||||
else if (selectedARRDateNeedsDataReview()) label = "arr_download.complete_data";
|
||||
else if (arrDownloadCanResume() || task?.status === "not_received") label = "arr_download.retry_date";
|
||||
button.textContent = I18N.t(label, { date: task?.report_date });
|
||||
button.setAttribute("aria-busy", String(state.arrDownloadBusy || arrDownloadActive()));
|
||||
@@ -375,6 +425,7 @@
|
||||
$("#arr-download-review").hidden = task?.status !== "needs_review" || !task.job_id;
|
||||
$("#arr-download-data-review").hidden = !arrDownloadNeedsDataReview();
|
||||
$("#arr-download-data-review").disabled = locked;
|
||||
renderARRPendingReviews();
|
||||
}
|
||||
|
||||
function clearARRDownloadPoll() {
|
||||
@@ -394,6 +445,7 @@
|
||||
|
||||
async function acceptARRDownloadTask(task, { sync = true } = {}) {
|
||||
state.arrDownloadTask = task;
|
||||
rememberARRPendingReview(task);
|
||||
state.arrDownloadDisconnected = false;
|
||||
rememberARRIntent({ request_id: task.request_id, report_date: task.report_date });
|
||||
if (!state.arrDownloadDateEdited) $("#arr-download-date").value = task.report_date;
|
||||
@@ -465,8 +517,13 @@
|
||||
state.arrDownloadTask = null;
|
||||
state.arrDownloadDisconnected = false;
|
||||
state.arrDownloadSynced = "";
|
||||
resetARRDataReview();
|
||||
state.arrDownloadPendingReviews = [];
|
||||
resetARRDataReview({ clearDrafts: true });
|
||||
}
|
||||
state.arrDownloadPendingReviews = Array.isArray(config.pending_data_reviews)
|
||||
? config.pending_data_reviews.filter((task) => task.status === "needs_data_review"
|
||||
&& /^[0-9a-f]{32}$/.test(task.request_id) && validARRDate(task.report_date)) : [];
|
||||
if (state.arrDownloadTask) rememberARRPendingReview(state.arrDownloadTask);
|
||||
if (!state.arrDownloadRestored) {
|
||||
state.arrDownloadRestored = true;
|
||||
let saved;
|
||||
@@ -505,7 +562,7 @@
|
||||
await loadARRDownloadTask();
|
||||
return;
|
||||
}
|
||||
if (arrDownloadNeedsDataReview()) {
|
||||
if (selectedARRDateNeedsDataReview()) {
|
||||
await loadARRDataReview(state.arrDownloadTask.request_id, { scroll: true });
|
||||
return;
|
||||
}
|
||||
@@ -522,6 +579,7 @@
|
||||
}
|
||||
rememberARRIntent(intent); // Persist before the HTTP call, including a lost response.
|
||||
state.arrDownloadTask = null;
|
||||
resetARRDataReview();
|
||||
state.arrDownloadBusy = true;
|
||||
clearARRDownloadPoll();
|
||||
renderARRDownload();
|
||||
@@ -553,7 +611,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
function resetARRDataReview() {
|
||||
function resetARRDataReview({ clearDrafts = false } = {}) {
|
||||
if (clearDrafts) state.arrDataReviewDraftsByRequest = {};
|
||||
else if (state.arrDataReviewRequestId) {
|
||||
state.arrDataReviewDraftsByRequest[state.arrDataReviewRequestId] = { ...state.arrDataReviewDrafts };
|
||||
}
|
||||
state.arrDataReview = null;
|
||||
state.arrDataReviewRequestId = "";
|
||||
state.arrDataReviewLoading = false;
|
||||
@@ -572,7 +634,8 @@
|
||||
}
|
||||
|
||||
function arrDataReviewCanFinalize(review = state.arrDataReview) {
|
||||
return Boolean(review && review.status === "editing" && review.can_finalize && Number(review.pending_count) === 0
|
||||
return Boolean(arrDownloadNeedsDataReview() && state.arrDownloadTask.request_id === state.arrDataReviewRequestId
|
||||
&& !state.arrDownloadBusy && review && review.status === "editing" && review.can_finalize && Number(review.pending_count) === 0
|
||||
&& Array.isArray(review.items) && review.items.every((item) => item.confirmed)
|
||||
&& !Object.keys(state.arrDataReviewDrafts).length && !state.arrDataReviewLoading && !state.arrDataReviewMutating
|
||||
&& !state.arrDataReviewDisconnected && !state.arrDataReviewFinalizing);
|
||||
@@ -589,7 +652,8 @@
|
||||
function renderARRDataReview() {
|
||||
const panel = $("#arr-data-review-panel");
|
||||
const review = state.arrDataReview;
|
||||
panel.hidden = !state.arrDataReviewRequestId || !arrDownloadNeedsDataReview();
|
||||
panel.hidden = !state.arrDataReviewRequestId || !arrDownloadNeedsDataReview()
|
||||
|| state.arrDownloadTask.request_id !== state.arrDataReviewRequestId;
|
||||
if (panel.hidden) return;
|
||||
const busy = state.arrDataReviewLoading || state.arrDataReviewMutating;
|
||||
const editable = review?.status === "editing" && !busy && !state.arrDataReviewDisconnected && !state.arrDataReviewFinalizing;
|
||||
@@ -637,6 +701,7 @@
|
||||
if (state.arrDataReviewRequestId !== requestId) {
|
||||
resetARRDataReview();
|
||||
state.arrDataReviewRequestId = requestId;
|
||||
state.arrDataReviewDrafts = { ...state.arrDataReviewDraftsByRequest[requestId] };
|
||||
}
|
||||
const contextId = state.arrDownloadContextId;
|
||||
state.arrDataReviewLoading = true;
|
||||
@@ -3172,7 +3237,7 @@
|
||||
});
|
||||
$("#upload-button").addEventListener("click", handleUpload);
|
||||
$("#arr-download-form").addEventListener("submit", submitARRDownload);
|
||||
$("#arr-download-date").addEventListener("input", () => { state.arrDownloadDateEdited = true; });
|
||||
$("#arr-download-date").addEventListener("input", handleARRDownloadDateChange);
|
||||
$("#arr-download-date").addEventListener("change", handleARRDownloadDateChange);
|
||||
$("#arr-download-review").addEventListener("click", async () => {
|
||||
const jobId = state.arrDownloadTask?.job_id;
|
||||
@@ -3180,6 +3245,10 @@
|
||||
try { await openDailyPriceReview(jobId, true); } catch (error) { showToast(error.message, true); }
|
||||
});
|
||||
$("#arr-download-data-review").addEventListener("click", () => loadARRDataReview(state.arrDownloadTask?.request_id, { scroll: true }));
|
||||
$("#arr-download-pending-list").addEventListener("click", (event) => {
|
||||
const button = event.target.closest("[data-arr-pending-review]");
|
||||
if (button) selectARRPendingReview(button.dataset.arrPendingReview);
|
||||
});
|
||||
$("#arr-data-review-refresh").addEventListener("click", () => loadARRDataReview());
|
||||
$("#arr-data-review-finalize").addEventListener("click", finalizeARRDataReview);
|
||||
$("#arr-data-review-body").addEventListener("input", (event) => {
|
||||
|
||||
@@ -124,6 +124,9 @@
|
||||
"arr_download.needs_review": ["等待人工价格复核", "Awaiting price review", "รอตรวจสอบราคาด้วยตนเอง"],
|
||||
"arr_download.needs_data_review": ["等待人工完善报表字段", "Awaiting source field review", "รอตรวจสอบข้อมูลรายงานด้วยตนเอง"],
|
||||
"arr_download.complete_data": ["完善报表字段", "Complete report fields", "กรอกข้อมูลรายงานให้ครบ"],
|
||||
"arr_download.date_independent": ["可选其他日期下载,当前待完善内容会保留。", "Choose another date to download; this review will be kept.", "เลือกวันอื่นเพื่อดาวน์โหลดได้ ข้อมูลที่รอตรวจสอบจะยังคงอยู่"],
|
||||
"arr_download.pending_dates": ["待完善日期", "Dates awaiting field review", "วันที่รอตรวจสอบข้อมูล"],
|
||||
"arr_download.pending_date": ["待完善", "Complete fields", "รอตรวจสอบ"],
|
||||
"arr_download.source_failed": ["到店数据获取未完成,请继续原任务重试。", "Arrival data could not be fetched. Resume the original task to retry.", "ยังดึงข้อมูลผู้เข้าพักไม่สำเร็จ โปรดดำเนินงานเดิมต่อเพื่อลองอีกครั้ง"],
|
||||
"arr_download.source_interrupted": ["到店数据获取中断,请继续原任务。", "Arrival data fetch was interrupted. Resume the original task.", "การดึงข้อมูลผู้เข้าพักขัดจังหวะ โปรดดำเนินงานเดิมต่อ"],
|
||||
"arr_download.failed": ["任务未完成,请查看任务日志", "Task failed. Check the task log.", "งานไม่สำเร็จ โปรดดูบันทึกงาน"],
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
<span class="arr-download-indicator" aria-hidden="true"></span>
|
||||
<span id="arr-download-status">正在连接下载服务…</span>
|
||||
</div>
|
||||
<div class="arr-download-pending" id="arr-download-pending" hidden>
|
||||
<span id="arr-download-pending-title">待完善日期</span>
|
||||
<div id="arr-download-pending-list"></div>
|
||||
</div>
|
||||
<div class="arr-download-actions">
|
||||
<button class="arr-download-review" id="arr-download-data-review" type="button" hidden>完善报表字段</button>
|
||||
<button class="arr-download-review" id="arr-download-review" type="button" hidden>查看价格复核</button>
|
||||
|
||||
@@ -201,6 +201,13 @@ button { color: inherit; }
|
||||
.arr-download-actions .primary-button { min-height: 34px; margin: 0; padding: 0 12px; border-radius: 8px; font-size: 11px; }
|
||||
.arr-download-review { padding: 4px 0; border: 0; color: var(--blue-dark); background: transparent; font-size: 11px; font-weight: 650; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
|
||||
.arr-download-review:hover { color: var(--blue); }
|
||||
.arr-download-pending { margin: 10px 0 12px; }
|
||||
.arr-download-pending[hidden] { display: none; }
|
||||
.arr-download-pending > span { display: block; margin-bottom: 5px; color: var(--muted); font-size: 11px; }
|
||||
#arr-download-pending-list { display: flex; flex-wrap: wrap; gap: 6px; max-height: 110px; overflow-y: auto; }
|
||||
#arr-download-pending-list button { padding: 5px 8px; border: 1px solid var(--line); border-radius: 6px; color: var(--blue-dark); background: #fff; font: inherit; font-size: 11px; cursor: pointer; }
|
||||
#arr-download-pending-list button[aria-pressed="true"] { border-color: var(--blue); background: #f0f4ff; }
|
||||
#arr-download-pending-list button:disabled { opacity: .55; cursor: default; }
|
||||
.arr-data-review-panel { margin: 20px 0; border-color: #e6d4b5; overflow: hidden; }
|
||||
.arr-data-review-panel[hidden] { display: none; }
|
||||
.arr-data-review-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; padding: 20px; background: #fffcf5; }
|
||||
|
||||
Reference in new issue
Block a user