cl
昨天 43d6ae86bc229a1a75637fae33be378e105016e3
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
@@ -26,7 +26,10 @@
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.MatnrServiceImpl;
import com.vincent.rsf.server.system.constant.DictTypeCode;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.entity.Config;
import com.vincent.rsf.server.system.service.ConfigService;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.entity.DictType;
import com.vincent.rsf.server.system.entity.Fields;
@@ -113,7 +116,36 @@
    private WaitPakinItemService waitPakinItemService;
    @Autowired
    private WarehouseAreasItemService warehouseAreasItemService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private TaskItemService taskItemService;
    @Autowired
    private TaskService taskService;
    /**
     * 云仓改单/取消前:任务明细已关联该单据且主任务未逻辑删除则不允许
     */
    private void assertWkOrderNoLinkedTask(Long wkOrderId) {
        if (wkOrderId == null) {
            return;
        }
        List<TaskItem> links = taskItemService.list(new LambdaQueryWrapper<TaskItem>()
                .select(TaskItem::getTaskId)
                .and(w -> w.eq(TaskItem::getOrderId, wkOrderId)
                        .or(o -> o.eq(TaskItem::getSourceId, wkOrderId)
                                .eq(TaskItem::getOrderType, OrderType.ORDER_OUT.type))));
        if (links.isEmpty()) {
            return;
        }
        Set<Long> taskIds = links.stream().map(TaskItem::getTaskId).filter(Objects::nonNull).collect(Collectors.toSet());
        if (taskIds.isEmpty()) {
            return;
        }
        if (taskService.count(new LambdaQueryWrapper<Task>().in(Task::getId, taskIds)) > 0) {
            throw new CoolException("该单据已生成任务,不可修改、取消或删除!!");
        }
    }
    /**
     * @author Ryan
@@ -460,23 +492,29 @@
                    WkOrder order = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>()
                            .eq(WkOrder::getPoCode, syncOrder.getOrderInternalCode()));
                    if (!Objects.isNull(order)) {
                        assertWkOrderNoLinkedTask(order.getId());
                        // 仅未执行状态可被 order/add 修改(入库未执行、出库任务初始)
                        List<Short> editableStatus = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val);
                        List<Short> editableStatus = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val
                                ,AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val
                                ,AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val
                                , AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val);
                        if (!editableStatus.contains(order.getExceStatus())) {
                            throw new CoolException("仅未执行状态的单据可修改!!");
                        }
                        // 存在则修改(1 和 2 均走此处),组托校验在 mergeOrderWithPakin/updateOrderNoPakin 内
                        long pakinCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>()
                                .eq(WaitPakinItem::getAsnId, order.getId()));
                                .eq(WaitPakinItem::getAsnId, order.getId()).eq(WaitPakinItem::getDeleted, 0));
                        if (pakinCount > 0) {
                            // 已组托:按 lineId(platItemId)合并,校验数量与删除
                            mergeOrderWithPakin(order, syncOrder, resolvedOrderType, typeCode, loginUserId);
                            // 收货区已停用 // syncReceiptAreaByOrder(order.getId());
                            return; // 本单已处理,跳过下方“新建主单+明细”
                            if (isDirectWaitPakin()) {
                                syncReceiptAreaByOrder(order.getId());
                            }
                            return;
                        }
                        // 未组托:在原单上更新主单+明细,保留 exceStatus/qty/workQty,避免再次触发定时任务导致重复收货
                        updateOrderNoPakin(order, syncOrder, loginUserId);
                        // 收货区已停用 // syncReceiptAreaByOrder(order.getId());
                        if (isDirectWaitPakin()) {
                            syncReceiptAreaByOrder(order.getId());
                        }
                        return;
                    } else if (Integer.valueOf(2).equals(syncOrder.getOperateType())) {
                        // 仅 operateType=2 时要求单据必须存在
@@ -500,7 +538,7 @@
                            .setArrTime(syncOrder.getArrTime())
                            .setStationId(syncOrder.getStationId())
                            .setId(null)
                            .setCreateTime(new Date())
                            .setCreateTime(syncOrder.getCreateTime() != null ? syncOrder.getCreateTime() : new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(loginUserId)
                            .setUpdateBy(loginUserId);
@@ -551,7 +589,7 @@
            }
        }
        List<WkOrderItem> existingItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
        List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()));
        List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()).eq(WaitPakinItem::getDeleted, 0));
        Map<Long, Double> palletizedByItemId = pakinItems.stream()
                .collect(Collectors.groupingBy(WaitPakinItem::getAsnItemId, Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0)));
        palletizedByItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v));
@@ -567,6 +605,15 @@
                .map(e -> StringUtils.isNotBlank(e.getPlatItemId()) ? e.getPlatItemId().trim() : null)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        // 已组托单据修改只能增加数量不能减少数量:云仓下发的总数量不得小于已组托总量
        double totalPalletized = QuantityUtils.roundToScale(pakinItems.stream().mapToDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0).sum());
        double incomingTotal = syncOrder.getOrderItems() == null ? 0.0 : syncOrder.getOrderItems().stream()
                .mapToDouble(it -> it.getAnfme() != null ? it.getAnfme() : 0.0).sum();
        incomingTotal = QuantityUtils.roundToScale(incomingTotal);
        if (QuantityUtils.compare(incomingTotal, totalPalletized) < 0) {
            throw new CoolException("已组托单据修改只能增加数量不能减少数量(当前已组托总量 " + totalPalletized + ",下发总量 " + incomingTotal + ")!!");
        }
        for (WkOrderItem existing : existingItems) {
            String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null;
@@ -603,7 +650,16 @@
                continue;
            }
            SyncOrdersItem inc = incomingByLineId.get(lineId);
            existing.setAnfme(QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme()));
            Double newAnfme = QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme());
            existing.setAnfme(newAnfme);
            if (inc.getQty() != null) {
                existing.setQty(QuantityUtils.roundToScale(inc.getQty()));
            } else {
                Double curQty = existing.getQty() != null ? existing.getQty() : 0.0;
                if (QuantityUtils.compare(curQty, 0.0) != 0) {
                    existing.setQty(QuantityUtils.roundToScale(newAnfme));
                }
            }
            existing.setMaktx(inc.getMaktx());
            existing.setSpec(inc.getSpec());
            existing.setModel(inc.getModel());
@@ -635,6 +691,9 @@
        Double sum = QuantityUtils.roundToScale(asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()))
                .stream().mapToDouble(WkOrderItem::getAnfme).sum());
        order.setAnfme(sum);
        List<WkOrderItem> afterItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
        double qtySum = afterItems.stream().mapToDouble(oi -> oi.getQty() != null ? oi.getQty() : 0.0).sum();
        order.setQty(QuantityUtils.roundToScale(qtySum));
        asnOrderService.updateById(order);
    }
@@ -672,12 +731,23 @@
        for (WkOrderItem existing : existingItems) {
            String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null;
            if (lineId == null || !incomingByLineId.containsKey(lineId)) {
                // 收货区已停用 // warehouseAreasItemService.remove(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnItemId, existing.getId()));
                if (isDirectWaitPakin()) {
                    warehouseAreasItemService.remove(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnItemId, existing.getId()));
                }
                asnOrderItemService.removeById(existing.getId());
                continue;
            }
            SyncOrdersItem inc = incomingByLineId.get(lineId);
            existing.setAnfme(QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme()));
            Double newAnfme = QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme());
            existing.setAnfme(newAnfme);
            if (inc.getQty() != null) {
                existing.setQty(QuantityUtils.roundToScale(inc.getQty()));
            } else {
                Double curQty = existing.getQty() != null ? existing.getQty() : 0.0;
                if (QuantityUtils.compare(curQty, 0.0) != 0) {
                    existing.setQty(QuantityUtils.roundToScale(newAnfme));
                }
            }
            existing.setMaktx(inc.getMaktx());
            existing.setSpec(inc.getSpec());
            existing.setModel(inc.getModel());
@@ -709,31 +779,37 @@
        Double sum = QuantityUtils.roundToScale(asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()))
                .stream().mapToDouble(WkOrderItem::getAnfme).sum());
        order.setAnfme(sum);
        List<WkOrderItem> afterItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
        double qtySum = afterItems.stream().mapToDouble(oi -> oi.getQty() != null ? oi.getQty() : 0.0).sum();
        order.setQty(QuantityUtils.roundToScale(qtySum));
        asnOrderService.updateById(order);
    }
    /** 收货区已停用,方法整体注释
     * 订单修改后同步收货区:按 asnItemId 将收货区记录的 anfme 更新为订单明细的 anfme。
     */
