Quellcode durchsuchen

Merge remote-tracking branch 'origin/dev_20260630' into dev_20260630

# Conflicts:
#	sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderService.java
xucaiqin vor 6 Stunden
Ursprung
Commit
48879e51e2
35 geänderte Dateien mit 2267 neuen und 127 gelöschten Zeilen
  1. 5 0
      sckw-modules-api/sckw-contract-api/src/main/java/com/sckw/contract/api/model/vo/TradeContractResDto.java
  2. 19 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/OrderDetailRes.java
  3. 19 0
      sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/OrderDetailVo.java
  4. 75 0
      sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/model/param/AddLogisticOrderParam.java
  5. 6 0
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/req/QueryListReqVo.java
  6. 5 0
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/req/QueryTradeReq.java
  7. 12 0
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/req/TradeBaseInfoReqVo.java
  8. 12 0
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/res/QueryListResVo.java
  9. 44 0
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/KwcContractTradeUnitService.java
  10. 290 71
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/operateService/KwcContractTradeService.java
  11. 34 0
      sckw-modules/sckw-contract/src/test/java/com/sckw/contract/service/operateService/KwcContractTradeServiceTest.java
  12. 56 2
      sckw-modules/sckw-order/src/main/java/com/sckw/order/dubbo/TradeOrderInfoServiceImpl.java
  13. 9 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/OrderListResDTO.java
  14. 3 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/TradeOrderListSelectDTO.java
  15. 3 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/req/TradeOrderListSelectParam.java
  16. 19 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/res/OrderDetailRes.java
  17. 8 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/res/OrderListResVO.java
  18. 180 31
      sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderService.java
  19. 9 1
      sckw-modules/sckw-order/src/main/resources/mapper/KwoTradeOrderMapper.xml
  20. 98 0
      sckw-modules/sckw-order/src/test/java/com/sckw/order/serivce/KwoTradeOrderServiceTest.java
  21. 15 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dubbo/TransportServiceImpl.java
  22. 75 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/dto/AddLogisticOrderDTO.java
  23. 10 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/LogisticsOrderResp.java
  24. 5 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/QueryLogisticsOrderReq.java
  25. 5 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/WaybillOrderReq.java
  26. 10 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/WaybillOrderResp.java
  27. 15 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/vo/LogisticsOrderDetailResp.java
  28. 12 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/vo/WaybillOrderDetailResp.java
  29. 19 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/repository/KwtLogisticsOrderUnitRepository.java
  30. 146 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtAcceptCarriageOrderService.java
  31. 358 12
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtLogisticsConsignmentService.java
  32. 402 10
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java
  33. 65 0
      sckw-modules/sckw-transport/src/test/java/com/sckw/transport/service/KwtAcceptCarriageOrderServiceTest.java
  34. 101 0
      sckw-modules/sckw-transport/src/test/java/com/sckw/transport/service/KwtLogisticsConsignmentServiceTest.java
  35. 123 0
      sckw-modules/sckw-transport/src/test/java/com/sckw/transport/service/KwtWaybillOrderV1ServiceTest.java

+ 5 - 0
sckw-modules-api/sckw-contract-api/src/main/java/com/sckw/contract/api/model/vo/TradeContractResDto.java

@@ -92,4 +92,9 @@ public class TradeContractResDto implements Serializable {
      * 计量方式
      */
     private Integer measurementWay;
+
+    /**
+     * 是否代理属性:0-否,1-是。
+     */
+    private Integer agentFlag;
 }

+ 19 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/OrderDetailRes.java

@@ -144,6 +144,25 @@ public class OrderDetailRes implements Serializable {
      * 订单状态
      */
     private Integer status;
+    /**
+     * 是否代理属性:0-否,1-是
+     */
+    private Integer agentFlag;
+    /**
+     * 代理单位ID
+     */
+    private Long agentEntId;
+    /**
+     * 代理单位名称
+     */
+    private String agentFirmName;
+    /**
+     * 代理联系电话
+     */
+    private String agentPhone;
+    private Long supplierEntId;
+    private String supplierFirmName;
+    private String supplierPhone;
 
     /**
      * 订单状态label

+ 19 - 0
sckw-modules-api/sckw-order-api/src/main/java/com/sckw/order/api/model/OrderDetailVo.java

@@ -113,6 +113,25 @@ public class OrderDetailVo implements Serializable {
      * 交易订单状态
      */
     private Integer status;
+    /**
+     * 是否代理属性:0-否,1-是
+     */
+    private Integer agentFlag;
+    /**
+     * 代理单位ID
+     */
+    private Long agentEntId;
+    /**
+     * 代理单位名称
+     */
+    private String agentFirmName;
+    /**
+     * 代理联系电话
+     */
+    private String agentPhone;
+    private Long supplierEntId;
+    private String supplierFirmName;
+    private String supplierPhone;
 
     /**
      * 商品信息

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

@@ -95,6 +95,81 @@ 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;
+
+    /**
+     * 采购单位
+     */
+    private String purchaseCompany;
+
+    /**
+     * 采购单位id
+     */
+    private Long purchaseCompanyId;
+
+    /**
+     * 采购单位联系电话
+     */
+    private String purchaseContactPhone;
+
+    /**
+     * 采购单位联系人
+     */
+    private String purchaseContacts;
+
+    /**
+     * 采购单位联系人id
+     */
+    private Long purchaseContactsId;
+
+    /**
+     * 供应单位
+     */
+    private String supplyCompany;
+
+    /**
+     * 供应单位id
+     */
+    private Long supplyCompanyId;
+
+    /**
+     * 供应单位联系电话
+     */
+    private String supplyContactPhone;
+
+    /**
+     * 供应单位联系人
+     */
+    private String supplyContacts;
+
+    /**
+     * 供应单位联系人id
+     */
+    private Long supplyContactsId;
+
 
 
     /**

+ 6 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/req/QueryListReqVo.java

@@ -117,6 +117,12 @@ public class QueryListReqVo extends PageReq implements Serializable {
     @Schema(description = "供应单位id")
     private String supplyEntId;
 
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private String agentEntId;
+
     /**
      * 派车方式
      */

+ 5 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/req/QueryTradeReq.java

@@ -42,6 +42,11 @@ public class QueryTradeReq extends PageReq implements Serializable {
      */
     @Schema(description = "供应单位id")
     private String supplyEntId;
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private String agentEntId;
     /**
      * 合同状态  0已签约 1已完结 2已保存(草稿) 3签约中
      */

+ 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;
+
     /**
      * 合同编号
      */

+ 12 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/model/vo/res/QueryListResVo.java

@@ -63,6 +63,18 @@ public class QueryListResVo implements Serializable {
     @Schema(description = "供应单位名")
     private String provideEntName;
 
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private String agentEntId;
+
+    /**
+     * 代理单位名
+     */
+    @Schema(description = "代理单位名")
+    private String agentEntName;
+
     /**
      * 托运单位名
      */

+ 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());
+        }
+
     }
 
     /**

+ 290 - 71
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/operateService/KwcContractTradeService.java

@@ -202,6 +202,7 @@ public class KwcContractTradeService {
         queryTradeReq.setSupplementCode(reqVo.getSupplementCode());
         queryTradeReq.setPurchaseEntId(reqVo.getPurchaseEntId());
         queryTradeReq.setSupplyEntId(reqVo.getSupplyEntId());
+        queryTradeReq.setAgentEntId(reqVo.getAgentEntId());
         queryTradeReq.setDispatchWay(reqVo.getDispatchWay());
         queryTradeReq.setStatus(reqVo.getStatus());
         queryTradeReq.setAgentFlag(reqVo.getAgentFlag());
@@ -359,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("合同编号超长!");
             }
@@ -428,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;
@@ -1738,6 +1762,9 @@ public class KwcContractTradeService {
             entIds.add(Long.valueOf(req.getSupplyEntId()));
             //type = CooperateTypeEnum.SUPPLIER.getCode();
         }
+        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAgentEntId())) {
+            entIds.add(Long.valueOf(req.getAgentEntId()));
+        }
         Set<Long> contractIds = buildTradeQueryContractIds(entId, req, entIds);
         if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
             return Collections.emptyList();
@@ -1874,6 +1901,11 @@ public class KwcContractTradeService {
                     .filter(x -> org.apache.commons.lang3.StringUtils.equals(x.getProvideEntId(), req.getSupplyEntId()))
                     .collect(Collectors.toList());
         }
+        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAgentEntId())) {
+            queryListResVos = queryListResVos.stream()
+                    .filter(x -> org.apache.commons.lang3.StringUtils.equals(x.getAgentEntId(), req.getAgentEntId()))
+                    .collect(Collectors.toList());
+        }
         return queryListResVos.stream()
                 .sorted(Comparator.comparing(QueryListResVo::getUpdateTime).reversed()
                         .thenComparing(Comparator.comparing(QueryListResVo::getId).reversed()))
@@ -1959,6 +1991,22 @@ public class KwcContractTradeService {
             log.debug("供应方过滤后剩余合同数量: {} (原数量: {})", contractIds.size(), beforeSize);
         }
 
+        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAgentEntId())) {
+            Long agentEntId = Long.valueOf(req.getAgentEntId());
+            log.debug("应用代理单位过滤条件: agentEntId = {}", agentEntId);
+
+            Set<Long> agentContractIds = units.stream()
+                    .filter(unit -> Objects.equals(unit.getEntId(), agentEntId))
+                    .filter(unit -> Objects.equals(unit.getUnitType(), CooperateTypeEnum.SUPPLIER.getCode()))
+                    .map(KwcContractTradeUnit::getContractId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toSet());
+
+            int beforeSize = contractIds.size();
+            contractIds.retainAll(agentContractIds);
+            log.debug("代理单位过滤后剩余合同数量: {} (原数量: {})", contractIds.size(), beforeSize);
+        }
+
         log.info("最终构建的合同ID集合大小: {}, entId: {}, purchaseEntId: {}, supplyEntId: {}", 
                 contractIds.size(), entId, req.getPurchaseEntId(), req.getSupplyEntId());
         return contractIds;
@@ -1979,6 +2027,9 @@ public class KwcContractTradeService {
         if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
             entIds.add(Long.valueOf(req.getSupplyEntId()));
         }
+        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAgentEntId())) {
+            entIds.add(Long.valueOf(req.getAgentEntId()));
+        }
         Set<Long> contractIds = buildTradeQueryContractIds(entId, req, entIds);
         if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
             return 0L;
@@ -2038,7 +2089,8 @@ public class KwcContractTradeService {
         }
 
         if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())
-                || org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
+                || org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())
+                || org.apache.commons.lang3.StringUtils.isNotBlank(req.getAgentEntId())) {
             Set<Long> tradeContractIds = records.stream().map(KwcContractTrade::getId).collect(Collectors.toSet());
             List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractIds(tradeContractIds);
             Map<String, KwcContractTradeUnit> contractUnitTypeKeyAndUnitMap = Maps.newHashMap();
@@ -2065,6 +2117,14 @@ public class KwcContractTradeService {
                     return org.apache.commons.lang3.StringUtils.equals(String.valueOf(provideEnt.getEntId()), req.getSupplyEntId());
                 }).collect(Collectors.toList());
             }
+            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAgentEntId())) {
+                records = records.stream().filter(record -> {
+                    KwcContractTradeUnit provideEnt =
+                            finalContractUnitTypeKeyAndUnitMap.getOrDefault(record.getId() + "-" + CooperateTypeEnum.SUPPLIER.getCode(),
+                                    new KwcContractTradeUnit());
+                    return org.apache.commons.lang3.StringUtils.equals(String.valueOf(provideEnt.getEntId()), req.getAgentEntId());
+                }).collect(Collectors.toList());
+            }
         }
         return records.size();
     }
@@ -2123,6 +2183,10 @@ public class KwcContractTradeService {
                         new KwcContractTradeUnit());
         queryListResVo.setProvideEntId(String.valueOf(provideEnt.getEntId()));
         queryListResVo.setProvideEntName(provideEnt.getFirmName());
+        if (Objects.equals(t.getAgentFlag(), Global.YES)) {
+            queryListResVo.setAgentEntId(String.valueOf(provideEnt.getEntId()));
+            queryListResVo.setAgentEntName(provideEnt.getFirmName());
+        }
         //queryListResVo.setCheckedEntName();
         queryListResVo.setContractNo(t.getContractNo());
         queryListResVo.setContractName(t.getName());
@@ -2191,72 +2255,133 @@ public class KwcContractTradeService {
     }
 
 
+    /**
+     * 查询符合条件的物流合同订单列表。
+     * <p>
+     * 主要逻辑:
+     * 1. 校验入参(商品ID、托运方企业ID)。
+     * 2. 根据托运方企业ID查询其关联的物流合同单位,获取合同ID集合。
+     * 3. 根据商品ID筛选出包含该商品的物流合同ID集合(用于后续过滤非通用价格合同)。
+     * 4. 查询物流合同主表信息,并进行过滤:
+     *    - 保留“指定商品关联的合同”或“拥有通用价格的合同”。
+     *    - 状态必须为“已签约”。
+     *    - 当前时间必须在合同有效期内(处理结束时间为空的情况,视为永久有效)。
+     * 5. 组装返回结果,填充托运方、承运方信息及商品价格(优先使用特定商品价格,其次使用通用价格)。
+     * 6. 特殊处理:如果传入了贸易合同ID,且该贸易合同满足“买家托运”且“按装货量结算”的条件,则在结果列表首位插入一条“平台默认物流”记录。
+     * </p>
+     *
+     * @param logisticsOrderDto 查询条件DTO,包含 goodsId, entId, tradeContractId
+     * @return 物流合同订单响应列表
+     */
     public List<ContractLogisticsOrderResDto> queryContractLogisticsOrder(LogisticsOrderDto logisticsOrderDto) {
-        log.info("查询物流合同请求:{}", JSON.toJSONString(logisticsOrderDto));
+        log.info("开始查询物流合同订单,请求参数:{}", JSON.toJSONString(logisticsOrderDto));
 
+        // 1. 参数校验
         if (Objects.isNull(logisticsOrderDto.getGoodsId())) {
+            log.warn("查询物流合同订单失败:商品ID为空");
             throw new BusinessException("商品id不能为空!");
         }
         if (Objects.isNull(logisticsOrderDto.getEntId())) {
+            log.warn("查询物流合同订单失败:托运方企业ID为空");
             throw new BusinessException("托运方企业id不能为空!");
         }
-        //通过托运企业查询物流公司
-        List<KwcContractLogisticsUnit> contractLogistics =
+
+        // 2. 根据托运方企业ID查询关联的物流合同单位
+        List<KwcContractLogisticsUnit> contractLogisticsUnits =
                 kwcContractLogisticsUnitRepository.queryByEntId(logisticsOrderDto.getEntId());
-        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractLogistics)) {
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractLogisticsUnits)) {
+            log.debug("未找到企业[{}]关联的物流合同单位,返回空列表", logisticsOrderDto.getEntId());
             return Collections.emptyList();
         }
-        //物流订单合id
-        Set<Long> logTradeContractIds = contractLogistics.stream()
-                .map(KwcContractLogisticsUnit::getContractId).collect(Collectors.toSet());
-
-        //查询商品信息
-        List<KwcContractLogisticsGoods> kwcContractLogisticsGoods = kwcContractLogisticsGoodsRepository.queryByLogIdsAndGoodsId(logTradeContractIds,
-                logisticsOrderDto.getGoodsId());
+        
+        // 提取物流合同ID集合
+        Set<Long> logTradeContractIds = contractLogisticsUnits.stream()
+                .map(KwcContractLogisticsUnit::getContractId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        log.debug("企业[{}]关联的物流合同ID数量: {}", logisticsOrderDto.getEntId(), logTradeContractIds.size());
+
+        // 3. 根据商品ID筛选包含该商品的物流合同
+        // 目的:识别哪些合同是明确约定了该商品价格的,这些合同即使没有设置通用价格也应被保留
+        List<KwcContractLogisticsGoods> kwcContractLogisticsGoods = kwcContractLogisticsGoodsRepository.queryByLogIdsAndGoodsId(
+                logTradeContractIds,
+                logisticsOrderDto.getGoodsId()
+        );
+        log.debug("包含商品ID[{}]的物流合同数量: {}", logisticsOrderDto.getGoodsId(), kwcContractLogisticsGoods.size());
         Map<Long, KwcContractLogisticsGoods> contractLogisticsGoodsMap = Maps.newHashMap();
         Set<Long> goodsContractIds = new HashSet<>();
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwcContractLogisticsGoods)) {
+            // 构建合同ID -> 商品信息的映射
             contractLogisticsGoodsMap = kwcContractLogisticsGoods.stream()
-                    .collect(Collectors.toMap(KwcContractLogisticsGoods::getContractId,
-                            Function.identity(), (x, y) -> x));
+                    .collect(Collectors.toMap(KwcContractLogisticsGoods::getContractId, Function.identity(), (x, y) -> x));
+            // 提取包含该商品的合同ID集合
             goodsContractIds = kwcContractLogisticsGoods.stream()
                     .map(KwcContractLogisticsGoods::getContractId)
                     .collect(Collectors.toSet());
+            log.debug("包含商品ID[{}]的物流合同数量: {}", logisticsOrderDto.getGoodsId(), goodsContractIds.size());
         }
 
