Prechádzať zdrojové kódy

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

donglang 3 týždňov pred
rodič
commit
c484cb3588

+ 3 - 0
.gitignore

@@ -29,3 +29,6 @@ logs
 
 /sckw-modules/.yapix
 /sckw-modules/sckw-transport/openapi.yaml
+**/rebel.xml
+*.rebel.xml
+**/*.rebel.xml

+ 1 - 1
sckw-common/sckw-common-remote/src/main/java/com/sckw/remote/annotation/SckwRemoteApplication.java

@@ -12,6 +12,6 @@ import java.lang.annotation.*;
 @Inherited
 @EnableDubbo
 @EnableFeignClients({"com.sckw.*.api.feign"})
-@ComponentScan(basePackages = {"com.sckw.message.consumer","com.sckw.file.config", "com.sckw.payment.config", "com.sckw.fleet.config", "com.sckw.remote.filter", "com.sckw.*.dao","com.sckw.*.controller", "com.sckw.*.service", "com.sckw.*.repository", "com.sckw.*.dubbo", "com.sckw.*.model", "com.sckw.transport.*", "com.sckw.*.serivce","com.sckw.transport.config","com.sckw.contract.config"})
+@ComponentScan(basePackages = {"com.sckw.message.consumer","com.sckw.order","com.sckw.file.config", "com.sckw.payment.config", "com.sckw.fleet.config", "com.sckw.remote.filter", "com.sckw.*.dao","com.sckw.*.controller", "com.sckw.*.service", "com.sckw.*.repository", "com.sckw.*.dubbo", "com.sckw.*.model", "com.sckw.transport.*", "com.sckw.*.serivce","com.sckw.transport.config","com.sckw.contract.config"})
 public @interface SckwRemoteApplication {
 }

+ 2 - 1
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/operateService/KwcContractLogisticsService.java

@@ -1520,7 +1520,8 @@ public class KwcContractLogisticsService {
         tradeBaseInfo.setDispatchWayDesc(DispatchingTypeEnum.getLabel(logistics.getDispatchWay()));
 
         tradeBaseInfo.setStartTime(logistics.getStartTime());
-        tradeBaseInfo.setCommonPrice(logistics.getCommonPrice());
+
+        tradeBaseInfo.setCommonPrice(logistics.getCommonPrice().compareTo(new BigDecimal("0.00"))==0 ? null: logistics.getCommonPrice());
         tradeBaseInfo.setContractStatus(String.valueOf(logistics.getStatus()));
         tradeBaseInfo.setContractStatusDesc(ContractStatusEnum.getNameByCode(logistics.getStatus()));
 

+ 2 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/OrderApplication.java

@@ -4,6 +4,7 @@ import com.sckw.remote.annotation.SckwRemoteApplication;
 import com.sckw.startup.annotation.SckwCloudApplication;
 import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy;
 import org.springframework.boot.SpringApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * @desc: 订单服务
@@ -13,6 +14,7 @@ import org.springframework.boot.SpringApplication;
 @EnableAutoDataSourceProxy
 @SckwRemoteApplication
 @SckwCloudApplication
+@EnableScheduling
 public class OrderApplication {
 
     public static void main(String[] args) {

+ 9 - 4
sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderService.java

@@ -683,7 +683,7 @@ public class KwoTradeOrderService {
         if (Objects.isNull(order)) {
             throw new BusinessException("不存在该订单!");
         }
-        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.TRADE_TYPE.getType(), DictTypeEnum.PICKUP_TYPE.getType(), DictTypeEnum.DELIVERY_TYPE.getType(), DictTypeEnum.TORDER_SOURCE.getType(), DictTypeEnum.TORDER_STATUS.getType(), DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.UNIT_TYPE.getType(), DictTypeEnum.TAX_RATE.getType(), DictTypeEnum.TORDER_UNIT_TYPE.getType(), DictTypeEnum.TORDER_ADDRESS_TYPE.getType(), DictTypeEnum.ADDRESS_TYPE.getType(), DictTypeEnum.CONSIGNMENT_WAY.getType(), DictTypeEnum.CHARGING_TYPE.getType()));
+        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.TRADE_TYPE.getType(), DictTypeEnum.PICKUP_TYPE.getType(), DictTypeEnum.DELIVERY_TYPE.getType(), DictTypeEnum.TORDER_SOURCE.getType(), DictTypeEnum.TORDER_STATUS.getType(), DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.UNIT_TYPE.getType(), DictTypeEnum.TAX_RATE.getType(), DictTypeEnum.TORDER_UNIT_TYPE.getType(), DictTypeEnum.TORDER_ADDRESS_TYPE.getType(), DictTypeEnum.ADDRESS_TYPE.getType(), DictTypeEnum.CONSIGNMENT_WAY.getType(), DictTypeEnum.CHARGING_TYPE.getType(), DictTypeEnum.GOODS_SPEC.getType()));
         Map<String, String> pickupMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> deleveryMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> sourceMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
@@ -693,6 +693,7 @@ public class KwoTradeOrderService {
         Map<String, String> taxRateMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> chargeTypeMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> consignmentWayMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
+        Map<String, String> goodspec = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> orderUnitMap, orderAddressMap, addressMap;
         if (CollUtil.isNotEmpty(dict)) {
             pickupMap = dict.get(DictTypeEnum.CONSIGNMENT_WAY.getType());
@@ -707,6 +708,7 @@ public class KwoTradeOrderService {
             addressMap = dict.get(DictTypeEnum.ADDRESS_TYPE.getType());
             chargeTypeMap = dict.get(DictTypeEnum.CHARGING_TYPE.getType());
             consignmentWayMap = dict.get(DictTypeEnum.CONSIGNMENT_WAY.getType());
+            goodspec = dict.get(DictTypeEnum.GOODS_SPEC.getType());
         } else {
             orderUnitMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
             orderAddressMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
@@ -740,6 +742,7 @@ public class KwoTradeOrderService {
                 EntCacheResDto entCache = remoteSystemService.queryEntCacheById(goods.getEntId());
                 GoodsInfoDetailRes goodsDetail = new GoodsInfoDetailRes();
                 goodsDetail.setGoodsTypeLabel(CollUtil.isNotEmpty(prodcutNameMap) ? prodcutNameMap.get(goods.getGoodsType()) : null).setUnitLabel(CollUtil.isNotEmpty(unitMap) ? unitMap.get(goods.getUnit()) : null).setTaxRateLabel(CollUtil.isNotEmpty(taxRateMap) ? taxRateMap.get(goods.getTaxRate()) : null).setGoodsAmount(goods.getAmount()).setGoodsId(goods.getId()).setCode(goods.getCode()).setName(goods.getName()).setGoodsType(goods.getGoodsType()).setTaxRate(goods.getTaxRate()).setSpec(goods.getSpec()).setUnit(goods.getUnit()).setPriceRangeId(orderGoods.getPriceRangeId()).setUnitPrice(orderGoods.getUnitPrice()).setSkuId(orderGoods.getSkuId()).setCollectionUnitId(goods.getEntId()).setGoodsThumb(goods.getThumb()).setPrepaidLimit(goods.getPrepaidLimit()).setAdvancePrice(goods.getAdvancePrice()).setCollectionUnit(Objects.isNull(entCache) ? null : entCache.getFirmName());
+                goodsDetail.setSpec(CollUtil.isNotEmpty(goodspec) ? goodspec.get(goods.getSpec()) : null);
                 detail.setGoodsInfo(goodsDetail);
                 if (Objects.equals(detail.getChargeType(), 1)) {//按装货量
                     detail.setDealMoney(NumberUtil.mul(orderGoods.getUnitPrice(), detail.getLoadAmount()));
@@ -1583,15 +1586,16 @@ public class KwoTradeOrderService {
         Map<Long, UserCacheResDto> userMap = remoteSystemService.queryUserCacheMapByIds(createByIds);
         Map<Long, KwpGoods> goodsMap = goodsInfoService.getGoodsByIds(goodIdList);
         Map<Long, ContractCommonInfoResDto> contractMap = remoteContractService.queryContractBaseInfo(contracIdList);
-        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.TORDER_STATUS.getType(), DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.TRADE_TYPE.getType(), DictTypeEnum.SETTLEMENT_WAY.getType(), DictTypeEnum.CONSIGNMENT_WAY.getType(), DictTypeEnum.TORDER_SOURCE.getType()));
+        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.TORDER_STATUS.getType(), DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.TRADE_TYPE.getType(), DictTypeEnum.SETTLEMENT_WAY.getType(), DictTypeEnum.CONSIGNMENT_WAY.getType(), DictTypeEnum.TORDER_SOURCE.getType(), DictTypeEnum.GOODS_SPEC.getType()));
         Map<String, SysDictResDto> unitType = remoteSystemService.queryDictMapByType(DictTypeEnum.UNIT_TYPE.getType());
-        Map<String, String> tradeMap, deliveryMap, pickupMap, sourceMap, nameMap;
+        Map<String, String> tradeMap, deliveryMap, pickupMap, sourceMap, nameMap, specMap;
         if (CollUtil.isNotEmpty(dict)) {
             tradeMap = CollUtil.isNotEmpty(dict.get(DictTypeEnum.TRADE_TYPE.getType())) ? dict.get(DictTypeEnum.TRADE_TYPE.getType()) : new HashMap<>(Global.NUMERICAL_SIXTEEN);
             deliveryMap = CollUtil.isNotEmpty(dict.get(DictTypeEnum.SETTLEMENT_WAY.getType())) ? dict.get(DictTypeEnum.SETTLEMENT_WAY.getType()) : new HashMap<>(Global.NUMERICAL_SIXTEEN);
             pickupMap = CollUtil.isNotEmpty(dict.get(DictTypeEnum.CONSIGNMENT_WAY.getType())) ? dict.get(DictTypeEnum.CONSIGNMENT_WAY.getType()) : new HashMap<>(Global.NUMERICAL_SIXTEEN);
             sourceMap = CollUtil.isNotEmpty(dict.get(DictTypeEnum.TORDER_SOURCE.getType())) ? dict.get(DictTypeEnum.TORDER_SOURCE.getType()) : new HashMap<>(Global.NUMERICAL_SIXTEEN);
             nameMap = CollUtil.isNotEmpty(dict.get(DictTypeEnum.PRODUCT_NAME_TYPE.getType())) ? dict.get(DictTypeEnum.PRODUCT_NAME_TYPE.getType()) : new HashMap<>(Global.NUMERICAL_SIXTEEN);
+            specMap = CollUtil.isNotEmpty(dict.get(DictTypeEnum.GOODS_SPEC.getType())) ? dict.get(DictTypeEnum.GOODS_SPEC.getType()) : new HashMap<>(Global.NUMERICAL_SIXTEEN);
 
         } else {
             tradeMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
@@ -1599,6 +1603,7 @@ public class KwoTradeOrderService {
             pickupMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
             sourceMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
             nameMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
+            specMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         }
         list.forEach(e -> {
             //装货地址
@@ -1617,7 +1622,7 @@ public class KwoTradeOrderService {
 
             OrderListResVO vo = BeanUtil.copyProperties(e, OrderListResVO.class);
             vo.setStatusLabel(TradeOrderStatusEnum.getMsg(e.getStatus())).setTradingLabel(tradeMap.get(e.getTrading())).setTrading(tradeMap.get(e.getTrading())).setDeliveryType(deliveryMap.get(e.getDeliveryType())).setPickupTypeLabel(pickupMap.get(e.getPickupType())).setSourceLabel(sourceMap.get(e.getSource())).setSource(sourceMap.get(e.getSource())).setContractName(Objects.isNull(contract) ? null : contract.getContactName()).setContractSigningWay(Objects.isNull(contract) ? null : contract.getSigningWayName()).setGoodsName(Objects.isNull(goods) ? null : goods.getName());
-            vo.setGoodsSpec(Objects.isNull(goods) ? null : goods.getSpec());
+            vo.setGoodsSpec(Objects.isNull(goods) ? "" : CollUtil.isNotEmpty(specMap) ? specMap.get(goods.getSpec()) : null);
             vo.setGoodsTaxRate(Objects.isNull(goods) ? null : goods.getTaxRate());
             vo.setGoodsThumb(Objects.isNull(goods) ? null : goods.getThumb());
             vo.setGoodsType(Objects.isNull(goods) ? null : goods.getGoodsType());

+ 110 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/task/TradeOrderTask.java

@@ -0,0 +1,110 @@
+package com.sckw.order.task;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.NumberUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.sckw.core.model.constant.Global;
+import com.sckw.core.model.enums.LogisticsOrderV1Enum;
+import com.sckw.order.dao.KwoTradeOrderGoodsMapper;
+import com.sckw.order.dao.KwoTradeOrderMapper;
+import com.sckw.order.dao.KwoTradeOrderUnitMapper;
+import com.sckw.order.enums.TradeOrderStatusEnum;
+import com.sckw.order.model.KwoTradeOrder;
+import com.sckw.order.model.KwoTradeOrderGoods;
+import com.sckw.order.model.KwoTradeOrderUnit;
+import com.sckw.payment.api.feign.WalletApi;
+import com.sckw.payment.api.model.WalletFreeze;
+import com.sckw.transport.api.dubbo.TransportRemoteService;
+import com.sckw.transport.api.model.param.OrderFinishParam;
+import com.sckw.transport.api.model.vo.KwtLogisticsOrderVO;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @author xucaiqin
+ * @date 2025-12-19 09:05:54
+ */
+@Slf4j
+@Component
+public class TradeOrderTask {
+    @Resource
+    private KwoTradeOrderMapper kwoTradeOrderMapper;
+    @Resource
+    private KwoTradeOrderUnitMapper kwoTradeOrderUnitMapper;
+    @Resource
+    private KwoTradeOrderGoodsMapper kwoTradeOrderGoodsMapper;
+    @Resource
+    private WalletApi walletApi;
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
+    private TransportRemoteService transportRemoteService;
+    private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(20));
+
+    @Scheduled(cron = "0 0/5 * * * ?")
+    public void task() {
+        List<KwoTradeOrder> kwoTradeOrders = kwoTradeOrderMapper.selectList(new LambdaQueryWrapper<KwoTradeOrder>()
+                .eq(KwoTradeOrder::getStatus, TradeOrderStatusEnum.DEAL.getCode())
+                .eq(KwoTradeOrder::getDelFlag, Global.UN_DELETED)
+        );
+        if (CollUtil.isNotEmpty(kwoTradeOrders)) {
+            for (KwoTradeOrder kwoTradeOrder : kwoTradeOrders) {
+                List<KwtLogisticsOrderVO> logisticOrderList = transportRemoteService.getLogisticOrderList(new OrderFinishParam(kwoTradeOrder.getId()));
+                if (logisticOrderList.stream().anyMatch(d -> Objects.equals(d.getStatus(), LogisticsOrderV1Enum.NEARING_COMPLETION.getCode()))) {
+                    return;
+                }
+                threadPoolExecutor.execute(() -> {
+                    try {
+                        List<KwoTradeOrderUnit> orderUnits = kwoTradeOrderUnitMapper.selectList(new LambdaQueryWrapper<KwoTradeOrderUnit>().eq(KwoTradeOrderUnit::getTOrderId, kwoTradeOrder.getId())
+                                .eq(KwoTradeOrderUnit::getDelFlag, 0)
+                        );
+                        if (CollUtil.isEmpty(orderUnits) || orderUnits.size() < 2) {
+                            log.error("订单异常,未找到关联企业。订单id {}", kwoTradeOrder.getId());
+                            return;
+                        }
+                        Map<String, KwoTradeOrderUnit> unitMap = orderUnits.stream().collect(Collectors.toMap(KwoTradeOrderUnit::getUnitType, Function.identity(), (a, b) -> a));
+                        BigDecimal sum;
+                        if (Objects.equals(kwoTradeOrder.getChargeType(), 1)) {
+                            //按装货量
+                            sum = logisticOrderList.stream().map(KwtLogisticsOrderVO::getLoadAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+                        } else {
+                            sum = logisticOrderList.stream().map(KwtLogisticsOrderVO::getUnloadAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+                        }
+                        KwoTradeOrderGoods kwoTradeOrderGoods = kwoTradeOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwoTradeOrderGoods>()
+                                .eq(KwoTradeOrderGoods::getDelFlag, 0)
+                                .eq(KwoTradeOrderGoods::getTOrderId, kwoTradeOrder.getId())
+                                .last("limit 1")
+                        );
+
+                        //更新贸易订单状态
+                        WalletFreeze walletFreeze = new WalletFreeze();
+                        walletFreeze.setBuyEntId(unitMap.getOrDefault("1", new KwoTradeOrderUnit()).getEntId());
+                        walletFreeze.setSaleEntId(unitMap.getOrDefault("2", new KwoTradeOrderUnit()).getEntId());
+                        walletFreeze.setMoney(NumberUtil.mul(sum, kwoTradeOrderGoods.getUnitPrice()));
+                        walletFreeze.setTTradeOrderId(kwoTradeOrder.getId());
+                        walletFreeze.setOrderNo(kwoTradeOrder.getTOrderNo());
+                        log.info("结算 {}", JSONObject.toJSONString(walletFreeze));
+                        walletApi.dealMoney(walletFreeze);
+                    } catch (Exception ex) {
+                        log.error("更新订单异常{}", ex.getMessage());
+                    }
+                });
+
+            }
+
+        }
+
+    }
+}

