From 42574f0412fbecc9059d1e388d2c99c691df960d Mon Sep 17 00:00:00 2001 From: dzc <2388224167@qq.com> Date: Mon, 26 Oct 2026 14:34:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E4=BC=98=E5=8C=96=E7=A6=BB=E7=BA=BF?= =?UTF-8?q?=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/order/HardOrderServiceImpl.java | 10 +++++ .../impl/order/HardOrderSyncServiceImpl.java | 42 ++++++++++++++++++- .../api/dto/WalletBalanceTransactionDto.java | 12 ++++++ .../impl/WalletTransactionServiceImpl.java | 19 +++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java index d99633cb9..8f77921ac 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java @@ -4180,6 +4180,11 @@ public class HardOrderServiceImpl extends ServiceImpl reduceRes = walletTransactionService.reduceWalletBalance(reduceBuild); diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java index 7f9d55f65..009b6cd8c 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.bsd.pjcloud.admin.api.dto.UserInfo; import com.bsd.pjcloud.admin.api.feign.RemoteUserService; import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum; @@ -144,9 +145,19 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { orderService.updateById(updateObj); } - // 同步安卓机单个离线订单 TODO 允许把金额扣为负数 + /** + * 保存单个终端离线订单及购物车,保留设备发生时间;无需审批时立即扣款,允许钱包透支。 + * + * @param order 已解析的离线订单,创建时间为空时沿用审计填充的同步时间 + * @param parentCar 待创建的父购物车 + * @param list 待创建的购物车明细 + * @param offlineOrder 终端原始订单 + * @param offLineOrderApplyEnable 是否等待后台审批后扣款 + * @return 订单保存及本次需要的扣款均成功时返回 true + */ @Transactional(rollbackFor = Exception.class) public Boolean createOfflineOrder(HardOrderEntity order, HardParentCarEntity parentCar, List list, OfflineOrder offlineOrder, boolean offLineOrderApplyEnable) { + boolean restoringOrderTime = false; try { // 创建父订单 hardParentCarService.save(parentCar); @@ -155,7 +166,21 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { hardCarService.saveBatch(list); // 创建订单 order.setParentCarId(parentCar.getId()); + LocalDateTime orderTime = order.getCreateTime(); orderService.save(order); + // 公共插入审计会覆盖 createTime;仅在离线同步事务内恢复设备时间,供统计和后续扣款共用。 + if (orderTime != null && !orderTime.equals(order.getCreateTime())) { + restoringOrderTime = true; + boolean updated = orderService.update(new LambdaUpdateWrapper() + .eq(HardOrderEntity::getId, order.getId()) + .set(HardOrderEntity::getCreateTime, orderTime)); + // 数据库时间精度可能使恢复成为同值更新,仅在订单也不存在时判定失败。 + if (!updated && orderService.getById(order.getId()) == null) { + throw new IllegalStateException("保存离线订单发生时间失败"); + } + order.setCreateTime(orderTime); + restoringOrderTime = false; + } // 支付 if (!offLineOrderApplyEnable) { orderService.fastReduceBalance(order); @@ -167,6 +192,10 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { } return true; } catch (Exception e) { + if (restoringOrderTime) { + // 时间恢复失败必须穿出事务边界并停止批次,避免错误时间订单提交或回滚后继续远程扣款。 + throw new IllegalStateException("保存离线订单发生时间失败", e); + } if (!offLineOrderApplyEnable) { HardOrderEntity updateObj = HardOrderEntity.builder().id(order.getId()).offlinePaySuccess(YesNoEnum.NO.getCode()).build(); orderService.updateById(updateObj); @@ -177,6 +206,16 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { return false; } + /** + * 将终端离线订单转换为云端订单,创建时间和预约使用日期均优先取设备下单时间,其次取支付时间。 + * + * @param order 终端上报的订单;两个时间均缺失时由保存流程使用同步时间 + * @param hardwareId 同步订单的设备 ID + * @param mchDetail 订单所属商户资料 + * @param merchantDeptId 订单归属部门 ID + * @param userInfo 下单用户及其当前部门资料 + * @return 尚未持久化的离线订单 + */ public HardOrderEntity parseOrder(OfflineOrder order, Long hardwareId, MchManageVo mchDetail, Long merchantDeptId, UserInfo userInfo) { HardOrderEntity res = new HardOrderEntity(); res.setAndroidOrderCode(order.getUniqueCode()); @@ -200,6 +239,7 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { res.setProductDesc(order.getProductDesc()); res.setHourType(order.getHourType()); LocalDateTime orderTime = Optional.ofNullable(order.getCreateTime()).orElse(order.getPayTime()); + res.setCreateTime(orderTime); // 离线订单优先保留设备原始下单日期,旧终端未传时才使用同步当天。 res.setApptUseDate(orderTime == null ? LocalDate.now() : orderTime.toLocalDate()); return res; diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java index 73c23393b..959b4c38b 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java @@ -9,6 +9,7 @@ import lombok.Builder; import lombok.Data; import java.io.Serializable; +import java.time.LocalDateTime; /** * 钱包余额变动参数;订单调用方可附带实际商户快照,账户级操作不传时由钱包服务按用户当前食堂解析。 @@ -51,6 +52,17 @@ public class WalletBalanceTransactionDto { */ private String sysRemark; + /** + * 离线订单实际发生时间,优先取设备下单时间,其次取设备支付时间;仅新建支付流水使用, + * 未传时保留钱包服务当前时间,退款不继承该时间。 + */ + private LocalDateTime createTime; + + /** + * 离线订单支付流水的业务备注,由订单服务传入“离线订单扣除”;未传时不覆盖流水原备注。 + */ + private String remark; + /** * 订单设备类型快照编码(HardTypeEnum.type);订单支付/退款调用传订单 sys_type, * 随流水固化为 hard_type 供设备类型筛选,非订单调用不传。 diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java index f71d67241..3de721780 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java @@ -220,6 +220,7 @@ public class WalletTransactionServiceImpl extends ServiceImpl 0; if (saved) { + if (isOrderPayment && context.getCreateTime() != null && !context.getCreateTime().equals(entity.getCreateTime())) { + // 公共插入审计强制使用当前时间,仅为显式携带设备时间的离线支付定向恢复,不改变其他流水审计规则。 + int updated = baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(WalletTransactionEntity::getId, entity.getId()) + .set(WalletTransactionEntity::getCreateTime, context.getCreateTime())); + // 数据库时间精度可能使恢复成为同值更新,仅在流水也不存在时判定失败。 + if (updated == 0 && baseMapper.selectById(entity.getId()) == null) { + throw new IllegalStateException("保存离线订单流水发生时间失败"); + } + entity.setCreateTime(context.getCreateTime()); + } createMessageOutbox(entity); } return saved;