const integrationsRoutes = require('../../../src/routes/integrations'); describe('Integrations asset ERP route helpers', () => { const { canReadAsset, enqueueAssetExportAndMaybeRun, parseRunNow } = integrationsRoutes.__testables; function createAsset(overrides = {}) { return { id: 'asset-1', asset_no: 'ZC-001', assignee_employee_id: 'employee-1', legal_entity_id: 'le-1', cost_center_id: 'cc-1', status: 'in_use', ...overrides, }; } it('respects asset read permission rules', () => { const asset = createAsset(); expect( canReadAsset( { employee: { id: 'employee-1', permissionCodes: ['asset.view_own'] } }, asset, ), ).toBe(true); expect( canReadAsset( { employee: { id: 'other', permissionCodes: ['asset.view_own'] } }, asset, ), ).toBe(false); expect( canReadAsset( { employee: { id: 'other', permissionCodes: ['asset.view_all'] } }, asset, ), ).toBe(true); }); it('retries same asset payload without triggering runNow when duplicated', async () => { const enqueueExport = vi.fn().mockResolvedValue({ id: 'outbox-1', status: 'succeeded', duplicated: true, requeued: false, eventType: 'erp.asset.export', }); const runOutboxOnce = vi.fn(); const result = await enqueueAssetExportAndMaybeRun({ prisma: {}, config: {}, logger: {}, context: { asset: createAsset() }, actorId: 'actor-1', runNow: true, findExistingOutbox: vi.fn().mockResolvedValue({ id: 'outbox-1', status: 'succeeded', payload: { exportType: 'asset_ledger_summary', entityId: 'asset-1', assetNo: 'ZC-001', legalEntity: { id: 'le-1' }, costCenter: { id: 'cc-1' }, status: 'in_use', }, }), enqueueExport, runOutboxOnce, }); expect(enqueueExport).toHaveBeenCalledWith( {}, {}, expect.objectContaining({ payload: expect.objectContaining({ assetNo: 'ZC-001', status: 'in_use', }), requeueOnFailure: true, }), ); expect(runOutboxOnce).not.toHaveBeenCalled(); expect(result.duplicated).toBe(true); }); it('resyncs current asset snapshot when financial drift exists', async () => { const enqueueExport = vi.fn().mockResolvedValue({ id: 'outbox-1', status: 'pending', duplicated: false, requeued: true, eventType: 'erp.asset.export', }); const runOutboxOnce = vi.fn().mockResolvedValue({ total: 1, succeeded: 1, failed: 0 }); const result = await enqueueAssetExportAndMaybeRun({ prisma: {}, config: {}, logger: {}, context: { asset: createAsset({ cost_center_id: 'cc-2', status: 'retired' }) }, actorId: 'actor-1', runNow: true, findExistingOutbox: vi.fn().mockResolvedValue({ id: 'outbox-1', status: 'succeeded', payload: { exportType: 'asset_ledger_summary', entityId: 'asset-1', assetNo: 'ZC-001', legalEntity: { id: 'le-1' }, costCenter: { id: 'cc-1' }, status: 'in_use', }, }), enqueueExport, runOutboxOnce, }); expect(enqueueExport).toHaveBeenCalledWith( {}, {}, expect.objectContaining({ payload: undefined, changeType: 'retired', changedFields: expect.arrayContaining(['costCenterId', 'status']), }), ); expect(runOutboxOnce).toHaveBeenCalled(); expect(result.requeued).toBe(true); }); it('parses runNow flags for asset requeue route', () => { expect(parseRunNow({ runNow: '1' })).toBe(true); expect(parseRunNow({ runNow: '0' })).toBe(false); }); });