Browse Source

修改订单保存历史记录,订单表id不变

caotao 2 weeks ago
parent
commit
83b9721fc7

+ 90 - 0
module-his/module-his-biz/src/main/java/com/yc/ship/module/his/dal/dataobject/tradeOrderPolicy/HisTradeOrderPolicyDO.java

@@ -0,0 +1,90 @@
+package com.yc.ship.module.his.dal.dataobject.tradeOrderPolicy;
+
+import lombok.*;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.*;
+import com.yc.ship.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 订单使用的优惠政策历史 DO
+ *
+ * @author 管理员
+ */
+@TableName("his_trade_order_policy")
+@KeySequence("his_trade_order_policy_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class HisTradeOrderPolicyDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    private Long hisId;
+    /**
+     * 版本号
+     */
+    private Integer version;
+    /**
+     * 当前版本号
+     */
+    private Integer currentVersion;
+    /**
+     * 历史时间
+     */
+    private LocalDateTime historyTime;
+    /**
+     * 原表主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 订单ID
+     */
+    private Long orderId;
+    /**
+     * 订单号
+     */
+    private String orderNo;
+    /**
+     * 政策ID
+     */
+    private Long policyId;
+    /**
+     * 政策名称
+     */
+    private String policyName;
+    /**
+     * 预占数量
+     */
+    private BigDecimal preUseNum;
+    /**
+     * 实占数量
+     */
+    private BigDecimal realUseNum;
+    /**
+     * 优惠金额
+     */
+    private BigDecimal amount;
+    /**
+     * 使用政策的房间
+     */
+    private String rooms;
+    /**
+     * 折扣
+     */
+    private BigDecimal discount;
+    /**
+     * 折扣类型
+     */
+    private Integer discountType;
+    /**
+     * 使用房间数
+     */
+    private BigDecimal useNum;
+
+}

+ 19 - 0
module-his/module-his-biz/src/main/java/com/yc/ship/module/his/dal/mysql/tradeOrderPolicy/HisTradeOrderPolicyMapper.java

@@ -0,0 +1,19 @@
+package com.yc.ship.module.his.dal.mysql.tradeOrderPolicy;
+
+import java.util.*;
+
+import com.yc.ship.framework.common.pojo.PageResult;
+import com.yc.ship.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.yc.ship.framework.mybatis.core.mapper.BaseMapperX;
+import com.yc.ship.module.his.dal.dataobject.tradeOrderPolicy.HisTradeOrderPolicyDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 订单使用的优惠政策历史 Mapper
+ *
+ * @author 管理员
+ */
+@Mapper
+public interface HisTradeOrderPolicyMapper extends BaseMapperX<HisTradeOrderPolicyDO> {
+
+}

+ 2 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/ShipTradeOrderCreateReqVO.java

