Files
boc/aamos-ledger-refactor/test/period-close.test.mjs
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

105 lines
3.6 KiB
JavaScript

/**
* test/period-close.test.mjs — Period closing validation tests
*/
import { describe, it } from 'node:test';
import assert from 'node:assert';
// Mock pool that simulates period states
function createMockPool(periodState = 'open') {
return {
query: async (sql, params) => {
if (sql.includes('SELECT status FROM ledger_periods')) {
return { rows: [{ status: periodState }] };
}
if (sql.includes('INSERT INTO ledger_journal_entries')) {
return { rows: [{ id: 'test-id', status: 'draft' }] };
}
return { rows: [] };
},
connect: async () => ({
query: async (sql, params) => {
if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') return {};
if (sql.includes('SELECT status FROM ledger_periods')) {
return { rows: [{ status: periodState }] };
}
if (sql.includes('INSERT INTO ledger_journal_entries')) {
return { rows: [{ id: 'test-id', status: 'draft' }] };
}
return { rows: [] };
},
release: () => {}
})
};
}
// Period validation logic (same as in routes)
async function validatePeriodOpen(pool, tenantId, period) {
const { rows } = await pool.query(
`SELECT status FROM ledger_periods WHERE tenant_id=$1 AND period=$2`,
[tenantId, period]
);
if (rows.length > 0 && rows[0].status === 'closed') {
return { allowed: false, status: 'closed', error: `Period ${period} är stängd` };
}
return { allowed: true, status: rows[0]?.status || 'open' };
}
describe('Period closing validation', () => {
it('should allow entries in open periods', async () => {
const pool = createMockPool('open');
const result = await validatePeriodOpen(pool, 'test-tenant', '2024-01');
assert.strictEqual(result.allowed, true);
assert.strictEqual(result.status, 'open');
});
it('should block entries in closed periods', async () => {
const pool = createMockPool('closed');
const result = await validatePeriodOpen(pool, 'test-tenant', '2024-01');
assert.strictEqual(result.allowed, false);
assert.strictEqual(result.status, 'closed');
assert.ok(result.error.includes('stängd'));
});
it('should allow entries when period does not exist yet', async () => {
const pool = {
query: async () => ({ rows: [] })
};
const result = await validatePeriodOpen(pool, 'test-tenant', '2024-01');
assert.strictEqual(result.allowed, true);
});
it('should handle period format correctly', async () => {
const validPeriods = ['2024-01', '2024-12', '2023-06'];
const invalidPeriods = ['01-2024', '2024', 'invalid', '24-01'];
for (const period of validPeriods) {
assert.match(period, /^\d{4}-\d{2}$/);
}
for (const period of invalidPeriods) {
assert.doesNotMatch(period, /^\d{4}-\d{2}$/);
}
});
});
describe('Period workflow states', () => {
it('should track period state transitions', () => {
const states = ['open', 'review', 'approved', 'closed'];
const validTransitions = {
'open': ['review', 'closed'],
'review': ['approved', 'open'],
'approved': ['closed', 'open'],
'closed': ['open'] // reopen
};
// Test valid transitions
assert.ok(validTransitions['open'].includes('review'));
assert.ok(validTransitions['review'].includes('approved'));
assert.ok(validTransitions['approved'].includes('closed'));
assert.ok(validTransitions['closed'].includes('open'));
// Test invalid transitions
assert.ok(!validTransitions['open'].includes('approved'));
assert.ok(!validTransitions['closed'].includes('review'));
});
});