chenxiaofei 3 часов назад
Родитель
Сommit
37ab9a6873

+ 25 - 0
sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/model/param/AddLogisticOrderParam.java

@@ -95,6 +95,31 @@ public class AddLogisticOrderParam implements Serializable {
     @NotBlank(message = "托运联系人id不能为空")
     private Long consignContactsId;
 
+    /**
+     * 代理单位
+     */
+    private String agentCompany;
+
+    /**
+     * 代理单位id
+     */
+    private Long agentCompanyId;
+
+    /**
+     * 代理单位联系电话
+     */
+    private String agentContactPhone;
+
+    /**
+     * 代理单位联系人
+     */
+    private String agentContacts;
+
+    /**
+     * 代理单位联系人id
+     */
+    private Long agentContactsId;
+
 
 
     /**

+ 12 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/req/TradeBaseInfoReqVo.java

@@ -53,6 +53,18 @@ public class TradeBaseInfoReqVo implements Serializable {
     @NotBlank(message = "供应单位联系电话不能为空")
     private String providePhone;
 
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private Long agentEntId;
+
+    /**
+     * 代理单位联系电话
+     */
+    @Schema(description = "代理单位联系电话")
+    private String agentPhone;
+
     /**
      * 合同编号
      */

+ 44 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/KwcContractTradeUnitService.java

@@ -13,6 +13,7 @@ import com.sckw.core.utils.IdWorker;
 import com.sckw.core.web.constant.HttpStatus;
 import com.sckw.core.web.context.LoginUserHolder;
 import com.sckw.system.api.model.dto.res.EntCacheResDto;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -24,8 +25,14 @@ import java.util.*;
 * @createDate 2023-07-13 13:36:19
 */
 @Service
+@Slf4j
 public class KwcContractTradeUnitService {
 
+    /**
+     * 贸易合同代理单位类型。
+     */
+    public static final int TRADE_AGENT_UNIT_TYPE = 3;
+
     @Autowired
     private KwcContractTradeUnitMapper kwcContractTradeUnitMapper;
 
@@ -48,6 +55,10 @@ public class KwcContractTradeUnitService {
             entIdList.add(baseInfo.getPurchaseEntId());
         }
 
+        if (Objects.nonNull(baseInfo.getAgentEntId())) {
+            entIdList.add(baseInfo.getAgentEntId());
+        }
+
         if (CollectionUtils.isEmpty(entIdList)) {
             return;
         }
@@ -98,6 +109,39 @@ public class KwcContractTradeUnitService {
             }
         }
 
+        // 处理代理单位信息
+        if (Objects.nonNull(baseInfo.getAgentEntId())) {
+            log.info("开始保存合同[{}]的代理单位信息,代理企业ID: {}", contractId, baseInfo.getAgentEntId());
+            
+            // 初始化代理单位实体对象
+            KwcContractTradeUnit agentUnit = new KwcContractTradeUnit();
+            agentUnit.setId(new IdWorker(1L).nextId());
+            agentUnit.setUnitType(TRADE_AGENT_UNIT_TYPE); // 设置单位为代理类型
+            agentUnit.setEntId(baseInfo.getAgentEntId());
+            agentUnit.setContractId(contractId);
+            
+            // 从缓存中获取并填充企业基础信息(如企业名称、联系人等)
+            saveEnt(entCacheResDtoMap, agentUnit);
+            
+            // 设置签署电话及其他通用字段
+            agentUnit.setSignPhone(baseInfo.getAgentPhone());
+            agentUnit.setStatus(Global.NO); // 状态:正常/未删除
+            Long currentUserId = LoginUserHolder.getUserId();
+            agentUnit.setCreateBy(currentUserId);
+            agentUnit.setCreateTime(date);
+            agentUnit.setUpdateBy(currentUserId);
+            agentUnit.setUpdateTime(date);
+            agentUnit.setDelFlag(Global.NO); // 删除标志:未删除
+
+            // 执行插入操作
+            int insertResult = kwcContractTradeUnitMapper.insert(agentUnit);
+            if (insertResult <= 0) {
+                log.error("保存合同[{}]的代理单位信息失败,企业ID: {}", contractId, baseInfo.getAgentEntId());
+                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
+            }
+            log.info("成功保存合同[{}]的代理单位信息,记录ID: {}", contractId, agentUnit.getId());
+        }
+
     }
 
     /**

+ 155 - 38
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/operateService/KwcContractTradeService.java

@@ -360,6 +360,7 @@ public class KwcContractTradeService {
 
     private void checkParam(TradeBaseInfoReqVo baseInfo, List<TradeGoodsInfoReqVo> goodsInfo) {
         if (Objects.nonNull(baseInfo)) {
+            validateAgentUnitParam(baseInfo);
             if (StringUtils.isNotBlank(baseInfo.getContractCode()) && baseInfo.getContractCode().length() > 20) {
                 throw new SystemException("合同编号超长!");
             }
@@ -429,6 +430,28 @@ public class KwcContractTradeService {
         }
     }
 
+    /**
+     * 校验代理单位参数,兼容不传代理单位的旧合同新增请求。
+     *
+     * @param baseInfo 贸易合同基础信息
+     */
+    static void validateAgentUnitParam(TradeBaseInfoReqVo baseInfo) {
+        if (Objects.isNull(baseInfo)) {
+            return;
+        }
+        boolean hasAgentEnt = Objects.nonNull(baseInfo.getAgentEntId());
+        boolean hasAgentPhone = StringUtils.isNotBlank(baseInfo.getAgentPhone());
+        if (!hasAgentEnt && !hasAgentPhone) {
+            return;
+        }
+        if (!hasAgentEnt) {
+            throw new SystemException("代理单位不能为空");
+        }
+        if (!hasAgentPhone) {
+            throw new SystemException("代理单位联系电话不能为空");
+        }
+    }
+
     private static boolean hasDuplicateGoodsId(List<TradeGoodsInfoReqVo> goodsInfo) {
         if (goodsInfo == null || goodsInfo.isEmpty()) {
             return false;
@@ -2366,63 +2389,157 @@ public class KwcContractTradeService {
     }
 
 
+    /**
+     * 查询贸易合同订单信息(主要用于下拉框选择等场景)。
+     * <p>
+     * 根据传入的企业ID、企业类型和商品ID,查询符合条件的已签约贸易合同列表。
+     * 针对供应商类型(Supplier),会进一步过滤为当前登录用户作为销售员的合同;
+     * 针对其他类型(如采购商),则基于当前登录企业进行过滤。
+     * </p>
+     *
+     * @param contractTradeOrderDto 查询条件DTO,包含 goodsId(商品ID)、entId(企业ID)、entType(企业类型)、keyword(搜索关键字)
+     * @return 贸易合同订单信息列表 {@link ContractTradeOrderInfo}
+     */
     public List<ContractTradeOrderInfo> queryContractTradeOrder(ContractTradeOrderDto contractTradeOrderDto) {
-        log.info("查询贸易合同订单,请求:{}", JSON.toJSONString(contractTradeOrderDto));
+        log.info("开始查询贸易合同订单,请求参数:{}", JSON.toJSONString(contractTradeOrderDto));
+
+        // 1. 参数校验:确保商品ID、企业ID和企业类型不为空
         checkParam(contractTradeOrderDto.getGoodsId(), contractTradeOrderDto.getEntId(), contractTradeOrderDto.getEntType());
-        //查询贸易合同企业信息
-        List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByEntIdAndUnitType(contractTradeOrderDto.getEntId(),
-                contractTradeOrderDto.getEntType());
+
+        // 2. 根据企业和类型查询关联的合同单位信息
+        // 例如:查询某供应商参与的所有作为“供应方”的合同,或某采购商参与的所有作为“采购方”的合同
+        List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByEntIdAndUnitType(
+                contractTradeOrderDto.getEntId(),
+                contractTradeOrderDto.getEntType()
+        );
+
         if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeUnits)) {
+            log.debug("未找到指定企业[{}]在类型[{}]下的合同单位信息,返回空列表", contractTradeOrderDto.getEntId(), contractTradeOrderDto.getEntType());
             return List.of();
         }
-        Set<Long> contractIds =
-                tradeUnits.stream().map(KwcContractTradeUnit::getContractId).collect(Collectors.toSet());
 
-        List<KwcContractTradeUnit> tradeUnits1 = kwcContractTradeUnitRepository.queryByContractIds(contractIds);
-        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeUnits1)) {
+        // 提取这些单位关联的所有合同ID
+        Set<Long> contractIds = tradeUnits.stream()
+                .map(KwcContractTradeUnit::getContractId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
+            log.debug("提取到的合同ID集合为空,返回空列表");
             return List.of();
         }
-        Map<String, KwcContractTradeUnit> conTractTradeUnitMap =
-                tradeUnits1.stream().collect(Collectors.toMap(x -> x.getContractId() +
-                                "_" + x.getUnitType(), Function.identity(),
-                        (x, y) -> x));
-        // 判断当前查询的企业类型是否为供应方(供应商)
-        if (Objects.equals(contractTradeOrderDto.getEntType(), CooperateTypeEnum.SUPPLIER.getCode())) {
-            log.debug("当前查询类型为供应方,执行销售员签约贸易合同查询逻辑。entId: {}, goodsId: {}",
-                    contractTradeOrderDto.getEntId(), contractTradeOrderDto.getGoodsId());
-            // 调用专用方法查询当前登录用户作为销售员且已签约的贸易合同信息
-            return querySalesmanSignedTradeOrder(contractTradeOrderDto, contractIds, conTractTradeUnitMap);
+        log.debug("初步筛选出的合同ID数量: {}", contractIds.size());
+
+        // 3. 批量查询这些合同的所有单位信息,用于后续构建返回对象中的企业名称等字段
+        List<KwcContractTradeUnit> allTradeUnits = kwcContractTradeUnitRepository.queryByContractIds(contractIds);
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(allTradeUnits)) {
+            log.warn("根据合同ID集合查询合同单位信息为空,contractIds: {}", contractIds);
+            return List.of();
         }
-        contractIds = tradeUnits1.stream()
-                .filter(x -> Objects.equals(x.getEntId(), LoginUserHolder.getEntId()) && Objects.equals(x.getUnitType(),
-                        2))
+
+        // 构建映射:Key为 "contractId_unitType",Value为单位对象
+        // 方便后续通过合同ID和单位类型快速获取对应的企业信息(如采购方名称、供应方名称)
+        Map<String, KwcContractTradeUnit> contractTradeUnitMap = allTradeUnits.stream()
+                .collect(Collectors.toMap(
+                        unit -> unit.getContractId() + "_" + unit.getUnitType(),
+                        Function.identity(),
+                        (existing, replacement) -> existing // 处理Key冲突,保留第一个
+                ));
+
+        // 4. 分支处理:根据企业类型执行不同的查询逻辑
+        Integer entType = contractTradeOrderDto.getEntType();
+
+        // 场景A:如果查询的是供应方(供应商)
+        // 业务规则:供应商查看合同时,通常只能看到自己作为销售员负责的、且已签约的合同
+        if (Objects.equals(entType, CooperateTypeEnum.SUPPLIER.getCode())) {
+            log.debug("当前查询类型为供应方(Supplier),进入销售员专属查询逻辑。entId: {}, goodsId: {}",
+                    contractTradeOrderDto.getEntId(), contractTradeOrderDto.getGoodsId());
+            
+            // 调用专用方法,内部会过滤 salesmanId = 当前登录用户ID 且状态为已签约的合同
+            return querySalesmanSignedTradeOrder(contractTradeOrderDto, contractIds, contractTradeUnitMap);
+        }
+
+        // 场景B:其他类型(主要是采购方 Purchaser)
+        // 业务规则:采购商查看合同时,需限制在当前登录企业范围内,且角色为采购方(unitType=2)
+        log.debug("当前查询类型非供应方,执行通用采购方查询逻辑。当前登录企业ID: {}", LoginUserHolder.getEntId());
+        
+        // 再次过滤合同ID:只保留当前登录企业作为“采购方”参与的合同
+        // 注意:这里硬编码了 unitType=2 (假设 2 代表 PURCHASER/采购方,需与 CooperateTypeEnum.PURCHASER.getCode() 保持一致)
+        Set<Long> filteredContractIds = allTradeUnits.stream()
+                .filter(unit -> Objects.equals(unit.getEntId(), LoginUserHolder.getEntId()) 
+                        && Objects.equals(unit.getUnitType(), CooperateTypeEnum.PURCHASER.getCode()))
                 .map(KwcContractTradeUnit::getContractId)
                 .collect(Collectors.toSet());
-        //查询商品信息
-        List<KwcContractTradeGoods> kwcContractGoods = kwcContractTradeGoodsRepository.queryByContractIdsAndGoodsId(contractIds,
-                contractTradeOrderDto.getGoodsId());
-        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwcContractGoods)) {
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(filteredContractIds)) {
+            log.debug("当前登录企业[{}]未作为采购方参与任何上述合同,返回空列表", LoginUserHolder.getEntId());
             return Collections.emptyList();
         }
