175 lines
6.3 KiB
JavaScript
175 lines
6.3 KiB
JavaScript
const {
|
|
dialogCursor,
|
|
dialogMessagesSince,
|
|
assertNoNewErpLoginRequired,
|
|
} = require('./erp_session_guard');
|
|
|
|
function isSubmitSuccessText(value) {
|
|
return /下单成功|操作成功|修改成功|成功|สำเร็จ|success/i.test(String(value || ''));
|
|
}
|
|
|
|
function createSubmitUnconfirmedError(source, evidence) {
|
|
const error = new Error(`ERP submit result was not confirmed (${source || 'erp.submit'})`);
|
|
error.code = 'erp_submit_unconfirmed';
|
|
error.details = evidence;
|
|
return error;
|
|
}
|
|
|
|
async function readFrameBodyText(pageOrFrame) {
|
|
return pageOrFrame.evaluate(() => document.body.innerText.replace(/\s+/g, ' ').trim()).catch(() => '');
|
|
}
|
|
|
|
async function installSubmitAjaxProbe(pageOrFrame, minimumTimeout) {
|
|
return pageOrFrame.evaluate((timeoutMs) => {
|
|
window.__erpSubmitAjaxEvents = [];
|
|
window.__erpSubmitAjaxMinimumTimeout = timeoutMs;
|
|
const jq = window.jQuery || window.$;
|
|
if (!jq || typeof jq.ajax !== 'function') {
|
|
return { installed: false, reason: 'jquery_ajax_missing', minimumTimeout: timeoutMs };
|
|
}
|
|
if (!jq.__erpSubmitAjaxOriginal) {
|
|
const originalAjax = jq.ajax;
|
|
jq.__erpSubmitAjaxOriginal = originalAjax;
|
|
jq.ajax = function erpSubmitAjaxWithProbe(rawOptions, ...rest) {
|
|
const eventList = window.__erpSubmitAjaxEvents || (window.__erpSubmitAjaxEvents = []);
|
|
const options = typeof rawOptions === 'string'
|
|
? { ...(rest[0] || {}), url: rawOptions }
|
|
: { ...(rawOptions || {}) };
|
|
const minTimeout = Number(window.__erpSubmitAjaxMinimumTimeout || 0);
|
|
const currentTimeout = Number(options.timeout || 0);
|
|
if (minTimeout && (!currentTimeout || currentTimeout < minTimeout)) {
|
|
options.timeout = minTimeout;
|
|
}
|
|
const base = () => ({
|
|
url: options.url || '',
|
|
type: options.type || options.method || '',
|
|
dataType: options.dataType || '',
|
|
timeout: Number(options.timeout || 0),
|
|
});
|
|
const originalSuccess = options.success;
|
|
const originalError = options.error;
|
|
const originalComplete = options.complete;
|
|
options.success = function successProbe(data, textStatus, jqXHR) {
|
|
eventList.push({
|
|
event: 'success',
|
|
...base(),
|
|
status: jqXHR && jqXHR.status || 0,
|
|
textStatus: textStatus || '',
|
|
responseText: String(jqXHR && jqXHR.responseText || data || '').slice(0, 2000),
|
|
});
|
|
if (typeof originalSuccess === 'function') return originalSuccess.apply(this, arguments);
|
|
return undefined;
|
|
};
|
|
options.error = function errorProbe(jqXHR, textStatus, errorThrown) {
|
|
eventList.push({
|
|
event: 'error',
|
|
...base(),
|
|
status: jqXHR && jqXHR.status || 0,
|
|
textStatus: textStatus || '',
|
|
error: errorThrown && errorThrown.message ? errorThrown.message : String(errorThrown || ''),
|
|
responseText: String(jqXHR && jqXHR.responseText || '').slice(0, 2000),
|
|
});
|
|
if (typeof originalError === 'function') return originalError.apply(this, arguments);
|
|
return undefined;
|
|
};
|
|
options.complete = function completeProbe(jqXHR, textStatus) {
|
|
eventList.push({
|
|
event: 'complete',
|
|
...base(),
|
|
status: jqXHR && jqXHR.status || 0,
|
|
textStatus: textStatus || '',
|
|
});
|
|
if (typeof originalComplete === 'function') return originalComplete.apply(this, arguments);
|
|
return undefined;
|
|
};
|
|
return originalAjax.call(this, options);
|
|
};
|
|
}
|
|
return { installed: true, minimumTimeout: timeoutMs };
|
|
}, minimumTimeout).catch((error) => ({
|
|
installed: false,
|
|
reason: error && error.message ? error.message : String(error),
|
|
minimumTimeout,
|
|
}));
|
|
}
|
|
|
|
async function readSubmitAjaxEvents(pageOrFrame) {
|
|
return pageOrFrame.evaluate(() =>
|
|
Array.isArray(window.__erpSubmitAjaxEvents) ? window.__erpSubmitAjaxEvents : []
|
|
).catch(() => []);
|
|
}
|
|
|
|
function isPrimarySubmitAjaxEvent(item = {}) {
|
|
return /\/System\/DAT\/(?:orders|plan)\.asp/i.test(String(item.url || ''));
|
|
}
|
|
|
|
function isAjaxFailure(item = {}) {
|
|
return item.event === 'error' || Number(item.status || 0) >= 400;
|
|
}
|
|
|
|
function ajaxEvidenceText(events = []) {
|
|
return events.map((item) => {
|
|
const parts = [];
|
|
if (item.event === 'error') {
|
|
parts.push(item.textStatus || '', item.error || '');
|
|
}
|
|
parts.push(item.responseText || '');
|
|
return parts.filter(Boolean).join(' ');
|
|
}).filter(Boolean).join('\n');
|
|
}
|
|
|
|
async function submitInfoFormAndConfirm(pageOrFrame, dialogState = null, options = {}) {
|
|
const source = options.source || 'erp.submit';
|
|
const waitMs = Number.isFinite(options.waitMs) ? options.waitMs : 30000;
|
|
const ajaxTimeoutMs = Number.isFinite(options.ajaxTimeoutMs) ? options.ajaxTimeoutMs : Math.max(waitMs, 30000);
|
|
const requireSuccess = options.requireSuccess !== false;
|
|
const cursor = dialogCursor(dialogState);
|
|
const ajaxProbe = await installSubmitAjaxProbe(pageOrFrame, ajaxTimeoutMs);
|
|
|
|
await pageOrFrame.evaluate(() => {
|
|
if (typeof SubmitInfoForm !== 'function') throw new Error('SubmitInfoForm not found');
|
|
SubmitInfoForm();
|
|
});
|
|
await pageOrFrame.waitForTimeout(waitMs);
|
|
|
|
assertNoNewErpLoginRequired(dialogState, cursor, source);
|
|
|
|
const newDialogs = dialogMessagesSince(dialogState, cursor);
|
|
const ajaxEvents = await readSubmitAjaxEvents(pageOrFrame);
|
|
const primaryAjaxEvents = ajaxEvents.filter(isPrimarySubmitAjaxEvent);
|
|
const primaryAjaxFailed = primaryAjaxEvents.some(isAjaxFailure);
|
|
const bodyText = await readFrameBodyText(pageOrFrame);
|
|
const evidenceText = [
|
|
newDialogs.map((item) => item.message || '').join('\n'),
|
|
ajaxEvidenceText(ajaxEvents),
|
|
bodyText,
|
|
].filter(Boolean).join('\n');
|
|
|
|
const result = {
|
|
ok: isSubmitSuccessText(evidenceText) && !primaryAjaxFailed,
|
|
source,
|
|
dialogs: newDialogs,
|
|
ajaxProbe,
|
|
ajaxEvents,
|
|
primaryAjaxEvents,
|
|
primaryAjaxFailed,
|
|
bodyPreview: bodyText.slice(0, 1000),
|
|
};
|
|
|
|
if (requireSuccess && !result.ok) {
|
|
throw createSubmitUnconfirmedError(source, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
module.exports = {
|
|
isSubmitSuccessText,
|
|
installSubmitAjaxProbe,
|
|
readSubmitAjaxEvents,
|
|
isPrimarySubmitAjaxEvent,
|
|
ajaxEvidenceText,
|
|
submitInfoFormAndConfirm,
|
|
createSubmitUnconfirmedError,
|
|
};
|