feat(P19ERP2-1,P19ERP2-2): 实现采购ERP凭证与摘要出站服务
这个提交包含在:
@@ -34,6 +34,13 @@ function resolveJournalExportEndpoint(config) {
|
||||
);
|
||||
}
|
||||
|
||||
function resolveProcurementExportEndpoint(config) {
|
||||
return (
|
||||
String(config.erpProcurementExportEndpoint ?? '').trim() ||
|
||||
String(config.erpSyncEndpoint ?? '').trim()
|
||||
);
|
||||
}
|
||||
|
||||
async function parseResponseBody(response) {
|
||||
const contentType = response.headers.get('content-type') || '';
|
||||
if (contentType.includes('application/json')) {
|
||||
@@ -192,12 +199,14 @@ async function exportJournalToErp(config, payload) {
|
||||
|
||||
const provider = normalizeProvider(config);
|
||||
if (provider === 'mock') {
|
||||
const identity = payload?.documentNo ?? payload?.formNumber ?? payload?.entityId ?? payload?.reimbursementId ?? 'UNKNOWN';
|
||||
return {
|
||||
ok: true,
|
||||
code: 'mock_synced',
|
||||
message: 'mock ERP synced',
|
||||
response: {
|
||||
externalId: `ERP-${payload?.documentNo ?? payload?.formNumber ?? payload?.entityId ?? payload?.reimbursementId ?? 'UNKNOWN'}`,
|
||||
externalId: `ERP-${identity}`,
|
||||
externalCode: `ERP-${identity}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -227,6 +236,59 @@ async function exportJournalToErp(config, payload) {
|
||||
};
|
||||
}
|
||||
|
||||
async function exportProcurementToErp(config, payload) {
|
||||
if (!config.erpSyncEnabled) {
|
||||
return {
|
||||
ok: false,
|
||||
code: 'erp_sync_disabled',
|
||||
message: 'ERP sync disabled',
|
||||
retryable: false,
|
||||
};
|
||||
}
|
||||
|
||||
const provider = normalizeProvider(config);
|
||||
if (provider === 'mock') {
|
||||
const identity = payload?.poNo ?? payload?.contractNo ?? payload?.entityId ?? 'UNKNOWN';
|
||||
return {
|
||||
ok: true,
|
||||
code: 'mock_synced',
|
||||
message: 'mock ERP procurement synced',
|
||||
response: {
|
||||
externalId: `ERP-PROC-${identity}`,
|
||||
externalCode: `ERP-PROC-${identity}`,
|
||||
externalPoId: payload?.poNo ? `ERP-PO-${payload.poNo}` : null,
|
||||
externalPoNo: payload?.poNo ? `ERP-PO-${payload.poNo}` : null,
|
||||
externalContractId: payload?.contractNo ? `ERP-CT-${payload.contractNo}` : null,
|
||||
externalContractNo: payload?.contractNo ? `ERP-CT-${payload.contractNo}` : null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (provider === 'http') {
|
||||
return postJsonToErp(config, {
|
||||
endpoint: resolveProcurementExportEndpoint(config),
|
||||
timeoutMs: coerceTimeout(config.erpProcurementTimeoutMs, config.erpSyncTimeoutMs),
|
||||
payload,
|
||||
successCode: 'http_synced',
|
||||
successMessage: 'ERP procurement synced',
|
||||
missingEndpointCode: 'erp_procurement_endpoint_missing',
|
||||
missingEndpointMessage: 'ERP procurement endpoint missing',
|
||||
http4xxCode: 'erp_procurement_http_4xx',
|
||||
http5xxCode: 'erp_procurement_http_5xx',
|
||||
timeoutCode: 'erp_procurement_timeout',
|
||||
networkCode: 'erp_procurement_network_error',
|
||||
messagePrefix: 'ERP procurement sync',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
code: 'erp_sync_provider_invalid',
|
||||
message: `Unsupported ERP sync provider: ${provider}`,
|
||||
retryable: false,
|
||||
};
|
||||
}
|
||||
|
||||
function buildErpPayload(input) {
|
||||
return buildReimbursementJournalPayload(input);
|
||||
}
|
||||
@@ -238,6 +300,7 @@ async function pushPaidReimbursementToErp(config, payload) {
|
||||
module.exports = {
|
||||
buildErpPayload,
|
||||
exportJournalToErp,
|
||||
exportProcurementToErp,
|
||||
normalizeProvider,
|
||||
pullMasterDataFromErp,
|
||||
pushPaidReimbursementToErp,
|
||||
|
||||
在新工单中引用
屏蔽一个用户