import { describe, it, expect } from 'vitest' import { openDb } from '../src/db' import { createClient } from '../src/repos-clients' import { upsertAwsUsage, getAwsUsage, listAwsUsage, costRanking, awsCostForClient, previousMonth } from '../src/repos-aws' async function setup() { const db = openDb(':memory:') const a = await createClient(db, 'u1', { name: 'Acme', code: 'ACME', stateCode: '32' }) const b = await createClient(db, 'u1', { name: 'Bolt', code: 'BOLT', stateCode: '29' }) return { db, a, b } } describe('aws usage repo', () => { it('upserts and merges a (client, month) row without clobbering the other source', async () => { const { db, a } = await setup() await upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', costPaise: 5_000_00, source: 'auto' }) await upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', storageGb: 42.5, source: 'manual' }) // merges const row = (await getAwsUsage(db, a.id, '2026-06'))! expect(row.costPaise).toBe(5_000_00) // auto cost preserved expect(row.storageGb).toBe(42.5) // manual storage applied expect(await db.get(`SELECT COUNT(*) AS n FROM aws_usage WHERE client_id=?`, a.id)).toMatchObject({ n: 1 }) const audits = await db.all(`SELECT action FROM audit_log WHERE entity='aws_usage'`) expect(audits.length).toBe(2) // create + update }) it('lists newest month first, capped', async () => { const { db, a } = await setup() for (const m of ['2026-04', '2026-05', '2026-06']) await upsertAwsUsage(db, 'u1', { clientId: a.id, month: m, costPaise: 100 }) expect((await listAwsUsage(db, a.id, 2)).map((r) => r.month)).toEqual(['2026-06', '2026-05']) }) it('rejects a bad month', async () => { const { db, a } = await setup() await expect(upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026/06', costPaise: 1 })).rejects.toThrow(/month/i) }) it('ranks clients by cost with share in basis points', async () => { const { db, a, b } = await setup() await upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', costPaise: 7_500_00 }) await upsertAwsUsage(db, 'u1', { clientId: b.id, month: '2026-06', costPaise: 2_500_00 }) const r = await costRanking(db, '2026-06') expect(r.total).toBe(10_000_00) expect(r.rows.map((x) => x.clientId)).toEqual([a.id, b.id]) // Acme first (higher cost) expect(r.rows[0]!.sharePctBp).toBe(7500) // 75.00% expect(r.rows[1]!.sharePctBp).toBe(2500) }) it('sums a client cost over a month range and derives the previous month', async () => { const { db, a } = await setup() await upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-05', costPaise: 100 }) await upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', costPaise: 200 }) await upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-07', costPaise: 400 }) expect(await awsCostForClient(db, a.id, '2026-05-01', '2026-06-30')).toBe(300) expect(await awsCostForClient(db, a.id)).toBe(700) expect(previousMonth('2026-07-10')).toBe('2026-06') expect(previousMonth('2026-01-05')).toBe('2025-12') // year rollover }) })