-        //查询物流订单  如果是通用价格不为空的不能过滤掉
+        // 4. 查询物流合同主表信息
         List<KwcContractLogistics> logistics = contractLogisticsRepository.queryByLogisticContractIds(logTradeContractIds);
+        if (CollectionUtils.isEmpty(logistics)) {
+            log.debug("未查询到任何物流合同主表信息,返回空列表");
+            return Collections.emptyList();
+        }
+
+        // 5. 初步过滤合同:
+        // 规则:合同必须包含指定商品(在 goodsContractIds 中) 或者 合同设置了通用价格(commonPrice 不为空)
         Set<Long> finalGoodsContractIds = goodsContractIds;
-        logistics = logistics.stream().filter(x-> finalGoodsContractIds.contains(x.getId()) || Objects.nonNull(x.getCommonPrice()))
-                .distinct().collect(Collectors.toList());
+        logistics = logistics.stream()
+                .filter(x -> finalGoodsContractIds.contains(x.getId()) || Objects.nonNull(x.getCommonPrice()))
+                .distinct()
+                .collect(Collectors.toList());
+        
         if (CollectionUtils.isEmpty(logistics)) {
+            log.debug("经过商品/通用价格过滤后,剩余物流合同数量为0,返回空列表");
             return Collections.emptyList();
         }
+        log.debug("经过商品/通用价格过滤后,剩余物流合同数量: {}", logistics.size());
+
+        // 6. 进一步过滤:状态校验与有效期校验
         Date date = new Date();
         logistics = logistics.stream()
                 .peek(log -> {
+                    // 如果结束时间为空,视为永久有效,设置为一个极大的日期以便后续比较
                     if (Objects.isNull(log.getEndTime())) {
                         LocalDate localDate = LocalDate.of(9999, 12, 30);
-                        Date date1 = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
-                        log.setEndTime(date1);
+                        Date maxDate = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+                        log.setEndTime(maxDate);
                     }
                 })
                 .filter(log -> Objects.nonNull(log.getStartTime()) && Objects.nonNull(log.getEndTime()))
-                .filter(log -> Objects.equals(log.getStatus(), ContractStatusEnum.SIGNED.getCode())
-                        && log.getStartTime().before(date) && log.getEndTime().after(date))
+                .filter(log -> 
+                    // 状态必须为已签约
+                    Objects.equals(log.getStatus(), ContractStatusEnum.SIGNED.getCode())
+                    // 当前时间必须在开始时间之后(或等于)
+                    && !log.getStartTime().after(date) && !log.getEndTime().before(date)
+                )
                 .collect(Collectors.toList());
+
         if (CollectionUtils.isEmpty(logistics)) {
+            log.debug("经过状态和有效期过滤后,剩余物流合同数量为0,返回空列表");
             return Collections.emptyList();
         }
-        //查询企业
+        log.debug("经过状态和有效期过滤后,最终符合条件的物流合同数量: {}", logistics.size());
+
+        // 7. 查询合同关联的单位信息(托运方、承运方等)
         List<KwcContractLogisticsUnit> units = kwcContractLogisticsUnitRepository.queryByContractIds(logTradeContractIds);
-        //物流订单和类型组成唯一key
         Map<String, KwcContractLogisticsUnit> contractLogisticsMap = Maps.newHashMap();
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
+            // Key格式: contractId_unitType
             contractLogisticsMap = units.stream()
-                    .collect(Collectors.toMap(c -> c.getContractId() + "_" + c.getUnitType(),
-                            Function.identity(), (x, y) -> x));
+                    .collect(Collectors.toMap(
+                            c -> c.getContractId() + "_" + c.getUnitType(),
+                            Function.identity(),
+                            (x, y) -> x // 冲突时保留第一个
+                    ));
         }
+
+        // 8. 组装返回结果
         Map<String, KwcContractLogisticsUnit> finalContractLogisticsMap = contractLogisticsMap;
         Map<Long, KwcContractLogisticsGoods> finalContractLogisticsGoodsMap = contractLogisticsGoodsMap;
         List<ContractLogisticsOrderResDto> collect = logistics.stream()
@@ -2325,63 +2450,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();
+        }
+
+        // 提取这些单位关联的所有合同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();
         }
-        Set<Long> contractIds =
-                tradeUnits.stream().map(KwcContractTradeUnit::getContractId).collect(Collectors.toSet());
+        log.debug("初步筛选出的合同ID数量: {}", contractIds.size());
 
-        List<KwcContractTradeUnit> tradeUnits1 = kwcContractTradeUnitRepository.queryByContractIds(contractIds);
-        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeUnits1)) {
+        // 3. 批量查询这些合同的所有单位信息,用于后续构建返回对象中的企业名称等字段
+        List<KwcContractTradeUnit> allTradeUnits = kwcContractTradeUnitRepository.queryByContractIds(contractIds);
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(allTradeUnits)) {
+            log.warn("根据合同ID集合查询合同单位信息为空,contractIds: {}", contractIds);
             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: {}",
+
+        // 构建映射: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());
-            // 调用专用方法查询当前登录用户作为销售员且已签约的贸易合同信息
-            return querySalesmanSignedTradeOrder(contractTradeOrderDto, contractIds, conTractTradeUnitMap);
-        }
-        contractIds = tradeUnits1.stream()
-                .filter(x -> Objects.equals(x.getEntId(), LoginUserHolder.getEntId()) && Objects.equals(x.getUnitType(),
-                        2))
+            
+            // 调用专用方法,内部会过滤 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();
+        }
+        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();
         }
-        kwcContractTrades = kwcContractTrades.stream()
-                .filter(x -> Objects.equals(x.getStatus(), ContractStatusEnum.SIGNED.getCode()))
+
+        // 双重保险:再次在内存中过滤状态,确保数据一致性
+        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;
     }
 
 
@@ -2449,14 +2668,14 @@ public class KwcContractTradeService {
         //    - 组装返回对象:利用之前构建的 map 填充详细信息
         List<ContractTradeOrderInfo> result = kwcContractTrades.stream()
                 .filter(trade -> Objects.equals(trade.getStatus(), ContractStatusEnum.SIGNED.getCode()))
-//                .filter(trade -> {
-//                    boolean isMySale = Objects.equals(trade.getSalesmanId(), currentUserId);
-//                    if (!isMySale) {
-//                        log.trace("合同ID: {} 被过滤,因为销售员ID: {} 不匹配当前用户: {}",
-//                                trade.getId(), trade.getSalesmanId(), currentUserId);
-//                    }
-//                    return isMySale;
-//                })
+                .filter(trade -> {
+                    boolean isMySale = Objects.equals(trade.getSalesmanId(), currentUserId);
+                    if (!isMySale) {
+                        log.trace("合同ID: {} 被过滤,因为销售员ID: {} 不匹配当前用户: {}",
+                                trade.getId(), trade.getSalesmanId(), currentUserId);
+                    }
+                    return isMySale;
+                })
                 .map(trade -> getContractTradeOrderInfo(trade, conTractTradeUnitMap, contractTradeOrderDto.getEntType(), contractGoodsMap))
                 .collect(Collectors.toList());
 

+ 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);
+    }
 }

+ 56 - 2
sckw-modules/sckw-order/src/main/java/com/sckw/order/dubbo/TradeOrderInfoServiceImpl.java