//    private void syncReceiptAreaByOrder(Long orderId) {
//        List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, orderId));
//        if (orderItems.isEmpty()) {
//            return;
//        }
//        List<WarehouseAreasItem> areaItems = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnId, orderId));
//        Map<Long, Double> itemAnfme = orderItems.stream().collect(Collectors.toMap(WkOrderItem::getId, i -> i.getAnfme() != null ? i.getAnfme() : 0.0, (a, b) -> b));
//        for (WarehouseAreasItem area : areaItems) {
//            if (area.getAsnItemId() == null || !itemAnfme.containsKey(area.getAsnItemId())) {
//                continue;
//            }
//            Double anfme = itemAnfme.get(area.getAsnItemId());
//            if (area.getAnfme() != null && area.getAnfme().equals(anfme)) {
//                continue;
//            }
//            area.setAnfme(anfme);
//            warehouseAreasItemService.updateById(area);
//        }
//    }
    /** DirectWaitPakin 启用时:订单修改后同步收货区,按 asnItemId 将收货区记录的 anfme 更新为订单明细的 anfme。 */
    private void syncReceiptAreaByOrder(Long orderId) {
        List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, orderId));
        if (orderItems.isEmpty()) {
            return;
        }
        List<WarehouseAreasItem> areaItems = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnId, orderId));
        Map<Long, Double> itemAnfme = orderItems.stream().collect(Collectors.toMap(WkOrderItem::getId, i -> i.getAnfme() != null ? i.getAnfme() : 0.0, (a, b) -> b));
        for (WarehouseAreasItem area : areaItems) {
            if (area.getAsnItemId() == null || !itemAnfme.containsKey(area.getAsnItemId())) {
                continue;
            }
            Double anfme = itemAnfme.get(area.getAsnItemId());
            if (area.getAnfme() != null && area.getAnfme().equals(anfme)) {
                continue;
            }
            area.setAnfme(anfme);
            warehouseAreasItemService.updateById(area);
        }
    }
    private boolean isDirectWaitPakin() {
        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
        return config != null && Boolean.parseBoolean(config.getVal());
    }
    /**
     * @author Ryan
@@ -895,6 +971,7 @@
            if (Objects.isNull(wkOrder)) {
                throw new CoolException("请确认单据:" + order.getOrderNo() + "是否已经执行或是否同步!!");
            }
            assertWkOrderNoLinkedTask(wkOrder.getId());
            order.getOrderItems().forEach(orderItem -> {
                WkOrderItem wkOrderItem = asnOrderItemService.getOne(new LambdaUpdateWrapper<WkOrderItem>()
                        .eq(WkOrderItem::getMatnrCode, orderItem.getMatnr())
@@ -958,6 +1035,7 @@
                throw new CoolException("单据不存在,无法取消!!请提供单据内码(orderInternalCode)或单号(orderNo)。");
            }
            final WkOrder finalWkOrder = wkOrder;
            assertWkOrderNoLinkedTask(finalWkOrder.getId());
            // 已组托不可取消
            long pakinCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>()
                    .eq(WaitPakinItem::getAsnId, finalWkOrder.getId()));