const assert = require('node:assert/strict'); const { randomUUID } = require('node:crypto'); const { createRequire } = require('node:module'); const path = require('node:path'); const { setTimeout: delay } = require('node:timers/promises'); const req = createRequire(path.resolve(__dirname, '../../server/package.json')); // Real Fastify routes and Prisma transactions; synthetic authorized identity. // Authentication and browser behavior remain covered by the ordinary full gate. module.exports = async ({ prisma, pool, check, contend, used }) => { const app = req('fastify')({ logger: false }); const department = await prisma.department.create({ data: { name: '合成预算并发部门' } }); const employee = async role => prisma.employee.create({ data: { email: `${randomUUID()}@example.invalid`, name: '合成预算用户', department_id: department.id, title: '合成岗位', hire_date: new Date('2025-01-01'), bank_name: 'synthetic', bank_account_encrypted: 'synthetic-unused', password_hash: 'synthetic-unused', roles: { create: { role_code: role } }, } }); const owner = await employee('employee'); const manager = await employee('manager'); await employee('finance'); const company = await prisma.legalEntity.create({ data: { code: `SYN-${randomUUID()}`, name: '合成公司' } }); const costCenter = await prisma.costCenter.create({ data: { code: 'SYN', name: '合成成本中心', legal_entity_id: company.id } }); const supplier = await prisma.supplier.create({ data: { code: `SYN-${randomUUID()}`, name: '合成供应商', legal_entity_id: company.id } }); const category = await prisma.documentCategory.create({ data: { code: `SYN-${randomUUID()}`, name: '合成采购类别', entity_type: 'purchase_request', sequence_prefix: 'SYN', reset_period: 'yearly' } }); const expense = await prisma.expenseType.create({ data: { code: `SYN-${randomUUID()}`, name: '合成办公费', category: 'office', sort_order: 999, requires_invoice: false } }); await prisma.approvalRule.create({ data: { name: '合成财务审批', min_amount: '0', level1_role: 'finance', priority: 1 } }); for (const entity_type of ['purchase_request', 'reimbursement']) { await prisma.workflowDefinition.create({ data: { entity_type, name: '合成预算流程', version: 1, definition_json: { steps: [{ id: 'approve', name: '合成审批', type: 'approval', assignee_rule: { type: 'role', value: 'manager' } }] } } }); } app.decorate('prisma', prisma); const config = { appTimezone: 'Asia/Shanghai', budgetPrecheckEnabled: false, budgetControlMode: 'block', emailEnabled: false, imNotifierEnabled: false, cutoverConsoleEnabled: false, reimbursementInvoiceGuardEnabled: false }; app.decorate('config', config); const actor = { ...owner, roleCodes: ['employee'], permissionCodes: ['*'] }; app.decorate('hasPermission', () => true); app.decorate('requirePermission', () => async request => { request.employee = actor; }); app.setErrorHandler((error, request, reply) => reply.code(error.statusCode ?? 500).send({ code: error.code ?? 'SYS_001', reason: error.details?.reasonCode ?? null, precheckCodes: error.details?.precheck?.map?.(item => item.code) ?? [], })); await app.register(req('./src/routes/purchaseRequests'), { prefix: '/api' }); await app.register(req('./src/routes/reimbursements'), { prefix: '/api' }); await app.register(req('./src/routes/travelTransactions'), { prefix: '/api' }); await app.ready(); let selected; const today = new Date(); async function setup({ enabled, mode = 'block' }) { config.budgetPrecheckEnabled = enabled; config.budgetControlMode = mode; await prisma.featureFlag.upsert({ where: { flag_key: 'budget_precheck_v1' }, update: { override_mode: enabled ? 'force_on' : 'force_off' }, create: { flag_key: 'budget_precheck_v1', override_mode: enabled ? 'force_on' : 'force_off', rollout_type: 'global' } }); await prisma.budgetPool.updateMany({ data: { status: 'archived', archived_at: today } }); selected = await prisma.budgetPool.create({ data: { code: `SYN-${randomUUID()}`, name: '合成共享预算', period_start: new Date(today.getFullYear(), 0, 1), period_end: new Date(today.getFullYear(), 11, 31), allocated_amount: '100.00', used_amount: '0.00', warning_threshold_percent: 100 } }); } async function purchase(explicit = false, amount = '60.00') { const row = await prisma.purchaseRequest.create({ data: { applicant_id: owner.id, department_id: department.id, title: '合成并发采购', legal_entity_id: company.id, cost_center_id: costCenter.id, supplier_id: supplier.id, document_category_id: category.id, request_no: `SYN-${randomUUID()}`, total_amount: amount, budget_pool_id: explicit ? selected.id : null, items: { create: { description: '合成用品', quantity: '1.00', unit_price: amount, line_amount: amount } } } }); return { id: row.id, type: 'purchase_request', url: `/api/purchase-requests/${row.id}/submit` }; } async function reimbursement(amount = '60.00') { const row = await prisma.reimbursementForm.create({ data: { owner_id: owner.id, submitter_id: owner.id, department_id: department.id, reimbursement_date: today, form_number: `SYN-${randomUUID()}`, total_amount: amount, items: { create: { expense_type_id: expense.id, expense_date: today, amount, description: '合成并发费用' } } }, include: { items: true } }); await prisma.invoicePool.create({ data: { owner_employee_id: owner.id, uploaded_by_employee_id: owner.id, storage_path: 'synthetic/not-a-real-file', original_name: 'synthetic.txt', mime_type: 'text/plain', file_size: 1, file_sha256: randomUUID(), status: 'bound', linked_reimbursement_id: row.id, linked_item_id: row.items[0].id, total_amount: amount, ocr_completed_at: today } }); return { id: row.id, type: 'reimbursement', url: `/api/reimbursements/${row.id}/submit` }; } const submit = entity => () => app.inject({ method: 'POST', url: entity.url }); async function assertRace(entities, expectedStatuses, expectedUsage) { const responses = await contend(selected.id, entities.map(submit), true); // Only safe codes are logged for unexpected route responses. if (responses.some(r => !expectedStatuses.includes(r.statusCode))) { console.log(JSON.stringify({ routeDiagnostics: responses.map(r => ({ status: r.statusCode, ...(r.statusCode >= 400 ? r.json() : {}) })) })); } assert.deepEqual(responses.map(r => r.statusCode).sort(), expectedStatuses.slice().sort()); assert.equal(await used(selected.id), expectedUsage); const winners = responses.filter(r => r.statusCode === 200).length; assert.equal(await prisma.budgetLedgerEntry.count({ where: { budget_pool_id: selected.id } }), winners); assert.equal(await prisma.workflowInstance.count({ where: { entity_id: { in: entities.map(e => e.id) } } }), winners); } try { for (const enabled of [false, true]) { for (const explicit of [false, true]) { await check(`purchase_block_concurrency_gate_${enabled}_explicit_${explicit}`, async () => { await setup({ enabled }); await assertRace([await purchase(explicit), await purchase(explicit)], [200, 409], '60.00'); }); } await check(`reimbursement_block_concurrency_gate_${enabled}`, async () => { await setup({ enabled }); await assertRace([await reimbursement(), await reimbursement()], [200, 409], '60.00'); }); await check(`mixed_purchase_reimbursement_block_gate_${enabled}`, async () => { await setup({ enabled }); await assertRace([await purchase(), await reimbursement()], [200, 409], '60.00'); }); await check(`mixed_warn_keeps_both_writes_gate_${enabled}`, async () => { await setup({ enabled, mode: 'warn' }); await assertRace([await purchase(), await reimbursement()], [200, 200], '120.00'); }); } await check('exact_capacity_and_duplicate_submit', async () => { await setup({ enabled: true }); const a = await purchase(false, '40.00'); const b = await reimbursement(); // Precheck block also blocks warning threshold hits under its existing rule. await prisma.budgetPool.update({ where: { id: selected.id }, data: { warning_threshold_percent: 101 } }); await assertRace([a, b], [200, 200], '100.00'); assert.equal((await submit(a)()).statusCode, 409); assert.equal(await used(selected.id), '100.00'); }); await check('submit_ledger_failure_rolls_back_usage_and_workflow', async () => { await setup({ enabled: false }); const form = await reimbursement(); await pool.query(`CREATE FUNCTION synthetic_budget_failure() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'synthetic failure'; END $$; CREATE TRIGGER synthetic_budget_failure BEFORE INSERT ON budget_ledger_entries FOR EACH ROW EXECUTE FUNCTION synthetic_budget_failure()`); try { assert.equal((await submit(form)()).statusCode, 500); assert.equal(await used(selected.id), '0.00'); assert.equal(await prisma.workflowInstance.count({ where: { entity_id: form.id } }), 0); assert.equal((await prisma.reimbursementForm.findUniqueOrThrow({ where: { id: form.id } })).status, 'draft'); } finally { await pool.query('DROP TRIGGER synthetic_budget_failure ON budget_ledger_entries; DROP FUNCTION synthetic_budget_failure()'); } }); for (const kind of ['purchase', 'reimbursement']) { await check(`legacy_block_exact_decimal_capacity_${kind}`, async () => { await setup({ enabled: false }); await prisma.budgetPool.update({ where: { id: selected.id }, data: { allocated_amount: '0.30', used_amount: '0.10' } }); const entity = kind === 'purchase' ? await purchase(false, '0.20') : await reimbursement('0.20'); assert.equal((await submit(entity)()).statusCode, 200); assert.equal(await used(selected.id), '0.30'); }); } await check('allocation_reduced_during_wait_is_used_by_both_submitters', async () => { await setup({ enabled: true }); const entities = [await purchase(), await reimbursement()]; const responses = await contend(selected.id, entities.map(submit), true, blocker => blocker.query('UPDATE budget_pools SET allocated_amount=50 WHERE id=$1', [selected.id])); assert.deepEqual(responses.map(r => r.statusCode), [409, 409]); assert.equal(await used(selected.id), '0.00'); assert.equal(await prisma.budgetLedgerEntry.count({ where: { budget_pool_id: selected.id } }), 0); }); for (const table of ['workflow_history', 'audit_logs']) { await check(`submit_${table}_failure_rolls_back_all_writes`, async () => { await setup({ enabled: false }); const form = await reimbursement(); if (table === 'audit_logs') await prisma.reimbursementForm.update({ where: { id: form.id }, data: { submitter_id: manager.id } }); // Table is from the fixed two-element allowlist above, not user input. await pool.query(`CREATE FUNCTION synthetic_budget_failure() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'synthetic failure'; END $$; CREATE TRIGGER synthetic_budget_failure BEFORE INSERT ON ${table} FOR EACH ROW EXECUTE FUNCTION synthetic_budget_failure()`); try { assert.equal((await submit(form)()).statusCode, 500); assert.equal(await used(selected.id), '0.00'); assert.equal(await prisma.budgetLedgerEntry.count({ where: { budget_pool_id: selected.id } }), 0); assert.equal(await prisma.workflowInstance.count({ where: { entity_id: form.id } }), 0); assert.equal((await prisma.reimbursementForm.findUniqueOrThrow({ where: { id: form.id } })).status, 'draft'); } finally { await pool.query(`DROP TRIGGER synthetic_budget_failure ON ${table}; DROP FUNCTION synthetic_budget_failure()`); } }); } await check('authorization_and_refund_share_entity_before_pool_lock_order', async () => { await setup({ enabled: false }); // Exercise the frozen import handler only in this synthetic Fastify app; // no deployment flag, external integration or browser scenario is enabled. config.travelSyncEnabled = true; const travel = await prisma.travelRequest.create({ data: { applicant_employee_id: owner.id, department_id: department.id, legal_entity_id: company.id, cost_center_id: costCenter.id, budget_pool_id: selected.id, purpose: '合成锁序验证', trip_type: 'domestic', start_date: today, end_date: today, estimated_amount: '60.00' } }); const authorization = await prisma.cardAuthorization.create({ data: { source: 'synthetic', external_auth_no: randomUUID(), employee_id: owner.id, department_id: department.id, travel_request_id: travel.id, budget_pool_id: selected.id, legal_entity_id: company.id, cost_center_id: costCenter.id, authorized_amount: '60.00' } }); let refund; try { await prisma.$transaction(async t => { await t.$queryRaw`SELECT id FROM card_authorizations WHERE id=${authorization.id}::uuid FOR NO KEY UPDATE`; refund = app.inject({ method: 'POST', url: '/api/travel/transactions/import', payload: { transactions: [{ source: 'synthetic', externalTxnId: randomUUID(), employeeId: owner.id, travelRequestId: travel.id, cardAuthorizationId: authorization.id, amount: '20.00', currency: 'CNY', txnType: 'refund', status: 'settled', }] } }); // Start the injection and observe its wait on the authorization. refund = Promise.resolve(refund); const deadline = Date.now() + 2000; let waiting = 0; while (Date.now() < deadline) { waiting = (await pool.query("SELECT count(*)::int n FROM pg_stat_activity WHERE datname=current_database() AND wait_event_type='Lock'")).rows[0].n; if (waiting) break; await delay(10); } assert.equal(waiting, 1); await req('./src/services/travelPayments').authorizeBudgetForEntity(t, { budgetPoolId: selected.id, entityId: authorization.id, amount: '60.00', actorId: owner.id, note: 'synthetic authorization' }); }); const response = await refund; assert.equal(response.statusCode, 200); assert.equal(response.json().data.reversedCount, 1); assert.equal(await used(selected.id), '40.00'); } finally { if (refund) await refund; config.travelSyncEnabled = false; } }); } finally { await app.close(); } };