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' function setup() { const db = openDb(':memory:') const a = createClient(db, 'u1', { name: 'Acme', code: 'ACME', stateCode: '32' }) const b = 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', () => { const { db, a } = setup() upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', costPaise: 5_000_00, source: 'auto' }) upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', storageGb: 42.5, source: 'manual' }) // merges const row = 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(db.prepare(`SELECT COUNT(*) AS n FROM aws_usage WHERE client_id=?`).get(a.id)).toMatchObject({ n: 1 }) const audits = db.prepare(`SELECT action FROM audit_log WHERE entity='aws_usage'`).all() expect(audits.length).toBe(2) // create + update }) it('lists newest month first, capped', () => { const { db, a } = setup() for (const m of ['2026-04', '2026-05', '2026-06']) upsertAwsUsage(db, 'u1', { clientId: a.id, month: m, costPaise: 100 }) expect(listAwsUsage(db, a.id, 2).map((r) => r.month)).toEqual(['2026-06', '2026-05']) }) it('rejects a bad month', () => { const { db, a } = setup() expect(() => upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026/06', costPaise: 1 })).toThrow(/month/i) }) it('ranks clients by cost with share in basis points', () => { const { db, a, b } = setup() upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', costPaise: 7_500_00 }) upsertAwsUsage(db, 'u1', { clientId: b.id, month: '2026-06', costPaise: 2_500_00 }) const r = 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', () => { const { db, a } = setup() upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-05', costPaise: 100 }) upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-06', costPaise: 200 }) upsertAwsUsage(db, 'u1', { clientId: a.id, month: '2026-07', costPaise: 400 }) expect(awsCostForClient(db, a.id, '2026-05-01', '2026-06-30')).toBe(300) expect(awsCostForClient(db, a.id)).toBe(700) expect(previousMonth('2026-07-10')).toBe('2026-06') expect(previousMonth('2026-01-05')).toBe('2025-12') // year rollover }) })