131 行
3.4 KiB
JavaScript
131 行
3.4 KiB
JavaScript
const purchaseRequestRoutes = require('../../../src/routes/purchaseRequests');
|
|
|
|
describe('purchase archive ERP helper', () => {
|
|
const { handlePurchaseArchiveErpSync } = purchaseRequestRoutes.__testables;
|
|
|
|
function createRequest() {
|
|
return {
|
|
id: 'req-1',
|
|
ip: '127.0.0.1',
|
|
headers: {},
|
|
employee: {
|
|
id: 'actor-1',
|
|
department_id: 'dept-1',
|
|
permissionCodes: ['procurement.manage'],
|
|
},
|
|
};
|
|
}
|
|
|
|
function createTx() {
|
|
return {
|
|
auditLog: {
|
|
create: vi.fn().mockResolvedValue({ id: 'audit-1' }),
|
|
},
|
|
};
|
|
}
|
|
|
|
function createContext() {
|
|
return {
|
|
purchaseRequest: {
|
|
id: 'pr-1',
|
|
department_id: 'dept-1',
|
|
order_archive: {
|
|
id: 'archive-1',
|
|
po_no: 'PO-001',
|
|
contract_no: 'CT-001',
|
|
archived_at: new Date('2026-03-08T10:30:00.000Z'),
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
it('first archive enqueues accrual and summary', async () => {
|
|
const tx = createTx();
|
|
const loadContext = vi.fn().mockResolvedValue(createContext());
|
|
const evaluateGate = vi.fn().mockResolvedValue({
|
|
enabled: true,
|
|
reason: 'env_inherit_department_allowed',
|
|
});
|
|
const enqueueAccrual = vi.fn().mockResolvedValue({
|
|
id: 'outbox-accrual',
|
|
status: 'pending',
|
|
duplicated: false,
|
|
requeued: false,
|
|
eventType: 'erp.journal.export',
|
|
erpTarget: 'accrual_journal',
|
|
});
|
|
const enqueueSummary = vi.fn().mockResolvedValue({
|
|
id: 'outbox-summary',
|
|
status: 'pending',
|
|
duplicated: false,
|
|
requeued: false,
|
|
eventType: 'erp.procurement.export',
|
|
erpTarget: 'archive_summary',
|
|
});
|
|
|
|
const result = await handlePurchaseArchiveErpSync({
|
|
tx,
|
|
config: {},
|
|
request: createRequest(),
|
|
actorId: 'actor-1',
|
|
purchaseRequestId: 'pr-1',
|
|
archiveId: 'archive-1',
|
|
isFirstArchive: true,
|
|
loadContext,
|
|
evaluateGate,
|
|
enqueueAccrual,
|
|
enqueueSummary,
|
|
});
|
|
|
|
expect(enqueueAccrual).toHaveBeenCalledWith(
|
|
tx,
|
|
{},
|
|
expect.objectContaining({ requeueOnFailure: false }),
|
|
);
|
|
expect(enqueueSummary).toHaveBeenCalledWith(
|
|
tx,
|
|
{},
|
|
expect.objectContaining({ requeueOnFailure: false }),
|
|
);
|
|
expect(result.items).toHaveLength(2);
|
|
expect(tx.auditLog.create).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('archive update only re-enqueues summary', async () => {
|
|
const tx = createTx();
|
|
const loadContext = vi.fn().mockResolvedValue(createContext());
|
|
const evaluateGate = vi.fn().mockResolvedValue({
|
|
enabled: true,
|
|
reason: 'env_inherit_department_allowed',
|
|
});
|
|
const enqueueAccrual = vi.fn();
|
|
const enqueueSummary = vi.fn().mockResolvedValue({
|
|
id: 'outbox-summary',
|
|
status: 'pending',
|
|
duplicated: false,
|
|
requeued: true,
|
|
eventType: 'erp.procurement.export',
|
|
erpTarget: 'archive_summary',
|
|
});
|
|
|
|
const result = await handlePurchaseArchiveErpSync({
|
|
tx,
|
|
config: {},
|
|
request: createRequest(),
|
|
actorId: 'actor-1',
|
|
purchaseRequestId: 'pr-1',
|
|
archiveId: 'archive-1',
|
|
isFirstArchive: false,
|
|
loadContext,
|
|
evaluateGate,
|
|
enqueueAccrual,
|
|
enqueueSummary,
|
|
});
|
|
|
|
expect(enqueueAccrual).not.toHaveBeenCalled();
|
|
expect(enqueueSummary).toHaveBeenCalled();
|
|
expect(result.items).toHaveLength(1);
|
|
expect(result.items[0].erpTarget).toBe('archive_summary');
|
|
});
|
|
});
|