文件
hyb-oa/server/tests/unit/services/erpProcurement.test.js
T

145 行
4.6 KiB
JavaScript

const {
buildPurchaseAccrualJournalPayload,
buildPurchaseArchiveSummaryPayload,
buildPurchaseCommitmentJournalPayload,
enqueuePurchaseArchiveSummaryExport,
hashProcurementPayload,
} = require('../../../src/services/integrations/erpProcurement');
describe('ERP Procurement Service', () => {
it('builds commitment payload with procurement dimensions', () => {
const payload = buildPurchaseCommitmentJournalPayload({
purchaseRequest: {
id: 'pr-1',
request_no: 'PR-001',
applicant_id: 'applicant-1',
submitter_id: 'submitter-1',
department_id: 'dept-1',
total_amount: { toString: () => '880.00' },
currency_code: 'CNY',
legal_entity: { code: 'HY' },
cost_center: { code: 'IT001' },
supplier: { code: 'SUP001' },
budget_pool: { code: 'BG-IT-2026' },
document_category: { code: 'PR_STANDARD' },
},
occurredAt: '2026-03-08T10:00:00.000Z',
});
expect(payload.journalType).toBe('purchase_request_commitment');
expect(payload.references.requestNo).toBe('PR-001');
expect(payload.dimensions.legalEntityCode).toBe('HY');
expect(payload.dimensions.costCenterCode).toBe('IT001');
expect(payload.dimensions.supplierCode).toBe('SUP001');
expect(payload.dimensions.budgetPoolCode).toBe('BG-IT-2026');
});
it('builds accrual payload from archive facts', () => {
const payload = buildPurchaseAccrualJournalPayload({
purchaseRequest: {
id: 'pr-1',
request_no: 'PR-001',
applicant_id: 'applicant-1',
submitter_id: 'submitter-1',
department_id: 'dept-1',
total_amount: '880.00',
currency_code: 'CNY',
legal_entity: { code: 'HY' },
cost_center: { code: 'IT001' },
supplier: { code: 'SUP001' },
budget_pool: { code: 'BG-IT-2026' },
},
archive: {
id: 'archive-1',
po_no: 'PO-001',
contract_no: 'CT-001',
archived_at: '2026-03-08T10:30:00.000Z',
},
});
expect(payload.journalType).toBe('purchase_order_accrual');
expect(payload.entityId).toBe('archive-1');
expect(payload.documentNo).toBe('PO-001');
expect(payload.references.contractNo).toBe('CT-001');
});
it('builds archive summary payload and hashes payload changes', () => {
const basePayload = buildPurchaseArchiveSummaryPayload({
purchaseRequest: {
id: 'pr-1',
request_no: 'PR-001',
department_id: 'dept-1',
total_amount: '880.00',
currency_code: 'CNY',
legal_entity: { code: 'HY' },
cost_center: { code: 'IT001' },
supplier: { id: 'sup-1', code: 'SUP001', name: '演示供应商' },
},
archive: {
id: 'archive-1',
po_no: 'PO-001',
contract_no: 'CT-001',
archived_at: '2026-03-08T10:30:00.000Z',
archived_files: [
{
storagePath: 'purchase-requests/pr-1/contract.pdf',
originalName: 'contract.pdf',
mimeType: 'application/pdf',
fileSize: 1024,
},
],
},
});
const changedPayload = {
...basePayload,
contractNo: 'CT-002',
};
expect(basePayload.files).toHaveLength(1);
expect(hashProcurementPayload(basePayload)).not.toBe(hashProcurementPayload(changedPayload));
});
it('resets archive summary outbox when payload changes', async () => {
const prisma = {
integrationOutbox: {
findUnique: vi.fn().mockResolvedValue({
id: 'outbox-1',
status: 'succeeded',
payload: { contractNo: 'CT-001', poNo: 'PO-001' },
}),
update: vi.fn().mockResolvedValue({ id: 'outbox-1', status: 'pending' }),
},
};
const result = await enqueuePurchaseArchiveSummaryExport(
prisma,
{ integrationOutboxMaxAttempts: 5 },
{
actorId: 'actor-1',
purchaseRequest: {
id: 'pr-1',
request_no: 'PR-001',
department_id: 'dept-1',
total_amount: '880.00',
currency_code: 'CNY',
supplier: { id: 'sup-1', code: 'SUP001', name: '演示供应商' },
legal_entity: { code: 'HY' },
cost_center: { code: 'IT001' },
},
archive: {
id: 'archive-1',
po_no: 'PO-001',
contract_no: 'CT-002',
archived_at: '2026-03-08T10:30:00.000Z',
archived_files: [],
},
},
);
expect(prisma.integrationOutbox.update).toHaveBeenCalled();
expect(result.requeued).toBe(true);
expect(result.eventType).toBe('erp.procurement.export');
});
});