# Release Notes ## 2026-03-29 - 场馆入场计费逻辑重构 ### 一、按时计费流程 ``` 入场 join() ├─ price = basePrice × 2 (2小时押金) ├─ 返回 flg=2, 等待支付 └─ 支付成功 → paySuccess() └─ 创建订单 (orderSn=原始订单号, paying=0) 出场 out() ├─ actualCost = (minutes / 60) × basePrice (保留2位小数) ├─ deposit = basePrice × 2 ├─ difference = actualCost - deposit │ ├─ difference > 0 (需补费) │ └─ 返回 flg=2, 等待支付 │ └─ 支付成功 → paySuccess(enterFlag=OUT) │ └─ 设置 orderAddSn=补费订单号, paying=2 │ ├─ difference < 0 (需退款) │ └─ payMoney = |difference| (BigDecimal, 2位小数) │ └─ paying=1, status=USED │ └─ 用户可立即重新入场 │ └─ 批处理退款 │ └─ difference = 0 (刚好) └─ paying=2, status=USED 批处理 refundOrder() ├─ 扫描 paying=1 的订单 ├─ 如果 orderAddSn 存在 → 跳过(补费订单) ├─ 如果 orderAddSn 不存在 → 退款 └─ 调用微信退款接口 (元转分) ``` ### 二、按次计费流程 ``` 入场 join() ├─ price = basePrice (单次费用) ├─ 返回 flg=2, 等待支付 └─ 支付成功 → paySuccess() └─ 创建订单 (orderSn=原始订单号, paying=0, 有效期=timePayHour) 出场 out() └─ paying=1, 10分钟宽限期 重新入场 join() ├─ 如果 paying=1 且按次计费 → 重置 paying=0 └─ 否则 → 已在场内 批处理 refundOrder() ├─ 扫描 paying=1 的订单 ├─ 按次计费: 10分钟后关闭订单 └─ 按时计费: 立即退款(如果无补费记录) 批处理 execute() └─ order_end < now → 关闭订单 ``` ### 三、管理员手动退费 ``` enterOrderAccount(enterId, payMoney) ├─ 检查: paying != 1 (不能重复结算) ├─ 检查: orderAddSn 为空 (不能退补费订单) ├─ 检查: 退款金额 <= 原订单金额 └─ 设置 paying=1, payMoney=指定金额 └─ 等待批处理处理 ``` ### 四、金额类型规范 | 位置 | 类型 | 精度 | 说明 | |---|---|---|---| | 数据库 pay_money | DECIMAL(10,2) | 2位小数 | | | 数据库 sum_pay_money | DECIMAL(10,2) | 2位小数 | | | 实体 BarcodeOrderTime.payMoney | BigDecimal | 2位小数 | | | 实体 BarcodeOrderTime.sumPayMoney | BigDecimal | 2位小数 | | | 微信支付接口 | Integer | 分 | 元×100 | | 微信退款接口 | Integer | 分 | 元×100 | ### 五、关键表字段变动 | 场景 | sv_barcode_order_time | sv_member_refund | sv_member_money_log | |---|---|---|---| | 入场支付成功 | order_sn=A, paying=0 | - | type=JOIN | | 出场需退款 | paying=1, payMoney=退款额 | - | - | | 批处理退款 | paying=0, status=USED | money=退款额 | type=REFUND | | 出场需补费 | paying=1, payMoney=-1 | - | - | | 补费支付成功 | order_add_sn=B, paying=2 | - | type=JOIN | | 管理员退费 | paying=1, payMoney=指定额 | - | - | ### 六、已修复的问题 | 问题 | 修复 | |---|---| | payMoney 类型 | Integer → BigDecimal | | sumPayMoney 类型 | Integer → BigDecimal | | XML 映射 | jdbcType INTEGER → DECIMAL | | 金额比较 | \> 0 → compareTo(ZERO) > 0 | | 金额计算 | int 加法 → BigDecimal.add() | | 退款金额精度 | intValue() → setScale(2) | | 退款金额单位混乱 | 统一为元,微信接口转分 | | 补费订单退款 | 跳过不处理 | | 管理员退费限制 | 有补费记录时拒绝 | | 8小时兜底逻辑 | 删除(冗余) | | 10分钟宽限期 | 只给按次计费 | | 出场退款后无法立即入场 | 设置 status=USED,允许立即重新入场 | ### 七、修改文件清单 | 文件 | 修改内容 | |---|---| | `BarcodeOrderTime.java` | payMoney, sumPayMoney: Integer → BigDecimal | | `BarcodeOrderTimeMapper.xml` | jdbcType: INTEGER → DECIMAL | | `VenueEnterService.java` | 重写 out() 按分钟计费;setPayMoney() 参数改为 BigDecimal | | `OrderService.java` | setPayMoney(-1) → setPayMoney(new BigDecimal(-1)) | | `MemberRefundService.java` | sumPayMoney 计算改为 BigDecimal.add() | | `BarcodeTimeOrderTask.java` | 删除8小时兜底;getPayMoney() 比较改为 compareTo() | | `ServerMessageHandlerAdapter.java` | getPayMoney() 比较改为 compareTo() | | `MemberEnterVeneuLogController.java` | payMoney 参数改为 BigDecimal | | `WechatPayService.java` | refundInputMoney() 方法签名改为接收原订单金额和退款金额 |