-        Map<Long, KwcContractTradeGoods> contractGoodsMap = kwcContractGoods.stream()
-                .collect(Collectors.toMap(KwcContractTradeGoods::getContractId, Function.identity(), (x, y) -> x));
-        //只查询已签约的
-        Set<Long> contractIdList = kwcContractGoods.stream()
-                .filter(x -> Objects.equals(x.getStatus(), ContractStatusEnum.SIGNED.getCode()))
+        log.debug("过滤后剩余合同ID数量: {}", filteredContractIds.size());
+
+        // 5. 根据商品ID进一步筛选合同
+        // 查询上述合同中,包含指定商品ID的合同商品信息
+        List<KwcContractTradeGoods> contractGoodsList = kwcContractTradeGoodsRepository.queryByContractIdsAndGoodsId(
+                filteredContractIds,
+                contractTradeOrderDto.getGoodsId()
+        );
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractGoodsList)) {
+            log.debug("在合同[{}]中未找到包含商品ID[{}]的商品信息,返回空列表", filteredContractIds, contractTradeOrderDto.getGoodsId());
+            return Collections.emptyList();
+        }
+
+        // 构建映射:Key为 contractId,Value为合同商品信息(用于获取价格、数量等)
+        Map<Long, KwcContractTradeGoods> contractGoodsMap = contractGoodsList.stream()
+                .collect(Collectors.toMap(
+                        KwcContractTradeGoods::getContractId,
+                        Function.identity(),
+                        (x, y) -> x
+                ));
+
+        // 6. 状态过滤:只保留“已签约”状态的合同
+        Set<Long> signedContractIds = contractGoodsList.stream()
+                .filter(goods -> Objects.equals(goods.getStatus(), ContractStatusEnum.SIGNED.getCode()))
                 .map(KwcContractTradeGoods::getContractId)
                 .collect(Collectors.toSet());