+ 6 - 1
sckw-modules/sckw-product/src/main/java/com/sckw/product/service/KwpGoodsService.java

@@ -262,16 +262,20 @@ public class KwpGoodsService {
                 DictTypeEnum.UNIT_TYPE.getType(),
                 DictTypeEnum.TAX_RATE.getType(),
                 DictTypeEnum.GOODS_STATUS.getType(),
-                DictTypeEnum.ADDRESS_TYPE.getType()));
+                DictTypeEnum.ADDRESS_TYPE.getType(),
+                DictTypeEnum.GOODS_SPEC.getType())
+        );
         Map<String, String> productNameMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> unitMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> goodsStatusMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         Map<String, String> addressMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
+        Map<String, String> goodsMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
         if (CollectionUtils.isNotEmpty(dict)) {
             productNameMap = dict.get(DictTypeEnum.PRODUCT_NAME_TYPE.getType());
             unitMap = dict.get(DictTypeEnum.UNIT_TYPE.getType());
             goodsStatusMap = dict.get(DictTypeEnum.GOODS_STATUS.getType());
             addressMap = dict.get(DictTypeEnum.ADDRESS_TYPE.getType());
+            goodsMap = dict.get(DictTypeEnum.GOODS_SPEC.getType());
         }
         List<SysDictResDto> types = remoteSystemService.queryDictFrontAll(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), detail.getGoodsType());
         if (CollectionUtils.isNotEmpty(types)) {
@@ -280,6 +284,7 @@ public class KwpGoodsService {
         }
         detail.setGoodsTypeLabel(CollectionUtils.isNotEmpty(productNameMap) ? productNameMap.get(detail.getGoodsType()) : null)
                 .setUnitLabel(CollectionUtils.isNotEmpty(unitMap) ? unitMap.get(detail.getUnit()) : null)
+                .setSpec(CollectionUtils.isNotEmpty(goodsMap) ? goodsMap.get(detail.getSpec()) : null)
                 .setStatusLabel(CollectionUtils.isNotEmpty(goodsStatusMap) ? goodsStatusMap.get(String.valueOf(detail.getStatus())) : null);
         //商品图片信息
         if (Objects.nonNull(goods.getThumb())) {

+ 2 - 3
sckw-modules/sckw-system/src/main/java/com/sckw/system/repository/SysDictRepository.java

@@ -27,11 +27,10 @@ public class SysDictRepository extends ServiceImpl<SysDictDao, SysDict> {
     /**
      * 根据条件查询唯一字典
      */
-    public SysDict selectUniqueDict(Long dictTypeId, String value, String label,String type, String parentId) {
+    public SysDict selectUniqueDict(Long dictTypeId,String label, String type, String parentId) {
         return this.getOne(Wrappers.<SysDict>lambdaQuery()
                 .eq(BaseModel::getDelFlag,0)
                 .eq(Objects.nonNull(dictTypeId),SysDict::getDictId, dictTypeId)
-                .eq(StringUtils.isNotBlank(value),SysDict::getValue, value)
                 .eq(StringUtils.isNotBlank(label),SysDict::getLabel, label)
                 .eq(StringUtils.isNotBlank( type),SysDict::getType, type)
                 .eq(StringUtils.isNotBlank(parentId),SysDict::getParentId, parentId)
@@ -70,7 +69,7 @@ public class SysDictRepository extends ServiceImpl<SysDictDao, SysDict> {
                 .eq(SysDict::getDelFlag, 0)
                 .eq(StringUtils.isNotBlank(type), SysDict::getType, type)
                 .eq(StringUtils.isNotBlank(parentId), SysDict::getParentId, parentId)
-                .eq(StringUtils.isNotBlank(label), SysDict::getLabel, label)
+                .like(StringUtils.isNotBlank(label), SysDict::getLabel, label)
                 .orderByDesc(BaseModel::getCreateTime)
                 .orderByAsc(SysDict::getSort);
         return page(page,wrapper);

+ 42 - 8
sckw-modules/sckw-system/src/main/java/com/sckw/system/service/SysDictFlexBusinessService.java

@@ -3,10 +3,12 @@ package com.sckw.system.service;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.google.common.collect.Maps;
+import com.sckw.core.exception.BusinessException;
 import com.sckw.core.model.base.BaseModel;
 import com.sckw.core.utils.IdWorker;
 import com.sckw.core.web.context.LoginUserHolder;
 import com.sckw.core.web.response.result.PageDataResult;
+import com.sckw.redis.utils.RedissonUtils;
 import com.sckw.system.model.SysDict;
 import com.sckw.system.model.SysDictType;
 import com.sckw.system.model.vo.req.SysDictReqVo;
@@ -47,22 +49,37 @@ public class SysDictFlexBusinessService {
         
         // 业务校验:检查是否存在相同的字典项
         SysDict existDict = sysDictRepository.selectUniqueDict(
-            entity.getDictId(), 
-            entity.getValue(), 
+            entity.getDictId(),
             entity.getLabel(),
             entity.getType(),
             entity.getParentId()
         );
         if (existDict != null) {
-            log.error("字典项已存在,请勿重复添加");
-            return Boolean.FALSE;
+           // return Boolean.FALSE;
+            if (StringUtils.equals(entity.getLabel(), existDict.getLabel())){
+                log.error("字典名称已存在,请勿重复添加");
+                throw new BusinessException("字典名称已存在,请勿重复添加");
+            }
+            if (StringUtils.equals(entity.getValue(), existDict.getValue())) {
+                log.error("字典项值已存在,请勿重复添加");
+                throw new BusinessException("字典项值已存在,请勿重复添加");
+            }
+
         }
         
         // 设置创建信息
         Long userId = LoginUserHolder.getUserId();
         long id = new IdWorker(1L).nextId();
         SysDict sysDict = getSysDict(entity, id, userId);
-        return sysDictRepository.save(sysDict) ;
+        Boolean result = sysDictRepository.save(sysDict);
+        
+        // 删除以"dictInfo:"开头的缓存
+        if (result) {
+            log.info("新增字典成功删除以\"dictInfo:\"开头的缓存");
+            RedissonUtils.deleteBactch("dictInfo:*");
+        }
+        
+        return result;
     }
 
     @NotNull
@@ -111,13 +128,25 @@ public class SysDictFlexBusinessService {
         // 设置更新信息
         Long userId = LoginUserHolder.getUserId();
         SysDict sysDict = new SysDict();
+        sysDict.setDictId(entity.getDictId());
+        sysDict.setValue(entity.getValue());
+        sysDict.setLabel(entity.getLabel());
+        sysDict.setType(entity.getType());
+        sysDict.setDescription(entity.getDescription());
+        sysDict.setParentId(StringUtils.isBlank(entity.getParentId()) ? "0" : entity.getParentId());
         sysDict.setId(existDict.getId());
         sysDict.setSort(entity.getSort());
         sysDict.setRemark(entity.getRemark());
         sysDict.setUpdateBy(userId);
         sysDict.setUpdateTime(new Date());
-        
-        return sysDictRepository.update(sysDict);
+
+        Boolean update = sysDictRepository.update(sysDict);
+        // 删除以"dictInfo:"开头的缓存
+        if (update) {
+            log.info("更新字典成功删除以\"dictInfo:\"开头的缓存");
+            RedissonUtils.deleteBactch("dictInfo:*");
+        }
+        return update;
     }
 
 
@@ -214,7 +243,12 @@ public class SysDictFlexBusinessService {
         }
         
         // 更新状态
-        return sysDictRepository.updateStatus(id, status);
+        Boolean update = sysDictRepository.updateStatus(id, status);
+        if (update) {
+            log.info("更新字典状态成功,删除缓存,字典id:{}", id);
+            RedissonUtils.deleteBactch("dictInfo:*");
+        }
+        return update;
     }
 
     /**

+ 7 - 2
sckw-modules/sckw-system/src/main/resources/mapper/SysDictDao.xml

@@ -193,6 +193,7 @@
     <include refid="Base_Column_List" />
     from sys_dict
     where del_flag = 0
+    and status = 0
     <if test="type != null and type != ''">
       and type = #{type, jdbcType=VARCHAR}
     </if>
@@ -210,6 +211,7 @@
       id, value, label, type, description, remark,url
     from sys_dict
     where del_flag = 0
+    and status = 0
     <if test="type != null and type != ''">
       and type = #{type, jdbcType=VARCHAR}
     </if>
@@ -223,7 +225,7 @@
   </select>
 
   <select id="queryByType" resultType="com.sckw.system.model.SysDict">
-    select * from sys_dict where del_flag = 0 and type = #{type} order by sort
+    select * from sys_dict where del_flag = 0 and type = #{type} and status = 0  order by sort
   </select>
 
   <select id="queryUnitDict" resultType="com.sckw.system.model.SysDict">
@@ -232,6 +234,7 @@
      where del_flag = 0
        and dict_id = #{dictTypeId}
        and parent_id = #{parentId}
+       and status = 0
        and (value = #{value} or label = #{label})
     order by sort
   </select>
@@ -240,6 +243,7 @@
     select *
     from sys_dict
     where del_flag = 0
+    and status = 0
       and type = #{type}
       and value = #{value} limit 1
   </select>
@@ -248,6 +252,7 @@
     select *
       from sys_dict
      where del_flag = 0
+       and status = 0
   </select>
 
   <select id="selectByKeys" resultType="com.sckw.system.model.SysDict">
@@ -261,4 +266,4 @@
      </foreach>
   </select>
 
-</mapper>
+</mapper>

+ 2 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/TransPortApplication.java

@@ -6,6 +6,7 @@ import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * @author lfdc
@@ -16,6 +17,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
 @SckwRemoteApplication
 @SckwCloudApplication
 @MapperScan("com.sckw.transport.dao")
+@EnableScheduling
 public class TransPortApplication {
     public static void main(String[] args) {
         SpringApplication.run(TransPortApplication.class, args);

+ 3 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java

@@ -3426,7 +3426,9 @@ public class KwtWaybillOrderV1Service {
 
         RFleetVo fleet = null;
         try {
+            log.info("查询车队信息车辆id:{}",  billOrder.getId());
             fleet = remoteFleetService.findFleetByTruckId(billOrder.getTruckId());
+            log.info("查询车队信息:{}", JSON.toJSONString( fleet));
         } catch (Exception e) {
             log.info("查询车队信息异常:{}",  e.getMessage());
         }
@@ -4335,7 +4337,7 @@ public class KwtWaybillOrderV1Service {
             vo.setImageUrl(node.getWeighUrl());
             if (Objects.equals(node.getOrderStatus(), CarWaybillV1Enum.COMPLETION_LOADING.getCode())){
                 KwtWaybillOrderSubtask subtask = waybillOrderSubtaskRepository.queryByWOrderId(node.getWOrderId());
-                vo.setCredential(Optional.ofNullable(subtask).map(KwtWaybillOrderSubtask::getUnloadUrl).orElse(""));
+                vo.setImageUrl(Optional.ofNullable(subtask).map(KwtWaybillOrderSubtask::getUnloadUrl).orElse(""));
             }
 
             // 构建状态描述

+ 138 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/task/LogisticsOrderCompletionTask.java

@@ -0,0 +1,138 @@
+package com.sckw.transport.task;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.sckw.core.exception.BusinessException;
+import com.sckw.core.model.enums.CarWaybillV1Enum;
+import com.sckw.core.model.enums.LogisticsOrderV1Enum;
+import com.sckw.transport.model.KwtLogisticsOrder;
+import com.sckw.transport.model.KwtWaybillOrderSubtask;
+import com.sckw.transport.repository.KwtLogisticsOrderRepository;
+import com.sckw.transport.repository.KwtWaybillOrderSubtaskRepository;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @desc: 物流订单自动完成定时任务
+ * @desc: 查询状态为"完结中"的物流订单,如果该订单下的所有运单状态都是"已完成",则将物流订单状态更新为"已完成"
+ * @author: cxf
+ * @date: 2025-12-19
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class LogisticsOrderCompletionTask {
+
+    private final KwtLogisticsOrderRepository logisticsOrderRepository;
+    private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
+
+    /**
+     * 定时任务:每5分钟执行一次
+     * cron表达式:0 0/5 * * * ? 表示每5分钟执行一次
+     * 可以根据实际需求调整执行频率
+     */
+    @Scheduled(cron = "${schedule.logistics-order-completion-cron}")
+    public void process() {
+        log.info("物流订单自动完成定时任务开始...");
+        
+        try {
+            // 查询状态为"完结中"的物流订单
+            List<KwtLogisticsOrder> nearingCompletionOrders = logisticsOrderRepository.list(
+                    new LambdaQueryWrapper<KwtLogisticsOrder>()
+                            .eq(KwtLogisticsOrder::getStatus, LogisticsOrderV1Enum.NEARING_COMPLETION.getCode())
+                            .eq(KwtLogisticsOrder::getDelFlag, 0)
+            );
+
+            if (CollectionUtils.isEmpty(nearingCompletionOrders)) {
+                log.info("没有状态为'完结中'的物流订单需要处理");
+                return;
+            }
+
+            log.info("查询到{}条状态为'完结中'的物流订单", nearingCompletionOrders.size());
+
+            // 提取物流订单ID列表
+            List<Long> logisticOrderIds = nearingCompletionOrders
+                    .stream()
+                    .map(KwtLogisticsOrder::getId)
+                    .collect(Collectors.toList());
+            
+            // 根据物流订单ID查询相关运单子任务
+            List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.queryByLogIds(logisticOrderIds);
+            
+            // 按照物流订单ID分组运单子任务
+            Map<Long, List<KwtWaybillOrderSubtask>> logOrderSubtasksMap = Optional.ofNullable(subtasks)
+                    .orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getLOrderId));
+            
+            // 准备需要更新的物流订单列表
+            List<KwtLogisticsOrder> updateLogisticOrders = new ArrayList<>();
+            
+            // 遍历每个物流订单及其关联的运单子任务
+            for (Map.Entry<Long, List<KwtWaybillOrderSubtask>> entry : logOrderSubtasksMap.entrySet()) {
+                Long logOrderId = entry.getKey();
+                List<KwtWaybillOrderSubtask> subtaskList = entry.getValue();
+                
+                try {
+                    // 如果没有运单,跳过
+                    if (CollectionUtils.isEmpty(subtaskList)) {
+                        log.warn("物流订单[{}]下没有运单,跳过处理", logOrderId);
+                        continue;
+                    }
+
+                    // 检查所有运单状态是否都是"已完成"(COMPLETED)和已取消(CANCELLED)
+
+                    List<Integer> statusList = Arrays.asList(CarWaybillV1Enum.COMPLETED.getCode(), CarWaybillV1Enum.CANCELLED.getCode());
+                    boolean allCompleted = subtaskList.stream()
+                            .allMatch(subtask -> statusList.contains(subtask.getStatus()));
+
+                    if (allCompleted) {
+                        // 更新物流订单状态为"已完成"
+                        KwtLogisticsOrder updateOrder = new KwtLogisticsOrder();
+                        updateOrder.setId(logOrderId);
+                        updateOrder.setStatus(LogisticsOrderV1Enum.COMPLETED.getCode());
+                        updateOrder.setUpdateTime(new Date());
+                        // 定时任务更新,updateBy 可以设置为系统用户或0
+                        updateOrder.setUpdateBy(0L);
+                        updateLogisticOrders.add(updateOrder);
+
+                    } else {
+                        // 存在未完成的运单,记录日志
+                        long completedCount = subtaskList.stream()
+                                .filter(subtask -> Objects.equals(subtask.getStatus(), CarWaybillV1Enum.COMPLETED.getCode()))
+                                .count();
+                        log.debug("物流订单下还有未完成的运单,已完成运单数:{}/{},订单ID:{}",
+                                 completedCount, subtaskList.size(), logOrderId);
+                    
+                    }
+                } catch (Exception e) {
+                    log.error("处理物流订单时发生异常,订单ID:{}", logOrderId, e);
+                }
+            }
+            
+            // 如果没有需要更新的物流订单,则直接返回
+            if (CollectionUtils.isEmpty(updateLogisticOrders)){
+                log.info("没有需要更新状态的物流订单");
+                return;
+            }
+            
+            // 批量更新物流订单状态
+            boolean updated = logisticsOrderRepository.updateBatchById(updateLogisticOrders);
+            Set<Long> logOrderIds = updateLogisticOrders.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toSet());
+            
+            // 记录更新结果日志
+            if (updated) {
+                log.info("物流订单自动完成定时任务结束,物流订单已更新为'已完成',订单ID:{},成功:{}条", JSON.toJSONString(logOrderIds), logOrderIds.size());
+            } else {
+                log.error("物流订单自动完成定时任务结束,物流订单状态更新失败,订单ID:{},失败:{}条", JSON.toJSONString(logOrderIds), logOrderIds.size());
+            }
+        } catch (Exception e) {
+            log.error("物流订单自动完成定时任务执行异常", e);
+            throw new BusinessException("物流订单自动完成定时任务执行异常", e);
+        }
+    }
+}