rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
@@ -18,9 +18,8 @@
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.dto.LocStockDto;
import com.vincent.rsf.server.manager.controller.params.OutStockToTaskParams;
import com.vincent.rsf.server.manager.controller.params.PakinItem;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.controller.dto.OrderOutItemDto;
import com.vincent.rsf.server.manager.controller.params.*;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.service.*;
@@ -208,7 +207,6 @@
    @Override
    @Transactional(timeout = 60, rollbackFor = Exception.class)
    public void syncMatnrs(List<BaseMatParms> matnrs) {
        List<Matnr> syncMatnrs = new ArrayList<>();
        if (!matnrs.isEmpty()) {
            matnrs.forEach(matnr -> {
                Matnr mat = new Matnr();
@@ -218,17 +216,28 @@
                BeanUtils.copyProperties(matnr, mat);
                mat.setCode(matnr.getMatnr()).setName(matnr.getMaktx());
                if (!Objects.isNull(matnr.getGroupName())) {
                    MatnrGroup matnrGroup = matnrGroupService.getOne(new LambdaQueryWrapper<MatnrGroup>().eq(MatnrGroup::getName, matnr.getGroupName()), false);
                    if (Objects.isNull(matnrGroup)) {
                    MatnrGroup matnrGroup = matnrGroupService.getOne(new LambdaQueryWrapper<MatnrGroup>().eq(MatnrGroup::getName, matnr.getGroupName()).last("limit 1"), false);
                    if (!Objects.isNull(matnrGroup)) {
                        mat.setGroupCode(matnrGroup.getCode()).setGroupId(matnrGroup.getId());
                    }
                }
                syncMatnrs.add(mat);
            });
                Matnr exist = matnrService.getOne(new LambdaQueryWrapper<Matnr>()
                        .eq(Matnr::getCode, matnr.getMatnr())
                        .last("limit 1"));
            if (!matnrService.saveOrUpdateBatch(syncMatnrs)) {
                throw new CoolException("物料信息保存成功!!");
            }
                mat.setStatus(Objects.isNull(matnr.getOperateType()) ? 1 : (matnr.getOperateType() == 1 ? 0 : 1));
                if (!Objects.isNull(exist)) {
                    mat.setId(exist.getId());
                    if (!matnrService.saveOrUpdate(mat)) {
                        throw new CoolException("物料信息更新失败!!");
                    }
                } else {
                    mat.setId(null);
                    if (!matnrService.save(mat)) {
                        throw new CoolException("物料信息保存失败!!");
                    }
                }
            });
        }
    }