-        //查询贸易合同
-        List<KwcContractTrade> kwcContractTrades = kwcContractTradeRepository.findByContractIds(contractIdList);
-        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwcContractTrades)) {
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(signedContractIds)) {
+            log.debug("未找到状态为“已签约”且包含指定商品的合同,返回空列表");
             return Collections.emptyList();
         }
-        kwcContractTrades = kwcContractTrades.stream()
-                .filter(x -> Objects.equals(x.getStatus(), ContractStatusEnum.SIGNED.getCode()))
+        log.debug("符合条件的已签约合同ID数量: {}", signedContractIds.size());
+
+        // 7. 查询合同主表信息
+        List<KwcContractTrade> contractTrades = kwcContractTradeRepository.findByContractIds(signedContractIds);
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractTrades)) {
+            log.warn("根据合同ID查询合同主表信息为空,signedContractIds: {}", signedContractIds);
+            return Collections.emptyList();
+        }
+
+        // 双重保险:再次在内存中过滤状态,确保数据一致性
+        List<KwcContractTrade> validTrades = contractTrades.stream()
+                .filter(trade -> Objects.equals(trade.getStatus(), ContractStatusEnum.SIGNED.getCode()))
                 .collect(Collectors.toList());
-        List<ContractTradeOrderInfo> result = kwcContractTrades.stream()
-                .map(x -> getContractTradeOrderInfo(x, conTractTradeUnitMap, contractTradeOrderDto.getEntType(), contractGoodsMap))
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(validTrades)) {
+            return Collections.emptyList();
+        }
+
+        // 8. 组装返回结果
+        List<ContractTradeOrderInfo> resultList = validTrades.stream()
+                .map(trade -> getContractTradeOrderInfo(
+                        trade, 
+                        contractTradeUnitMap, 
+                        contractTradeOrderDto.getEntType(), 
+                        contractGoodsMap
+                ))
                 .collect(Collectors.toList());
