// 已读取AGENTS.md import * as fs from 'fs'; import * as path from 'path'; /** * 第九十八批:后台人工调整余额。 * 背景:测试与运营需要给用户钱包充值/扣减,但后台没有入口,只能改库。 * 要求:必须管理员权限、事务锁行、禁止扣成负数、写财务流水。 */ describe('第九十八批后台余额调整闸门', () => { const root = path.resolve(__dirname, '../../'); const read = (rel: string) => fs.readFileSync(path.join(root, rel), 'utf-8'); const indexCode = read('server/src/index.ts'); const repo = read('server/src/db/repository.ts'); const adminPage = read('admin/arco-design-pro-vite/src/views/user/list/index.vue'); it('接口必须要求管理员权限', () => { expect(indexCode).toContain("app.post('/api/admin/users/:id/balance', requireAdmin"); expect(indexCode).toContain('adjustUserBalance'); }); it('仓储层必须锁行、校验负数并写财务流水', () => { const start = repo.indexOf('async adjustUserBalance('); expect(start).toBeGreaterThan(-1); const block = repo.slice(start, start + 3200); expect(block).toContain('FOR UPDATE'); expect(block).toContain('余额不足'); expect(block).toContain('后台余额充值'); expect(block).toContain('后台余额扣减'); expect(block).toContain('INSERT INTO finance_records'); }); it('后台用户列表必须提供「调余额」入口与弹窗', () => { expect(adminPage).toContain('openBalanceModal'); expect(adminPage).toContain('balanceModalVisible'); expect(adminPage).toContain('/api/admin/users/${balanceTarget.value.id}/balance'); expect(adminPage).toContain('调整用户钱包余额'); }); });