import { describe, expect, it } from 'vitest'; import { buildApp } from '../../src/app.js'; import { loadConfig } from '../../src/config.js'; import { newUlid } from '../../src/core/ids.js'; import { insertOutboxEvent } from '../../src/core/outbox.js'; import { Database } from '../../src/infrastructure/database.js'; const connectionString = process.env.DATABASE_TEST_URL; const describeDatabase = connectionString ? describe : describe.skip; describeDatabase('live PostgreSQL audit remediations', () => { it('creates an employee and completes the outbox-producing shift and payroll workflow', async () => { const database = new Database(connectionString!); const tenantId = newUlid(); const actorId = newUlid(); const managerToken = 'm'.repeat(64); const orgUnitId = newUlid(); const sessionId = newUlid(); const probeOutboxId = await database.tenantTransaction(tenantId, actorId, (client) => insertOutboxEvent(client, { tenantId, eventType: 'staff.audit_probe.created', subjectType: 'AuditProbe', subjectId: newUlid(), actorType: 'user', actorId, payload: { source: 'live-postgres-test' }, correlationId: newUlid(), }), ); const role = await database.pool.query( 'SELECT rolsuper, rolbypassrls FROM pg_roles WHERE rolname = current_user', ); expect(role.rows[0]).toEqual({ rolsuper: false, rolbypassrls: false }); const probe = await database.tenantTransaction(tenantId, actorId, (client) => client.query<{ occurred_at: Date }>('SELECT occurred_at FROM staff_outbox WHERE id = $1', [ probeOutboxId, ]), ); expect(probe.rows[0]?.occurred_at).toBeTruthy(); const app = await buildApp({ config: loadConfig({ DATABASE_URL: connectionString!, STANDALONE_TENANT_ID: tenantId, STANDALONE_ACTOR_ID: actorId, STANDALONE_MANAGER_TOKEN: managerToken, STANDALONE_TERMINAL_TOKEN: 't'.repeat(64), STANDALONE_ACCESS: 'manager', LOG_LEVEL: 'silent', NODE_ENV: 'test', }), database, }); const authorization = { authorization: `Bearer ${managerToken}` }; let employeeId: string | undefined; try { const employee = await app.inject({ method: 'POST', url: '/api/v1/staff/employees', headers: authorization, payload: { personnel_number: `AUDIT-${newUlid()}`, display_name: 'Тестовый сотрудник', position: 'Тестовая профессия', }, }); expect(employee.statusCode).toBe(201); employeeId = employee.json<{ id: string }>().id; await database.tenantTransaction(tenantId, actorId, async (client) => { await client.query( `INSERT INTO staff_org_units (id, tenant_id, code, name) VALUES ($1, $2, $3, 'Тестовая точка')`, [orgUnitId, tenantId, `audit-${newUlid().toLowerCase()}`], ); await client.query( `INSERT INTO staff_work_sessions (id, tenant_id, employee_id, org_unit_id, business_date, started_at, ended_at, worked_minutes, status) VALUES ($1, $2, $3, $4, '2040-01-15', '2040-01-15T01:00:00Z', '2040-01-15T09:00:00Z', 480, 'pending_review')`, [sessionId, tenantId, employeeId, orgUnitId], ); }); const confirmed = await app.inject({ method: 'PATCH', url: `/api/v1/staff/work-sessions/${sessionId}`, headers: authorization, payload: { status: 'confirmed' }, }); expect(confirmed.statusCode).toBe(200); const calculated = await app.inject({ method: 'POST', url: '/api/v1/staff/payroll/calculate', headers: authorization, payload: { month: '2040-01' }, }); expect(calculated.statusCode).toBe(200); const runId = calculated.json<{ run_id: string }>().run_id; const approved = await app.inject({ method: 'POST', url: `/api/v1/staff/payroll/runs/${runId}/approve`, headers: authorization, payload: {}, }); expect(approved.statusCode).toBe(200); } finally { await database.tenantTransaction(tenantId, actorId, async (client) => { await client.query('DELETE FROM staff_outbox WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_audit_log WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_timesheet_entries WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_payroll_lines WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_payroll_runs WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_work_sessions WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_pay_assignments WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_pay_rules WHERE tenant_id = $1', [tenantId]); await client.query('DELETE FROM staff_metric_definitions WHERE tenant_id = $1', [tenantId]); if (employeeId) { await client.query('DELETE FROM staff_employees WHERE tenant_id = $1 AND id = $2', [ tenantId, employeeId, ]); } await client.query('DELETE FROM staff_org_units WHERE tenant_id = $1', [tenantId]); }); await app.close(); } }); });