-        return filterContractTradeOrderInfo(result, contractTradeOrderDto.getKeyword());
+
+        // 9. 关键字模糊匹配过滤(如有)
+        List<ContractTradeOrderInfo> finalResult = filterContractTradeOrderInfo(resultList, contractTradeOrderDto.getKeyword());
+        
+        log.info("查询贸易合同订单完成,最终返回记录数: {}", finalResult.size());
+        return finalResult;
     }
 
 

+ 34 - 0
sckw-modules/sckw-contract/src/test/java/com/sckw/contract/service/operateService/KwcContractTradeServiceTest.java

@@ -1,5 +1,8 @@
 package com.sckw.contract.service.operateService;
 
+import com.sckw.contract.model.vo.req.TradeBaseInfoReqVo;
+import com.sckw.contract.service.KwcContractTradeUnitService;
+import com.sckw.core.exception.SystemException;
 import com.sckw.system.api.model.dto.res.EntTypeResDto;
 import org.junit.Assert;
 import org.junit.Test;
@@ -43,4 +46,35 @@ public class KwcContractTradeServiceTest {
 
         Assert.assertFalse(result);
     }
+
+    /**
+     * 代理单位参数完整时允许新增销售合同。
+     */
+    @Test
+    public void validateAgentUnitParamWhenAgentInfoComplete() {
+        TradeBaseInfoReqVo baseInfo = new TradeBaseInfoReqVo();
+        baseInfo.setAgentEntId(3001L);
+        baseInfo.setAgentPhone("13800000000");
+
+        KwcContractTradeService.validateAgentUnitParam(baseInfo);
+    }
+
+    /**
+     * 代理单位已选择但未填写联系电话时应拦截,避免落库半截数据。
+     */
+    @Test(expected = SystemException.class)
+    public void validateAgentUnitParamWhenAgentPhoneMissing() {
+        TradeBaseInfoReqVo baseInfo = new TradeBaseInfoReqVo();
+        baseInfo.setAgentEntId(3001L);
+
+        KwcContractTradeService.validateAgentUnitParam(baseInfo);
+    }
+
+    /**
+     * 销售合同代理单位落库类型固定为3。
+     */
+    @Test
+    public void tradeAgentUnitTypeShouldBeThree() {
+        Assert.assertEquals(3, KwcContractTradeUnitService.TRADE_AGENT_UNIT_TYPE);
+    }
 }

