fix(correctness): 并发/事务/实体/时区/状态一致性修复
由 OCR(open-codereview.ai,deepseek-v4-flash)审查驱动修复: - wallets 原子扣款防 double-spend;refund 条件更新幂等;findTransactions 分页 - financial/imports/occupancies/attendance 事务与 advisory lock;重复生成/提交幂等 - 矛盾校验器、日期区间、实体双映射/DECIMAL/nullable、时区统一(china-time) - rbac-seed 防重激活、exam 权限恢复、状态一致性、路由顺序、N+1/IN 分块等性能项 Reviewed-by: OCR (open-codereview.ai)
This commit is contained in:
@@ -75,7 +75,14 @@ export class OccupancyOperationsService {
|
||||
await manager.save(occ);
|
||||
if (occ.bedId) await manager.update(Bed, occ.bedId, { status: 'available' });
|
||||
if (occ.lockerId) await manager.update(Locker, occ.lockerId, { status: 'available' });
|
||||
await manager.update(Room, occ.roomId, { status: 'available' });
|
||||
// 多床位房间不能因为单条退宿就置为 available:
|
||||
// 只有该房间不再有任何在住记录时才更新房间状态。
|
||||
const remainingActive = await manager.count(Occupancy, {
|
||||
where: { roomId: occ.roomId, checkOutDate: IsNull() },
|
||||
});
|
||||
if (remainingActive === 0) {
|
||||
await manager.update(Room, occ.roomId, { status: 'available' });
|
||||
}
|
||||
return occ;
|
||||
});
|
||||
}
|
||||
@@ -113,7 +120,14 @@ export class OccupancyOperationsService {
|
||||
if (oldOcc.lockerId) {
|
||||
await runner.manager.update(Locker, oldOcc.lockerId, { status: 'available' });
|
||||
}
|
||||
await runner.manager.update(Room, oldOcc.roomId, { status: 'available' });
|
||||
// 多床位房间不能因为单次换房就置为 available:
|
||||
// 只有原房间不再有任何在住记录时才更新房间状态。
|
||||
const oldRoomRemaining = await runner.manager.count(Occupancy, {
|
||||
where: { roomId: oldOcc.roomId, checkOutDate: IsNull() },
|
||||
});
|
||||
if (oldRoomRemaining === 0) {
|
||||
await runner.manager.update(Room, oldOcc.roomId, { status: 'available' });
|
||||
}
|
||||
// 检查新房容量
|
||||
const newRoom = await withPessimisticWriteLock(
|
||||
runner.manager
|
||||
@@ -365,12 +379,18 @@ export class OccupancyOperationsService {
|
||||
occ.billingEndDate = dto.billingEndDate || dto.checkOutDate;
|
||||
occ.checkOutReason = dto.checkOutReason || '';
|
||||
await runner.manager.save(occ);
|
||||
// 更新房间状态
|
||||
await runner.manager.update(Room, occ.roomId, { status: 'available' });
|
||||
// 释放床位/柜子
|
||||
if (occ.bedId) await runner.manager.update(Bed, occ.bedId, { status: 'available' });
|
||||
if (occ.lockerId)
|
||||
await runner.manager.update(Locker, occ.lockerId, { status: 'available' });
|
||||
// 多床位房间不能因为单条退宿就置为 available:
|
||||
// 只有该房间不再有任何在住记录时才更新房间状态。
|
||||
const remainingActive = await runner.manager.count(Occupancy, {
|
||||
where: { roomId: occ.roomId, checkOutDate: IsNull() },
|
||||
});
|
||||
if (remainingActive === 0) {
|
||||
await runner.manager.update(Room, occ.roomId, { status: 'available' });
|
||||
}
|
||||
success++;
|
||||
}
|
||||
await runner.commitTransaction();
|
||||
|
||||
Reference in New Issue
Block a user