@@ -241,14 +250,14 @@
    @Override
    public R queryOrderStatus(QueryOrderParam queryParams) {
        WkOrder wkOrders = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>()
                .eq(WkOrder::getPoCode, queryParams.getOrderNo()));
                .eq(WkOrder::getPoCode, queryParams.getOrderNo()).last("limit 1"));
        if (Objects.isNull(wkOrders)) {
            Map<String, Object> map = new HashMap<>();
            map.put("exceStatus", "-1");
            return R.ok("单据不存在 !!").add(map);
        }
        AsnOrderLog orderLog = asnOrderLogService.getOne(new LambdaQueryWrapper<AsnOrderLog>().eq(AsnOrderLog::getCode, queryParams.getOrderNo()));
        AsnOrderLog orderLog = asnOrderLogService.getOne(new LambdaQueryWrapper<AsnOrderLog>().eq(AsnOrderLog::getCode, queryParams.getOrderNo()).last("limit 1"));
        if (!Objects.isNull(orderLog)) {
            Map<String, Object> map = new HashMap<>();
            map.put("exceStatus", "4");
@@ -308,7 +317,8 @@
    @Override
    @Transactional(timeout = 60, rollbackFor = Exception.class)
    public R syncMatGroups(List<SyncMatGroupsParams> matGroupsParams) {
        List<MatnrGroup> syncMatGroups = new ArrayList<>();
        final int[] insertCount = {0};
        final int[] updateCount = {0};
        matGroupsParams.forEach(matGroupsParam -> {
            MatnrGroup matnrGroup = new MatnrGroup();
            BeanUtils.copyProperties(matGroupsParam, matnrGroup);
@@ -321,12 +331,36 @@
            if (Objects.isNull(matGroupsParam.getParCode())) {
                throw new CoolException("上级物料分组编码不能为空!!");
            }
            syncMatGroups.add(matnrGroup);
            // 幂等同步:优先按编码匹配,找不到再按名称匹配
            MatnrGroup one = matnrGroupService.getOne(new LambdaQueryWrapper<MatnrGroup>()
                    .eq(MatnrGroup::getCode, matGroupsParam.getCode())
                    .last("limit 1"));
            if (Objects.isNull(one)) {
                one = matnrGroupService.getOne(new LambdaQueryWrapper<MatnrGroup>()
                        .eq(MatnrGroup::getName, matGroupsParam.getName())
                        .last("limit 1"));
            }
            if (!Objects.isNull(one)) {
                matnrGroup.setId(one.getId());
                if (!matnrGroupService.saveOrUpdate(matnrGroup)) {
                    throw new CoolException("物料分组更新失败!!");
                }
                updateCount[0]++;
            } else {
                matnrGroup.setId(null);
                if (!matnrGroupService.save(matnrGroup)) {
                    throw new CoolException("物料分组保存失败!!");
                }
                insertCount[0]++;
            }
        });
        if (!matnrGroupService.saveBatch(syncMatGroups)) {
            throw new CoolException("物料分组保存失败!!");
        }
        return R.ok();
        Map<String, Object> result = new HashMap<>();
        result.put("total", matGroupsParams.size());
        result.put("insertCount", insertCount[0]);
        result.put("updateCount", updateCount[0]);
        return R.ok(result);
    }
    /**
@@ -338,23 +372,45 @@
    @Override
    @Transactional(timeout = 60, rollbackFor = Exception.class)
    public R syncWarehouseAreas(List<LocAreasParams> areasParams) {
        final int[] insertCount = {0};
        final int[] updateCount = {0};
        areasParams.forEach(param -> {
            WarehouseAreas locArea = new WarehouseAreas();
            BeanUtils.copyProperties(param, locArea);
            WarehouseAreas warehouseAreas = warehouseAreasService
                    .getOne(new LambdaQueryWrapper<WarehouseAreas>()
                            .eq(WarehouseAreas::getName, param.getName()));
            // 幂等同步:优先按编码匹配,找不到再按名称匹配
            WarehouseAreas warehouseAreas = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>()
                    .eq(WarehouseAreas::getCode, param.getCode())
                    .last("limit 1"));
            if (Objects.isNull(warehouseAreas)) {
                warehouseAreas = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>()
                        .eq(WarehouseAreas::getName, param.getName())
                        .last("limit 1"));
            }
            if (!Objects.isNull(warehouseAreas)) {
                locArea.setWarehouseId(warehouseAreas.getId());
            }
            locArea.setName(param.getName())
                    .setCode(param.getCode())
                    .setId(null);
            if (!warehouseAreasService.save(locArea)) {
                throw new CoolException("库区保存失败!!");
                    .setCode(param.getCode());
            if (!Objects.isNull(warehouseAreas)) {
                locArea.setId(warehouseAreas.getId());
                if (!warehouseAreasService.saveOrUpdate(locArea)) {
                    throw new CoolException("库区更新失败!!");
                }
                updateCount[0]++;
            } else {
                locArea.setId(null);
                if (!warehouseAreasService.save(locArea)) {
                    throw new CoolException("库区保存失败!!");
                }
                insertCount[0]++;
            }
        });
        return R.ok();
        Map<String, Object> result = new HashMap<>();
        result.put("total", areasParams.size());
        result.put("insertCount", insertCount[0]);
        result.put("updateCount", updateCount[0]);
        return R.ok(result);
    }
    /**
@@ -366,15 +422,35 @@
    @Override
    @Transactional(timeout = 60, rollbackFor = Exception.class)
    public R syncWarehouse(List<WarehouseParams> warehouses) {
        final int[] insertCount = {0};
        final int[] updateCount = {0};
        warehouses.forEach(warehouse -> {
            Warehouse ware = new Warehouse();
            BeanUtils.copyProperties(warehouse, ware);
            ware.setId(null);
            if (!warehouseService.save(ware)) {
                throw new CoolException("仓库同步保存失败!!");
            // 幂等同步:按仓库名称匹配
            Warehouse one = warehouseService.getOne(new LambdaQueryWrapper<Warehouse>()
                    .eq(Warehouse::getName, warehouse.getName())
                    .last("limit 1"));
            ware.setStatus(Objects.isNull(warehouse.getOperateType()) ? 1 : (warehouse.getOperateType() == 1 ? 0 : 1));
            if (!Objects.isNull(one)) {
                ware.setId(one.getId());
                if (!warehouseService.saveOrUpdate(ware)) {
                    throw new CoolException("仓库同步更新失败!!");
                }
                updateCount[0]++;
            } else {
                ware.setId(null);
                if (!warehouseService.save(ware)) {
                    throw new CoolException("仓库同步保存失败!!");
                }
                insertCount[0]++;
            }
        });
        return R.ok();
        Map<String, Object> result = new HashMap<>();
        result.put("total", warehouses.size());
        result.put("insertCount", insertCount[0]);
        result.put("updateCount", updateCount[0]);
        return R.ok(result);
    }
    /**
@@ -389,20 +465,37 @@
        companyParams.forEach(param -> {
            Companys companys = new Companys();
            BeanUtils.copyProperties(param, companys);
            if (Objects.isNull(companys.getCode())) {
            if (Objects.isNull(companys.getCode()) || StringUtils.isBlank(companys.getCode())) {
                throw new CoolException("企业编码不能为空!!");
            }
            Companys one = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getName, param.getName()));
            if (Objects.isNull(one)) {
                String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_COMPANYS_CODE, null);
                companys.setCode(ruleCode);
            } else {
                throw new CoolException(one.getName() + ",企业名重复!!");
            if (Objects.isNull(companys.getName()) || StringUtils.isBlank(companys.getName())) {
                throw new CoolException("企业名称不能为空!!");
            }
            companys.setType(CompanysType.getCustomVal(param.getType()))
                    .setId(null);
            if (!companysService.save(companys)) {
                throw new CoolException("企业保存失败!!");
            // 幂等同步:优先按编码匹配,找不到再按名称匹配
            Companys one = companysService.getOne(new LambdaQueryWrapper<Companys>()
                    .eq(Companys::getCode, param.getCode())
                    .last("limit 1"));
            if (Objects.isNull(one)) {
                one = companysService.getOne(new LambdaQueryWrapper<Companys>()
                        .eq(Companys::getName, param.getName())
                        .last("limit 1"));
            }
            companys.setType(CompanysType.getCustomVal(param.getType()));
            companys.setStatus(Objects.isNull(param.getOperateType()) ? 1 : (param.getOperateType() == 1 ? 0 : 1));
            if (!Objects.isNull(one)) {
                companys.setId(one.getId());
                // 已存在则更新,不重复报错
                if (!companysService.saveOrUpdate(companys)) {
                    throw new CoolException("企业更新失败!!");
                }
            } else {
                companys.setId(null);
                // 新增时保留ERP传入编码,不再覆盖生成
                if (!companysService.save(companys)) {
                    throw new CoolException("企业保存失败!!");
                }
            }
        });
        return R.ok();
@@ -419,6 +512,9 @@
    public R syncCheckOrder(List<SyncOrderParams> syncOrders, Long loginUserId) {
        if (!syncOrders.isEmpty()) {
            syncOrders.forEach(syncOrder -> {
                if (!syncOrder.getWkType().matches("\\d+")){
                    syncOrder.setWkType(OrderWorkType.getOrderTypeUpdate(syncOrder.getWkType()));
                }
                WkOrder wkOrder = new WkOrder(syncOrder);
                DictData one = dictDataService.getOne(new LambdaQueryWrapper<DictData>().eq(DictData::getDictTypeCode, DictTypeCode.DICT_SYS_BUSINESS_TYPE)
                        .eq(DictData::getValue, syncOrder.getWkType()), false);
@@ -551,25 +647,22 @@
                    // 立即触发异步任务,不等待结果
                    if (!Cools.isEmpty(palletId.get()) && StringUtils.isNotBlank(syncOrder.getOrderNo()) && !Cools.isEmpty(syncOrder.getStationId())) {
                        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, palletId.get()));
                        if (!Cools.isEmpty(loc)) {
                        if (!Cools.isEmpty(loc) && loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) {
//                            outStockService.getOrderOutTaskItem(orderOutTaskParam,param.getOrderItemId());
                            //出库
                            List<OutStockToTaskParams> param = new ArrayList<>();
                            for (WkOrderItem wkOrderItem : orderItems){
                                OutStockToTaskParams outStockToTaskParams = new OutStockToTaskParams(wkOrderItem);
                                outStockToTaskParams.setLocCode(loc.getCode());
                                outStockToTaskParams.setSiteNo(syncOrder.getStationId());
                                param.add(outStockToTaskParams);
                            }
//                        boolean itemsCheck = waitPakinService.mergeItemsCheck(pakinParam, loginUserId);
//                            if (true) {
                            CompletableFuture.runAsync(() -> {
                                try {
                                    asyncOutboundExecutionWcs(param, wkOrder.getId(), loginUserId);
                                    asyncOutboundExecutionWcs(syncOrder.getStationId(), wkOrder.getId(), loginUserId,loc.getCode());
                                } catch (Exception e) {
                                    log.warn("订单 {} 开始自动出库", syncOrder.getOrderNo());
                                }
                            });
//                            }
                        } else {
                            log.warn("订单 {} 自动出库失败!!未查询到指定库存!!", syncOrder.getOrderNo());
                            throw new CoolException("自动出库失败!!未查询到指定库存!!");
                        }
                    }
                }
@@ -613,31 +706,52 @@
    }
    @Async
    public void asyncOutboundExecutionWcs(List<OutStockToTaskParams> param, Long orderId, Long loginUserId) {
    public void asyncOutboundExecutionWcs(String stationId ,Long orderId, Long loginUserId,String locCode) {
        try {
//            int i = 0;
//            List<OutStockToTaskParams> tasks = new ArrayList<>();
//            while (true) {
//                tasks = new ArrayList<>();
//                i++;
//                if (i > 5) return;
//                Thread.sleep(3000);
//                for (OutStockToTaskParams taskParam : new OutStockToTaskParams[param.size()]) {
//                    if (StringUtils.isNotBlank(taskParam.getLocCode())) {
//                        tasks.add(taskParam);
//                    }
//                }
//                break;
//            }
            if (param.isEmpty()){
                log.warn("订单ID {} 没有找到可出库明细,跳过自动出库", orderId);
                return;
            int i = 0;
            while (true) {
                i++;
                if (i > 5) return;
                Thread.sleep(3000);
                WkOrder byId = asnOrderService.getById(orderId);
                if (Cools.isEmpty(byId)) {
                    continue;
                }
                break;
            }
            outStockService.genOutStockTask(param, loginUserId, orderId);
            log.info("订单ID {} 自动出库,共处理 {} 个明细", orderId, param.size());
            GenWaveParams genWaveParams = new GenWaveParams();
            List<Long> ids = new ArrayList<>();
            ids.add(orderId);
            genWaveParams.setIds(ids);
            genWaveParams.setWaveRuleId(16L);
//            OrderOutTaskParam orderOutTaskParam = new OrderOutTaskParam();
//            orderOutTaskParam.setOrderId(orderId);
//            orderOutTaskParam.setWaveId(16L);
//            List<OrderOutItemDto> orderOutTaskItemAuto = outStockService.getOrderOutTaskItemAuto(orderOutTaskParam);
//
//            List<OutStockToTaskParams> tasks = new ArrayList<>();
//            for (OrderOutItemDto orderOutItemDto : orderOutTaskItemAuto){
//                for (LocItem locItem : orderOutItemDto.getLocItemList()) {
//                    OutStockToTaskParams outStockToTaskParams = new OutStockToTaskParams(orderOutItemDto,locItem);
//                    outStockToTaskParams.setId(locItem.getId());
//                    outStockToTaskParams.setOutQty(locItem.getOutQty());
//                    outStockToTaskParams.setLocCode(locItem.getLocCode());
//                    outStockToTaskParams.setBarcode(locItem.getBarcode());
//                    outStockToTaskParams.setSiteNo(stationId);
//                    tasks.add(outStockToTaskParams);
//                }
//            }
//            if (tasks.isEmpty()){
//                log.warn("订单ID {} 没有找到可出库明细,跳过自动出库", orderId);
//                return;
//            }
//            outStockService.genOutStockTask(tasks, loginUserId, orderId);
            R r = outStockService.generateWavesOrderAuto(genWaveParams, stationId,locCode);
            log.info("订单ID {} 自动转波次", orderId);
        } catch (Exception e) {
            log.error("订单ID {} 自动出库: {}", orderId, e.getMessage(), e);
            log.error("订单ID {} 自动转波次: {}", orderId, e.getMessage(), e);
        }
    }
@@ -1121,6 +1235,32 @@
                }
            }
            // 仓库编码过滤
            if (StringUtils.isNotBlank(condition.getWareHouseAreaId())) {
                String wareHouseAreaId = condition.getWareHouseAreaId();
                LambdaQueryWrapper<WarehouseAreas> whWrapper = new LambdaQueryWrapper<>();
                whWrapper.eq(WarehouseAreas::getCode, wareHouseAreaId);
                // 调用WarehouseService查询仓库信息(复用Service层方法)
                List<WarehouseAreas> warehouses = warehouseAreasService.list(whWrapper);
                if (!warehouses.isEmpty()) {
                    Long targetWarehouseId = warehouses.get(0).getId();
                    // 过滤库位,只保留目标仓库的库位
                    locMap = locMap.entrySet().stream()
                            .filter(entry -> Objects.equals(entry.getValue().getAreaId(), targetWarehouseId))
                            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                    // 过滤locItems,只保留目标仓库的
                    Set<Long> validLocIds = locMap.keySet();
                    locItems = locItems.stream()
                            .filter(item -> item.getLocId() != null && validLocIds.contains(item.getLocId()))
                            .collect(Collectors.toList());
                    List<Long> warehouseAreaIds = Collections.singletonList(targetWarehouseId);
                } else {
                    return R.ok().add(new ArrayList<>());
                }
            }
            // 调用WarehouseService查询仓库信息(复用Service层方法)
            Map<Long, Warehouse> warehouseMap = new HashMap<>();
            if (!warehouseIds.isEmpty()) {
@@ -1444,3 +1584,4 @@
        }
    }
}