+ 71 - 1
sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderService.java

@@ -128,6 +128,10 @@ public class KwoTradeOrderService {
      * 供应商企业类型。
      */
     static final int SUPPLIER_ENT_TYPE = 1;
+    /**
+     * 贸易合同/贸易订单代理单位类型。
+     */
+    static final String AGENT_UNIT_TYPE = "3";
 
     @DubboReference(version = "1.0.0", group = "design", check = false)
     private RemoteSystemService remoteSystemService;
@@ -2646,7 +2650,7 @@ public class KwoTradeOrderService {
             KwoTradeOrderUnit unit = BeanUtil.copyProperties(e, KwoTradeOrderUnit.class);
             unit.setId(new IdWorker(1).nextId());
             unit.setTOrderId(order.getId()).setTOrderNo(order.getTOrderNo()).setTopEntId(e.getEntId());
-            unit.setUnitType(StrUtil.equals(e.getUnitType(), "1") ? "2" : "1");//贸易合同和订单的单位类型相反
+            unit.setUnitType(convertContractUnitTypeToOrderUnitType(e.getUnitType()));//贸易合同和订单的采购/销售单位类型相反,代理单位类型保持为3
             if (StrUtil.equals(unit.getUnitType(), "1")) {
 //                walletFreeze.setBuyEntId(unit.getEntId());
                 walletFreeze.setProEntId(unit.getEntId());
@@ -2678,6 +2682,70 @@ public class KwoTradeOrderService {
         }
     }
 
+    /**
+     * 根据贸易合同ID查询合同企业信息,订单单位落库以贸易合同实际企业为准。
+     *
+     * @param tradeContractId 贸易合同ID
+     * @return 贸易合同企业信息集合
+     */
+    private List<TradeContractUnitDto> queryTradeContractUnits(Long tradeContractId) {
+        if (Objects.isNull(tradeContractId)) {
+            throw new BusinessException("贸易合同ID不能为空");
+        }
+        try {
+            List<TradeContractUnitDto> unitList = remoteContractService.queryContractUnitByContractId(tradeContractId);
+            if (CollUtil.isEmpty(unitList)) {
+                log.warn("贸易合同企业信息不存在,tradeContractId={}", tradeContractId);
+                throw new BusinessException("贸易合同企业信息不存在");
+            }
+            return unitList;
+        } catch (BusinessException e) {
+            throw e;
+        } catch (Exception e) {
+            log.error("查询贸易合同企业信息失败,tradeContractId={}", tradeContractId, e);
+            throw new BusinessException("查询贸易合同企业信息失败");
+        }
+    }
+
+    /**
+     * 将贸易合同单位类型转换为贸易订单单位类型。
+     * <p>
+     * 贸易合同中的供应/采购单位与贸易订单中的采购/销售单位方向相反;
+     * 代理单位不参与方向反转,固定落库为类型3。
+     * </p>
+     *
+     * @param contractUnitType 贸易合同单位类型
+     * @return 贸易订单单位类型
+     */
+    static String convertContractUnitTypeToOrderUnitType(String contractUnitType) {
+        if (StrUtil.equals(contractUnitType, AGENT_UNIT_TYPE)) {
+            return AGENT_UNIT_TYPE;
+        }
+        return StrUtil.equals(contractUnitType, "1") ? "2" : "1";
+    }
+
+    /**
+     * 代理订单创建物流订单时,将贸易订单企业表中的代理单位同步传递给运输模块。
+     *
+     * @param param     物流订单新增参数
+     * @param unitMap   贸易订单企业类型映射
+     * @param agentFlag 是否代理
+     */
+    static void setAgentCompanyInfo(AddLogisticOrderParam param, Map<String, KwoTradeOrderUnit> unitMap, Integer agentFlag) {
+        if (Objects.isNull(param) || !Objects.equals(agentFlag, Global.YES) || CollUtil.isEmpty(unitMap)) {
+            return;
+        }
+        KwoTradeOrderUnit agentUnit = unitMap.get(AGENT_UNIT_TYPE);
+        if (Objects.isNull(agentUnit)) {
+            return;
+        }
+        param.setAgentCompany(agentUnit.getFirmName());
+        param.setAgentCompanyId(agentUnit.getEntId());
+        param.setAgentContactPhone(agentUnit.getPhone());
+        param.setAgentContacts(agentUnit.getContacts());
+        param.setAgentContactsId(agentUnit.getContactsId());
+    }
+
     /**
      * 买家撤销贸易订单
      */
@@ -3124,6 +3192,7 @@ public class KwoTradeOrderService {
         addLogisticOrderParam.setUserId(LoginUserHolder.getUserId());
         addLogisticOrderParam.setMeasurementWay(tradeContractResDto.getMeasurementWay());
         addLogisticOrderParam.setAgentFlag(kwoTradeOrder.getAgentFlag());
+        setAgentCompanyInfo(addLogisticOrderParam, unitMap, kwoTradeOrder.getAgentFlag());
         log.info("创建物流订单:{}", JSONObject.toJSONString(addLogisticOrderParam));
         Integer result = transportRemoteService.addLogisticOrder(addLogisticOrderParam);
         //自动派单运力不足
@@ -3572,6 +3641,7 @@ public class KwoTradeOrderService {
         addLogisticOrderParam.setUserId(LoginUserHolder.getUserId());
         addLogisticOrderParam.setDispatchWay(DispatchWayEnums.MANUAL_DISPATCH.getCode());
         addLogisticOrderParam.setAgentFlag(kwoTradeOrder.getAgentFlag());
+        setAgentCompanyInfo(addLogisticOrderParam, unitMap, kwoTradeOrder.getAgentFlag());
         log.info("创建物流订单:{}", JSONObject.toJSONString(addLogisticOrderParam));
         transportRemoteService.addLogisticOrder(addLogisticOrderParam);
 

+ 38 - 0
sckw-modules/sckw-order/src/test/java/com/sckw/order/serivce/KwoTradeOrderServiceTest.java

@@ -1,13 +1,17 @@
 package com.sckw.order.serivce;
 
 import com.sckw.order.model.dto.TradeOrderListSelectDTO;
+import com.sckw.order.model.KwoTradeOrderUnit;
 import com.sckw.system.api.model.dto.res.EntTypeResDto;
+import com.sckw.transport.api.model.param.AddLogisticOrderParam;
 import org.junit.Assert;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -146,4 +150,38 @@ public class KwoTradeOrderServiceTest {
         Assert.assertEquals(Integer.valueOf(0), KwoTradeOrderService.normalizeContractAgentFlag(0));
         Assert.assertEquals(Integer.valueOf(0), KwoTradeOrderService.normalizeContractAgentFlag(null));
     }
+
+    /**
+     * 贸易合同采购/供应单位创建订单时保持原反转规则,代理单位类型3不反转。
+     */
+    @Test
+    public void convertContractUnitTypeToOrderUnitTypeKeepsAgentType() {
+        Assert.assertEquals("2", KwoTradeOrderService.convertContractUnitTypeToOrderUnitType("1"));
+        Assert.assertEquals("1", KwoTradeOrderService.convertContractUnitTypeToOrderUnitType("2"));
+        Assert.assertEquals("3", KwoTradeOrderService.convertContractUnitTypeToOrderUnitType("3"));
+    }
+
+    /**
+     * Agent trade order should pass agent unit fields to logistics order param.
+     */
+    @Test
+    public void setAgentCompanyInfoWhenOrderIsAgent() {
+        AddLogisticOrderParam param = new AddLogisticOrderParam();
+        KwoTradeOrderUnit agentUnit = new KwoTradeOrderUnit();
+        agentUnit.setFirmName("Agent Company");
+        agentUnit.setEntId(3001L);
+        agentUnit.setPhone("13800000000");
+        agentUnit.setContacts("Alice");
+        agentUnit.setContactsId(9001L);
+        Map<String, KwoTradeOrderUnit> unitMap = new HashMap<>();
+        unitMap.put(KwoTradeOrderService.AGENT_UNIT_TYPE, agentUnit);
+
+        KwoTradeOrderService.setAgentCompanyInfo(param, unitMap, 1);
+
+        Assert.assertEquals("Agent Company", param.getAgentCompany());
+        Assert.assertEquals(Long.valueOf(3001L), param.getAgentCompanyId());
+        Assert.assertEquals("13800000000", param.getAgentContactPhone());
+        Assert.assertEquals("Alice", param.getAgentContacts());
+        Assert.assertEquals(Long.valueOf(9001L), param.getAgentContactsId());
+    }
 }

+ 5 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dubbo/TransportServiceImpl.java

@@ -1302,6 +1302,11 @@ public class TransportServiceImpl implements TransportRemoteService {
         addLogisticOrderDTO.setConsignContactPhone(param.getConsignContactPhone());
         addLogisticOrderDTO.setConsignContacts(param.getConsignContacts());
         addLogisticOrderDTO.setConsignContactsId(param.getConsignContactsId());
+        addLogisticOrderDTO.setAgentCompany(param.getAgentCompany());
+        addLogisticOrderDTO.setAgentCompanyId(param.getAgentCompanyId());
+        addLogisticOrderDTO.setAgentContactPhone(param.getAgentContactPhone());
+        addLogisticOrderDTO.setAgentContacts(param.getAgentContacts());
+        addLogisticOrderDTO.setAgentContactsId(param.getAgentContactsId());
         addLogisticOrderDTO.setGoodsId(param.getGoodsId());
         addLogisticOrderDTO.setGoodsName(param.getGoodsName());
         addLogisticOrderDTO.setGoodsType(param.getGoodsType());

+ 25 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/dto/AddLogisticOrderDTO.java

@@ -93,6 +93,31 @@ public class AddLogisticOrderDTO implements Serializable {
     @NotBlank(message = "托运联系人id不能为空")
     private Long consignContactsId;
 
+    /**
+     * 代理单位
+     */
+    private String agentCompany;
+
+    /**
+     * 代理单位id
+     */
+    private Long agentCompanyId;
+
+    /**
+     * 代理单位联系电话
+     */
+    private String agentContactPhone;
+
+    /**
+     * 代理单位联系人
+     */
+    private String agentContacts;
+
+    /**
+     * 代理单位联系人id
+     */
+    private Long agentContactsId;
+
 
 
     /**

+ 72 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtAcceptCarriageOrderService.java

@@ -103,6 +103,11 @@ import static com.sckw.excel.utils.DateUtil.DEF_DATE_FORMAT;
 @RequiredArgsConstructor
 public class KwtAcceptCarriageOrderService {
 
+    /**
+     * 物流订单企业表代理单位类型。
+     */
+    static final int LOGISTICS_AGENT_UNIT_TYPE = 4;
+
     @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
     RemoteSystemService remoteSystemService;
 
@@ -3522,6 +3527,10 @@ public class KwtAcceptCarriageOrderService {
         entIds.add(orderDTO.getConsignCompanyId());
         entIds.add(x.getAcceptCompanyId());
         entIds.add(orderDTO.getNonConsignCompanyId());
+        if (shouldSaveAgentUnit(orderDTO)) {
+            entIds.add(orderDTO.getAgentCompanyId());
+        }
+        entIds = entIds.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
         Map<Long, EntCacheResDto> entMap = remoteSystemService.queryEntTreeByIds(entIds);
         EntCacheResDto ent = entMap.get(orderDTO.getConsignCompanyId());
         if (Objects.isNull(ent)) {
@@ -3583,6 +3592,69 @@ public class KwtAcceptCarriageOrderService {
         notifyUnit.setUpdateBy(orderDTO.getUserId());
         notifyUnit.setUpdateTime(new Date());
         savelogOrderUnitList.add(notifyUnit);
+        log.info("物流订单新增代理企业信息");
+        appendAgentUnit(orderDTO, lOrderId, savelogOrderUnitList, entMap);
+    }
+
+    /**
+     * 代理贸易订单同步创建物流订单时,追加代理单位信息。
+     *
+     * @param orderDTO             物流订单新增DTO
+     * @param lOrderId             物流订单id
+     * @param savelogOrderUnitList 待批量保存企业列表
+     * @param entMap               企业缓存
+     */
+    private void appendAgentUnit(AddLogisticOrderDTO orderDTO, Long lOrderId,
+                                 List<KwtLogisticsOrderUnit> savelogOrderUnitList,
+                                 Map<Long, EntCacheResDto> entMap) {
+        if (!shouldSaveAgentUnit(orderDTO)) {
+            return;
+        }
+        EntCacheResDto agentEnt = MapUtils.isEmpty(entMap) ? null : entMap.get(orderDTO.getAgentCompanyId());
+        if (Objects.isNull(agentEnt)) {
+            log.warn("代理物流订单未找到代理单位一级企业信息,lOrderId:{}, agentCompanyId:{}", lOrderId, orderDTO.getAgentCompanyId());
+            return;
+        }
+        savelogOrderUnitList.add(buildAgentLogisticsOrderUnit(orderDTO, lOrderId, agentEnt));
+    }
+
+    /**
+     * 是否需要保存代理单位。
+     *
+     * @param orderDTO 物流订单新增DTO
+     * @return true-需要保存,false-不需要保存
+     */
+    static boolean shouldSaveAgentUnit(AddLogisticOrderDTO orderDTO) {
+        return Objects.nonNull(orderDTO)
+                && Objects.equals(orderDTO.getAgentFlag(), Global.YES)
+                && Objects.nonNull(orderDTO.getAgentCompanyId());
+    }
+
+    /**
+     * 构建物流订单代理单位记录。
+     *
+     * @param orderDTO 物流订单新增DTO
+     * @param lOrderId 物流订单id
+     * @param agentEnt 代理单位企业缓存
+     * @return 代理单位记录
+     */
+    static KwtLogisticsOrderUnit buildAgentLogisticsOrderUnit(AddLogisticOrderDTO orderDTO, Long lOrderId, EntCacheResDto agentEnt) {
+        KwtLogisticsOrderUnit agentUnit = new KwtLogisticsOrderUnit();
+        agentUnit.setId(new IdWorker(NumberConstant.FOUR).nextId());
+        agentUnit.setLOrderId(lOrderId);
+        agentUnit.setUnitType(LOGISTICS_AGENT_UNIT_TYPE);
+        agentUnit.setEntId(orderDTO.getAgentCompanyId());
+        agentUnit.setContactsId(agentEnt.getContactsId());
+        agentUnit.setTopEntId(agentEnt.getId());
+        agentUnit.setFirmName(agentEnt.getFirmName());
+        agentUnit.setContacts(agentEnt.getContacts());
+        agentUnit.setPhone(agentEnt.getPhone());
+        agentUnit.setStatus(NumberConstant.ZERO);
+        agentUnit.setCreateBy(orderDTO.getUserId());
+        agentUnit.setCreateTime(new Date());
+        agentUnit.setUpdateBy(orderDTO.getUserId());
+        agentUnit.setUpdateTime(new Date());
+        return agentUnit;
     }
 
     private static void setLogisticContractInfo(AddLogisticOrderDTO orderDTO,LogisticData x, Long lOrderId, List<KwtLogisticsOrderContract> saveContractList) {

+ 31 - 0
sckw-modules/sckw-transport/src/test/java/com/sckw/transport/service/KwtAcceptCarriageOrderServiceTest.java

@@ -1,6 +1,10 @@
 package com.sckw.transport.service;
 
 import com.sckw.fleet.api.model.vo.RTruckVo;
+import com.sckw.core.model.constant.Global;
+import com.sckw.system.api.model.dto.res.EntCacheResDto;
+import com.sckw.transport.model.KwtLogisticsOrderUnit;
+import com.sckw.transport.model.dto.AddLogisticOrderDTO;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -61,4 +65,31 @@ public class KwtAcceptCarriageOrderServiceTest {
 
         Assert.assertFalse(result);
     }
+
+    /**
+     * Agent logistics order unit should use type 4.
+     */
+    @Test
+    public void buildAgentLogisticsOrderUnitWhenAgentExists() {
+        AddLogisticOrderDTO orderDTO = new AddLogisticOrderDTO();
+        orderDTO.setAgentFlag(Global.YES);
+        orderDTO.setAgentCompanyId(3001L);
+        orderDTO.setUserId(1001L);
+
+        EntCacheResDto agentEnt = new EntCacheResDto();
+        agentEnt.setId(3001L);
+        agentEnt.setFirmName("Agent Company");
+        agentEnt.setContacts("Alice");
+        agentEnt.setPhone("13800000000");
+        agentEnt.setContactsId(9001L);
+
+        KwtLogisticsOrderUnit result = KwtAcceptCarriageOrderService.buildAgentLogisticsOrderUnit(orderDTO, 5001L, agentEnt);
+
+        Assert.assertEquals(Long.valueOf(5001L), result.getLOrderId());
+        Assert.assertEquals(Integer.valueOf(4), result.getUnitType());
+        Assert.assertEquals(Long.valueOf(3001L), result.getEntId());
+        Assert.assertEquals("Agent Company", result.getFirmName());
+        Assert.assertEquals(Long.valueOf(9001L), result.getContactsId());
+        Assert.assertEquals(Long.valueOf(1001L), result.getCreateBy());
+    }
 }