fix: harden financial transaction boundaries

This commit is contained in:
2026-07-18 15:33:41 +08:00
parent 4af7acbeaa
commit 5836b421d8
19 changed files with 514 additions and 314 deletions

View File

@@ -25,6 +25,7 @@ import PermissionButton from '../../components/PermissionButton';
import { downloadBlob } from '../../utils/download';
import { message } from '../../ui/app-message';
import { buildBillPrintHtml, type BillPrintData } from './bill-print';
import { newOperationId } from '../../utils/operation-id';
const statusMap: Record<string, { text: string; color: string }> = {
@@ -93,6 +94,7 @@ const BillsPage: React.FC = () => {
const values = await generateForm.validateFields();
try {
const res: any = await api.post('/bills/generate', {
operationId: newOperationId(),
billingMonth: values.billingMonth.format('YYYY-MM'),
});
message.success(res.message || '生成成功');
@@ -128,7 +130,7 @@ const BillsPage: React.FC = () => {
okText: '确认取消', cancelText: '返回',
onOk: async () => {
if (!reason.trim()) { message.error('请输入取消原因'); throw new Error('reason required'); }
await api.post(`/bills/${id}/cancel`, { reason: reason.trim() });
await api.post(`/bills/${id}/cancel`, { operationId: newOperationId(), reason: reason.trim() });
message.success('账单已取消,已扣余额已冲正退回');
fetchData();
},

View File

@@ -5,6 +5,7 @@ import dayjs from 'dayjs';
import api from '../../api';
import PermissionButton from '../../components/PermissionButton';
import { message } from '../../ui/app-message';
import { newOperationId } from '../../utils/operation-id';
interface WalletRow {
studentId: number;
@@ -59,7 +60,7 @@ const WalletsPage: React.FC = () => {
const values = await form.validateFields();
setSaving(true);
try {
const result: any = await api.post('/wallets/change-balance', { studentId: selected.studentId, ...values });
const result: any = await api.post('/wallets/change-balance', { operationId: newOperationId(), studentId: selected.studentId, ...values });
const paid = (result.payments || []).reduce((sum: number, bill: any) => sum + Number(bill.paidAmount || 0), 0);
message.success(paid > 0 ? `余额已更新,并自动补扣历史账单` : '余额已更新');
setSelected(null);
@@ -73,6 +74,7 @@ const WalletsPage: React.FC = () => {
setSaving(true);
try {
const result: any = await api.post('/wallets/batch-change-balance', {
operationId: newOperationId(),
studentIds: selectedRowKeys,
...values,
});

View File

@@ -0,0 +1 @@
export const newOperationId = () => crypto.randomUUID();