@@ -265,6 +265,8 @@ public class ShipTradeOrderCreateReqVO implements Serializable {
     @Valid
     public static class OrderDetail {
 
+        private Long id;
+
         @Schema(description = "游船产品:楼层ID OR 附加产品:附加产品ID", example = "")
         @NotBlank(message = "楼层ID/附加产品ID不能为空")
         private String productId;

+ 2 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderPolicyReqVO.java

@@ -10,6 +10,8 @@ import java.util.List;
 @Data
 public class TradeOrderPolicyReqVO {
 
+    private Long id;
+
     @Schema(description = "政策ID", example = "25357")
     private Long policyId;
 

+ 1 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderRoomModelVO.java

@@ -9,6 +9,7 @@ import java.math.BigDecimal;
 @Data
 public class TradeOrderRoomModelVO {
 
+    private Long id;
 
     @Schema(description = "房型索引ID", example = "")
     private String roomIndexId;

+ 1 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeSpuReqVO.java

@@ -8,6 +8,7 @@ import java.util.List;
 
 @Data
 public class TradeSpuReqVO {
+    private Long id;
 
     @Schema(description = "附加产品ID")
     private Long productId;

+ 278 - 44
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/TradeOrderRepositoryServiceImpl.java

@@ -13,10 +13,21 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.yc.ship.framework.common.util.object.BeanUtils;
 import com.yc.ship.framework.mybatis.core.query.LambdaQueryWrapperX;
 import com.yc.ship.framework.mybatis.core.query.MPJLambdaWrapperX;
 import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
 import com.yc.ship.framework.tenant.core.util.TenantUtils;
+import com.yc.ship.module.his.dal.dataobject.tradedetail.HisTradeDetailDO;
+import com.yc.ship.module.his.dal.dataobject.tradedetailbase.HisTradeDetailBaseDO;
+import com.yc.ship.module.his.dal.dataobject.tradeorder.HisTradeOrderDO;
+import com.yc.ship.module.his.dal.dataobject.tradeorderuser.HisTradeOrderUserDO;
+import com.yc.ship.module.his.dal.dataobject.tradevisitor.HisTradeVisitorDO;
+import com.yc.ship.module.his.dal.mysql.tradedetail.HisTradeDetailMapper;
+import com.yc.ship.module.his.dal.mysql.tradedetailbase.HisTradeDetailBaseMapper;
+import com.yc.ship.module.his.dal.mysql.tradeorder.HisTradeOrderMapper;
+import com.yc.ship.module.his.dal.mysql.tradeorderuser.HisTradeOrderUserMapper;
+import com.yc.ship.module.his.dal.mysql.tradevisitor.HisTradeVisitorMapper;
 import com.yc.ship.module.trade.api.sms.dto.SmsSendLogDTO;
 import com.yc.ship.module.trade.controller.admin.order.vo.check.CheckOrderPageVO;
 import com.yc.ship.module.trade.controller.admin.order.vo.order.TradeDetailRespVO;
@@ -106,7 +117,16 @@ public class TradeOrderRepositoryServiceImpl implements TradeOrderRepositoryServ
 
     @Resource
     private TradeDetailBizMapper tradeDetailBizMapper;
-
+    @Resource
+    private HisTradeOrderMapper hisTradeOrderMapper;
+    @Resource
+    private HisTradeOrderUserMapper hisTradeOrderUserMapper;
+    @Resource
+    private HisTradeDetailBaseMapper hisTradeDetailBaseMapper;
+    @Resource
+    private HisTradeVisitorMapper hisTradeVisitorMapper;
+    @Resource
+    private HisTradeDetailMapper  hisTradeDetailMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -151,65 +171,136 @@ public class TradeOrderRepositoryServiceImpl implements TradeOrderRepositoryServ
             Long oldOrderId = oldOrder.getId();
 
             // ============ 先查询旧接站相关数据(在软删除之前),用于后续重建 ============
-            List<OrderJzDO> oldJzList = orderJzMapper.selectList(new LambdaQueryWrapper<OrderJzDO>()
-                    .eq(OrderJzDO::getOrderId, oldOrderId));
-            List<Long> oldJzIdList = oldJzList.stream().map(OrderJzDO::getId).collect(Collectors.toList());
-            List<OrderJzDetailDO> oldJzDetailList = Collections.emptyList();
-            if (CollUtil.isNotEmpty(oldJzIdList)) {
-                oldJzDetailList = orderJzDetailMapper.selectList(new LambdaQueryWrapper<OrderJzDetailDO>()
-                        .in(OrderJzDetailDO::getJzId, oldJzIdList));
-            }
+//            List<OrderJzDO> oldJzList = orderJzMapper.selectList(new LambdaQueryWrapper<OrderJzDO>()
+//                    .eq(OrderJzDO::getOrderId, oldOrderId));
+//            List<Long> oldJzIdList = oldJzList.stream().map(OrderJzDO::getId).collect(Collectors.toList());
+//            List<OrderJzDetailDO> oldJzDetailList = Collections.emptyList();
+//            if (CollUtil.isNotEmpty(oldJzIdList)) {
+//                oldJzDetailList = orderJzDetailMapper.selectList(new LambdaQueryWrapper<OrderJzDetailDO>()
+//                        .in(OrderJzDetailDO::getJzId, oldJzIdList));
+//            }
 
             // ============ 软删除旧订单主表 ============
-            tradeOrderMapper.updateOrderDeleted(oldOrderId,1);
+//            tradeOrderMapper.updateOrderDeleted(oldOrderId,1);
+            HisTradeOrderDO latestHisOrder = hisTradeOrderMapper.selectOne(new LambdaQueryWrapper<HisTradeOrderDO>()
+                    .eq(HisTradeOrderDO::getId, oldOrderId)
+                    .orderByDesc(HisTradeOrderDO::getVersion)
+                    .last("limit 1"));
+            HisTradeOrderDO hisTradeOrderDO = new HisTradeOrderDO();
+            BeanUtils.copyProperties(oldOrder,hisTradeOrderDO);
+            hisTradeOrderDO.setHisId(IdWorker.getId());
+            hisTradeOrderDO.setCurrentVersion(1);
+            if(latestHisOrder!=null){
+                // 版本号加1
+                hisTradeOrderDO.setVersion(latestHisOrder.getVersion()+1);
+            }
+            // 将历史订单表其他数据的当前版本设置为0
+            hisTradeOrderMapper.update(new LambdaUpdateWrapper<HisTradeOrderDO>()
+                    .set(HisTradeOrderDO::getCurrentVersion, 0)
+                    .set(HisTradeOrderDO::getUpdateTime, new Date())
+                    .eq(HisTradeOrderDO::getId, oldOrderId));
+            hisTradeOrderMapper.insert(hisTradeOrderDO);
             TradeOrderDO tradeOrderDO = tradeOrderBO.getTradeOrderDO();
+            tradeOrderDO.setId(oldOrderId);
             tradeOrderDO.setUpdateTime(LocalDateTime.now());
-            tradeOrderMapper.insert(tradeOrderDO);
+            tradeOrderMapper.updateById(tradeOrderDO);
 
             // ============ 软删除旧接站头表 + 旧接站明细 ============
-            orderJzMapper.updateDeleted(oldOrderId, 1);
-            if (CollUtil.isNotEmpty(oldJzIdList)) {
-                orderJzDetailMapper.updateDeletedByJzIds(oldJzIdList, 1);
-            }
+//            orderJzMapper.updateDeleted(oldOrderId, 1);
+//            if (CollUtil.isNotEmpty(oldJzIdList)) {
+//                orderJzDetailMapper.updateDeletedByJzIds(oldJzIdList, 1);
+//            }
 
             // ============ 插入新接站头表(同步旧接站头表数据) ============
-            OrderJzDO newOrderJzDO = tradeOrderBO.getOrderJzDO();
+//            OrderJzDO newOrderJzDO = tradeOrderBO.getOrderJzDO();
             // 将旧接站头表数据同步到新记录:前端未传的字段用旧值补齐
-            if (CollUtil.isNotEmpty(oldJzList)) {
-                OrderJzDO oldJzDO = oldJzList.get(0);
-                if (newOrderJzDO.getIsJz() == null || newOrderJzDO.getIsJz() >= 0) {
-                    newOrderJzDO.setIsJz(oldJzDO.getIsJz());
-                }
-                if (newOrderJzDO.getJzAddress() == null) {
-                    newOrderJzDO.setJzAddress(oldJzDO.getJzAddress());
-                }
-                if (newOrderJzDO.getJzLinkName() == null) {
-                    newOrderJzDO.setJzLinkName(oldJzDO.getJzLinkName());
-                }
-                if (newOrderJzDO.getJzLinkPhone() == null) {
-                    newOrderJzDO.setJzLinkPhone(oldJzDO.getJzLinkPhone());
-                }
-                newOrderJzDO.setDeleted(false);
-            }
-            orderJzMapper.insert(newOrderJzDO);
+//            if (CollUtil.isNotEmpty(oldJzList)) {
+//                OrderJzDO oldJzDO = oldJzList.get(0);
+//                if (newOrderJzDO.getIsJz() == null || newOrderJzDO.getIsJz() >= 0) {
+//                    newOrderJzDO.setIsJz(oldJzDO.getIsJz());
+//                }
+//                if (newOrderJzDO.getJzAddress() == null) {
+//                    newOrderJzDO.setJzAddress(oldJzDO.getJzAddress());
+//                }
+//                if (newOrderJzDO.getJzLinkName() == null) {
+//                    newOrderJzDO.setJzLinkName(oldJzDO.getJzLinkName());
+//                }
+//                if (newOrderJzDO.getJzLinkPhone() == null) {
+//                    newOrderJzDO.setJzLinkPhone(oldJzDO.getJzLinkPhone());
+//                }
+//                newOrderJzDO.setDeleted(false);
+//            }
+//            orderJzMapper.insert(newOrderJzDO);
 
             // ============ 为新订单重建接站明细 ============
-            rebuildOrderJzDetail(oldJzDetailList, tradeOrderBO);
+//            rebuildOrderJzDetail(oldJzDetailList, tradeOrderBO);
 
             tradeOrderBindMapper.update(new LambdaUpdateWrapper<TradeOrderBindDO>().set(TradeOrderBindDO::getDeleted, 1).set(TradeOrderBindDO::getUpdateTime, tradeOrderBO.getUpdateTime()==null?new Date():tradeOrderBO.getUpdateTime()).eq(TradeOrderBindDO::getOrderId, oldOrderId));
             if (tradeOrderBO.getTradeOrderBindDO() != null) {
                 tradeOrderBindMapper.insert(tradeOrderBO.getTradeOrderBindDO());
             }
-            tradeOrderUserMapper.updateDeleted(oldOrderId,1);
-            tradeOrderUserMapper.insert(tradeOrderBO.getTradeOrderUserDO());
-
+            TradeOrderUserDO tradeOrderUserDO = tradeOrderBO.getTradeOrderUserDO();
+            TradeOrderUserDO oldTradeOrderUserDO = tradeOrderUserMapper.selectOne(new LambdaQueryWrapper<TradeOrderUserDO>().eq(TradeOrderUserDO::getOrderId, oldOrderId));
+            HisTradeOrderUserDO latestHisOrderUser = hisTradeOrderUserMapper.selectOne(new LambdaQueryWrapper<HisTradeOrderUserDO>()
+                    .eq(HisTradeOrderUserDO::getOrderId, oldOrderId)
+                    .orderByDesc(HisTradeOrderUserDO::getVersion)
+                    .last("limit 1"));
+            //            tradeOrderUserMapper.updateDeleted(oldOrderId,1);
+            HisTradeOrderUserDO histTradeOrderUserDO = new HisTradeOrderUserDO();
+            BeanUtils.copyProperties(oldTradeOrderUserDO,histTradeOrderUserDO);
+            histTradeOrderUserDO.setHisId(IdWorker.getId());
+            histTradeOrderUserDO.setCurrentVersion(1);
+            if(latestHisOrderUser!=null){
+                // 版本号加1
+                histTradeOrderUserDO.setVersion(latestHisOrder.getVersion()+1);
+            }
+            // 将历史订单表其他数据的当前版本设置为0
+            hisTradeOrderUserMapper.update(new LambdaUpdateWrapper<HisTradeOrderUserDO>()
+                    .set(HisTradeOrderUserDO::getCurrentVersion, 0)
+                    .set(HisTradeOrderUserDO::getUpdateTime, new Date())
+                    .eq(HisTradeOrderUserDO::getOrderId, oldOrderId));
+            hisTradeOrderUserMapper.insert(histTradeOrderUserDO);
+
+            tradeOrderUserDO.setId(oldTradeOrderUserDO.getId());
+            tradeOrderUserDO.setOrderId(oldTradeOrderUserDO.getOrderId());
+            tradeOrderUserMapper.updateById(tradeOrderUserDO);
+
+            // 先是查出数据库中的数据放入历史表中
+            List<TradeDetailBaseDO> tradeDetailBaseDOS = tradeDetailBaseMapper.selectList(new LambdaQueryWrapper<TradeDetailBaseDO>().eq(TradeDetailBaseDO::getOrderId, oldOrderId));
+            HisTradeDetailBaseDO latestHisTradeDetailBase = hisTradeDetailBaseMapper.selectOne(new LambdaQueryWrapper<HisTradeDetailBaseDO>()
+                    .eq(HisTradeDetailBaseDO::getOrderId, oldOrderId)
+                    .orderByDesc(HisTradeDetailBaseDO::getVersion)
+                    .last("limit 1"));
+            Integer hisTradeDetailBaseVersion = 0;
+            if(latestHisTradeDetailBase!=null){
+                // 版本号加1
+                hisTradeDetailBaseVersion = latestHisTradeDetailBase.getVersion() + 1;
+            }
+            List<HisTradeDetailBaseDO> hisTradeDetailBaseS = new ArrayList<>();
+            for (TradeDetailBaseDO tradeDetailBaseDO : tradeDetailBaseDOS) {
+                HisTradeDetailBaseDO hisTradeDetailBaseDO = new HisTradeDetailBaseDO();
+                BeanUtils.copyProperties(tradeDetailBaseDO,hisTradeDetailBaseDO);
+                hisTradeDetailBaseDO.setHisId(IdWorker.getId());
+                hisTradeDetailBaseDO.setCurrentVersion(1);
+                hisTradeDetailBaseDO.setVersion(hisTradeDetailBaseVersion);
+                hisTradeDetailBaseS.add(hisTradeDetailBaseDO);
+            }
+            hisTradeDetailBaseMapper.insertBatch(hisTradeDetailBaseS);
+            //旧数据删除
+            tradeDetailBaseMapper.deleteAllByOrderId(oldOrderId);
+            List<TradeDetailDO> tradeDetailDOList = new ArrayList<>();
+            List<TradeDetailBaseDO> tradeDetailBaseDOList = new ArrayList<>();
+            List<TradeVisitorDO> tradeVisitorDOList = new ArrayList<>();
             tradeOrderBO.getTradeOrderDetailBOList().forEach(tradeOrderDetailBO -> {
-                tradeDetailMapper.updateDeleted(oldOrderId,1);
-                tradeDetailMapper.insertBatch(tradeOrderDetailBO.getTradeDetailDOList());
-                tradeDetailBaseMapper.updateDeleted(oldOrderId,1);
-                tradeDetailBaseMapper.insertBatch(tradeOrderDetailBO.getTradeDetailBaseDOList());
-                tradeVisitorMapper.updateDeleted(oldOrderId,1);
-                tradeVisitorMapper.insertBatch(tradeOrderDetailBO.getTradeVisitorDOList());
+                tradeDetailDOList.addAll(tradeOrderDetailBO.getTradeDetailDOList());
+                tradeDetailBaseDOList.addAll(tradeOrderDetailBO.getTradeDetailBaseDOList());
+                tradeVisitorDOList.addAll(tradeOrderDetailBO.getTradeVisitorDOList());
+//                tradeDetailMapper.updateDeleted(oldOrderId,1);
+//                tradeDetailMapper.insertBatch(tradeOrderDetailBO.getTradeDetailDOList());
+//                tradeDetailBaseMapper.updateDeleted(oldOrderId,1);
+//                tradeDetailBaseMapper.insertBatch(tradeOrderDetailBO.getTradeDetailBaseDOList());
+//                tradeVisitorMapper.updateDeleted(oldOrderId,1);
+//                tradeVisitorMapper.insertBatch(tradeOrderDetailBO.getTradeVisitorDOList());
 
                 if (CollUtil.isNotEmpty(tradeOrderDetailBO.getTradeDetailPriceDOList())) {
                     tradeDetailPriceMapper.update(new LambdaUpdateWrapper<TradeDetailPriceDO>()
@@ -220,7 +311,9 @@ public class TradeOrderRepositoryServiceImpl implements TradeOrderRepositoryServ
                     tradeDetailPriceMapper.insertBatch(tradeOrderDetailBO.getTradeDetailPriceDOList());
                 }
             });
-
+            tradeDetailBaseMapper.insertBatch(tradeDetailBaseDOList);
+            updateTradeVisitor(tradeVisitorDOList, oldOrderId);
+            updateTradeDetail(tradeDetailDOList, oldOrderId);
         } catch (Exception e) {
             log.error("订单保存异常", e);
             //极端情况下会出现,上层会回滚库存
@@ -228,6 +321,147 @@ public class TradeOrderRepositoryServiceImpl implements TradeOrderRepositoryServ
         }
     }
 
+    private void updateTradeVisitor(List<TradeVisitorDO> list,Long orderId) {
+        // 查询现在数据库中的游客数据
+        List<TradeVisitorDO> tradeVisitorList = tradeVisitorMapper.selectListByOrderId(orderId);
+        // 历史游客记录
+        List<HisTradeVisitorDO> hisTradeVisitorList = new ArrayList<>();
+        // 获取历史游客中最新的记录
+        HisTradeVisitorDO latestHisTradeVisitor = hisTradeVisitorMapper.selectOne(new LambdaQueryWrapper<HisTradeVisitorDO>()
+                .eq(HisTradeVisitorDO::getOrderId, orderId)
+                .orderByDesc(HisTradeVisitorDO::getVersion)
+                .last("limit 1"));
+        Integer version;
+        if(latestHisTradeVisitor!=null){
+            version = latestHisTradeVisitor.getVersion() + 1;
+        } else {
+            version = 0;
+        }
+        // 删除的游客数据
+        if (CollUtil.isNotEmpty(tradeVisitorList)) {
+            // 获取传入的游客ID列表
+            List<Long> newIds = CollUtil.emptyIfNull(tradeVisitorList).stream()
+                    .map(TradeVisitorDO::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            // 找出需要删除的游客(数据库中存在但新数据中不存在的)
+            List<Long> deleteTradeVisitorIds = list.stream()
+                    .map(TradeVisitorDO::getId)
+                    .filter(id -> !newIds.contains(id))
+                    .collect(Collectors.toList());
+            tradeVisitorList.forEach(item -> {
+                HisTradeVisitorDO hisTradeVisitor = new HisTradeVisitorDO();
+                BeanUtils.copyProperties(item,hisTradeVisitor);
+                hisTradeVisitor.setHisId(IdWorker.getId());
+                hisTradeVisitor.setCurrentVersion(1);
+                hisTradeVisitor.setVersion(version);
+                hisTradeVisitorList.add(hisTradeVisitor);
+            });
+            // 执行删除操作
+            if (CollUtil.isNotEmpty(deleteTradeVisitorIds)) {
+                tradeVisitorMapper.deleteByIds(deleteTradeVisitorIds);
+            }
+        }
+        //创建订单游客数据
+        List<TradeVisitorDO> insetList = new ArrayList<>();
+        //修改订单游客数据
+        List<TradeVisitorDO> updateList = new ArrayList<>();
+        list.forEach(item -> {
+            item.setOrderId(orderId);
+            if(item.getId() == null){
+                item.setId(IdWorker.getId());
+                insetList.add(item);
+            }else{
+                updateList.add(item);
+            }
+        });
+        hisTradeVisitorMapper.update(new LambdaUpdateWrapper<HisTradeVisitorDO>()
+                .set(HisTradeVisitorDO::getCurrentVersion, 0)
+                .set(HisTradeVisitorDO::getUpdateTime, new Date())
+                .eq(HisTradeVisitorDO::getOrderId, orderId));
+        if(!hisTradeVisitorList.isEmpty()){
+            hisTradeVisitorMapper.insertBatch(hisTradeVisitorList);
+        }
+        if (!insetList.isEmpty()) {
+            tradeVisitorMapper.insertBatch(insetList);
+        }
+        if (!updateList.isEmpty()) {
+            tradeVisitorMapper.updateBatch(updateList);
+        }
+    }
+
+    private void updateTradeDetail(List<TradeDetailDO> list,Long orderId) {
+        // 查询现在数据库中的详情数据
+        List<TradeDetailDO> tradeDetailList = tradeDetailMapper.selectList( new LambdaQueryWrapper<TradeDetailDO>()
+                .eq(TradeDetailDO::getOrderId, orderId));
+        // 历史详情记录
+        List<HisTradeDetailDO> hisTradeDetailList = new ArrayList<>();
+        // 获取历史详情中最新的记录
+        HisTradeDetailDO latestHisTradeDetail = hisTradeDetailMapper.selectOne(new LambdaQueryWrapper<HisTradeDetailDO>()
+                .eq(HisTradeDetailDO::getOrderId, orderId)
+                .orderByDesc(HisTradeDetailDO::getVersion)
+                .last("limit 1"));
+        Integer version;
+        if(latestHisTradeDetail!=null){
+            version = latestHisTradeDetail.getVersion() + 1;
+        } else {
+            version = 0;
+        }
+        // 删除的详情数据
+        if (CollUtil.isNotEmpty(tradeDetailList)) {
+            // 获取传入的详情ID列表
+            List<Long> newIds = CollUtil.emptyIfNull(tradeDetailList).stream()
+                    .map(TradeDetailDO::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            // 找出需要删除的详情(数据库中存在但新数据中不存在的)
+            List<Long> deleteIds = list.stream()
+                    .map(TradeDetailDO::getId)
+                    .filter(id -> !newIds.contains(id))
+                    .collect(Collectors.toList());
+            tradeDetailList.forEach(item -> {
+                HisTradeDetailDO hisTradeDetail = new HisTradeDetailDO();
+                BeanUtils.copyProperties(item,hisTradeDetail);
+                hisTradeDetail.setHisId(IdWorker.getId());
+                hisTradeDetail.setCurrentVersion(1);
+                hisTradeDetail.setVersion(version);
+                hisTradeDetailList.add(hisTradeDetail);
+            });
+            // 执行删除操作
+            if (CollUtil.isNotEmpty(deleteIds)) {
+                tradeDetailMapper.deleteByIds(deleteIds);
+            }
+        }
+        //创建订单游客数据
+        List<TradeDetailDO> insetList = new ArrayList<>();
+        //修改订单游客数据
+        List<TradeDetailDO> updateList = new ArrayList<>();
+        list.forEach(item -> {
+            item.setOrderId(orderId);
+            if(item.getId() == null){
+                item.setId(IdWorker.getId());
+                insetList.add(item);
+            }else{
+                updateList.add(item);
+            }
+        });
+        hisTradeDetailMapper.update(new LambdaUpdateWrapper<HisTradeDetailDO>()
+                .set(HisTradeDetailDO::getCurrentVersion, 0)
+                .set(HisTradeDetailDO::getUpdateTime, new Date())
+                .eq(HisTradeDetailDO::getOrderId, orderId));
+        if(!hisTradeDetailList.isEmpty()){
+            hisTradeDetailMapper.insertBatch(hisTradeDetailList);
+        }
+        if (!insetList.isEmpty()) {
+            tradeDetailMapper.insertBatch(insetList);
+        }
+        if (!updateList.isEmpty()) {
+            tradeDetailMapper.updateBatch(updateList);
+        }
+    }
+
     /**
      * 修改订单时,为新订单重建接站明细数据。
      * 通过旧接站明细的证件号(id_card)匹配新游客表(trade_visitor)中的记录,

+ 20 - 4
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/TradeOrderServiceImpl.java

@@ -550,7 +550,9 @@ public class TradeOrderServiceImpl implements TradeOrderService {
             tradeOrderDO.setSellerId(oldtradeOrderDO.getSellerId());
             tradeOrderDO.setMemberId(oldtradeOrderDO.getMemberId());
             tradeOrderDO.setTravelStatus(oldtradeOrderDO.getTravelStatus());
+            tradeOrderDO.setId(oldtradeOrderDO.getId());
         } else {
+            tradeOrderDO.setId(IdWorker.getId());
             tradeOrderDO.setStoreId(orderCreateReqDTO.getOrderProperty().getStoreId());
             tradeOrderDO.setStoreName(orderCreateReqDTO.getOrderProperty().getStoreName());
             tradeOrderDO.setExternalOrderNo(orderCreateReqDTO.getExternalOrderNo());
@@ -584,7 +586,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                 tradeOrderDO.setVisitorType(0);
             }
         }
-        tradeOrderDO.setId(IdWorker.getId());
+
         //旅行社编号 +  航次编号 + 3位 旅行社当天订单流水号
         if (org.apache.commons.lang3.StringUtils.isNotEmpty(orderCreateReqDTO.getOrderNo())) {
             tradeOrderDO.setOrderNo(orderCreateReqDTO.getOrderNo());
@@ -708,6 +710,12 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                     product = finalProductSpuRespDTO;
                 }
                 for (ShipTradeOrderCreateReqVO.Visitor visitor : orderDetail.getVisitorList()) {
+                    Long visitorId = IdWorker.getId();
+                    if(orderDetail.getVisitorId()!=null){
+                        visitorId = orderDetail.getVisitorId();
+                    }
+                    // 根据订单号和游客id获取订单详情
+                    TradeDetailDO oldTradeDetailDO = tradeDetailMapper.selectOne(TradeDetailDO::getOrderId, tradeOrderDO.getId(), TradeDetailDO::getVisitorId, visitorId, TradeDetailDO::getProductType, 0);
                     //订单详情
                     TradeDetailDO tradeDetailDO = new TradeDetailBO();
                     tradeDetailDO.setOrderId(tradeOrderDO.getId());
@@ -719,7 +727,11 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                     tradeDetailDO.setValidityStartDate(LocalDateTimeUtil.of(orderDetail.getBoardingTime()));
                     tradeDetailDO.setValidityEndDate(LocalDateTimeUtil.of(orderDetail.getLeaveTime()));
                     tradeDetailDO.setSpecType(orderDetail.getSpecType());
-                    tradeDetailDO.setId(IdWorker.getId());
+                    if(oldTradeDetailDO!=null){
+                        tradeDetailDO.setId(oldTradeDetailDO.getId());
+                    }else{
+                        tradeDetailDO.setId(IdWorker.getId());
+                    }
                     tradeDetailDO.setProductType(orderDetail.getProductType());
                     tradeDetailDO.setVoucherCode(ticketNoList.get(i));
                     i++;
@@ -731,7 +743,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                     }
                     List<TradeDetailBaseDO> detailBaseDOList = buildShipDetailBase(orderDetail, tradeDetailDO, product);
                     tradeDetailBaseDOList.addAll(detailBaseDOList);
-                    Long visitorId = IdWorker.getId();
+
                     tradeDetailDO.setVisitorId(visitorId);
                     vmap.put(visitor.getVid(), visitorId);
                     TradeVisitorDO tradeVisitorDO = new TradeVisitorDO();
@@ -792,7 +804,11 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                     tradeDetailDO.setPrice(orderDetail.getOriginPrice()==null?BigDecimal.ZERO:orderDetail.getOriginPrice());
                     tradeDetailDO.setActualPrice(orderDetail.getPrice()==null?BigDecimal.ZERO:orderDetail.getPrice());
                     tradeDetailDO.setSpecType(orderDetail.getSpecType());
-                    tradeDetailDO.setId(IdWorker.getId());
+                    if(orderDetail.getId()!=null){
+                        tradeDetailDO.setId(orderDetail.getId());
+                    }else{
+                        tradeDetailDO.setId(IdWorker.getId());
+                    }
                     tradeDetailDO.setValidityStartDate(LocalDateTimeUtil.of(orderDetail.getBoardingTime()));
                     tradeDetailDO.setValidityEndDate(LocalDateTimeUtil.of(orderDetail.getLeaveTime()));
                     tradeDetailDO.setProductType(orderDetail.getProductType());

+ 220 - 41
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java

@@ -43,10 +43,12 @@ import com.yc.ship.module.his.dal.dataobject.tradedetailbase.HisTradeDetailBaseD
 import com.yc.ship.module.his.dal.dataobject.tradeorder.HisTradeOrderDO;
 import com.yc.ship.module.his.dal.dataobject.tradeordercountry.HisTradeOrderCountryDO;
 import com.yc.ship.module.his.dal.dataobject.tradeorderfloor.HisTradeOrderFloorDO;
+import com.yc.ship.module.his.dal.dataobject.tradeOrderPolicy.HisTradeOrderPolicyDO;
 import com.yc.ship.module.his.dal.dataobject.tradeorderroommodel.HisTradeOrderRoomModelDO;
 import com.yc.ship.module.his.dal.dataobject.tradeordertotal.HisTradeOrderTotalDO;
 import com.yc.ship.module.his.dal.dataobject.tradeorderuser.HisTradeOrderUserDO;
 import com.yc.ship.module.his.dal.dataobject.tradevisitor.HisTradeVisitorDO;
+import com.yc.ship.module.his.dal.mysql.tradeOrderPolicy.HisTradeOrderPolicyMapper;
 import com.yc.ship.module.his.dal.mysql.tradedetail.HisTradeDetailMapper;
 import com.yc.ship.module.his.dal.mysql.tradedetailbase.HisTradeDetailBaseMapper;
 import com.yc.ship.module.his.dal.mysql.tradeorder.HisTradeOrderMapper;
@@ -56,14 +58,6 @@ import com.yc.ship.module.his.dal.mysql.tradeorderroommodel.HisTradeOrderRoomMod
 import com.yc.ship.module.his.dal.mysql.tradeordertotal.HisTradeOrderTotalMapper;
 import com.yc.ship.module.his.dal.mysql.tradeorderuser.HisTradeOrderUserMapper;
 import com.yc.ship.module.his.dal.mysql.tradevisitor.HisTradeVisitorMapper;
-import com.yc.ship.module.his.service.tradedetail.HisTradeDetailService;
-import com.yc.ship.module.his.service.tradedetailbase.HisTradeDetailBaseService;
-import com.yc.ship.module.his.service.tradeordercountry.HisTradeOrderCountryService;
-import com.yc.ship.module.his.service.tradeorderfloor.HisTradeOrderFloorService;
-import com.yc.ship.module.his.service.tradeorderroommodel.HisTradeOrderRoomModelService;
-import com.yc.ship.module.his.service.tradeordertotal.HisTradeOrderTotalService;
-import com.yc.ship.module.his.service.tradeorderuser.HisTradeOrderUserService;
-import com.yc.ship.module.his.service.tradevisitor.HisTradeVisitorService;
 import com.yc.ship.module.infra.api.config.ConfigApi;
 import com.yc.ship.module.marketing.api.policy.PolicyApi;
 import com.yc.ship.module.member.api.address.MemberAddressApi;
@@ -194,6 +188,8 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
     @Resource
     private PolicyApi policyApi;
     @Resource
+    private HisTradeOrderPolicyMapper hisTradeOrderPolicyMapper;
+    @Resource
     private NotifyMessageSendApi notifyMessageSendApi;
 
     @Resource
@@ -304,7 +300,6 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
     @Resource
     private ConfigUtils configUtils;
 
-
     public final static String AGENCY_LOGIN_INFO = "agencyLoginInfo";
 
 
@@ -2530,7 +2525,9 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
     @Transactional(rollbackFor = Exception.class)
     @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ORDER_MODIFY)
     public CommonResult<?> motifyOtcOrder(LoginUser loginUser, TradeOrderOtcCreateVO createVO) {
+        // 获取分销商id
         Long distributorId = createVO.getDistributorId() != null ? createVO.getDistributorId() : loginUser.getDistributorId();
+        // 获取门店id
         Long storeId = createVO.getStoreId() != null ? createVO.getStoreId() : loginUser.getStoreId();
         //获取当前分销商信息
         if (distributorId == null) {
@@ -2546,21 +2543,26 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
         if (storeId != null) {
             storeInfo = storeApi.getStoreInfo(storeId);
         }
+        // 查询订单信息
         Long orderId = createVO.getOrderId();
         TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(orderId);
         if (tradeOrderDO == null) {
             return CommonResult.error(ORDER_NOT_EXIST);
         }
+        // 判断订单是否开票,开票则不允许修改
         if (tradeOrderDO.getIsInvoice() != null && tradeOrderDO.getIsInvoice() == 1) {
             return CommonResult.error(ORDER_ISINVOICE);
         }
+        // 审核类型:0-无需审核,2-二级审核,3-三级审核,4-四级审核
         int auditType = 0;
         String orderNo = tradeOrderDO.getOrderNo();
         Long oldvoyageId = tradeOrderDO.getVoyageId();
         Long newvoyageId = createVO.getVoyageId();
+        // 航次ID
         if (newvoyageId == null) {
             return CommonResult.error(ORDER_NOT_VOYAGE);
         }
+        // 不允许修改航次
         if(!Objects.equals(oldvoyageId, newvoyageId)){
             return CommonResult.error(ORDER_NOT_VOYAGE_CHANGE);
         }
@@ -2570,6 +2572,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
         try {
             lock.lock(60, TimeUnit.SECONDS);
             Date updateTime = new Date();
+            // 构建创建订单的参数
             ShipTradeOrderCreateReqVO shipTradeOrderCreateReqVO = BeanUtils.toBean(createVO, ShipTradeOrderCreateReqVO.class);
             shipTradeOrderCreateReqVO.setDistributorId(loginUser.getDistributorId());
             shipTradeOrderCreateReqVO.setGroupNo(createVO.getGroupNo());
@@ -2578,6 +2581,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             shipTradeOrderCreateReqVO.setDeposi(createVO.getSummary().getDeposi());
             shipTradeOrderCreateReqVO.setOrderSort(tradeOrderDO.getOrderSort());
             shipTradeOrderCreateReqVO.setIsRead(0);
+            // 订单金额
             TradeOrderTotalVO summary = createVO.getSummary();
             BigDecimal realAmount = summary.getRealMoney()==null?BigDecimal.ZERO:summary.getRealMoney()  ;
             BigDecimal orderMoney = summary.getOrderMoney();
@@ -2585,6 +2589,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             shipTradeOrderCreateReqVO.setAmount(orderMoney);
             shipTradeOrderCreateReqVO.setPayAmount(realAmount);
             if ((orderMoney != null && realAmount != null && (realAmount.compareTo(orderMoney) != 0) || shipTradeOrderCreateReqVO.getAmount().compareTo(tradeOrderDO.getAmount())!=0)) {
+                // 判断订单金额是否发生变化,记录变更日志
                 //shipTradeOrderCreateReqVO.setConfirmType(1);
                 TradeOrderBindDO tradeOrderBindDO = new TradeOrderBindDO();
                 tradeOrderBindDO.setId(IdWorker.getId());
@@ -2594,6 +2599,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 tradeOrderBindDO.setRemark("modify订单金额修改,订单金额:" + orderMoney + ",订单修改后实际金额:" + realAmount);
                 shipTradeOrderCreateReqVO.setTradeOrderBindDO(tradeOrderBindDO);
             } else if (createVO.getSummary().getDeposi() != null && shipTradeOrderCreateReqVO.getDeposi().compareTo(tradeOrderDO.getDeposi())!=0) {
+                // 判断定金金额是否发生变化,记录变更日志
                 //shipTradeOrderCreateReqVO.setConfirmType(1);
                 TradeOrderBindDO tradeOrderBindDO = new TradeOrderBindDO();
                 tradeOrderBindDO.setId(IdWorker.getId());
@@ -2604,6 +2610,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 shipTradeOrderCreateReqVO.setTradeOrderBindDO(tradeOrderBindDO);
                 shipTradeOrderCreateReqVO.setDeposiStatus(1);
             }else if (!createVO.getPolicyList().isEmpty()) {
+                // 判断是否提交了营销政策,记录变更日志
                 //shipTradeOrderCreateReqVO.setConfirmType(1);
                 TradeOrderBindDO tradeOrderBindDO = new TradeOrderBindDO();
                 tradeOrderBindDO.setId(IdWorker.getId());
@@ -2622,6 +2629,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             if (createVO.getSummary().getRealOrderMoney() != null) {
                 shipTradeOrderCreateReqVO.setPayAmount(createVO.getSummary().getRealOrderMoney());
             }
+            // 设置订单联系人信息
             ShipTradeOrderCreateReqVO.OrderUser orderUser = new ShipTradeOrderCreateReqVO.OrderUser();
             orderUser.setContactName(createVO.getLinkMan());
             orderUser.setMobile(createVO.getLinkMobile());
@@ -2631,7 +2639,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             shipTradeOrderCreateReqVO.setIsYd(createVO.getIsYd());
             shipTradeOrderCreateReqVO.setTravelDate(createVO.getBoardingTime());
             shipTradeOrderCreateReqVO.setOrderNo(orderNo);
-
+            // 设置订单属性
             ShipTradeOrderCreateReqVO.OrderProperty orderProperty = new ShipTradeOrderCreateReqVO.OrderProperty();
             orderProperty.setSellMethod(SellMethodEnum.OTC.getType());
             orderProperty.setSourceId(distributorDO.getId() + "");
@@ -2640,18 +2648,21 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 orderProperty.setStoreId(storeInfo.getId());
                 orderProperty.setStoreName(storeInfo.getName());
             }
+            // 构建订单明细
             orderProperty.setSellMethod(SellMethodEnum.OTC.getType());
             shipTradeOrderCreateReqVO.setOrderProperty(orderProperty);
             ShipTradeOrderCreateReqVO.OrderItem orderItem = new ShipTradeOrderCreateReqVO.OrderItem();
             List<ShipTradeOrderCreateReqVO.OrderDetail> detailList = new ArrayList<>();
             ShipTradeOrderCreateReqVO.OrderDetail orderDetail = new ShipTradeOrderCreateReqVO.OrderDetail();
+            // 处理游客信息
             for (TradeVistorReqVO tradeVistorReqVO : createVO.getTourist()) {
                 List<ShipTradeOrderCreateReqVO.Visitor> visitorList = new ArrayList<>();
                 ShipTradeOrderCreateReqVO.OrderDetail visitorDetailId = new ShipTradeOrderCreateReqVO.OrderDetail();
-                BeanUtils.copyProperties(orderDetail, ShipTradeOrderCreateReqVO.OrderDetail.class);
+//                BeanUtils.copyProperties(orderDetail, ShipTradeOrderCreateReqVO.OrderDetail.class);
                 visitorDetailId.setPrice(tradeVistorReqVO.getPrice());
                 visitorDetailId.setOriginPrice(tradeVistorReqVO.getPrice());
                 visitorDetailId.setProductType(0);
+                visitorDetailId.setVisitorId(Long.valueOf(tradeVistorReqVO.getId()));
                 visitorDetailId.setBoardingTime(createVO.getBoardingTime());
                 visitorDetailId.setLeaveTime(createVO.getLeaveTime());
                 ShipTradeOrderCreateReqVO.Visitor visitor = getVisitor1(tradeVistorReqVO);
@@ -2663,6 +2674,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 visitorDetailId.setProductType(0);
                 detailList.add(visitorDetailId);
             }
+            // 处理附加产品
             BigDecimal spuMoney = new BigDecimal(0);
             for (TradeSpuReqVO tradeSpuReqVO : createVO.getSpuList()) {
                 ShipTradeOrderCreateReqVO.OrderDetail orderDetail1 = new ShipTradeOrderCreateReqVO.OrderDetail();
@@ -2682,6 +2694,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                     BigDecimal price = tradeSpuReqVO.getPrice() == null ? BigDecimal.ZERO : tradeSpuReqVO.getPrice();
                     spuMoney = spuMoney.add(price);
                 }
+                orderDetail1.setId(tradeSpuReqVO.getId());
                 orderDetail1.setVisitorList(visitorList1);
                 orderDetail1.setProductId(tradeSpuReqVO.getProductId() + "");
                 orderDetail1.setPrice(tradeSpuReqVO.getPrice());
@@ -2694,6 +2707,7 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             orderItem.setDetailList(detailList);
             shipTradeOrderCreateReqVO.setItemlList(Collections.singletonList(orderItem));
             shipTradeOrderCreateReqVO.setSpuAmount(spuMoney);
+            // 验证修改时间是否在允许范围内
             Date travelDate = tradeOrderDO.getTravelDate();
             if (loginUser.getDistributorId() != null && DateUtil.compare(DateUtil.beginOfDay(travelDate), DateUtil.offsetDay(new Date(), 3)) < 0) {
                 return CommonResult.error(500, "已过最晚修改时间");
@@ -2704,8 +2718,10 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             }
             shipTradeOrderCreateReqVO.setUpdateTime(updateTime);
             shipTradeOrderCreateReqVO.setOldtradeOrderDO(tradeOrderDO);
+            // 查询旧的订单汇总信息
             TradeOrderTotalDO oldTradeOrderTotal = tradeOrderTotalMapper.selectOne(new LambdaQueryWrapper<TradeOrderTotalDO>().eq(TradeOrderTotalDO::getOldOrderId, orderId));
             shipTradeOrderCreateReqVO.setOldtradeOrderTotalDO(oldTradeOrderTotal);
+            // 构建新的订单汇总信息
             TradeOrderTotalDO tradeOrderTotalDO = BeanUtils.toBean(summary, TradeOrderTotalDO.class);
             if(tradeOrderTotalDO.getUpFloorTotalMoney()==null){
                 tradeOrderTotalDO.setUpFloorTotalMoney(BigDecimal.ZERO);
@@ -2753,27 +2769,48 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             Long neworderId = result.getCheckedData().getOrderId();
             Integer neworderStatus = result.getCheckedData().getOrderStatus();
             String content  = result.getCheckedData().getContent();
-
-            tradeOrderTotalMapper.update(new LambdaUpdateWrapper<TradeOrderTotalDO>()
-                    .set(TradeOrderTotalDO::getDeleted, 1)
-                    .set(TradeOrderTotalDO::getUpdateTime, updateTime)
-                    .eq(TradeOrderTotalDO::getOldOrderId, orderId)
-            );
-            tradeOrderTotalDO.setId(IdWorker.getId());
-            tradeOrderTotalDO.setOldOrderId(neworderId);
-            tradeOrderTotalMapper.insert(tradeOrderTotalDO);
-
-            //创建订单房型数据
-            List<TradeOrderRoomModelDO> list = new ArrayList<>();
-            List<TradeOrderRoomModelVO> roomModelList = createVO.getRoomModelList();
-            roomModelList.forEach(item -> {
-                TradeOrderRoomModelDO tradeOrderRoomModelDO = BeanUtils.toBean(item, TradeOrderRoomModelDO.class);
-                tradeOrderRoomModelDO.setId(IdWorker.getId());
-                tradeOrderRoomModelDO.setOrderId(neworderId);
-                tradeOrderRoomModelDO.setDiscount(tradeOrderRoomModelDO.getUnitPrice().subtract(tradeOrderRoomModelDO.getRealMoney()));
-                tradeOrderRoomModelDO.setOrderNo(orderNo);
-                list.add(tradeOrderRoomModelDO);
-            });
+            HisTradeOrderTotalDO latestHisRecord = hisTradeOrderTotalMapper.selectOne(new LambdaQueryWrapper<HisTradeOrderTotalDO>()
+                    .eq(HisTradeOrderTotalDO::getId, oldTradeOrderTotal.getId())
+                    .orderByDesc(HisTradeOrderTotalDO::getVersion)
+                    .last("limit 1"));
+            HisTradeOrderTotalDO hisTradeOrderTotalDO = new HisTradeOrderTotalDO();
+
+            BeanUtils.copyProperties(oldTradeOrderTotal,hisTradeOrderTotalDO);
+            hisTradeOrderTotalDO.setHisId(IdWorker.getId());
+            hisTradeOrderTotalDO.setCurrentVersion(1);
+            if(latestHisRecord!=null){
+                // 版本号加1
+                hisTradeOrderTotalDO.setVersion(latestHisRecord.getVersion()+1);
+            }
+            // 将历史订单汇总表其他数据的当前版本
+            hisTradeOrderTotalMapper.update(new LambdaUpdateWrapper<HisTradeOrderTotalDO>()
+                    .set(HisTradeOrderTotalDO::getCurrentVersion, 0)
+                    .set(HisTradeOrderTotalDO::getUpdateTime, updateTime)
+                    .eq(HisTradeOrderTotalDO::getId, oldTradeOrderTotal.getId()));
+            hisTradeOrderTotalMapper.insert(hisTradeOrderTotalDO);
+
+            // 20260427 以前删除逻辑
+//            tradeOrderTotalMapper.update(new LambdaUpdateWrapper<TradeOrderTotalDO>()
+//                    .set(TradeOrderTotalDO::getDeleted, 1)
+//                    .set(TradeOrderTotalDO::getUpdateTime, updateTime)
+//                    .eq(TradeOrderTotalDO::getOldOrderId, orderId)
+//            );
+            tradeOrderTotalDO.setId(oldTradeOrderTotal.getId());
+            tradeOrderTotalDO.setOldOrderId(orderId);
+            tradeOrderTotalMapper.updateById(tradeOrderTotalDO);
+            // 处理订单房型数据
+            updateRoomModel(createVO.getRoomModelList(),orderId,orderNo);
+//            //创建订单房型数据
+//            List<TradeOrderRoomModelDO> list = new ArrayList<>();
+//            List<TradeOrderRoomModelVO> roomModelList = createVO.getRoomModelList();
+//            roomModelList.forEach(item -> {
+//                TradeOrderRoomModelDO tradeOrderRoomModelDO = BeanUtils.toBean(item, TradeOrderRoomModelDO.class);
+//                tradeOrderRoomModelDO.setId(IdWorker.getId());
+//                tradeOrderRoomModelDO.setOrderId(orderId);
+//                tradeOrderRoomModelDO.setDiscount(tradeOrderRoomModelDO.getUnitPrice().subtract(tradeOrderRoomModelDO.getRealMoney()));
+//                tradeOrderRoomModelDO.setOrderNo(orderNo);
+//                list.add(tradeOrderRoomModelDO);
+//            });
             BigDecimal oldleaderAmount = oldTradeOrderTotal.getLeaderAmount();
             BigDecimal oldwithAmount = oldTradeOrderTotal.getWithAmount();
             BigDecimal oldotherMoney = oldTradeOrderTotal.getOtherMoney();
@@ -2786,10 +2823,23 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             //1.先删除原来的
             List<OrderPolicyDO> orderPolicyList = orderPolicyMapper.selectList(OrderPolicyDO::getOrderId, orderId);
             boolean isAudit = true;
-            orderPolicyMapper.deleteByOrderId(orderId);
+//            orderPolicyMapper.deleteByOrderId(orderId);
+            insertHisOrderPolicy(orderPolicyList,orderId);
             List<OrderPolicyDO> orderPolicyDOList = new ArrayList<>();
             List<TradeOrderPolicyReqVO> policyList = createVO.getPolicyList();
+            List<OrderPolicyDO> insetOrderPolicyDOList = new ArrayList<>();
+            List<OrderPolicyDO> updateOrderPolicyDOList = new ArrayList<>();
             if (policyList != null) {
+                // 传入的优惠政策id
+                List<Long> newIds = CollUtil.emptyIfNull(policyList).stream()
+                        .map(TradeOrderPolicyReqVO::getId)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+                // 找出需要删除的优惠政策(数据库中存在但新数据中不存在的)
+                List<Long> deleteOrderPolicyIds = orderPolicyList.stream()
+                        .map(OrderPolicyDO::getId)
+                        .filter(id -> !newIds.contains(id))
+                        .collect(Collectors.toList());
                 policyList.forEach(policy -> {
                     OrderPolicyDO orderPolicyDO = new OrderPolicyDO();
                     orderPolicyDO.setOrderId(orderId);
@@ -2810,21 +2860,31 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                     }
                     orderPolicyDO.setAmount(policy.getAmount());
                     orderPolicyDO.setRooms(policy.getRooms());
-                    orderPolicyDOList.add(orderPolicyDO);
+                    if(policy.getId()!=null){
+                        orderPolicyDO.setId(policy.getId());
+                        updateOrderPolicyDOList.add(orderPolicyDO);
+                    }else{
+                        insetOrderPolicyDOList.add(orderPolicyDO);
+                    }
+//                    orderPolicyDOList.add(orderPolicyDO);
                 });
-                if (!orderPolicyDOList.isEmpty()) {
+                if (!updateOrderPolicyDOList.isEmpty()) {
+                    orderPolicyMapper.updateBatch(updateOrderPolicyDOList);
+                    orderPolicyDOList.addAll(updateOrderPolicyDOList);
+                }
+                if(!insetOrderPolicyDOList.isEmpty()){
+                    orderPolicyMapper.insertBatch(insetOrderPolicyDOList);
+                    orderPolicyDOList.addAll(insetOrderPolicyDOList);
+                }
+                if(!orderPolicyDOList.isEmpty()){
                     //TODO: 判断优惠政策是否需要审核
-                    String changedFields11 = com.yc.ship.module.trade.utils.BeanUtils.getChangedFields(orderPolicyList, orderPolicyDOList);
+                    String changedFields11 = com.yc.ship.module.trade.utils.BeanUtils.getChangedFields(orderPolicyList, updateOrderPolicyDOList);
                     if(StringUtils.isEmpty(changedFields11)){
                         isAudit = false;
                     }
-                    orderPolicyMapper.insertBatch(orderPolicyDOList);
                 }
             }
-            tradeOrderRoomModelMapper.deleteByOrderId(orderId);
-            if (!list.isEmpty()) {
-                tradeOrderRoomModelMapper.insertBatch(list);
-            }
+
             String desc = "";
             if (!Objects.equals(shipTradeOrderCreateReqVO.getRemark(), tradeOrderDO.getRemark()) || !Objects.equals(shipTradeOrderCreateReqVO.getLinkMobile(), tradeOrderDO.getLinkMobile()) || !Objects.equals(shipTradeOrderCreateReqVO.getLinkMan(), tradeOrderDO.getLinkMan())) {
                 auditType = 2;
@@ -2940,6 +3000,125 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
         }
     }
 
+    /**
+     * 保存历史优惠政策
+     * @param policyList
+     * @param orderId
+     */
+    private void insertHisOrderPolicy(List<OrderPolicyDO> policyList,Long orderId){
+        // 历史优惠政策记录
+        List<HisTradeOrderPolicyDO> hisTradeOrderPolicyDOList = new ArrayList<>();
+        // 获取历史优惠政策中最新的记录
+        HisTradeOrderPolicyDO latestHisTradeOrderPolicy = hisTradeOrderPolicyMapper.selectOne(new LambdaQueryWrapper<HisTradeOrderPolicyDO>()
+                .eq(HisTradeOrderPolicyDO::getOrderId, orderId)
+                .orderByDesc(HisTradeOrderPolicyDO::getVersion)
+                .last("limit 1"));
+        Integer version;
+        if(latestHisTradeOrderPolicy!=null){
+            version = latestHisTradeOrderPolicy.getVersion() + 1;
+        } else {
+            version = 0;
+        }
+        if (CollUtil.isNotEmpty(policyList)) {
+            //创建订单优惠政策数据
+            policyList.forEach(item -> {
+                HisTradeOrderPolicyDO hisTradeOrderPolicyDO = new HisTradeOrderPolicyDO();
+                BeanUtils.copyProperties(item,hisTradeOrderPolicyDO);
+                hisTradeOrderPolicyDO.setHisId(IdWorker.getId());
+                hisTradeOrderPolicyDO.setCurrentVersion(1);
+                hisTradeOrderPolicyDO.setVersion(version);
+                hisTradeOrderPolicyDOList.add(hisTradeOrderPolicyDO);
+
+            });
+        }
+        hisTradeOrderPolicyMapper.update(new LambdaUpdateWrapper<HisTradeOrderPolicyDO>()
+                .set(HisTradeOrderPolicyDO::getCurrentVersion, 0)
+                .set(HisTradeOrderPolicyDO::getUpdateTime, new Date())
+                .eq(HisTradeOrderPolicyDO::getOrderId, orderId));
+        if(!hisTradeOrderPolicyDOList.isEmpty()){
+            hisTradeOrderPolicyMapper.insertBatch(hisTradeOrderPolicyDOList);
+        }
+    }
+
+    /**
+     * 修改订单房型,保存历史房型
+     * @param roomModelList
+     * @param orderId
+     * @param orderNo
+     */
+    private void updateRoomModel(List<TradeOrderRoomModelVO> roomModelList,Long orderId,String orderNo){
+        // 查询现在数据库中的房型数据
+        List<TradeOrderRoomModelDO> tradeOrderRoomModelList = tradeOrderRoomModelMapper.selectListByOrderId(orderId);
+        // 历史房型记录
+        List<HisTradeOrderRoomModelDO> hisTradeOrderRoomModelList = new ArrayList<>();
+        // 获取历史房型中最新的记录
+        HisTradeOrderRoomModelDO latestHisOrderRoomModel = hisTradeOrderRoomModelMapper.selectOne(new LambdaQueryWrapper<HisTradeOrderRoomModelDO>()
+                .eq(HisTradeOrderRoomModelDO::getOrderId, orderId)
+                .orderByDesc(HisTradeOrderRoomModelDO::getVersion)
+                .last("limit 1"));
+        Integer version;
+        if(latestHisOrderRoomModel!=null){
+            version = latestHisOrderRoomModel.getVersion() + 1;
+        } else {
+            version = 0;
+        }
+        // 删除的房型数据
+        if (CollUtil.isNotEmpty(tradeOrderRoomModelList)) {
+            // 获取传入的房型ID列表
+            List<Long> newRoomModelIds = CollUtil.emptyIfNull(roomModelList).stream()
+                    .map(TradeOrderRoomModelVO::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            // 找出需要删除的房型(数据库中存在但新数据中不存在的)
+            List<Long> deleteRoomModelIds = tradeOrderRoomModelList.stream()
+                    .map(TradeOrderRoomModelDO::getId)
+                    .filter(id -> !newRoomModelIds.contains(id))
+                    .collect(Collectors.toList());
+            tradeOrderRoomModelList.forEach(item -> {
+                HisTradeOrderRoomModelDO hisTradeOrderRoomModelDO = new HisTradeOrderRoomModelDO();
+                BeanUtils.copyProperties(item,hisTradeOrderRoomModelDO);
+                hisTradeOrderRoomModelDO.setHisId(IdWorker.getId());
+                hisTradeOrderRoomModelDO.setCurrentVersion(1);
+                hisTradeOrderRoomModelDO.setVersion(version);
+                hisTradeOrderRoomModelList.add(hisTradeOrderRoomModelDO);
+            });
+            // 执行删除操作
+            if (CollUtil.isNotEmpty(deleteRoomModelIds)) {
+                tradeOrderRoomModelMapper.deleteByIds(deleteRoomModelIds);
+            }
+        }
+        //创建订单房型数据
+        List<TradeOrderRoomModelDO> insetList = new ArrayList<>();
+        List<TradeOrderRoomModelDO> updateList = new ArrayList<>();
+        roomModelList.forEach(item -> {
+            TradeOrderRoomModelDO tradeOrderRoomModelDO = BeanUtils.toBean(item, TradeOrderRoomModelDO.class);
+            tradeOrderRoomModelDO.setSyncStatus("0");
+            tradeOrderRoomModelDO.setOrderId(orderId);
+            tradeOrderRoomModelDO.setDiscount(tradeOrderRoomModelDO.getUnitPrice().subtract(tradeOrderRoomModelDO.getRealMoney()));
+            tradeOrderRoomModelDO.setOrderNo(orderNo);
+            if(tradeOrderRoomModelDO.getId() == null){
+                tradeOrderRoomModelDO.setId(IdWorker.getId());
+                insetList.add(tradeOrderRoomModelDO);
+            }else{
+                updateList.add(tradeOrderRoomModelDO);
+            }
+        });
+        hisTradeOrderRoomModelMapper.update(new LambdaUpdateWrapper<HisTradeOrderRoomModelDO>()
+                .set(HisTradeOrderRoomModelDO::getCurrentVersion, 0)
+                .set(HisTradeOrderRoomModelDO::getUpdateTime, new Date())
+                .eq(HisTradeOrderRoomModelDO::getOrderId, orderId));
+        if(!hisTradeOrderRoomModelList.isEmpty()){
+            hisTradeOrderRoomModelMapper.insertBatch(hisTradeOrderRoomModelList);
+        }
+        if (!insetList.isEmpty()) {
+            tradeOrderRoomModelMapper.insertBatch(insetList);
+        }
+        if (!updateList.isEmpty()) {
+            tradeOrderRoomModelMapper.updateBatch(updateList);
+        }
+    }
+
 
     @Override
     public TradeOrderRespNewVO getOrderInfoNew(Long id) {

+ 44 - 28
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/BeanUtils.java

@@ -1,59 +1,75 @@
 package com.yc.ship.module.trade.utils;
 
 import com.yc.ship.module.trade.framework.annotation.ForUpdate;
+import lombok.extern.slf4j.Slf4j;
 
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
-/**
- * @author :qsl
- * &#064;description:TODO
- * &#064;date  :2026/1/12 16:10
- **/
+@Slf4j
 public class BeanUtils {
 
-    /**
-     * 获取变更内容
-     *
-     * @param newBean 更改前的Bean
-     * @param oldBean 更改后的Bean
-     * @param <T>
-     * @return
-     */
     public static <T> String getChangedFields(T newBean, T oldBean) {
         if (newBean == null || oldBean == null) {
             return "";
         }
-        Field[] fields = newBean.getClass().getDeclaredFields();
-        StringBuilder builder = new StringBuilder();
-        for (Field field : fields) {
-            field.setAccessible(true);
-            if (field.isAnnotationPresent(ForUpdate.class)) {
+
+        try {
+            Map<String, Field> fieldMap = Arrays.stream(newBean.getClass().getDeclaredFields())
+                    .filter(f -> f.isAnnotationPresent(ForUpdate.class))
+                    .collect(Collectors.toMap(Field::getName, f -> f));
+
+            PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(newBean.getClass()).getPropertyDescriptors();
+            StringBuilder builder = new StringBuilder();
+
+            for (PropertyDescriptor pd : propertyDescriptors) {
+                String propertyName = pd.getName();
+                if ("class".equals(propertyName) || !fieldMap.containsKey(propertyName)) {
+                    continue;
+                }
+
+                Method readMethod = pd.getReadMethod();
+                if (readMethod == null) {
+                    continue;
+                }
+
                 try {
-                    Object newValue = field.get(newBean);
-                    Object oldValue = field.get(oldBean);
-                    if(newValue instanceof BigDecimal && oldValue instanceof BigDecimal) {
-                        if(((BigDecimal) newValue).compareTo((BigDecimal) oldValue) == 0) {
+                    Object newValue = readMethod.invoke(newBean);
+                    Object oldValue = readMethod.invoke(oldBean);
+
+                    if (newValue instanceof BigDecimal && oldValue instanceof BigDecimal) {
+                        if (((BigDecimal) newValue).compareTo((BigDecimal) oldValue) == 0) {
                             continue;
                         }
                     }
+
                     newValue = newValue == null ? "" : newValue;
                     oldValue = oldValue == null ? "" : oldValue;
+
                     if (!Objects.equals(newValue, oldValue)) {
-                        //获取字段名称
+                        Field field = fieldMap.get(propertyName);
                         builder.append(field.getAnnotation(ForUpdate.class).fieldName());
                         builder.append(": 【更改前:");
-                        builder.append(newValue);
-                        builder.append(", 更改后:");
                         builder.append(oldValue);
+                        builder.append(", 更改后:");
+                        builder.append(newValue);
                         builder.append("】\n");
                     }
                 } catch (Exception e) {
-                    System.out.println(e);
+                    log.warn("比较属性 {} 时发生异常,已跳过", propertyName, e);
                 }
             }
+            return builder.toString();
+        } catch (Exception e) {
+            log.error("获取变更字段失败", e);
+            return "";
         }
-        return builder.toString();
     }
-}
+}