@@ -86,6 +86,11 @@ public class TradeOrderInfoServiceImpl implements TradeOrderInfoService {
     @Override
     public OrderDetailRes getOrderDetailById(Long tOrderId) {
         OrderDetailRes order = BeanUtil.copyProperties(kwoTradeOrderService.detail(tOrderId), OrderDetailRes.class);
+        KwoTradeOrder tradeOrder = kwoTradeOrderRepository.queryByTradeOrderId(tOrderId);
+        if (Objects.nonNull(tradeOrder)) {
+            order.setAgentFlag(tradeOrder.getAgentFlag());
+        }
+        populateSupplierAndAgentInfo(order);
         BigDecimal actualPrice = Objects.isNull(order.getActualAmount()) || Objects.isNull(order.getGoodsInfo()) || Objects.isNull(order.getGoodsInfo().getUnitPrice()) ? BigDecimal.ZERO : order.getActualAmount().multiply(order.getGoodsInfo().getUnitPrice()).setScale(2, RoundingMode.HALF_UP);
         order.setActualPrice(actualPrice);
         return order;
@@ -503,6 +508,7 @@ public class TradeOrderInfoServiceImpl implements TradeOrderInfoService {
         orderDetailRes.setChargeType(kwoTradeOrder.getChargeType());
         orderDetailRes.setConsignmentWay(kwoTradeOrder.getConsignmentWay());
         orderDetailRes.setStatus(kwoTradeOrder.getStatus());
+        orderDetailRes.setAgentFlag(kwoTradeOrder.getAgentFlag());
 
         if (Objects.nonNull(kwoTradeOrderGoods)) {
             OrderDetailVo.GoodsInfo goodsInfo = new OrderDetailVo.GoodsInfo();
@@ -533,6 +539,7 @@ public class TradeOrderInfoServiceImpl implements TradeOrderInfoService {
                 return unitInfo;
             }).collect(Collectors.toList()));
         }
+        populateSupplierAndAgentInfo(orderDetailRes, kwoTradeOrderUnits);
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwoTradeOrderAddresses)) {
             List<OrderDetailVo.AddressInfo> addressInfos = kwoTradeOrderAddresses.stream().map(a -> {
                 OrderDetailVo.AddressInfo addressInfo = new OrderDetailVo.AddressInfo();
@@ -573,11 +580,16 @@ public class TradeOrderInfoServiceImpl implements TradeOrderInfoService {
             return List.of();
         }
 
-        return kwoTradeOrders.stream().map(TradeOrderInfoServiceImpl::getOrderDetailVo).collect(Collectors.toList());
+        Map<Long, List<KwoTradeOrderUnit>> unitMap = kwoTradeOrderUnitRepository.queryByOrderIds(tradeOrderIds)
+                .stream()
+                .collect(Collectors.groupingBy(KwoTradeOrderUnit::getTOrderId));
+        return kwoTradeOrders.stream()
+                .map(order -> getOrderDetailVo(order, unitMap.getOrDefault(order.getId(), Collections.emptyList())))
+                .collect(Collectors.toList());
     }
 
     @NotNull
-    private static OrderDetailVo getOrderDetailVo(KwoTradeOrder x) {
+    private static OrderDetailVo getOrderDetailVo(KwoTradeOrder x, List<KwoTradeOrderUnit> units) {
         OrderDetailVo orderDetailVo = new OrderDetailVo();
         orderDetailVo.setEntId(x.getEntId());
         orderDetailVo.setId(x.getId());
@@ -597,9 +609,51 @@ public class TradeOrderInfoServiceImpl implements TradeOrderInfoService {
         orderDetailVo.setChargeType(x.getChargeType());
         orderDetailVo.setConsignmentWay(x.getConsignmentWay());
         orderDetailVo.setStatus(x.getStatus());
+        orderDetailVo.setAgentFlag(x.getAgentFlag());
+        populateSupplierAndAgentInfo(orderDetailVo, units);
         return orderDetailVo;
     }
 
+    private static void populateSupplierAndAgentInfo(OrderDetailRes order) {
+        if (Objects.isNull(order) || CollectionUtils.isEmpty(order.getUnitInfo())) {
+            return;
+        }
+        order.getUnitInfo().stream()
+                .filter(Objects::nonNull)
+                .filter(unit -> String.valueOf(NumberConstant.TWO).equals(unit.getUnitType()))
+                .findFirst()
+                .ifPresent(unit -> {
+                    order.setSupplierEntId(unit.getEntId());
+                    order.setSupplierFirmName(unit.getFirmName());
+                    order.setSupplierPhone(unit.getPhone());
+                    if (Objects.equals(order.getAgentFlag(), NumberConstant.ONE)) {
+                        order.setAgentEntId(unit.getEntId());
+                        order.setAgentFirmName(unit.getFirmName());
+                        order.setAgentPhone(unit.getPhone());
+                    }
+                });
+    }
+
+    private static void populateSupplierAndAgentInfo(OrderDetailVo order, List<KwoTradeOrderUnit> units) {
+        if (Objects.isNull(order) || CollectionUtils.isEmpty(units)) {
+            return;
+        }
+        units.stream()
+                .filter(Objects::nonNull)
+                .filter(unit -> String.valueOf(NumberConstant.TWO).equals(unit.getUnitType()))
+                .findFirst()
+                .ifPresent(unit -> {
+                    order.setSupplierEntId(unit.getEntId());
+                    order.setSupplierFirmName(unit.getFirmName());
+                    order.setSupplierPhone(unit.getPhone());
+                    if (Objects.equals(order.getAgentFlag(), NumberConstant.ONE)) {
+                        order.setAgentEntId(unit.getEntId());
+                        order.setAgentFirmName(unit.getFirmName());
+                        order.setAgentPhone(unit.getPhone());
+                    }
+                });
+    }
+
 
     @Override
     public void orderSettle(TradeOrderSettlePara tradeOrderSettlePara) {

+ 9 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/OrderListResDTO.java

@@ -55,6 +55,15 @@ public class OrderListResDTO {
      * 销售单位
      */
     private String supplyFirmName;
+
+    /**
+     * 代理单位ID
+     */
+    private Long agentEntId;
+    /**
+     * 代理单位
+     */
+    private String agentFirmName;
     /**
      * 交易方式(预付款、货到付款)
      */

+ 3 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/dto/TradeOrderListSelectDTO.java

@@ -117,6 +117,9 @@ public class TradeOrderListSelectDTO {
     @Schema(description = "采购单位")
     private Long buyEntId;
 
+    @Schema(description = "代理单位")
+    private Long agentEntId;
+
     @Schema(description = "承运单位")
     private Long transportEntId;
     @Schema(description = "贸易合同")

+ 3 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/req/TradeOrderListSelectParam.java

@@ -31,6 +31,9 @@ public class TradeOrderListSelectParam extends TradeOrderListStatisticParam {
     @Schema(description = "供应单位")
     private Long buyEntId;
 
+    @Schema(description = "代理单位")
+    private Long agentEntId;
+
     @Schema(description = "承运单位")
     private Long transportEntId;
 

+ 19 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/res/OrderDetailRes.java

@@ -170,6 +170,25 @@ public class OrderDetailRes implements Serializable {
      * 订单状态
      */
     private Integer status;
+    /**
+     * 是否代理属性:0-否,1-是
+     */
+    private Integer agentFlag;
+    /**
+     * 代理单位ID
+     */
+    private Long agentEntId;
+    /**
+     * 代理单位名称
+     */
+    private String agentFirmName;
+    /**
+     * 代理联系电话
+     */
+    private String agentPhone;
+    private Long supplierEntId;
+    private String supplierFirmName;
+    private String supplierPhone;
 
     /**
      * 订单状态label

+ 8 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/res/OrderListResVO.java

@@ -58,6 +58,14 @@ public class OrderListResVO {
      * 销售单位
      */
     private String supplyFirmName;
+    /**
+     * 代理单位主键ID
+     */
+    private Long agentEntId;
+    /**
+     * 代理单位
+     */
+    private String agentFirmName;
     /**
      * 交易方式(预付款、货到付款)
      */

+ 180 - 31
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;
@@ -809,6 +813,7 @@ public class KwoTradeOrderService {
                 unitInfos.add(unit);
             });
             detail.setUnitInfo(unitInfos);
+            populateAgentUnitInfo(detail, unitInfos);
         }
         //地址信息
         List<KwoTradeOrderAddress> addressList = kwoTradeOrderAddressService.getByOrderId(id);
@@ -905,6 +910,50 @@ public class KwoTradeOrderService {
         return detail;
     }
 
+    /**
+     * 填充订单详情中的供应商及代理单位信息。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 校验入参有效性,若订单详情对象为空或单位列表为空,则直接返回。
+     * 2. 从单位列表中筛选出类型为“供应方”(unitType="2")的单位记录。
+     * 3. 将首个匹配的供应方单位信息填充至订单详情的供应商字段(供应商ID、名称、电话)。
+     * 4. 若订单标记为代理订单(agentFlag=1),则将同样的供应方单位信息同时填充至代理字段(代理ID、名称、电话)。
+     * <p>
+     * 注意:该方法为静态私有方法,仅用于内部数据组装,不涉及数据库操作或远程调用。
+     *
+     * @param detail   订单详情响应对象,用于接收填充后的数据
+     * @param unitInfos 订单关联的单位信息列表
+     */
+    private static void populateAgentUnitInfo(OrderDetailRes detail, List<UnitInfoDetailRes> unitInfos) {
+        // 参数预校验:确保订单详情对象和单位列表非空,避免后续处理出现空指针异常
+        if (Objects.isNull(detail) || CollUtil.isEmpty(unitInfos)) {
+            log.debug("填充代理单位信息跳过:detail为空或unitInfos为空");
+            return;
+        }
+
+        // 流式处理:过滤非空单位 -> 筛选供应方类型(unitType="2") -> 获取第一个匹配项
+        unitInfos.stream()
+                .filter(Objects::nonNull)
+                .filter(unit -> String.valueOf(NumberConstant.TWO).equals(unit.getUnitType()))
+                .findFirst()
+                .ifPresent(unit -> {
+                    log.debug("找到供应方单位信息,entId={}, firmName={}", unit.getEntId(), unit.getFirmName());
+
+                    // 设置基础供应商信息
+                    detail.setSupplierEntId(unit.getEntId());
+                    detail.setSupplierFirmName(unit.getFirmName());
+                    detail.setSupplierPhone(unit.getPhone());
+
+                    // 若为代理订单,则同时设置代理信息(通常代理即为供应方)
+                    if (Objects.equals(detail.getAgentFlag(), Global.YES)) {
+                        log.debug("订单为代理订单,同步设置代理单位信息");
+                        detail.setAgentEntId(unit.getEntId());
+                        detail.setAgentFirmName(unit.getFirmName());
+                        detail.setAgentPhone(unit.getPhone());
+                    }
+                });
+    }
+
     /**
      * @desc: 修改订单
      * @author: yzc
@@ -1844,6 +1893,7 @@ public class KwoTradeOrderService {
      */
     public TradeOrderListSelectDTO buildSelectParam(TradeOrderListStatisticParam params) {
         TradeOrderListSelectDTO dto = BeanUtil.copyProperties(params, TradeOrderListSelectDTO.class);
+        applyAgentEntCondition(dto);
         EntTypeResDto entTypeResDto = remoteSystemService.queryEntTypeById(LoginUserHolder.getEntId());
         dto.setEntId(LoginUserHolder.getEntId()).setManager(LoginUserHolder.isManager()).setEntType(Objects.nonNull(entTypeResDto) ? entTypeResDto.getType() : null).setEntList(LoginUserHolder.getChildEntList()).setIsMain(LoginUserHolder.getIsMain());
         //装卸货地址
@@ -1892,6 +1942,18 @@ public class KwoTradeOrderService {
         dto.setKeywords(null);
     }
 
+    /**
+     * 代理单位查询条件存在时,仅查询具备代理属性的订单。
+     *
+     * @param dto 贸易订单列表查询DTO
+     */
+    static void applyAgentEntCondition(TradeOrderListSelectDTO dto) {
+        if (Objects.isNull(dto) || Objects.isNull(dto.getAgentEntId())) {
+            return;
+        }
+        dto.setAgentFlag(Global.YES);
+    }
+
     /**
      * @desc: 设置两位小数
      * @author: yzc
@@ -2262,13 +2324,12 @@ public class KwoTradeOrderService {
      * <p>
      * 逻辑说明:
      * 1. 校验贸易合同ID是否为空。
-     * 2. 调用远程服务查询该合同下的所有单位信息。
-     * 3. 筛选出类型为“供应方”(unitType="1")的单位,并获取其企业ID。
-     * 4. 根据供应方企业ID,进一步查询该企业是否具备“代理”属性。
+     * 2. 查询贸易合同自身的代理属性标识。
+     * 3. 贸易订单代理属性跟随贸易合同标识,不再根据合同企业类型二次判断。
      *
      * @param tradeContractId 贸易合同ID
      * @return 代理属性标识:1-是代理,0-非代理
-     * @throws BusinessException 当合同ID为空、未找到供应单位或查询过程异常时抛出
+     * @throws BusinessException 当合同ID为空、合同不存在或查询过程异常时抛出
      */
     private Integer queryOrderAgentFlag(Long tradeContractId) {
         // 参数校验:贸易合同ID不能为空
@@ -2277,33 +2338,15 @@ public class KwoTradeOrderService {
         }
 
         try {
-            // 记录开始查询日志
-            log.debug("开始查询贸易合同代理属性,tradeContractId={}", tradeContractId);
-
-            // 1. 调用远程服务获取合同关联的单位列表
-            List<TradeContractUnitDto> unitList = remoteContractService.queryContractUnitByContractId(tradeContractId);
+            log.debug("开始查询贸易合同代理标识,tradeContractId={}", tradeContractId);
+            TradeContractResDto tradeContract = remoteContractService.queryTradeContract(tradeContractId, null);
+            if (Objects.isNull(tradeContract)) {
+                log.warn("贸易合同不存在,tradeContractId={}", tradeContractId);
+                throw new BusinessException("贸易合同不存在");
+            }
+            Integer agentFlag = normalizeContractAgentFlag(tradeContract.getAgentFlag());
 
-            // 2. 从单位列表中筛选出供应方(unitType="1")的企业ID
-            Long supplyEntId = Optional.ofNullable(unitList)
-                    .orElseGet(Collections::emptyList)
-                    .stream()
-                    .filter(Objects::nonNull)
-                    // 过滤出单位类型为供应方的记录 (假设 "1" 代表供应方)
-                    .filter(item -> StrUtil.equals("1", item.getUnitType()))
-                    .map(TradeContractUnitDto::getEntId)
-                    .filter(Objects::nonNull)
-                    .findFirst()
-                    .orElseThrow(() -> {
-                        log.warn("贸易合同中未找到有效的供应单位,tradeContractId={}", tradeContractId);
-                        return new BusinessException("贸易合同供应单位不存在");
-                    });
-
-            log.debug("找到供应单位ID,supplyEntId={},准备查询代理属性", supplyEntId);
-
-            // 3. 根据供应方企业ID查询其是否具备代理属性
-            Integer agentFlag = querySupplyAgentFlag(supplyEntId);
-
-            log.debug("贸易合同代理属性查询完成,tradeContractId={}, agentFlag={}", tradeContractId, agentFlag);
+            log.debug("贸易合同代理标识查询完成,tradeContractId={}, agentFlag={}", tradeContractId, agentFlag);
             return agentFlag;
 
         } catch (Exception e) {
@@ -2313,6 +2356,16 @@ public class KwoTradeOrderService {
         }
     }
 
+    /**
+     * 归一化贸易合同代理标识。
+     *
+     * @param agentFlag 贸易合同代理标识
+     * @return 1-代理,0-非代理
+     */
+    static Integer normalizeContractAgentFlag(Integer agentFlag) {
+        return Objects.equals(agentFlag, Global.YES) ? Global.YES : Global.NO;
+    }
+
 
     /**
      * 查询供应单位企业类型,判断是否包含代理属性。
@@ -2596,7 +2649,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());
@@ -2628,6 +2681,98 @@ 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());
+    }
+
+    /**
+     * 创建物流订单时同步传递贸易订单采购单位和供应单位。
+     *
+     * @param param   物流订单新增参数
+     * @param unitMap 贸易订单企业类型映射
+     */
+    static void setTradeCompanyInfo(AddLogisticOrderParam param, Map<String, KwoTradeOrderUnit> unitMap) {
+        if (Objects.isNull(param) || CollUtil.isEmpty(unitMap)) {
+            return;
+        }
+        KwoTradeOrderUnit purchaseUnit = unitMap.get("1");
+        if (Objects.nonNull(purchaseUnit)) {
+            param.setPurchaseCompany(purchaseUnit.getFirmName());
+            param.setPurchaseCompanyId(purchaseUnit.getEntId());
+            param.setPurchaseContactPhone(purchaseUnit.getPhone());
+            param.setPurchaseContacts(purchaseUnit.getContacts());
+            param.setPurchaseContactsId(purchaseUnit.getContactsId());
+        }
+        KwoTradeOrderUnit supplyUnit = unitMap.get("2");
+        if (Objects.nonNull(supplyUnit)) {
+            param.setSupplyCompany(supplyUnit.getFirmName());
+            param.setSupplyCompanyId(supplyUnit.getEntId());
+            param.setSupplyContactPhone(supplyUnit.getPhone());
+            param.setSupplyContacts(supplyUnit.getContacts());
+            param.setSupplyContactsId(supplyUnit.getContactsId());
+        }
+    }
+
     /**
      * 买家撤销贸易订单
      */
@@ -3074,6 +3219,8 @@ public class KwoTradeOrderService {
         addLogisticOrderParam.setUserId(LoginUserHolder.getUserId());
         addLogisticOrderParam.setMeasurementWay(tradeContractResDto.getMeasurementWay());
         addLogisticOrderParam.setAgentFlag(kwoTradeOrder.getAgentFlag());
+        setAgentCompanyInfo(addLogisticOrderParam, unitMap, kwoTradeOrder.getAgentFlag());
+        setTradeCompanyInfo(addLogisticOrderParam, unitMap);
         log.info("创建物流订单:{}", JSONObject.toJSONString(addLogisticOrderParam));
         Integer result = transportRemoteService.addLogisticOrder(addLogisticOrderParam);
         //自动派单运力不足
@@ -3522,6 +3669,8 @@ public class KwoTradeOrderService {
         addLogisticOrderParam.setUserId(LoginUserHolder.getUserId());
         addLogisticOrderParam.setDispatchWay(DispatchWayEnums.MANUAL_DISPATCH.getCode());
         addLogisticOrderParam.setAgentFlag(kwoTradeOrder.getAgentFlag());
+        setAgentCompanyInfo(addLogisticOrderParam, unitMap, kwoTradeOrder.getAgentFlag());
+        setTradeCompanyInfo(addLogisticOrderParam, unitMap);
         log.info("创建物流订单:{}", JSONObject.toJSONString(addLogisticOrderParam));
         transportRemoteService.addLogisticOrder(addLogisticOrderParam);
 

+ 9 - 1
sckw-modules/sckw-order/src/main/resources/mapper/KwoTradeOrderMapper.xml

@@ -9,6 +9,8 @@
         <result column="procureFirmName" property="procureFirmName"/>
         <result column="supplyEntId" property="supplyEntId"/>
         <result column="supplyFirmName" property="supplyFirmName"/>
+        <result column="agentEntId" property="agentEntId"/>
+        <result column="agentFirmName" property="agentFirmName"/>
         <result column="trading" property="trading"/>
         <result column="deliveryType" property="deliveryType"/>
         <result column="pickupType" property="pickupType"/>
@@ -55,6 +57,8 @@
         d.firm_name      AS procureFirmName,
         e.ent_id         AS supplyEntId,
         e.firm_name      AS supplyFirmName,
+        if(a.agent_flag = 1, e.ent_id, null) AS agentEntId,
+        if(a.agent_flag = 1, e.firm_name, null) AS agentFirmName,
         a.trading        AS trading,
         a.delivery_type  AS deliveryType,
         a.pickup_type    AS pickupType,
@@ -172,9 +176,13 @@
             <if test="query.saleEntId != null">
                 and e.ent_id = #{query.saleEntId}
             </if>
-            <if test="query.agentFlag != null">
+            <if test="query.agentFlag != null and query.agentEntId == null">
                 and a.agent_flag = #{query.agentFlag}
             </if>
+            <if test="query.agentEntId != null">
+                and a.agent_flag = 1
+                and e.ent_id = #{query.agentEntId}
+            </if>
             <if test="query.status != null">
                 and a.status = #{query.status}
             </if>

+ 98 - 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;
 
 /**
@@ -122,4 +126,98 @@ public class KwoTradeOrderServiceTest {
         Assert.assertNull(dto.getAgentFlag());
         Assert.assertEquals("钢材", dto.getKeywords());
     }
+
+    /**
+     * 代理单位条件存在时,应自动转换为代理属性过滤。
+     */
+    @Test
+    public void applyAgentEntConditionWhenAgentEntIdExists() {
+        TradeOrderListSelectDTO dto = new TradeOrderListSelectDTO();
+        dto.setAgentEntId(1001L);
+        dto.setAgentFlag(0);
+
+        KwoTradeOrderService.applyAgentEntCondition(dto);
+
+        Assert.assertEquals(Integer.valueOf(1), dto.getAgentFlag());
+    }
+
+    /**
+     * 贸易订单代理属性应跟随贸易合同代理标识。
+     */
+    @Test
+    public void normalizeContractAgentFlagOnlyYesMeansAgent() {
+        Assert.assertEquals(Integer.valueOf(1), KwoTradeOrderService.normalizeContractAgentFlag(1));
+        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());
+    }
+
+    /**
+     * Trade order purchase and supply units should be passed to logistics order param.
+     */
+    @Test
+    public void setTradeCompanyInfoWhenPurchaseAndSupplyExist() {
+        AddLogisticOrderParam param = new AddLogisticOrderParam();
+        KwoTradeOrderUnit purchaseUnit = new KwoTradeOrderUnit();
+        purchaseUnit.setFirmName("Purchase Company");
+        purchaseUnit.setEntId(1001L);
+        purchaseUnit.setPhone("13700000000");
+        purchaseUnit.setContacts("Bob");
+        purchaseUnit.setContactsId(8001L);
+        KwoTradeOrderUnit supplyUnit = new KwoTradeOrderUnit();
+        supplyUnit.setFirmName("Supply Company");
+        supplyUnit.setEntId(2001L);
+        supplyUnit.setPhone("13600000000");
+        supplyUnit.setContacts("Carol");
+        supplyUnit.setContactsId(7001L);
+        Map<String, KwoTradeOrderUnit> unitMap = new HashMap<>();
+        unitMap.put("1", purchaseUnit);
+        unitMap.put("2", supplyUnit);
+
+        KwoTradeOrderService.setTradeCompanyInfo(param, unitMap);
+
+        Assert.assertEquals("Purchase Company", param.getPurchaseCompany());
+        Assert.assertEquals(Long.valueOf(1001L), param.getPurchaseCompanyId());
+        Assert.assertEquals("13700000000", param.getPurchaseContactPhone());
+        Assert.assertEquals("Bob", param.getPurchaseContacts());
+        Assert.assertEquals(Long.valueOf(8001L), param.getPurchaseContactsId());
+        Assert.assertEquals("Supply Company", param.getSupplyCompany());
+        Assert.assertEquals(Long.valueOf(2001L), param.getSupplyCompanyId());
+        Assert.assertEquals("13600000000", param.getSupplyContactPhone());
+        Assert.assertEquals("Carol", param.getSupplyContacts());
+        Assert.assertEquals(Long.valueOf(7001L), param.getSupplyContactsId());
+    }
 }

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

@@ -1302,6 +1302,21 @@ 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.setPurchaseCompany(param.getPurchaseCompany());
+        addLogisticOrderDTO.setPurchaseCompanyId(param.getPurchaseCompanyId());
+        addLogisticOrderDTO.setPurchaseContactPhone(param.getPurchaseContactPhone());
+        addLogisticOrderDTO.setPurchaseContacts(param.getPurchaseContacts());
+        addLogisticOrderDTO.setPurchaseContactsId(param.getPurchaseContactsId());
+        addLogisticOrderDTO.setSupplyCompany(param.getSupplyCompany());
+        addLogisticOrderDTO.setSupplyCompanyId(param.getSupplyCompanyId());
+        addLogisticOrderDTO.setSupplyContactPhone(param.getSupplyContactPhone());
+        addLogisticOrderDTO.setSupplyContacts(param.getSupplyContacts());
+        addLogisticOrderDTO.setSupplyContactsId(param.getSupplyContactsId());
         addLogisticOrderDTO.setGoodsId(param.getGoodsId());
         addLogisticOrderDTO.setGoodsName(param.getGoodsName());
         addLogisticOrderDTO.setGoodsType(param.getGoodsType());

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

@@ -93,6 +93,81 @@ 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;
+
+    /**
+     * 采购单位
+     */
+    private String purchaseCompany;
+
+    /**
+     * 采购单位id
+     */
+    private Long purchaseCompanyId;
+
+    /**
+     * 采购单位联系电话
+     */
+    private String purchaseContactPhone;
+
+    /**
+     * 采购单位联系人
+     */
+    private String purchaseContacts;
+
+    /**
+     * 采购单位联系人id
+     */
+    private Long purchaseContactsId;
+
+    /**
+     * 供应单位
+     */
+    private String supplyCompany;
+
+    /**
+     * 供应单位id
+     */
+    private Long supplyCompanyId;
+
+    /**
+     * 供应单位联系电话
+     */
+    private String supplyContactPhone;
+
+    /**
+     * 供应单位联系人
+     */
+    private String supplyContacts;
+
+    /**
+     * 供应单位联系人id
+     */
+    private Long supplyContactsId;
+
 
 
     /**

+ 10 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/LogisticsOrderResp.java

@@ -39,6 +39,16 @@ public class LogisticsOrderResp implements Serializable {
      */
     @Schema(description = "托运单位名称")
     private String consignCompanyName;
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private String agentEntId;
+    /**
+     * 代理单位名称
+     */
+    @Schema(description = "代理单位名称")
+    private String agentFirmName;
     /**
      * 承运单位id
      */

+ 5 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/QueryLogisticsOrderReq.java

@@ -52,6 +52,11 @@ public class QueryLogisticsOrderReq extends PageReq implements Serializable {
      */
     @Schema(description = "托运单位id")
     private String consignCompanyId;
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private String agentEntId;
     /**
      * 承运单位id
      */

+ 5 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/WaybillOrderReq.java

@@ -77,6 +77,11 @@ public class WaybillOrderReq extends PageReq implements Serializable {
      */
     @Schema(description = "承运单位 id")
     private String carrierId;
+    /**
+     * 代理单位id
+     */
+    @Schema(description = "代理单位id")
+    private String agentEntId;
     /**
      * 计费方式
      */

+ 10 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/WaybillOrderResp.java

@@ -47,6 +47,16 @@ public class WaybillOrderResp implements Serializable {
      */
     @Schema(description = "托运单位名称")
     private String consignUnitName;
+    /**
+     * 代理单位ID
+     */
+    @Schema(description = "代理单位ID")
+    private String agentEntId;
+    /**
+     * 代理单位
+     */
+    @Schema(description = "代理单位")
+    private String agentFirmName;
     /**
      * 承运单位id
      */

+ 15 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/vo/LogisticsOrderDetailResp.java

@@ -91,6 +91,21 @@ public class LogisticsOrderDetailResp implements Serializable {
          */
         @Schema(description = "托运联系电话")
         private String consignUnitPhone;
+        /**
+         * 代理单位id
+         */
+        @Schema(description = "代理单位id")
+        private String agentUnitId;
+        /**
+         * 代理单位名称
+         */
+        @Schema(description = "代理单位名称")
+        private String agentUnitName;
+        /**
+         * 代理联系电话
+         */
+        @Schema(description = "代理联系电话")
+        private String agentUnitPhone;
         /**
          * 承运单位id
          */

+ 12 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/vo/WaybillOrderDetailResp.java

@@ -139,6 +139,18 @@ public class WaybillOrderDetailResp implements Serializable {
     @Schema(description = "供应单位")
     private String supplyEntName;
 
+    /**
+     * 代理单位ID
+     */
+    @Schema(description = "代理单位ID")
+    private String agentEntId;
+
+    /**
+     * 代理单位
+     */
+    @Schema(description = "代理单位")
+    private String agentFirmName;
+
     /**
      * 托运企业
      */

+ 19 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/repository/KwtLogisticsOrderUnitRepository.java

@@ -31,6 +31,25 @@ public class KwtLogisticsOrderUnitRepository extends ServiceImpl<KwtLogisticsOrd
                 .eq(KwtLogisticsOrderUnit::getUnitType,unitType));
     }
 
+    public List<KwtLogisticsOrderUnit> queryByEntIdAndUnitType(Long entId, int unitType) {
+        return list(Wrappers.<KwtLogisticsOrderUnit>lambdaQuery()
+                .eq(KwtLogisticsOrderUnit::getDelFlag, 0)
+                .eq(KwtLogisticsOrderUnit::getEntId, entId)
+                .eq(KwtLogisticsOrderUnit::getUnitType, unitType)
+                .select(KwtLogisticsOrderUnit::getId, KwtLogisticsOrderUnit::getLOrderId,
+                        KwtLogisticsOrderUnit::getEntId, KwtLogisticsOrderUnit::getUnitType));
+    }
+
+    public List<KwtLogisticsOrderUnit> queryByFirmNameAndUnitType(String firmName, int unitType) {
+        return list(Wrappers.<KwtLogisticsOrderUnit>lambdaQuery()
+                .eq(KwtLogisticsOrderUnit::getDelFlag, 0)
+                .eq(KwtLogisticsOrderUnit::getUnitType, unitType)
+                .like(KwtLogisticsOrderUnit::getFirmName, firmName)
+                .select(KwtLogisticsOrderUnit::getId, KwtLogisticsOrderUnit::getLOrderId,
+                        KwtLogisticsOrderUnit::getEntId, KwtLogisticsOrderUnit::getUnitType,
+                        KwtLogisticsOrderUnit::getFirmName));
+    }
+
     public List<KwtLogisticsOrderUnit> queryByLogOrderIds(List<Long> logIds) {
         return list(Wrappers.<KwtLogisticsOrderUnit>lambdaQuery()
                 .eq(KwtLogisticsOrderUnit::getDelFlag,0)

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

@@ -103,6 +103,19 @@ import static com.sckw.excel.utils.DateUtil.DEF_DATE_FORMAT;
 @RequiredArgsConstructor
 public class KwtAcceptCarriageOrderService {
 
+    /**
+     * 物流订单企业表代理单位类型。
+     */
+    static final int LOGISTICS_AGENT_UNIT_TYPE = 4;
+    /**
+     * 物流订单企业表采购单位类型。
+     */
+    static final int LOGISTICS_PURCHASE_UNIT_TYPE = 5;
+    /**
+     * 物流订单企业表供应单位类型。
+     */
+    static final int LOGISTICS_SUPPLY_UNIT_TYPE = 6;
+
     @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
     RemoteSystemService remoteSystemService;
 
@@ -3522,6 +3535,16 @@ public class KwtAcceptCarriageOrderService {
         entIds.add(orderDTO.getConsignCompanyId());
         entIds.add(x.getAcceptCompanyId());
         entIds.add(orderDTO.getNonConsignCompanyId());
+        if (shouldSaveAgentUnit(orderDTO)) {
+            entIds.add(orderDTO.getAgentCompanyId());
+        }
+        if (Objects.nonNull(orderDTO.getPurchaseCompanyId())) {
+            entIds.add(orderDTO.getPurchaseCompanyId());
+        }
+        if (Objects.nonNull(orderDTO.getSupplyCompanyId())) {
+            entIds.add(orderDTO.getSupplyCompanyId());
+        }
+        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 +3606,129 @@ public class KwtAcceptCarriageOrderService {
         notifyUnit.setUpdateBy(orderDTO.getUserId());
         notifyUnit.setUpdateTime(new Date());
         savelogOrderUnitList.add(notifyUnit);
+        log.info("物流订单新增代理企业信息");
+        appendAgentUnit(orderDTO, lOrderId, savelogOrderUnitList, entMap);
+        appendTradeOrderUnits(orderDTO, lOrderId, savelogOrderUnitList, entMap);
+    }
+
+    /**
+     * 创建物流订单时追加贸易订单采购单位和供应单位。
+     *
+     * @param orderDTO             物流订单新增DTO
+     * @param lOrderId             物流订单id
+     * @param savelogOrderUnitList 待批量保存企业列表
+     * @param entMap               企业缓存
+     */
+    private void appendTradeOrderUnits(AddLogisticOrderDTO orderDTO, Long lOrderId,
+                                       List<KwtLogisticsOrderUnit> savelogOrderUnitList,
+                                       Map<Long, EntCacheResDto> entMap) {
+        appendTradeOrderUnit(orderDTO, lOrderId, savelogOrderUnitList, entMap,
+                orderDTO.getPurchaseCompanyId(), orderDTO.getPurchaseCompany(), LOGISTICS_PURCHASE_UNIT_TYPE);
+        appendTradeOrderUnit(orderDTO, lOrderId, savelogOrderUnitList, entMap,
+                orderDTO.getSupplyCompanyId(), orderDTO.getSupplyCompany(), LOGISTICS_SUPPLY_UNIT_TYPE);
+    }
+
+    /**
+     * 创建物流订单时追加贸易订单企业。
+     *
+     * @param orderDTO             物流订单新增DTO
+     * @param lOrderId             物流订单id
+     * @param savelogOrderUnitList 待批量保存企业列表
+     * @param entMap               企业缓存
+     * @param companyId            企业id
+     * @param companyName          企业名称
+     * @param unitType             企业类型
+     */
+    private void appendTradeOrderUnit(AddLogisticOrderDTO orderDTO, Long lOrderId,
+                                      List<KwtLogisticsOrderUnit> savelogOrderUnitList,
+                                      Map<Long, EntCacheResDto> entMap,
+                                      Long companyId, String companyName, int unitType) {
+        if (Objects.isNull(companyId)) {
+            return;
+        }
+        EntCacheResDto ent = MapUtils.isEmpty(entMap) ? null : entMap.get(companyId);
+        if (Objects.isNull(ent)) {
+            log.warn("物流订单未找到贸易订单企业一级企业信息,lOrderId:{}, companyId:{}, companyName:{}, unitType:{}",
+                    lOrderId, companyId, companyName, unitType);
+            return;
+        }
+        savelogOrderUnitList.add(buildLogisticsOrderUnit(orderDTO, lOrderId, companyId, ent, unitType));
+    }
+
+    /**
+     * 代理贸易订单同步创建物流订单时,追加代理单位信息。
+     *
+     * @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) {
+        return buildLogisticsOrderUnit(orderDTO, lOrderId, orderDTO.getAgentCompanyId(), agentEnt, LOGISTICS_AGENT_UNIT_TYPE);
+    }
+
+    /**
+     * 构建物流订单企业记录。
+     *
+     * @param orderDTO 物流订单新增DTO
+     * @param lOrderId 物流订单id
+     * @param entId    企业id
+     * @param ent      企业缓存
+     * @param unitType 企业类型
+     * @return 物流订单企业记录
+     */
+    static KwtLogisticsOrderUnit buildLogisticsOrderUnit(AddLogisticOrderDTO orderDTO, Long lOrderId,
+                                                         Long entId, EntCacheResDto ent, int unitType) {
+        KwtLogisticsOrderUnit orderUnit = new KwtLogisticsOrderUnit();
+        orderUnit.setId(new IdWorker(unitType).nextId());
+        orderUnit.setLOrderId(lOrderId);
+        orderUnit.setUnitType(unitType);
+        orderUnit.setEntId(entId);
+        orderUnit.setContactsId(ent.getContactsId());
+        orderUnit.setTopEntId(ent.getId());
+        orderUnit.setFirmName(ent.getFirmName());
+        orderUnit.setContacts(ent.getContacts());
+        orderUnit.setPhone(ent.getPhone());
+        orderUnit.setStatus(NumberConstant.ZERO);
+        orderUnit.setCreateBy(orderDTO.getUserId());
+        orderUnit.setCreateTime(new Date());
+        orderUnit.setUpdateBy(orderDTO.getUserId());
+        orderUnit.setUpdateTime(new Date());
+        return orderUnit;
     }
 
     private static void setLogisticContractInfo(AddLogisticOrderDTO orderDTO,LogisticData x, Long lOrderId, List<KwtLogisticsOrderContract> saveContractList) {

+ 358 - 12
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtLogisticsConsignmentService.java

@@ -2266,6 +2266,10 @@ public class KwtLogisticsConsignmentService {
      * 代理商企业类型。
      */
     private static final int SUPPLY_AGENT_ENT_TYPE = 4;
+    /**
+     * 物流订单企业表代理单位类型。
+     */
+    private static final int LOGISTICS_AGENT_UNIT_TYPE = 4;
 
 
     public PageDataResult<LogisticsOrderResp> queryLogisticsOrderByPage(QueryLogisticsOrderReq req) {
@@ -2352,7 +2356,7 @@ public class KwtLogisticsConsignmentService {
      */
     private boolean shouldReturnEmptyResult(Set<Long> logOrderIds, Set<Long> entList, QueryLogisticsOrderReq req) {
         return CollectionUtils.isEmpty(logOrderIds) &&
-                (!org.apache.commons.lang3.StringUtils.isAllBlank(req.getContractId(), req.getGoodsName(), req.getConsignCompanyId(), req.getCarriageCompanyId(), req.getKeywords())
+                (!org.apache.commons.lang3.StringUtils.isAllBlank(req.getContractId(), req.getGoodsName(), req.getConsignCompanyId(), req.getAgentEntId(), req.getCarriageCompanyId(), req.getKeywords())
                         || org.apache.commons.collections4.CollectionUtils.isNotEmpty(entList));
     }
 
@@ -3147,6 +3151,7 @@ public class KwtLogisticsConsignmentService {
     @NotNull
     private Set<Long> getLogOrderIds(QueryLogisticsOrderReq req, Set<Long> entList, Long allEnt) {
         applyAgentKeywordCondition(req);
+        applyAgentEntCondition(req);
         Set<Long> logOrderIds = Sets.newHashSet();
         if (Objects.nonNull(allEnt)) {
             entList.add(allEnt);
@@ -3207,6 +3212,9 @@ public class KwtLogisticsConsignmentService {
 
             logOrderIds.addAll(logOrderIdList);
         }
+        log.debug("物流订单ID数量: {}", logOrderIds.size());
+        logOrderIds = applyAgentEntFilterToLogOrderIds(req, logOrderIds);
+        log.debug("代理单位过滤后物流订单ID数量: {}", logOrderIds.size());
         if (StringUtils.isNotBlank(req.getContractId())) {
             List<KwtLogisticsOrderContract> kwtLogisticsOrderContracts = logisticsOrderContractRepository.queryByContractId(Long.parseLong(req.getContractId()));
             if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwtLogisticsOrderContracts)) {
@@ -3242,7 +3250,8 @@ public class KwtLogisticsConsignmentService {
         // 如果存在这些条件,后续的关键字搜索必须与这些条件的结果取交集(AND关系)
         boolean hasLogOrderIdRestrictedCondition = org.apache.commons.collections4.CollectionUtils.isNotEmpty(entList)
                 || StringUtils.isNotBlank(req.getContractId())
-                || StringUtils.isNotBlank(req.getGoodsName());
+                || StringUtils.isNotBlank(req.getGoodsName())
+                || StringUtils.isNotBlank(req.getAgentEntId());
         
         log.debug("关键字过滤前置检查: hasLogOrderIdRestrictedCondition={}, 当前logOrderIds大小={}", 
                 hasLogOrderIdRestrictedCondition, logOrderIds.size());
@@ -3250,6 +3259,87 @@ public class KwtLogisticsConsignmentService {
         return applyKeywordFilterToLogOrderIds(req, logOrderIds, hasLogOrderIdRestrictedCondition);
     }
 
+    /**
+     * 根据代理单位ID过滤物流订单ID集合。
+     * <p>
+     * 业务逻辑链路:
+     * 1. 校验请求参数,若无代理单位ID则直接返回原始订单ID集合。
+     * 2. 根据代理单位ID查询关联的贸易订单ID集合(远程调用)。
+     * 3. 查询这些贸易订单的详细信息,筛选出标记为“代理”且代理单位ID匹配的贸易订单ID。
+     * 4. 根据筛选后的贸易订单ID,查询关联的物流订单ID集合。
+     * 5. 将查询到的代理物流订单ID与原始传入的物流订单ID取交集(若原始集合为空,则直接返回代理物流订单ID)。
+     * </p>
+     *
+     * @param req         查询请求参数,包含代理单位ID
+     * @param logOrderIds 原始物流订单ID集合
+     * @return 过滤后的物流订单ID集合
+     */
+    private Set<Long> applyAgentEntFilterToLogOrderIds(QueryLogisticsOrderReq req, Set<Long> logOrderIds) {
+        if (Objects.isNull(req) || StringUtils.isBlank(req.getAgentEntId())) {
+            log.debug("代理单位过滤:未指定代理单位ID,跳过过滤");
+            return logOrderIds;
+        }
+
+        Long agentEntId;
+        try {
+            agentEntId = Long.valueOf(req.getAgentEntId());
+        } catch (NumberFormatException e) {
+            log.warn("代理单位过滤:代理单位ID格式非法,agentEntId={}", req.getAgentEntId(), e);
+            throw new BusinessException("代理单位ID格式错误");
+        }
+
+        log.info("开始执行代理单位过滤,agentEntId: {}, 初始物流订单ID数量: {}", agentEntId,
+                CollectionUtils.isEmpty(logOrderIds) ? 0 : logOrderIds.size());
+
+        List<KwtLogisticsOrderUnit> agentUnits;
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logOrderIds)) {
+            agentUnits = kwtLogisticsOrderUnitRepository.queryByEntIdAndUnitType(agentEntId, LOGISTICS_AGENT_UNIT_TYPE);
+        } else {
+            agentUnits = kwtLogisticsOrderUnitRepository.queryByLOrderIdsAndUnitType(logOrderIds, LOGISTICS_AGENT_UNIT_TYPE);
+        }
+
+        Set<Long> agentLogOrderIds = extractAgentLogOrderIdsByLogisticsUnit(agentUnits, agentEntId);
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(agentLogOrderIds)) {
+            log.warn("代理单位过滤:物流订单企业表未找到代理单位[{}]关联的物流订单,返回空集合", agentEntId);
+            return Sets.newHashSet();
+        }
+        log.debug("代理单位过滤:从物流订单企业表查询到代理物流订单ID数量: {}", agentLogOrderIds.size());
+
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logOrderIds)) {
+            log.info("代理单位过滤完成:无前置过滤条件,直接返回代理物流订单ID,数量: {}", agentLogOrderIds.size());
+            return agentLogOrderIds;
+        }
+
+        Set<Long> result = Sets.newHashSet(logOrderIds);
+        int beforeSize = result.size();
+        result.retainAll(agentLogOrderIds);
+
+        log.info("代理单位过滤完成:原始ID数: {}, 代理关联ID数: {}, 过滤后剩余ID数: {}",
+                beforeSize, agentLogOrderIds.size(), result.size());
+
+        return result;
+    }
+
+    /**
+     * 从物流订单企业表记录中提取指定代理单位关联的物流订单ID。
+     *
+     * @param agentUnits 物流订单企业表代理单位记录
+     * @param agentEntId 代理单位ID
+     * @return 物流订单ID集合
+     */
+    static Set<Long> extractAgentLogOrderIdsByLogisticsUnit(List<KwtLogisticsOrderUnit> agentUnits, Long agentEntId) {
+        if (Objects.isNull(agentEntId) || org.apache.commons.collections4.CollectionUtils.isEmpty(agentUnits)) {
+            return Sets.newHashSet();
+        }
+        return agentUnits.stream()
+                .filter(Objects::nonNull)
+                .filter(unit -> Objects.equals(unit.getEntId(), agentEntId))
+                .map(KwtLogisticsOrderUnit::getLOrderId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+    }
+
     /**
      * 处理物流订单关键字段中的代理关键字。
      * 业务规则:当keywords包含“代理”时,将其转换为代理属性过滤(agentFlag=1),并清空keywords。
@@ -3268,6 +3358,19 @@ public class KwtLogisticsConsignmentService {
         req.setKeywords(null);
     }
 
+    /**
+     * 代理单位查询存在时,仅查询代理属性订单。
+     *
+     * @param req 物流订单分页查询请求
+     */
+    static void applyAgentEntCondition(QueryLogisticsOrderReq req) {
+        if (Objects.isNull(req) || org.apache.commons.lang3.StringUtils.isBlank(req.getAgentEntId())) {
+            return;
+        }
+        log.info("检测到代理单位查询条件,转换为代理标识过滤。agentEntId={}", req.getAgentEntId());
+        req.setAgentFlag(Global.YES);
+    }
+
     /**
      * 根据关键字段过滤物流订单ID。
      * 逻辑说明:
@@ -3332,10 +3435,95 @@ public class KwtLogisticsConsignmentService {
             keywordLogOrderIds.addAll(goodsOrderIds);
             log.debug("通过商品名称匹配到 {} 个订单", goodsOrderIds.size());
         }
+
+        // 3. 根据贸易订单代理商名称模糊查询
+        Set<Long> agentOrderIds = queryLogisticsOrderIdsByAgentFirmName(keywords);
+        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(agentOrderIds)) {
+            keywordLogOrderIds.addAll(agentOrderIds);
+            log.debug("通过贸易订单代理商名称匹配到 {} 个物流订单", agentOrderIds.size());
+        }
         
         return keywordLogOrderIds;
     }
 
+
+    /**
+     * 根据贸易订单代理商名称关键字查询关联的物流订单ID集合。
+     * <p>
+     * 业务逻辑链路:
+     * 1. 根据企业名称关键字查询贸易订单单位信息(远程调用)。
+     * 2. 筛选出单位为“收货单位/承运方”(unitType=2)的贸易订单ID。
+     * 3. 批量查询这些贸易订单的详情。
+     * 4. 在贸易订单详情中,进一步筛选出标记为“代理”且代理商名称包含关键字的贸易订单ID。
+     * 5. 根据筛选后的贸易订单ID,查询关联的物流订单ID并返回。
+     * </p>
+     *
+     * @param keywords 代理商名称关键字
+     * @return 命中的物流订单ID集合,若查询失败或无结果则返回空集合
+     */
+    private Set<Long> queryLogisticsOrderIdsByAgentFirmName(String keywords) {
+        // 1. 前置校验:关键字为空直接返回空集合
+        if (org.apache.commons.lang3.StringUtils.isBlank(keywords)) {
+            log.debug("通过代理商名称查询物流订单:关键字为空,返回空集合");
+            return Sets.newHashSet();
+        }
+        
+        log.info("开始通过物流订单企业表代理单位名称关键字查询物流订单,keywords: {}", keywords);
+
+        try {
+            List<KwtLogisticsOrderUnit> agentUnits = kwtLogisticsOrderUnitRepository.queryByFirmNameAndUnitType(
+                    keywords, LOGISTICS_AGENT_UNIT_TYPE);
+            Set<Long> resultLogOrderIds = extractAgentLogOrderIdsByAgentFirmName(agentUnits, keywords);
+
+            log.info("通过物流订单企业表代理单位名称关键字查询物流订单完成,keywords: {}, 最终命中物流订单数量: {}", keywords, resultLogOrderIds.size());
+            return resultLogOrderIds;
+        } catch (Exception e) {
+            log.warn("通过物流订单企业表代理单位名称关键字查询物流订单发生异常,keywords: {}, 错误信息: {}", keywords, e.getMessage(), e);
+            return Sets.newHashSet();
+        }
+    }
+
+    /**
+     * 从物流订单企业表代理单位记录中提取代理商名称命中的物流订单ID。
+     *
+     * @param agentUnits 物流订单企业表代理单位记录
+     * @param keywords   代理商名称关键字
+     * @return 命中的物流订单ID集合
+     */
+    static Set<Long> extractAgentLogOrderIdsByAgentFirmName(List<KwtLogisticsOrderUnit> agentUnits, String keywords) {
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(agentUnits)
+                || org.apache.commons.lang3.StringUtils.isBlank(keywords)) {
+            return Sets.newHashSet();
+        }
+        return agentUnits.stream()
+                .filter(Objects::nonNull)
+                .filter(unit -> org.apache.commons.lang3.StringUtils.contains(unit.getFirmName(), keywords))
+                .map(KwtLogisticsOrderUnit::getLOrderId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+    }
+
+    /**
+     * 从贸易订单详情中过滤代理商名称命中的代理订单ID。
+     *
+     * @param tradeOrderDetails 贸易订单详情集合
+     * @param keywords          代理商名称关键字
+     * @return 代理商名称命中的贸易订单ID集合
+     */
+    static Set<Long> extractAgentTradeOrderIdsByAgentName(List<OrderDetailVo> tradeOrderDetails, String keywords) {
+        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeOrderDetails)
+                || org.apache.commons.lang3.StringUtils.isBlank(keywords)) {
+            return Sets.newHashSet();
+        }
+        return tradeOrderDetails.stream()
+                .filter(Objects::nonNull)
+                .filter(order -> Objects.equals(order.getAgentFlag(), Global.YES))
+                .filter(order -> org.apache.commons.lang3.StringUtils.contains(order.getAgentFirmName(), keywords))
+                .map(OrderDetailVo::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+    }
+
     /**
      * 合并关键字段命中的物流订单ID。
      * 合并策略:
@@ -3406,11 +3594,6 @@ public class KwtLogisticsConsignmentService {
                 new KwtLogisticsOrderUnit());
         logisticsOrderResp.setConsignCompanyId(String.valueOf(consignCompany.getId()));
         logisticsOrderResp.setConsignCompanyName(consignCompany.getFirmName());
-        KwtLogisticsOrderUnit carriageCompany = finalLogOrderIdAndUnitTypeKeyAndUnitMap.getOrDefault(kwtLogisticsOrder.getId() +
-                        "-" + NumberConstant.TWO,
-                new KwtLogisticsOrderUnit());
-        logisticsOrderResp.setCarriageCompanyId(String.valueOf(carriageCompany.getId()));
-        logisticsOrderResp.setCarriageCompanyName(carriageCompany.getFirmName());
         logisticsOrderResp.setTradeOrderNo(kwtLogisticsOrder.getTOrderNo());
 
         KwtLogisticsOrderGoods goods = finalLogIdAndGoodsMap.getOrDefault(kwtLogisticsOrder.getId(), new KwtLogisticsOrderGoods());
@@ -3429,6 +3612,13 @@ public class KwtLogisticsConsignmentService {
         logisticsOrderResp.setChargeTypeDesc(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(),
                 String.valueOf(kwtLogisticsOrder.getBillingMode())));
         OrderDetailVo orderDetailVo = tradeIdAndOrderDetailVoMap.getOrDefault(kwtLogisticsOrder.getTOrderId(), new OrderDetailVo());
+        setConsignCompanyInfo(logisticsOrderResp, orderDetailVo, consignCompany);
+        setAgentUnitInfo(logisticsOrderResp, orderDetailVo);
+        KwtLogisticsOrderUnit carriageCompany = finalLogOrderIdAndUnitTypeKeyAndUnitMap.getOrDefault(kwtLogisticsOrder.getId() +
+                        "-" + NumberConstant.TWO,
+                new KwtLogisticsOrderUnit());
+        logisticsOrderResp.setCarriageCompanyId(String.valueOf(carriageCompany.getId()));
+        logisticsOrderResp.setCarriageCompanyName(carriageCompany.getFirmName());
         logisticsOrderResp.setAmount((Objects.nonNull(orderDetailVo.getAmount()) ?
                 orderDetailVo.getAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + kwtLogisticsOrder.getUnit());
 
@@ -3504,6 +3694,85 @@ public class KwtLogisticsConsignmentService {
         return logisticsOrderResp;
     }
 
+    /**
+     * 设置代理商单位信息到响应对象中。
+     * <p>
+     * 业务逻辑:
+     * 1. 校验贸易订单是否为代理模式(agentFlag=1)且存在有效的代理企业ID。
+     * 2. 如果满足条件,则将代理企业ID和名称填充到物流订单响应对象中。
+     * 3. 如果不满足条件(非代理订单或无代理企业信息),则不执行任何操作,保持响应对象中相关字段为空或默认值。
+     * </p>
+     *
+     * @param logisticsOrderResp 物流订单响应对象,用于设置代理商信息
+     * @param orderDetailVo      贸易订单详情对象,包含代理标识及代理企业信息
+     */
+    private static void setAgentUnitInfo(LogisticsOrderResp logisticsOrderResp, OrderDetailVo orderDetailVo) {
+        // 1. 前置校验:判断是否为代理订单且代理企业ID不为空
+        // Global.YES 通常代表常量 1,表示是/启用
+        if (!Objects.equals(orderDetailVo.getAgentFlag(), Global.YES) || Objects.isNull(orderDetailVo.getAgentEntId())) {
+            log.debug("跳过设置代理单位信息:agentFlag={}, agentEntId={}", 
+                    orderDetailVo.getAgentFlag(), orderDetailVo.getAgentEntId());
+            return;
+        }
+
+        // 2. 设置代理企业ID
+        logisticsOrderResp.setAgentEntId(String.valueOf(orderDetailVo.getAgentEntId()));
+        
+        // 3. 设置代理企业名称
+        logisticsOrderResp.setAgentFirmName(orderDetailVo.getAgentFirmName());
+        
+        log.debug("成功设置代理单位信息:agentEntId={}, agentFirmName={}", 
+                orderDetailVo.getAgentEntId(), orderDetailVo.getAgentFirmName());
+    }
+
+    /**
+     * 设置托运单位(发货方)信息到响应对象中。
+     * <p>
+     * 业务逻辑优先级:
+     * 1. 优先从贸易订单详情(OrderDetailVo)中获取托运单位信息。
+     *    - 如果订单标记为代理订单(agentFlag=1)且存在代理企业ID,则使用代理企业信息作为托运方。
+     *    - 否则,使用供应商企业信息作为托运方。
+     * 2. 如果贸易订单详情中未获取到有效的企业ID,则降级使用物流订单单位表中的备用数据(fallbackConsignUnit)。
+     * </p>
+     *
+     * @param logisticsOrderResp 物流订单响应对象,用于设置最终展示的托运单位信息
+     * @param orderDetailVo      贸易订单详情对象,包含代理商、供应商等企业基础信息
+     * @param fallbackConsignUnit 物流订单单位表中的备用托运单位记录,作为兜底数据源
+     */
+    private static void setConsignCompanyInfo(LogisticsOrderResp logisticsOrderResp, OrderDetailVo orderDetailVo,
+                                              KwtLogisticsOrderUnit fallbackConsignUnit) {
+        // 1. 确定托运单位的企业ID
+        // 逻辑:如果是代理模式且有代理企业ID,则取代理企业ID;否则取供应商企业ID
+        Long consignEntId = Objects.equals(orderDetailVo.getAgentFlag(), Global.YES) && Objects.nonNull(orderDetailVo.getAgentEntId())
+                ? orderDetailVo.getAgentEntId()
+                : orderDetailVo.getSupplierEntId();
+
+        // 2. 确定托运单位的企业名称
+        // 逻辑:与上述ID获取逻辑保持一致,确保ID和名称来源相同
+        String consignFirmName = Objects.equals(orderDetailVo.getAgentFlag(), Global.YES) && Objects.nonNull(orderDetailVo.getAgentEntId())
+                ? orderDetailVo.getAgentFirmName()
+                : orderDetailVo.getSupplierFirmName();
+
+        // 3. 校验并设置主要数据源
+        if (Objects.nonNull(consignEntId)) {
+            log.debug("设置托运单位信息-来源贸易订单: entId={}, firmName={}", consignEntId, consignFirmName);
+            logisticsOrderResp.setConsignCompanyId(String.valueOf(consignEntId));
+            logisticsOrderResp.setConsignCompanyName(consignFirmName);
+            return;
+        }
+
+        // 4. 降级处理:使用备用数据源
+        // 当贸易订单中缺失托运单位信息时,使用物流订单关联的单位表数据进行填充,防止前端展示空白
+        if (Objects.nonNull(fallbackConsignUnit)) {
+            log.warn("贸易订单中缺失托运单位信息,使用物流订单单位表备用数据: entId={}, firmName={}", 
+                    fallbackConsignUnit.getEntId(), fallbackConsignUnit.getFirmName());
+            logisticsOrderResp.setConsignCompanyId(String.valueOf(fallbackConsignUnit.getEntId()));
+            logisticsOrderResp.setConsignCompanyName(fallbackConsignUnit.getFirmName());
+        } else {
+            log.error("无法获取托运单位信息:贸易订单无数据且备用单位对象为空");
+        }
+    }
+
     /**
      * 计算贸易订单的剩余可分配量(余量)
      * <p>
@@ -3680,7 +3949,7 @@ public class KwtLogisticsConsignmentService {
         //设置合同信息
         setContractInfo(orderContract, tradeContractResDto, logisticsOrderDetailResp);
         //设置单位信息
-        setUnitInfo(logOrderIdUnitTypeKeyAndUnitMap, logisticsOrder, logisticsOrderDetailResp);
+        setUnitInfo(logOrderIdUnitTypeKeyAndUnitMap, logisticsOrder, orderDetailVo, logisticsOrderDetailResp);
 
         //设置贸易信息
         setGoodsInfo(kwpGoods, logisticsOrder, logisticsOrderDetailResp, orderDetailVo, dictValueAndDictResDtoMap);
@@ -3844,14 +4113,29 @@ public class KwtLogisticsConsignmentService {
         logisticsOrderDetailResp.setGoodsInfoVO(goodsInfoVO);
     }
 
-    private static void setUnitInfo(Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap, KwtLogisticsOrder logisticsOrder, LogisticsOrderDetailResp logisticsOrderDetailResp) {
+    private static void setUnitInfo(Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap, KwtLogisticsOrder logisticsOrder,
+                                    OrderDetailVo orderDetailVo, LogisticsOrderDetailResp logisticsOrderDetailResp) {
         LogisticsOrderDetailResp.UnitInfoVO unitInfoVO = new LogisticsOrderDetailResp.UnitInfoVO();
         KwtLogisticsOrderUnit consignUnit =
                 logOrderIdUnitTypeKeyAndUnitMap.getOrDefault(logisticsOrder.getId() + "-" + NumberConstant.ONE,
                         new KwtLogisticsOrderUnit());
-        unitInfoVO.setConsignUnitId(String.valueOf(consignUnit.getEntId()));
-        unitInfoVO.setConsignUnitName(consignUnit.getFirmName());
-        unitInfoVO.setConsignUnitPhone(consignUnit.getPhone());
+        setConsignUnitInfo(unitInfoVO, orderDetailVo, consignUnit);
+        // 从映射中获取代理单位信息,若不存在则使用空对象作为默认值,避免空指针异常
+        // key由物流订单ID和代理单位类型常量组成
+        KwtLogisticsOrderUnit agentUnit =
+                logOrderIdUnitTypeKeyAndUnitMap.getOrDefault(logisticsOrder.getId() + "-" + LOGISTICS_AGENT_UNIT_TYPE,
+                        new KwtLogisticsOrderUnit());
+
+        // 记录调试日志,便于追踪代理单位信息的获取情况
+        if (Objects.nonNull(agentUnit) && Objects.nonNull(agentUnit.getEntId())) {
+            log.debug("物流订单[{}]获取到代理单位信息: entId={}, firmName={}",
+                    logisticsOrder.getId(), agentUnit.getEntId(), agentUnit.getFirmName());
+        } else {
+            log.debug("物流订单[{}]未获取到代理单位信息或代理单位ID为空", logisticsOrder.getId());
+        }
+
+        // 将代理单位信息设置到响应VO中
+        setDetailAgentUnitInfo(unitInfoVO, agentUnit);
         KwtLogisticsOrderUnit carriageUnit =
                 logOrderIdUnitTypeKeyAndUnitMap.getOrDefault(logisticsOrder.getId() + "-" + NumberConstant.TWO,
                         new KwtLogisticsOrderUnit());
@@ -3861,6 +4145,68 @@ public class KwtLogisticsConsignmentService {
         logisticsOrderDetailResp.setUnitInfoVO(unitInfoVO);
     }
 
+
+    /**
+     * 设置物流订单详情中的代理单位信息。
+     * <p>
+     * 该方法用于将物流订单企业表(KwtLogisticsOrderUnit)中类型为“代理单位”的记录,
+     * 填充到物流订单详情响应对象(LogisticsOrderDetailResp.UnitInfoVO)的对应字段中。
+     * </p>
+     *
+     * @param unitInfoVO 物流订单详情响应对象中的单位信息VO,用于接收代理单位数据
+     * @param agentUnit  物流订单企业表记录,代表代理单位信息。若为null或企业ID为空,则不进行设置
+     */
+    static void setDetailAgentUnitInfo(LogisticsOrderDetailResp.UnitInfoVO unitInfoVO, KwtLogisticsOrderUnit agentUnit) {
+        // 1. 前置参数校验:防止空指针异常
+        // 如果响应VO为空、代理单位对象为空、或代理单位的企业ID为空,则直接返回,不执行后续赋值操作
+        if (Objects.isNull(unitInfoVO) || Objects.isNull(agentUnit) || Objects.isNull(agentUnit.getEntId())) {
+            log.debug("设置代理单位信息跳过:unitInfoVO={}, agentUnit={}, agentEntId={}",
+                    unitInfoVO != null, agentUnit != null, agentUnit != null ? agentUnit.getEntId() : null);
+            return;
+        }
+
+        // 2. 提取并设置代理单位ID
+        // 将Long类型的企业ID转换为String类型存入VO
+        String agentEntIdStr = String.valueOf(agentUnit.getEntId());
+        unitInfoVO.setAgentUnitId(agentEntIdStr);
+
+        // 3. 提取并设置代理单位名称
+        // 直接从实体对象获取企业名称
+        String agentFirmName = agentUnit.getFirmName();
+        unitInfoVO.setAgentUnitName(agentFirmName);
+
+        // 4. 提取并设置代理单位联系电话
+        // 直接从实体对象获取联系电话
+        String agentPhone = agentUnit.getPhone();
+        unitInfoVO.setAgentUnitPhone(agentPhone);
+
+        // 5. 记录成功设置的日志,便于排查数据展示问题
+        log.debug("成功设置物流订单详情代理单位信息:agentUnitId={}, agentUnitName={}, agentUnitPhone={}",
+                agentEntIdStr, agentFirmName, agentPhone);
+    }
+
+    private static void setConsignUnitInfo(LogisticsOrderDetailResp.UnitInfoVO unitInfoVO, OrderDetailVo orderDetailVo,
+                                           KwtLogisticsOrderUnit fallbackConsignUnit) {
+        Long consignEntId = Objects.equals(orderDetailVo.getAgentFlag(), Global.YES) && Objects.nonNull(orderDetailVo.getAgentEntId())
+                ? orderDetailVo.getAgentEntId()
+                : orderDetailVo.getSupplierEntId();
+        String consignFirmName = Objects.equals(orderDetailVo.getAgentFlag(), Global.YES) && Objects.nonNull(orderDetailVo.getAgentEntId())
+                ? orderDetailVo.getAgentFirmName()
+                : orderDetailVo.getSupplierFirmName();
+        String consignPhone = Objects.equals(orderDetailVo.getAgentFlag(), Global.YES) && Objects.nonNull(orderDetailVo.getAgentEntId())
+                ? orderDetailVo.getAgentPhone()
+                : orderDetailVo.getSupplierPhone();
+        if (Objects.nonNull(consignEntId)) {
+            unitInfoVO.setConsignUnitId(String.valueOf(consignEntId));
+            unitInfoVO.setConsignUnitName(consignFirmName);
+            unitInfoVO.setConsignUnitPhone(consignPhone);
+            return;
+        }
+        unitInfoVO.setConsignUnitId(String.valueOf(fallbackConsignUnit.getEntId()));
+        unitInfoVO.setConsignUnitName(fallbackConsignUnit.getFirmName());
+        unitInfoVO.setConsignUnitPhone(fallbackConsignUnit.getPhone());
+    }
+
     private static void setContractInfo(KwtLogisticsOrderContract orderContract, KwcContractLogisticsDto tradeContractResDto, LogisticsOrderDetailResp logisticsOrderDetailResp) {
         LogisticsOrderDetailResp.ContractInfoVO contractInfoVO = new LogisticsOrderDetailResp.ContractInfoVO();
         if (Objects.nonNull(tradeContractResDto)) {

+ 402 - 10
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java

@@ -189,6 +189,14 @@ public class KwtWaybillOrderV1Service {
      * 代理商企业类型。
      */
     private static final int SUPPLY_AGENT_ENT_TYPE = 4;
+    /**
+     * 物流订单企业表代理单位类型。
+     */
+    private static final int LOGISTICS_AGENT_UNIT_TYPE = 4;
+    /**
+     * 物流订单企业表供应单位类型。
+     */
+    private static final int LOGISTICS_SUPPLY_UNIT_TYPE = 6;
     /**
      * @param params 请求参数
      * @desc 统计
@@ -3216,7 +3224,7 @@ public class KwtWaybillOrderV1Service {
     private boolean shouldReturnEmptyResultForLogistics(WaybillOrderReq req, Set<Long> logOrderIds) {
         boolean hasLogisticsFilter = Stream.of(
                         req.getLogisticsOrderNo(), req.getGoodsName(),
-                        req.getCarrierId(), req.getConsignorId(), req.getLogisticsOrderId())
+                        req.getCarrierId(), req.getConsignorId(), req.getAgentEntId(), req.getLogisticsOrderId())
                 .anyMatch(StringUtils::isNotBlank);
 
         boolean hasEnterpriseFilter = Objects.nonNull(LoginUserHolder.getEntId());
@@ -3650,6 +3658,19 @@ public class KwtWaybillOrderV1Service {
             log.debug("企业ID集合为空,跳过基于企业的物流订单ID查询");
         }
 
+        // 如果指定了代理单位,基于物流订单企业表代理单位记录过滤物流订单ID
+        if (StringUtils.isNotBlank(req.getAgentEntId())) {
+            Set<Long> orderIdsByAgentEnt = getLogOrderIdsByAgentEntId(req.getAgentEntId(), logOrderIds);
+            log.debug("根据代理单位查询到物流订单ID数量: {}", orderIdsByAgentEnt.size());
+            if (CollectionUtils.isNotEmpty(orderIdsByAgentEnt)) {
+                intersectLogOrderIds(logOrderIds, orderIdsByAgentEnt);
+                log.debug("代理单位查询后,当前物流订单ID数量: {}", logOrderIds.size());
+            } else {
+                log.debug("根据代理单位未查询到物流订单,返回空集合");
+                return Collections.emptySet();
+            }
+        }
+
         // 如果指定了物流订单号,根据订单号查询
         if (StringUtils.isNotBlank(req.getLogisticsOrderNo())) {
             Set<Long> orderIdsByNo = getLogOrderIdsByNo(req.getLogisticsOrderNo());
@@ -3722,9 +3743,97 @@ public class KwtWaybillOrderV1Service {
         return entIds;
     }
 
+
+    /**
+     * 根据代理单位ID查询关联的物流订单ID集合。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 校验并解析代理单位ID,确保格式合法。
+     * 2. 根据是否存在前置过滤的物流订单ID集合(logOrderIds),选择不同的查询策略以优化性能:
+     *    - 若 logOrderIds 为空:直接根据代理单位ID和单位类型(代理/承运)查询所有关联的物流订单单位记录。
+     *    - 若 logOrderIds 不为空:在指定的物流订单ID范围内,查询属于该代理单位的记录,缩小查询范围。
+     * 3. 从查询结果中提取并返回符合条件的物流订单ID集合。
+     * </p>
+     *
+     * @param agentEntId  代理单位ID字符串
+     * @param logOrderIds 前置条件过滤后的物流订单ID集合,可为空
+     * @return 关联的物流订单ID集合
+     * @throws BusinessException 当代理单位ID格式非法时抛出
+     */
+    private Set<Long> getLogOrderIdsByAgentEntId(String agentEntId, Set<Long> logOrderIds) {
+        log.debug("开始根据代理单位ID查询物流订单,agentEntId: {}, 前置物流订单ID数量: {}",
+                agentEntId, CollectionUtils.isEmpty(logOrderIds) ? 0 : logOrderIds.size());
+
+        // 1. 解析代理单位ID
+        Long parsedAgentEntId;
+        try {
+            parsedAgentEntId = Long.valueOf(agentEntId);
+        } catch (NumberFormatException e) {
+            log.warn("代理单位查询失败:代理单位ID格式非法,agentEntId={}", agentEntId, e);
+            throw new BusinessException("代理单位ID格式错误");
+        }
+
+        // 2. 查询物流订单单位信息(类型为代理/承运)
+        List<KwtLogisticsOrderUnit> agentUnits;
+        if (CollectionUtils.isEmpty(logOrderIds)) {
+            // 场景A:无前置订单ID限制,全量查询该代理单位关联的所有物流订单单位
+            log.debug("执行全量查询:根据代理单位ID [{}] 和单位类型 [{}] 查询物流订单单位", parsedAgentEntId, LOGISTICS_AGENT_UNIT_TYPE);
+            agentUnits = kwtLogisticsOrderUnitRepository.queryByEntIdAndUnitType(parsedAgentEntId, LOGISTICS_AGENT_UNIT_TYPE);
+        } else {
+            // 场景B:有前置订单ID限制,仅在指定订单范围内查询,提高查询效率
+            log.debug("执行范围查询:在 {} 个物流订单ID中,筛选代理单位ID [{}] 和单位类型 [{}] 的记录",
+                    logOrderIds.size(), parsedAgentEntId, LOGISTICS_AGENT_UNIT_TYPE);
+            agentUnits = kwtLogisticsOrderUnitRepository.queryByLOrderIdsAndUnitType(logOrderIds, LOGISTICS_AGENT_UNIT_TYPE);
+        }
+
+        log.debug("查询到物流订单单位记录数量: {}", CollectionUtils.isEmpty(agentUnits) ? 0 : agentUnits.size());
+
+        // 3. 提取物流订单ID
+        Set<Long> result = extractAgentLogOrderIdsByLogisticsUnit(agentUnits, parsedAgentEntId);
+        log.debug("根据代理单位ID [{}] 最终筛选出的物流订单ID数量: {}", parsedAgentEntId, result.size());
+
+        return result;
+    }
+
+
     /**
-     * 获取当前登录用户的数据权限配置
+     * 从物流订单企业表记录中提取指定代理单位关联的物流订单ID。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 基础校验:若代理单位ID为空或待处理的企业列表为空,直接返回空集合,避免无效计算。
+     * 2. 流式过滤:
+     *    - 过滤掉列表中的空对象,防止NPE。
+     *    - 筛选出企业ID(entId)与目标代理单位ID(agentEntId)一致的记录。
+     * 3. 提取与清洗:
+     *    - 提取匹配记录的物流订单ID(lOrderId)。
+     *    - 再次过滤掉可能为空的订单ID,确保结果集的纯净性。
+     * 4. 结果收集:将符合条件的物流订单ID收集到Set集合中并返回,自动去重。
+     * </p>
+     *
+     * @param agentUnits 物流订单企业表代理单位记录列表
+     * @param agentEntId 目标代理单位ID
+     * @return 关联的物流订单ID集合,若无匹配数据则返回空集合
      */
+    static Set<Long> extractAgentLogOrderIdsByLogisticsUnit(List<KwtLogisticsOrderUnit> agentUnits, Long agentEntId) {
+        // 1. 参数有效性校验
+        if (Objects.isNull(agentEntId) || CollectionUtils.isEmpty(agentUnits)) {
+            log.debug("提取代理单位关联物流订单ID失败:参数无效,agentEntId={}, listSize={}",
+                    agentEntId, agentUnits == null ? 0 : agentUnits.size());
+            return Sets.newHashSet();
+        }
+
+        // 2. 流式处理:过滤、映射、收集
+        Set<Long> result = agentUnits.stream()
+                .filter(Objects::nonNull) // 过滤空对象
+                .filter(unit -> Objects.equals(unit.getEntId(), agentEntId)) // 匹配代理单位ID
+                .map(KwtLogisticsOrderUnit::getLOrderId) // 提取物流订单ID
+                .filter(Objects::nonNull) // 过滤空订单ID
+                .collect(Collectors.toSet()); // 收集结果并去重
+
+        log.debug("提取代理单位[{}]关联的物流订单ID完成,数量: {}", agentEntId, result.size());
+        return result;
+    }
+
     private DataPermissionDTO fetchDataPermissionForCurrentUser() {
         try {
             DataPermissionFilterReqDto reqDto = new DataPermissionFilterReqDto();
@@ -4287,9 +4396,119 @@ public class KwtWaybillOrderV1Service {
             }
         }
         
+        // 通过贸易订单代理商名称关键字查询关联的运单ID
+        log.debug("开始通过代理商名称关键字查询运单ID,关键字: {}", keywords);
+        Set<Long> orderIdsByAgentFirmName = queryBillOrderIdsByAgentFirmName(keywords);
+        
+        // 如果查询到匹配的运单ID,则合并到结果集中
+        if (CollectionUtils.isNotEmpty(orderIdsByAgentFirmName)) {
+            keywordBillOrderIds.addAll(orderIdsByAgentFirmName);
+            log.info("通过贸易订单代理商名称[{}]查询到运单ID数量: {}", keywords, orderIdsByAgentFirmName.size());
+        } else {
+            log.debug("通过贸易订单代理商名称[{}]未查询到匹配的运单ID", keywords);
+        }
+
         return keywordBillOrderIds;
     }
 
+
+    /**
+     * 通过物流订单企业表代理单位名称关键字查询关联的运单ID集合。
+     * <p>
+     * 业务逻辑链路:
+     * 1. 根据代理商名称关键字查询物流订单企业表中的代理单位记录(UnitType=4)。
+     * 2. 提取代理单位关联的物流订单ID。
+     * 3. 根据物流订单ID查询关联的子运单,最终提取主运单ID集合。
+     * </p>
+     *
+     * @param keywords 代理商名称关键字
+     * @return 匹配的运单ID集合,若查询失败或无数据则返回空集合
+     */
+    private Set<Long> queryBillOrderIdsByAgentFirmName(String keywords) {
+        // 参数校验:关键字为空直接返回空集合
+        if (org.apache.commons.lang3.StringUtils.isBlank(keywords)) {
+            log.debug("通过代理商名称查询运单:关键字为空,返回空集合");
+            return Sets.newHashSet();
+        }
+        
+        log.info("开始通过代理商名称关键字查询运单,keywords: {}", keywords);
+        
+        try {
+            // 1. 根据代理商名称查询物流订单企业表中的代理单位记录
+            List<KwtLogisticsOrderUnit> agentUnits = kwtLogisticsOrderUnitRepository.queryByFirmNameAndUnitType(
+                    keywords, LOGISTICS_AGENT_UNIT_TYPE);
+            if (CollectionUtils.isEmpty(agentUnits)) {
+                log.debug("通过代理商名称[{}]未查询到物流订单代理单位信息", keywords);
+                return Sets.newHashSet();
+            }
+            log.debug("查询到物流订单代理单位数量: {}", agentUnits.size());
+
+            // 2. 提取物流订单ID
+            Set<Long> logOrderIds = extractAgentLogOrderIdsByAgentFirmName(agentUnits, keywords);
+            
+            if (CollectionUtils.isEmpty(logOrderIds)) {
+                log.warn("物流订单代理单位记录中物流订单ID为空,无法继续查询子运单,keywords: {}", keywords);
+                return Sets.newHashSet();
+            }
+            log.debug("通过代理商名称[{}]匹配到物流订单ID数量: {}", keywords, logOrderIds.size());
+
+            // 3. 根据物流订单ID查询子运单,并提取主运单ID
+            List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.queryByLogIds(new ArrayList<>(logOrderIds));
+            Set<Long> resultBillOrderIds = Optional.ofNullable(subtasks)
+                    .orElseGet(Collections::emptyList)
+                    .stream()
+                    .map(KwtWaybillOrderSubtask::getWOrderId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toSet());
+            
+            log.info("通过代理商名称[{}]查询运单完成,最终匹配运单ID数量: {}", keywords, resultBillOrderIds.size());
+            return resultBillOrderIds;
+            
+        } catch (Exception e) {
+            // 异常捕获:记录警告日志,避免因远程服务波动导致主流程中断,返回空集合表示无匹配数据
+            log.warn("通过代理商名称关键字查询运单发生异常,keywords: {}, 错误信息: {}", keywords, e.getMessage(), e);
+            return Sets.newHashSet();
+        }
+    }
+
+
+    /**
+     * 从物流订单企业表代理单位记录中,根据代理商名称关键字过滤并提取关联的物流订单ID。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 基础校验:若代理单位列表为空或搜索关键字为空/空白,直接返回空集合,避免无效计算。
+     * 2. 流式过滤与映射:
+     *    - 过滤掉列表中的空对象,防止NPE。
+     *    - 使用 StringUtils.contains 进行模糊匹配,筛选出企业名称包含关键字的记录。
+     *    - 提取匹配记录的物流订单ID(lOrderId)。
+     *    - 再次过滤掉可能为空的订单ID,确保结果集的纯净性。
+     * 3. 结果收集:将符合条件的物流订单ID收集到Set集合中并返回,自动去重。
+     * </p>
+     *
+     * @param agentUnits 物流订单企业表代理单位记录列表
+     * @param keywords   代理商名称关键字
+     * @return 代理商名称命中的物流订单ID集合,若无匹配数据则返回空集合
+     */
+    static Set<Long> extractAgentLogOrderIdsByAgentFirmName(List<KwtLogisticsOrderUnit> agentUnits, String keywords) {
+        // 1. 参数有效性校验
+        if (CollectionUtils.isEmpty(agentUnits) || org.apache.commons.lang3.StringUtils.isBlank(keywords)) {
+            log.debug("提取代理商名称关联物流订单ID失败:参数无效,agentUnitsSize={}, keywords={}",
+                    agentUnits == null ? 0 : agentUnits.size(), keywords);
+            return Sets.newHashSet();
+        }
+
+        // 2. 流式处理:过滤、映射、收集
+        Set<Long> result = agentUnits.stream()
+                .filter(Objects::nonNull) // 过滤空对象
+                .filter(unit -> org.apache.commons.lang3.StringUtils.contains(unit.getFirmName(), keywords)) // 模糊匹配代理商名称
+                .map(KwtLogisticsOrderUnit::getLOrderId) // 提取物流订单ID
+                .filter(Objects::nonNull) // 过滤空订单ID
+                .collect(Collectors.toSet()); // 收集结果并去重
+
+        log.debug("根据代理商名称关键字[{}]提取物流订单ID完成,命中数量: {}", keywords, result.size());
+        return result;
+    }
+
     /**
      * 合并关键字段命中的运单ID。
      * <p>
@@ -4509,10 +4728,16 @@ public class KwtWaybillOrderV1Service {
         Integer agentFlag = Objects.nonNull(record.getAgentFlag()) ? record.getAgentFlag() : billOrder.getAgentFlag();
         waybillOrderResp.setAgentFlag(agentFlag);
         waybillOrderResp.setAgentFlagDesc(Objects.equals(agentFlag, Global.YES) ? "是" : "否");
-        KwtLogisticsOrderUnit consignUnit = finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(record.getLOrderId() + "-" + NumberConstant.ONE,
-                new KwtLogisticsOrderUnit());
-        waybillOrderResp.setConsignUnitId(String.valueOf(consignUnit.getEntId()));
-        waybillOrderResp.setConsignUnitName(consignUnit.getFirmName());
+        KwtLogisticsOrderUnit agentUnit = finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(
+                record.getLOrderId() + "-" + LOGISTICS_AGENT_UNIT_TYPE, new KwtLogisticsOrderUnit());
+        KwtLogisticsOrderUnit supplyUnit = finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(
+                record.getLOrderId() + "-" + LOGISTICS_SUPPLY_UNIT_TYPE, new KwtLogisticsOrderUnit());
+        KwtLogisticsOrderUnit consignUnit = finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(
+                record.getLOrderId() + "-" + NumberConstant.ONE, new KwtLogisticsOrderUnit());
+        KwtLogisticsOrderUnit displayConsignUnit = chooseWaybillConsignUnit(agentUnit, supplyUnit, consignUnit);
+        waybillOrderResp.setConsignUnitId(String.valueOf(displayConsignUnit.getEntId()));
+        waybillOrderResp.setConsignUnitName(displayConsignUnit.getFirmName());
+        setListAgentUnitInfo(waybillOrderResp, agentUnit);
         KwtLogisticsOrderUnit carriageUnit =
                 finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(record.getLOrderId() + "-" + NumberConstant.TWO,
                 new KwtLogisticsOrderUnit());
@@ -4851,7 +5076,7 @@ public class KwtWaybillOrderV1Service {
         log.info("运单详情查询完成,运单ID: {}", billOrder.getId());
         return getWaybillOrderDetailResp(subtask, billOrder, logOrder, truck, fleet, goods,
                 keyAndAddressMap, kwpGoods, logisticsOrderUnitMap, nodeList, userCacheResDto,
-                billOrders, ticketMap, dictValueAndDictResDtoMap, tradeContractUnitDtos,contractGoodsDto);
+                billOrders, ticketMap, dictValueAndDictResDtoMap, tradeContractUnitDtos, orderDetailVo, contractGoodsDto);
     }
 
     /**
@@ -4989,6 +5214,7 @@ public class KwtWaybillOrderV1Service {
                                                                     Map<String, KwtWaybillOrderTicket> ticketMap,
                                                                     Map<String, Map<String, String>> dictValueAndDictResDtoMap,
                                                                     List<TradeContractUnitDto> tradeContractUnitDtos,
+                                                                    OrderDetailVo orderDetailVo,
                                                                     TradeContractGoodsDto contractGoodsDto) {
         WaybillOrderDetailResp resp = new WaybillOrderDetailResp();
 
@@ -5061,19 +5287,38 @@ public class KwtWaybillOrderV1Service {
         resp.setUnloadAmount(formatAmount(subtask.getUnloadAmount()) + unit);
 
         // 企业信息
+        String agentEntKey = logOrder.getId() + "-" + LOGISTICS_AGENT_UNIT_TYPE;
+        String supplyEntKey = logOrder.getId() + "-" + LOGISTICS_SUPPLY_UNIT_TYPE;
         String transEntKey = logOrder.getId() + "-" + UnitTypeEnum.CONSIGN.getCode();
         String carrierEntKey = logOrder.getId() + "-" + UnitTypeEnum.CARRIAGE.getCode();
+        KwtLogisticsOrderUnit agentEnt = logisticsOrderUnitMap.getOrDefault(agentEntKey, new KwtLogisticsOrderUnit());
+        KwtLogisticsOrderUnit supplyEnt = logisticsOrderUnitMap.getOrDefault(supplyEntKey, new KwtLogisticsOrderUnit());
         KwtLogisticsOrderUnit transEnt = logisticsOrderUnitMap.getOrDefault(transEntKey, new KwtLogisticsOrderUnit());
         KwtLogisticsOrderUnit carrierEnt = logisticsOrderUnitMap.getOrDefault(carrierEntKey, new KwtLogisticsOrderUnit());
-        resp.setTransEntName(transEnt.getFirmName());
+        resp.setTransEntName(chooseWaybillConsignUnit(agentEnt, supplyEnt, transEnt).getFirmName());
         resp.setCarrierEntName(carrierEnt.getFirmName());
+        setDetailAgentUnitInfo(resp, agentEnt);
 
         // 供应商信息
-        if (!CollectionUtils.isEmpty(tradeContractUnitDtos)) {
+        // 设置供应单位名称:优先使用物流订单中的供应单位,若无则从贸易合同单位中查找供应商类型的单位
+        if (hasValidLogisticsUnit(supplyEnt)) {
+            log.debug("运单详情-设置供应单位名称,来源:物流订单供应单位,名称:{}", supplyEnt.getFirmName());
+            resp.setSupplyEntName(supplyEnt.getFirmName());
+        } else if (!CollectionUtils.isEmpty(tradeContractUnitDtos)) {
+            // 从贸易合同单位列表中过滤出类型为“供应商”的单位,并取第一个匹配项
             tradeContractUnitDtos.stream()
                     .filter(x -> org.apache.commons.lang3.StringUtils.equals(x.getUnitType(), String.valueOf(CooperateTypeEnum.SUPPLIER.getCode())))
                     .findFirst()
-                    .ifPresent(x -> resp.setSupplyEntName(x.getFirmName()));
+                    .ifPresent(x -> {
+                        log.debug("运单详情-设置供应单位名称,来源:贸易合同供应商单位,名称:{}", x.getFirmName());
+                        resp.setSupplyEntName(x.getFirmName());
+                    });
+        }
+
+        // 设置代理单位信息:若物流订单中无有效代理单位,则尝试从贸易订单详情中获取代理信息
+        if (!hasValidLogisticsUnit(agentEnt)) {
+            log.debug("运单详情-物流订单无有效代理单位,尝试从贸易订单详情中获取代理信息");
+            setAgentUnitInfo(resp, orderDetailVo);
         }
 
         // 状态信息
@@ -5118,6 +5363,153 @@ public class KwtWaybillOrderV1Service {
         return resp;
     }
 
+
+    /**
+     * 按运单展示规则选择托运单位:有代理单位展示代理单位,否则展示供应单位,最后兼容原托运单位。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 优先展示代理单位(Agent Unit):若存在有效的代理单位信息,则直接返回。
+     * 2. 其次展示供应单位(Supply Unit):若无代理单位但存在有效的供应单位,则返回供应单位。
+     * 3. 兜底展示原托运单位(Consign Unit):若上述两者均无效,则返回原托运单位;若原托运单位也为空,则返回空对象以避免NPE。
+     * </p>
+     *
+     * @param agentUnit   物流订单代理单位
+     * @param supplyUnit  物流订单供应单位
+     * @param consignUnit 原物流订单托运单位
+     * @return 运单列表/详情需要展示的托运单位
+     */
+    static KwtLogisticsOrderUnit chooseWaybillConsignUnit(KwtLogisticsOrderUnit agentUnit,
+                                                          KwtLogisticsOrderUnit supplyUnit,
+                                                          KwtLogisticsOrderUnit consignUnit) {
+        // 1. 优先判断代理单位是否有效
+        if (hasValidLogisticsUnit(agentUnit)) {
+            log.debug("选择托运单位:命中代理单位,EntId: {}, FirmName: {}", agentUnit.getEntId(), agentUnit.getFirmName());
+            return agentUnit;
+        }
+
+        // 2. 其次判断供应单位是否有效
+        if (hasValidLogisticsUnit(supplyUnit)) {
+            log.debug("选择托运单位:无代理单位,命中供应单位,EntId: {}, FirmName: {}", supplyUnit.getEntId(), supplyUnit.getFirmName());
+            return supplyUnit;
+        }
+
+        // 3. 兜底返回原托运单位或空对象
+        if (Objects.isNull(consignUnit)) {
+            log.debug("选择托运单位:代理及供应单位均无效,且原托运单位为空,返回空对象");
+            return new KwtLogisticsOrderUnit();
+        }
+
+        log.debug("选择托运单位:代理及供应单位均无效,返回原托运单位,EntId: {}, FirmName: {}", consignUnit.getEntId(), consignUnit.getFirmName());
+        return consignUnit;
+    }
+
+    /**
+     * 判断物流订单单位是否具备有效企业信息。
+     *
+     * @param logisticsOrderUnit 物流订单单位
+     * @return true-有效,false-无效
+     */
+    static boolean hasValidLogisticsUnit(KwtLogisticsOrderUnit logisticsOrderUnit) {
+        return Objects.nonNull(logisticsOrderUnit) && Objects.nonNull(logisticsOrderUnit.getEntId());
+    }
+
+
+    /**
+     * 设置运单列表响应对象中的代理单位信息。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 校验响应对象和代理单位数据的有效性,若任一为空或无效则直接返回,避免空指针异常。
+     * 2. 将代理单位的企业ID转换为字符串并设置到响应对象中。
+     * 3. 安全地获取代理单位名称,若名称为空则设置为默认空字符串,防止前端展示null。
+     * </p>
+     *
+     * @param resp      运单列表响应对象,用于承载展示数据
+     * @param agentUnit 物流订单中的代理单位实体,包含企业ID和名称等信息
+     */
+    static void setListAgentUnitInfo(WaybillOrderResp resp, KwtLogisticsOrderUnit agentUnit) {
+        // 1. 基础参数校验:若响应对象为空或代理单位无效(无有效企业ID),则无需处理,直接返回
+        if (Objects.isNull(resp) || !hasValidLogisticsUnit(agentUnit)) {
+            log.debug("跳过设置代理单位信息:响应对象为空或代理单位无效");
+            return;
+        }
+
+        // 2. 设置代理企业ID:确保非空转换,记录日志以便追踪数据来源
+        String agentEntId = String.valueOf(agentUnit.getEntId());
+        resp.setAgentEntId(agentEntId);
+        log.debug("设置运单列表代理企业ID: {}", agentEntId);
+
+        // 3. 设置代理企业名称:使用StringUtils.defaultString处理可能的null值,确保前端展示友好
+        String agentFirmName = org.apache.commons.lang3.StringUtils.defaultString(agentUnit.getFirmName());
+        resp.setAgentFirmName(agentFirmName);
+        log.debug("设置运单列表代理企业名称: {}", agentFirmName);
+    }
+
+
+    /**
+     * 设置运单详情响应对象中的代理单位信息。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 校验响应对象和代理单位数据的有效性,若任一为空或无效则直接返回,避免空指针异常及无效赋值。
+     * 2. 将代理单位的企业ID转换为字符串并设置到响应对象中。
+     * 3. 安全地获取代理单位名称,若名称为空则设置为默认空字符串,防止前端展示null,提升用户体验。
+     * 4. 记录调试日志,便于追踪代理单位信息的赋值过程及排查数据问题。
+     * </p>
+     *
+     * @param resp      运单详情响应对象,用于承载展示数据
+     * @param agentUnit 物流订单中的代理单位实体,包含企业ID和名称等信息
+     */
+    static void setDetailAgentUnitInfo(WaybillOrderDetailResp resp, KwtLogisticsOrderUnit agentUnit) {
+        // 1. 基础参数校验:若响应对象为空或代理单位无效(无有效企业ID),则无需处理,直接返回
+        if (Objects.isNull(resp) || !hasValidLogisticsUnit(agentUnit)) {
+            log.debug("跳过设置运单详情代理单位信息:响应对象为空或代理单位无效");
+            return;
+        }
+
+        // 2. 提取并设置代理企业ID
+        String agentEntId = String.valueOf(agentUnit.getEntId());
+        resp.setAgentEntId(agentEntId);
+        log.debug("设置运单详情代理企业ID: {}", agentEntId);
+
+        // 3. 提取并设置代理企业名称,使用StringUtils.defaultString处理可能的null值,确保前端展示友好
+        String agentFirmName = org.apache.commons.lang3.StringUtils.defaultString(agentUnit.getFirmName());
+        resp.setAgentFirmName(agentFirmName);
+        log.debug("设置运单详情代理企业名称: {}", agentFirmName);
+    }
+
+
+    /**
+     * 设置运单详情响应对象中的代理单位信息。
+     * <p>
+     * 业务逻辑说明:
+     * 1. 校验响应对象、贸易订单详情数据的有效性,以及是否为代理贸易订单(agentFlag == Global.YES)。
+     * 2. 若满足条件,则从贸易订单详情中提取代理企业ID和代理企业名称,并设置到响应对象中。
+     * 3. 对代理企业名称进行空值处理,确保前端展示友好。
+     * </p>
+     *
+     * @param resp          运单详情响应对象,用于承载展示数据
+     * @param orderDetailVo 贸易订单详情对象,包含代理标识、代理企业ID及名称等信息
+     */
+    static void setAgentUnitInfo(WaybillOrderDetailResp resp, OrderDetailVo orderDetailVo) {
+        // 1. 基础参数校验:若响应对象为空、贸易订单详情为空,或非代理订单,则直接返回,无需设置代理信息
+        if (Objects.isNull(resp) || Objects.isNull(orderDetailVo)
+                || !Objects.equals(orderDetailVo.getAgentFlag(), Global.YES)) {
+            log.debug("跳过设置代理单位信息:响应对象为空、订单详情为空或非代理订单(agentFlag={})",
+                    orderDetailVo != null ? orderDetailVo.getAgentFlag() : "null");
+            return;
+        }
+
+        // 2. 提取并设置代理企业ID
+        Long agentEntId = orderDetailVo.getAgentEntId();
+        String agentEntIdStr = Objects.isNull(agentEntId) ? null : String.valueOf(agentEntId);
+        resp.setAgentEntId(agentEntIdStr);
+        log.debug("设置运单详情代理企业ID: {}", agentEntIdStr);
+
+        // 3. 提取并设置代理企业名称,使用StringUtils.defaultString处理可能的null值,防止前端展示null
+        String agentFirmName = org.apache.commons.lang3.StringUtils.defaultString(orderDetailVo.getAgentFirmName());
+        resp.setAgentFirmName(agentFirmName);
+        log.debug("设置运单详情代理企业名称: {}", agentFirmName);
+    }
+
     /**
      * 格式化金额
      */

+ 65 - 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,65 @@ 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());
+    }
+
+    /**
+     * Purchase and supply logistics order units should use type 5 and 6.
+     */
+    @Test
+    public void buildLogisticsOrderUnitWhenPurchaseAndSupplyExist() {
+        AddLogisticOrderDTO orderDTO = new AddLogisticOrderDTO();
+        orderDTO.setUserId(1001L);
+
+        EntCacheResDto purchaseEnt = new EntCacheResDto();
+        purchaseEnt.setId(9001L);
+        purchaseEnt.setFirmName("Purchase Company");
+        purchaseEnt.setContacts("Bob");
+        purchaseEnt.setPhone("13700000000");
+        purchaseEnt.setContactsId(8001L);
+        EntCacheResDto supplyEnt = new EntCacheResDto();
+        supplyEnt.setId(9002L);
+        supplyEnt.setFirmName("Supply Company");
+        supplyEnt.setContacts("Carol");
+        supplyEnt.setPhone("13600000000");
+        supplyEnt.setContactsId(7001L);
+
+        KwtLogisticsOrderUnit purchaseUnit = KwtAcceptCarriageOrderService.buildLogisticsOrderUnit(
+                orderDTO, 5001L, 1001L, purchaseEnt, KwtAcceptCarriageOrderService.LOGISTICS_PURCHASE_UNIT_TYPE);
+        KwtLogisticsOrderUnit supplyUnit = KwtAcceptCarriageOrderService.buildLogisticsOrderUnit(
+                orderDTO, 5001L, 2001L, supplyEnt, KwtAcceptCarriageOrderService.LOGISTICS_SUPPLY_UNIT_TYPE);
+
+        Assert.assertEquals(Integer.valueOf(5), purchaseUnit.getUnitType());
+        Assert.assertEquals(Long.valueOf(1001L), purchaseUnit.getEntId());
+        Assert.assertEquals(Long.valueOf(9001L), purchaseUnit.getTopEntId());
+        Assert.assertEquals(Integer.valueOf(6), supplyUnit.getUnitType());
+        Assert.assertEquals(Long.valueOf(2001L), supplyUnit.getEntId());
+        Assert.assertEquals(Long.valueOf(9002L), supplyUnit.getTopEntId());
+    }
 }

+ 101 - 0
sckw-modules/sckw-transport/src/test/java/com/sckw/transport/service/KwtLogisticsConsignmentServiceTest.java

@@ -1,9 +1,13 @@
 package com.sckw.transport.service;
 
+import com.sckw.order.api.model.OrderDetailVo;
+import com.sckw.transport.model.KwtLogisticsOrderUnit;
 import com.sckw.transport.model.param.QueryLogisticsOrderReq;
+import com.sckw.transport.model.vo.LogisticsOrderDetailResp;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -39,6 +43,19 @@ public class KwtLogisticsConsignmentServiceTest {
         Assert.assertEquals("煤炭", req.getKeywords());
     }
 
+    /**
+     * 代理单位查询存在时,应自动追加代理属性过滤。
+     */
+    @Test
+    public void applyAgentEntConditionWhenAgentEntIdExists() {
+        QueryLogisticsOrderReq req = new QueryLogisticsOrderReq();
+        req.setAgentEntId("1001");
+
+        KwtLogisticsConsignmentService.applyAgentEntCondition(req);
+
+        Assert.assertEquals(Integer.valueOf(1), req.getAgentFlag());
+    }
+
     /**
      * 无原有物流订单ID范围限制时,关键字段命中的ID作为最终范围。
      */
@@ -71,4 +88,88 @@ public class KwtLogisticsConsignmentServiceTest {
 
         Assert.assertTrue(result.isEmpty());
     }
+
+    /**
+     * 代理商名称关键字只应命中代理订单。
+     */
+    @Test
+    public void extractAgentTradeOrderIdsByAgentNameOnlyMatchesAgentOrders() {
+        OrderDetailVo agentOrder = new OrderDetailVo();
+        agentOrder.setId(1001L);
+        agentOrder.setAgentFlag(1);
+        agentOrder.setAgentFirmName("测试代理商");
+
+        OrderDetailVo normalOrder = new OrderDetailVo();
+        normalOrder.setId(1002L);
+        normalOrder.setAgentFlag(0);
+        normalOrder.setAgentFirmName("测试代理商");
+
+        OrderDetailVo otherAgentOrder = new OrderDetailVo();
+        otherAgentOrder.setId(1003L);
+        otherAgentOrder.setAgentFlag(1);
+        otherAgentOrder.setAgentFirmName("其他单位");
+
+        Set<Long> result = KwtLogisticsConsignmentService.extractAgentTradeOrderIdsByAgentName(
+                List.of(agentOrder, normalOrder, otherAgentOrder), "代理商");
+
+        Assert.assertEquals(Set.of(1001L), result);
+    }
+
+    /**
+     * 代理单位过滤应从物流订单企业表记录中提取指定代理单位关联的物流订单ID。
+     */
+    @Test
+    public void extractAgentLogOrderIdsByLogisticsUnitOnlyMatchesAgentEnt() {
+        KwtLogisticsOrderUnit matchedUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1001L)
+                .setEntId(2001L);
+        KwtLogisticsOrderUnit otherAgentUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1002L)
+                .setEntId(2002L);
+        KwtLogisticsOrderUnit invalidUnit = new KwtLogisticsOrderUnit()
+                .setEntId(2001L);
+
+        Set<Long> result = KwtLogisticsConsignmentService.extractAgentLogOrderIdsByLogisticsUnit(
+                List.of(matchedUnit, otherAgentUnit, invalidUnit), 2001L);
+
+        Assert.assertEquals(Set.of(1001L), result);
+    }
+
+    /**
+     * 代理商名称关键字查询应从物流订单企业表代理单位记录中提取物流订单ID。
+     */
+    @Test
+    public void extractAgentLogOrderIdsByAgentFirmNameOnlyMatchesKeyword() {
+        KwtLogisticsOrderUnit matchedUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1001L)
+                .setFirmName("测试代理商");
+        KwtLogisticsOrderUnit otherUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1002L)
+                .setFirmName("其他单位");
+        KwtLogisticsOrderUnit invalidUnit = new KwtLogisticsOrderUnit()
+                .setFirmName("测试代理商");
+
+        Set<Long> result = KwtLogisticsConsignmentService.extractAgentLogOrderIdsByAgentFirmName(
+                List.of(matchedUnit, otherUnit, invalidUnit), "代理商");
+
+        Assert.assertEquals(Set.of(1001L), result);
+    }
+
+    /**
+     * 物流订单详情代理单位应从物流订单企业表代理单位记录中设置。
+     */
+    @Test
+    public void setDetailAgentUnitInfoWhenAgentLogisticsUnitExists() {
+        LogisticsOrderDetailResp.UnitInfoVO unitInfoVO = new LogisticsOrderDetailResp.UnitInfoVO();
+        KwtLogisticsOrderUnit agentUnit = new KwtLogisticsOrderUnit()
+                .setEntId(2001L)
+                .setFirmName("测试代理单位")
+                .setPhone("13800000000");
+
+        KwtLogisticsConsignmentService.setDetailAgentUnitInfo(unitInfoVO, agentUnit);
+
+        Assert.assertEquals("2001", unitInfoVO.getAgentUnitId());
+        Assert.assertEquals("测试代理单位", unitInfoVO.getAgentUnitName());
+        Assert.assertEquals("13800000000", unitInfoVO.getAgentUnitPhone());
+    }
 }

+ 123 - 0
sckw-modules/sckw-transport/src/test/java/com/sckw/transport/service/KwtWaybillOrderV1ServiceTest.java

@@ -1,7 +1,11 @@
 package com.sckw.transport.service;
 
+import com.sckw.order.api.model.OrderDetailVo;
 import com.sckw.system.api.model.dto.res.EntTypeResDto;
+import com.sckw.transport.model.KwtLogisticsOrderUnit;
 import com.sckw.transport.model.param.WaybillOrderReq;
+import com.sckw.transport.model.param.WaybillOrderResp;
+import com.sckw.transport.model.vo.WaybillOrderDetailResp;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -156,4 +160,123 @@ public class KwtWaybillOrderV1ServiceTest {
 
         Assert.assertTrue(result.isEmpty());
     }
+
+    /**
+     * 代理商名称关键字应从物流订单企业表记录中提取命中的物流订单ID。
+     */
+    @Test
+    public void extractAgentLogOrderIdsByAgentFirmNameOnlyMatchesLogisticsUnits() {
+        KwtLogisticsOrderUnit matchedUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1001L)
+                .setFirmName("测试代理商");
+        KwtLogisticsOrderUnit otherUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1002L)
+                .setFirmName("其他单位");
+        KwtLogisticsOrderUnit invalidUnit = new KwtLogisticsOrderUnit()
+                .setFirmName("测试代理商");
+
+        Set<Long> result = KwtWaybillOrderV1Service.extractAgentLogOrderIdsByAgentFirmName(
+                List.of(matchedUnit, otherUnit, invalidUnit), "代理商");
+
+        Assert.assertEquals(Set.of(1001L), result);
+    }
+
+    /**
+     * 运单详情仅在代理贸易订单场景返回代理单位信息。
+     */
+    @Test
+    public void setAgentUnitInfoWhenAgentOrder() {
+        WaybillOrderDetailResp resp = new WaybillOrderDetailResp();
+        OrderDetailVo orderDetailVo = new OrderDetailVo();
+        orderDetailVo.setAgentFlag(1);
+        orderDetailVo.setAgentEntId(2001L);
+        orderDetailVo.setAgentFirmName("测试代理单位");
+
+        KwtWaybillOrderV1Service.setAgentUnitInfo(resp, orderDetailVo);
+
+        Assert.assertEquals("2001", resp.getAgentEntId());
+        Assert.assertEquals("测试代理单位", resp.getAgentFirmName());
+    }
+
+    /**
+     * 非代理贸易订单不返回代理单位信息。
+     */
+    @Test
+    public void setAgentUnitInfoWhenNotAgentOrder() {
+        WaybillOrderDetailResp resp = new WaybillOrderDetailResp();
+        OrderDetailVo orderDetailVo = new OrderDetailVo();
+        orderDetailVo.setAgentFlag(0);
+        orderDetailVo.setAgentEntId(2001L);
+        orderDetailVo.setAgentFirmName("测试代理单位");
+
+        KwtWaybillOrderV1Service.setAgentUnitInfo(resp, orderDetailVo);
+
+        Assert.assertNull(resp.getAgentEntId());
+        Assert.assertNull(resp.getAgentFirmName());
+    }
+
+    /**
+     * 运单托运单位展示有代理单位时,应优先展示代理单位。
+     */
+    @Test
+    public void chooseWaybillConsignUnitWhenAgentExists() {
+        KwtLogisticsOrderUnit agentUnit = new KwtLogisticsOrderUnit().setEntId(2001L).setFirmName("测试代理单位");
+        KwtLogisticsOrderUnit supplyUnit = new KwtLogisticsOrderUnit().setEntId(3001L).setFirmName("测试供应单位");
+        KwtLogisticsOrderUnit consignUnit = new KwtLogisticsOrderUnit().setEntId(4001L).setFirmName("测试托运单位");
+
+        KwtLogisticsOrderUnit result = KwtWaybillOrderV1Service.chooseWaybillConsignUnit(
+                agentUnit, supplyUnit, consignUnit);
+
+        Assert.assertEquals(Long.valueOf(2001L), result.getEntId());
+        Assert.assertEquals("测试代理单位", result.getFirmName());
+    }
+
+    /**
+     * 运单托运单位展示无代理单位时,应展示供应单位。
+     */
+    @Test
+    public void chooseWaybillConsignUnitWhenAgentMissing() {
+        KwtLogisticsOrderUnit supplyUnit = new KwtLogisticsOrderUnit().setEntId(3001L).setFirmName("测试供应单位");
+        KwtLogisticsOrderUnit consignUnit = new KwtLogisticsOrderUnit().setEntId(4001L).setFirmName("测试托运单位");
+
+        KwtLogisticsOrderUnit result = KwtWaybillOrderV1Service.chooseWaybillConsignUnit(
+                new KwtLogisticsOrderUnit(), supplyUnit, consignUnit);
+
+        Assert.assertEquals(Long.valueOf(3001L), result.getEntId());
+        Assert.assertEquals("测试供应单位", result.getFirmName());
+    }
+
+    /**
+     * 运单列表应从物流订单企业表代理单位记录补充代理单位列。
+     */
+    @Test
+    public void setListAgentUnitInfoWhenAgentLogisticsUnitExists() {
+        WaybillOrderResp resp = new WaybillOrderResp();
+        KwtLogisticsOrderUnit agentUnit = new KwtLogisticsOrderUnit().setEntId(2001L).setFirmName("测试代理单位");
+
+        KwtWaybillOrderV1Service.setListAgentUnitInfo(resp, agentUnit);
+
+        Assert.assertEquals("2001", resp.getAgentEntId());
+        Assert.assertEquals("测试代理单位", resp.getAgentFirmName());
+    }
+
+    /**
+     * 运单列表代理单位查询应从物流订单企业表记录中提取指定代理单位关联的物流订单ID。
+     */
+    @Test
+    public void extractAgentLogOrderIdsByLogisticsUnitOnlyMatchesAgentEnt() {
+        KwtLogisticsOrderUnit matchedUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1001L)
+                .setEntId(2001L);
+        KwtLogisticsOrderUnit otherAgentUnit = new KwtLogisticsOrderUnit()
+                .setLOrderId(1002L)
+                .setEntId(2002L);
+        KwtLogisticsOrderUnit invalidUnit = new KwtLogisticsOrderUnit()
+                .setEntId(2001L);
+
+        Set<Long> result = KwtWaybillOrderV1Service.extractAgentLogOrderIdsByLogisticsUnit(
+                List.of(matchedUnit, otherAgentUnit, invalidUnit), 2001L);
+
+        Assert.assertEquals(Set.of(1001L), result);
+    }
 }