chen.lin
昨天 b003a49794f49a329e2702918ecfc8d14b371d0d
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -14,12 +14,14 @@
import com.vincent.rsf.server.common.security.JwtSubject;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.common.utils.JwtUtil;
import com.vincent.rsf.server.common.utils.QuantityUtils;
import com.vincent.rsf.server.manager.controller.params.GenerateTaskParams;
import com.vincent.rsf.server.manager.controller.params.IsptItemsParams;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.mapper.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.BasContainerServiceImpl;
import com.vincent.rsf.server.system.constant.CodeRes;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
@@ -34,6 +36,8 @@
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -56,6 +60,8 @@
 */
@Service
public class MobileServiceImpl implements MobileService {
    private static final Logger logger = LoggerFactory.getLogger(MobileServiceImpl.class);
    @Value("${super.pwd}")
    private String superPwd;
@@ -127,6 +133,8 @@
    private CompanysService companysService;
    @Autowired
    private OutStockService outStockService;
    @Autowired
    private BasContainerService basContainerService;
    /**
     * @return
@@ -251,8 +259,9 @@
            throw new CoolException("数据错误:主单不存在!!");
        }
        //TODO /**收货数量累加,1. 会出超收情况 2. 会有收货不足情况*/
        Double rcptedQty = Math.round((wkOrder.getQty() + receiptQty) * 10000) / 10000.0;
        wkOrder.setQty(rcptedQty).setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val);
        Double rcptedQty = QuantityUtils.add(wkOrder.getQty(), receiptQty);
        // 新顺序:未执行(组托)→任务执行中→已完成,不再设置执行中/收货完成
        wkOrder.setQty(rcptedQty); // .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val)
        if (!asnOrderMapper.updateById(wkOrder)) {
            throw new CoolException("已收货数量修改失败!!");
        }
@@ -299,14 +308,14 @@
                throw new CoolException("请输入正确的时间格式!!");
            }
            Double itemRcptQty = Math.round((dto.getReceiptQty() + orderItem.getQty()) * 10000) / 10000.0;
            Double itemRcptQty = QuantityUtils.add(dto.getReceiptQty(), orderItem.getQty());
            Boolean allowOver = false;
            if (!Objects.isNull(config)) {
                if (Boolean.parseBoolean(config.getVal())) {
                    allowOver = true;
                }
            }
            if (itemRcptQty.compareTo(orderItem.getAnfme()) > 0 && !allowOver) {
            if (QuantityUtils.compare(itemRcptQty, orderItem.getAnfme()) > 0 && !allowOver) {
                throw new CoolException("收货数量不能大于计划数量!!");
            }
@@ -343,18 +352,18 @@
            if (asnOrderItemMapper.updateById(orderItem) < 1) {
                throw new CoolException("通知单明细数量修改失败!!");
            }
            /**保存明细至收货区**/
            extracted(loginUserId, dto, areasItem, orderItem, wkOrder, matnr);
            // 收货区已停用,不再保存至收货区
            // extracted(loginUserId, dto, areasItem, orderItem, wkOrder, matnr);
        }
        WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode));
        if (order.getQty().compareTo(order.getAnfme()) >= 0.00) {
            order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val).setRleStatus(Short.valueOf("1"));
            if (!asnOrderMapper.updateById(order)) {
                throw new CoolException("订单状态修改失败!!");
            }
        }
        // 新顺序:未执行(组托)→任务执行中→已完成,不再设置收货完成
        // WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode));
        // if (order.getQty().compareTo(order.getAnfme()) >= 0.00) {
        //     order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val).setRleStatus(Short.valueOf("1"));
        //     if (!asnOrderMapper.updateById(order)) {
        //         throw new CoolException("订单状态修改失败!!");
        //     }
        // }
        return R.ok("收货成功!!");
    }
@@ -383,7 +392,7 @@
                .setUnit(orderItem.getStockUnit())
                .setStockUnit(orderItem.getStockUnit())
                .setBatch(StringUtils.isBlank(orderItem.getBatch()) ? SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_RECEIPT_BATCH, dto) : orderItem.getBatch())
                .setAnfme(dto.getReceiptQty())
                .setAnfme(QuantityUtils.roundToScale(dto.getReceiptQty()))
                .setSplrBatch(dto.getSplrBatch())
                .setMatnrCode(matnr.getCode())
                .setUpdateBy(loginUserId)
@@ -412,8 +421,7 @@
        if (!Objects.isNull(serviceOne)) {
            item.setId(serviceOne.getId());
            Double anfme = Math.round((item.getAnfme() + serviceOne.getAnfme()) * 10000) / 10000.0;
            item.setAnfme(anfme);
            item.setAnfme(QuantityUtils.add(item.getAnfme(), serviceOne.getAnfme()));
        }
        //未质检
@@ -504,11 +512,13 @@
     * @description 获取收货区
     * @time 2025/3/11 10:12
     */
    /** 收货区已停用,返回空列表 */
    @Override
    public R getReceiptAreas() {
        List<WarehouseAreas> areas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>()
                .eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type));
        return R.ok(areas);
        // List<WarehouseAreas> areas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>()
        //         .eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type));
        // return R.ok(areas);
        return R.ok(Collections.emptyList());
    }
    /**
@@ -533,20 +543,282 @@
     * @time 2025/4/7 16:58
     */
    @Override
    public R getDeltByCode(Map<String, Object> params) {
        Object code = params.get("code");
        Object matnrCode = params.get("matnrCode");
        Object asnCode = params.get("asnCode");
        Object batch = params.get("batch");
    public R getDeltByCode(Map<String, String> params) {
        String code = params.get("code");
        String matnrCode = params.get("matnrCode");
        String asnCode = params.get("asnCode");
        String crushNo = params.get("fieldsIndex");
        String batch = params.get("batch");
//        String barcode = params.get("barcode");
        //TODO 后续需根据策略配置,获取组拖数据。如:混装,按批次混装等
        LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<WarehouseAreasItem>()
                .or().eq(!Cools.isEmpty(code), WarehouseAreasItem::getTrackCode, code)
                .or().eq(!Cools.isEmpty(batch), WarehouseAreasItem::getSplrBatch, batch)
                .or().eq(!Cools.isEmpty(matnrCode), WarehouseAreasItem::getMatnrCode, matnrCode)
                .or().eq(!Cools.isEmpty(asnCode), WarehouseAreasItem::getAsnCode, asnCode);
//        if (Objects.isNull(crushNo)) {
//            throw new CoolException("票号不能为空!!");
//        }
//        if (Objects.isNull(code)) {
//            throw new CoolException("料箱码不能为空!!");
//        }
//        BasContainer container = basContainerService.getOne(new LambdaQueryWrapper<BasContainer>().eq(BasContainer::getCode, barcode));
//        if (Objects.isNull(container)) {
//            throw new CoolException("容器不存在!!");
//        }
//        if (!Objects.isNull(params.get("isHalf")) && !params.get("isHalf").equals("0")) {
//            container.setIsHalf(1);
//            if (!basContainerService.updateById(container)) {
//                throw new CoolException("容器状态修改失败!!");
//            }
//        }
        String fieldIndexTemp = null;
        if (!Objects.isNull(crushNo)) {
            FieldsItem fieldsItem = fieldsItemService.getOne(new LambdaQueryWrapper<FieldsItem>().eq(FieldsItem::getValue, crushNo).last("Limit 1"));
            if (!Objects.isNull(fieldsItem)) {
                fieldIndexTemp = fieldsItem.getUuid();
            }
        }
        final String fieldIndex = fieldIndexTemp;
        // 检查是否有至少一个有效查询条件
        boolean hasValidCondition = !Cools.isEmpty(code) || !Cools.isEmpty(batch)
                || !Objects.isNull(fieldIndex) || !Cools.isEmpty(matnrCode) || !Cools.isEmpty(asnCode);
        if (!hasValidCondition) {
            throw new CoolException("请至少输入一个查询条件:物料编码、WMS单号、批号");/*、跟踪码、批次或票号*/
        }
        // 如果扫描物料编码且ASN单号为空,直接从物料信息表获取,不查询收货区
        if (!Cools.isEmpty(matnrCode) && Cools.isEmpty(asnCode) && Cools.isEmpty(code)
                && Cools.isEmpty(batch) && Objects.isNull(fieldIndex)) {
            logger.info("=== 从物料信息表查询物料信息(不查询收货区) ===");
            logger.info("查询参数 - matnrCode: {}", matnrCode);
            Matnr matnr = matnrMapper.selectOne(new LambdaQueryWrapper<Matnr>()
                    .eq(Matnr::getCode, matnrCode)
                    .eq(Matnr::getDeleted, 0)
                    .last("LIMIT 1"));
            if (matnr == null) {
                logger.warn("物料信息表中未找到物料编码: {}", matnrCode);
                return R.ok(new ArrayList<>());
            }
            // 构造一个虚拟的 WarehouseAreasItem 对象返回物料信息
            WarehouseAreasItem item = new WarehouseAreasItem();
            item.setMatnrId(matnr.getId());
            item.setMatnrCode(matnr.getCode());
            item.setMaktx(matnr.getName());
            item.setStockUnit(matnr.getStockUnit());
            item.setUnit(matnr.getUnit());
            item.setAnfme(0.0); // 数量设为0,因为不是从收货区查询的
            item.setWorkQty(0.0);
            item.setQty(0.0);
            // 设置扩展字段
            Map<String, String> fields = FieldsUtils.getFields(matnr.getFieldsIndex());
            item.setExtendFields(fields);
            List<WarehouseAreasItem> resultList = new ArrayList<>();
            resultList.add(item);
            logger.info("从物料信息表返回 1 条物料数据");
            return R.ok(resultList);
        }
        // 收货区已停用:有ASN单号时从订单明细查可组托物料;可组盘数量 = 计划数量 - 已组托数量 - 已上架数量
        if (!Cools.isEmpty(asnCode)) {
            WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode));
            if (order == null) {
                logger.info("未找到ASN单号: {}", asnCode);
                return R.ok(Collections.emptyList());
            }
            // 按明细汇总已组托数量(组托数量不会因改单而变)
            List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()));
            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));
            LambdaQueryWrapper<WkOrderItem> itemWrapper = new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId());
            if (!Cools.isEmpty(matnrCode)) itemWrapper.eq(WkOrderItem::getMatnrCode, matnrCode);
            if (!Cools.isEmpty(batch)) itemWrapper.eq(WkOrderItem::getSplrBatch, batch);
            if (!Objects.isNull(fieldIndex)) itemWrapper.eq(WkOrderItem::getFieldsIndex, fieldIndex);
            if (!Cools.isEmpty(code)) itemWrapper.eq(WkOrderItem::getTrackCode, code);
            List<WkOrderItem> orderItems = asnOrderItemMapper.selectList(itemWrapper);
            List<WarehouseAreasItem> list = new ArrayList<>();
            for (WkOrderItem oi : orderItems) {
                Double anfme = QuantityUtils.roundToScale(oi.getAnfme() != null ? oi.getAnfme() : 0.0);
                Double qty = QuantityUtils.roundToScale(oi.getQty() != null ? oi.getQty() : 0.0);
                Double workQty = palletizedByItemId.getOrDefault(oi.getId(), 0.0); // 已组托数量
                if (QuantityUtils.compare(QuantityUtils.subtract(QuantityUtils.subtract(anfme, workQty), qty), 0.0) <= 0) continue; // 可组盘数量<=0 不返回
                WarehouseAreasItem v = new WarehouseAreasItem();
                v.setId(oi.getId());
                v.setAsnItemId(oi.getId());
                v.setAsnId(order.getId());
                v.setAsnCode(order.getCode());
                v.setAnfme(anfme);
                v.setQty(qty);
                v.setWorkQty(QuantityUtils.roundToScale(workQty));
                v.setMatnrCode(oi.getMatnrCode());
                v.setMaktx(oi.getMaktx());
                v.setSplrBatch(oi.getSplrBatch());
                v.setPlatItemId(oi.getPlatItemId());
                v.setStockUnit(oi.getStockUnit());
                v.setUnit(oi.getStockUnit());
                v.setMatnrId(oi.getMatnrId());
                v.setFieldsIndex(oi.getFieldsIndex());
                v.setTrackCode(oi.getTrackCode());
                if (oi.getFieldsIndex() != null) {
                    v.setExtendFields(FieldsUtils.getFields(oi.getFieldsIndex()));
                }
                list.add(v);
            }
            logger.info("=== 从订单明细查询可组托物料(收货区已停用)asnCode: {} 返回 {} 条", asnCode, list.size());
            return R.ok(list);
        }
        // 无ASN单号时按其他条件查(收货区已停用,此处仅保留兼容,通常无数据)
        LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<>();
        {
            // 没有ASN单号时,可以扫描任意物料组托,使用OR连接多个条件
            // 统计有效条件数量
            int conditionCount = 0;
            if (!Cools.isEmpty(code)) conditionCount++;
            if (!Cools.isEmpty(batch)) conditionCount++;
            if (!Objects.isNull(fieldIndex)) conditionCount++;
            if (!Cools.isEmpty(matnrCode)) conditionCount++;
            // 如果只有一个条件,直接使用eq
            if (conditionCount == 1) {
                if (!Cools.isEmpty(code)) {
                    queryWrapper.eq(WarehouseAreasItem::getTrackCode, code);
                } else if (!Cools.isEmpty(batch)) {
                    queryWrapper.eq(WarehouseAreasItem::getSplrBatch, batch);
                } else if (!Objects.isNull(fieldIndex)) {
                    queryWrapper.eq(WarehouseAreasItem::getFieldsIndex, fieldIndex);
                } else if (!Cools.isEmpty(matnrCode)) {
                    queryWrapper.eq(WarehouseAreasItem::getMatnrCode, matnrCode);
                }
            } else if (conditionCount > 1) {
                // 多个条件,使用OR连接
                queryWrapper.and(wrapper -> {
                    boolean first = true;
                    if (!Cools.isEmpty(code)) {
                        wrapper.eq(WarehouseAreasItem::getTrackCode, code);
                        first = false;
                    }
                    if (!Cools.isEmpty(batch)) {
                        if (!first) wrapper.or();
                        wrapper.eq(WarehouseAreasItem::getSplrBatch, batch);
                        first = false;
                    }
                    if (!Objects.isNull(fieldIndex)) {
                        if (!first) wrapper.or();
                        wrapper.eq(WarehouseAreasItem::getFieldsIndex, fieldIndex);
                        first = false;
                    }
                    if (!Cools.isEmpty(matnrCode)) {
                        if (!first) wrapper.or();
                        wrapper.eq(WarehouseAreasItem::getMatnrCode, matnrCode);
                    }
                });
            }
        }
        // 打印查询参数到控制台
        logger.info("=== 查询可组托物料 ===");
        logger.info("查询参数 - code: {}, matnrCode: {}, asnCode: {}, batch: {}, fieldIndex: {}",
                code, matnrCode, asnCode, batch, fieldIndex);
        List<WarehouseAreasItem> list = warehouseAreasItemService.list(queryWrapper);
        list.removeIf(e -> e.getAnfme() <= e.getWorkQty());
        logger.info("查询到 {} 条收货区库存数据", list.size());
        // 过滤条件:只返回可组托数量 > 0 的数据
        // 可组托数量 = anfme - workQty - qty
        if (!list.isEmpty()) {
            int beforeFilterSize = list.size();
            list.removeIf(e -> {
                // 如果anfme为null,移除该数据
                Double anfme = e.getAnfme();
                if (Objects.isNull(anfme) || anfme <= 0) {
                    logger.debug("过滤数据 - ID: {}, matnrCode: {}, anfme为null或<=0: {}",
                            e.getId(), e.getMatnrCode(), anfme);
                    return true; // 移除数量为null或<=0的数据
                }
                Double workQty = Objects.isNull(e.getWorkQty()) ? 0.0 : e.getWorkQty();
                Double qty = Objects.isNull(e.getQty()) ? 0.0 : e.getQty();
                // 可组托数量 = 总数量 - 已执行数量 - 已收货数量
                Double availableQty = anfme - workQty - qty;
                if (availableQty <= 0) {
                    logger.debug("过滤数据 - ID: {}, matnrCode: {}, anfme: {}, workQty: {}, qty: {}, 可组托数量: {} <= 0",
                            e.getId(), e.getMatnrCode(), anfme, workQty, qty, availableQty);
                }
                return availableQty <= 0; // 移除可组托数量 <= 0 的数据
            });
            // 如果过滤后数据为空,说明所有数据都被过滤掉了
            if (list.isEmpty() && beforeFilterSize > 0) {
                logger.warn("未找到可组托的物料,请检查:1.物料编码是否正确 2.物料是否已收货至收货区 3.是否还有可组托数量");
                logger.warn("查询条件 - code: {}, matnrCode: {}, asnCode: {}, batch: {}, fieldIndex: {}",
                        code, matnrCode, asnCode, batch, fieldIndex);
                logger.warn("查询到 {} 条数据,但全部被过滤(可组托数量 <= 0)", beforeFilterSize);
            }
        } else {
            logger.warn("未找到可组托的物料,请检查:1.物料编码是否正确 2.物料是否已收货至收货区 3.是否还有可组托数量");
            logger.warn("查询条件 - code: {}, matnrCode: {}, asnCode: {}, batch: {}, fieldIndex: {}",
                    code, matnrCode, asnCode, batch, fieldIndex);
            logger.warn("数据库查询结果为空,可能原因:1.物料编码不匹配 2.物料未收货至收货区 3.数据已被删除");
        }
        // 如果扫描物料编码加载物料并且ASN单号为空时,从物料信息表获取物料信息并更新
        if (!Cools.isEmpty(matnrCode) && Cools.isEmpty(asnCode) && !list.isEmpty()) {
            // 收集所有唯一的物料编码
            Set<String> matnrCodes = list.stream()
                    .map(WarehouseAreasItem::getMatnrCode)
                    .filter(matCode -> !Cools.isEmpty(matCode))
                    .collect(Collectors.toSet());
            // 批量查询物料信息
            if (!matnrCodes.isEmpty()) {
                Map<String, Matnr> matnrMap = new HashMap<>();
                for (String matCode : matnrCodes) {
                    Matnr matnr = matnrMapper.selectOne(new LambdaQueryWrapper<Matnr>()
                            .eq(Matnr::getCode, matCode)
                            .eq(Matnr::getDeleted, 0)
                            .last("LIMIT 1"));
                    if (matnr != null) {
                        matnrMap.put(matCode, matnr);
                    }
                }
                // 更新列表中的物料信息
                list.forEach(item -> {
                    String itemMatnrCode = item.getMatnrCode();
                    if (!Cools.isEmpty(itemMatnrCode) && matnrMap.containsKey(itemMatnrCode)) {
                        Matnr matnr = matnrMap.get(itemMatnrCode);
                        // 从物料信息表更新物料名称
                        if (!Cools.isEmpty(matnr.getName())) {
                            item.setMaktx(matnr.getName());
                        }
                        // 从物料信息表更新库存单位
                        if (!Cools.isEmpty(matnr.getStockUnit())) {
                            item.setStockUnit(matnr.getStockUnit());
                        }
                        // 从物料信息表更新单位
                        if (!Cools.isEmpty(matnr.getUnit())) {
                            item.setUnit(matnr.getUnit());
                        }
                        logger.debug("已从物料信息表更新物料信息 - matnrCode: {}, name: {}, stockUnit: {}",
                                itemMatnrCode, matnr.getName(), matnr.getStockUnit());
                    }
                });
            }
        }
        list.forEach(item -> {
            Map<String, String> fields = FieldsUtils.getFields(item.getFieldsIndex());
            item.setExtendFields(fields);
        });
        logger.info("返回 {} 条可组托物料数据", list.size());
        return R.ok(list);
    }
@@ -718,7 +990,7 @@
    @Override
    public R operateToStock(OpStockParams params) {
        if (org.apache.commons.lang3.StringUtils.isBlank(params.getBarcode())) {
            throw new CoolException("托盘码不能为空!!");
            throw new CoolException("料箱码不能为空!!");
        }
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, params.getBarcode())
@@ -773,7 +1045,7 @@
            throw new CoolException("当前业务:" + SerialRuleCode.SYS_STOCK_CODE + ",编码规则不存在!!");
        }
        List<WkOrderItem> itemList = params.getItemList();
        double sum = itemList.stream().mapToDouble(WkOrderItem::getAnfme).sum();
        Double sum = QuantityUtils.roundToScale(itemList.stream().mapToDouble(WkOrderItem::getAnfme).sum());
        stock.setAnfme(sum)
                .setSourceId(order.getId())
                .setType(order.getType())
@@ -916,27 +1188,36 @@
     */
    @Override
    public R getItemByContainer(Map<String, Object> params) {
//        if (Objects.isNull(params.get("code"))) {
//            throw new CoolException("参数不能为空!!");
//        }
        //获取组拖未生成任务的组拖档
        List<Short> asList = Arrays.asList(Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_DONE.val));
        Short flagDefect = 0;
        if (!Objects.isNull(params.get("type")) && params.get("type").equals("defective")) {
            flagDefect = 1;
        }
        List<WaitPakin> waitPakin = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>()
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, params.get("barcode").toString())
//                .eq(WaitPakin::getFlagDefect, flagDefect)
                .eq(WaitPakin::getFlagDefect, flagDefect)
                .in(WaitPakin::getIoStatus, asList));
        if (!Cools.isEmpty(waitPakin)) {
            throw new CoolException("托盘不可用,在组托中已存在");
//        if (!Cools.isEmpty(waitPakin)) {
//            throw new CoolException("料箱不可用,在组托中已存在");
//        }
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.get("barcode").toString()));
        if (!tasks.isEmpty()) {
            throw new CoolException("料箱码已在任务档执行!!");
        }
        List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, params.get("barcode").toString()));
        if (!Cools.isEmpty(locs)) {
            throw new CoolException("托盘不可用,在库位中已存在");
            throw new CoolException("料箱不可用,在库位中已存在");
        }
        return R.ok("托盘可用");
//        List<WaitPakinItem> items = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
//        items.forEach(item -> {
//            FieldsItem fieldsItem = fieldsItemService.getOne(new LambdaQueryWrapper<FieldsItem>().eq(FieldsItem::getUuid, item.getFieldsIndex()).last("limit 1"));
//            if (!Objects.isNull(fieldsItem) && !Objects.isNull(item.getFieldsIndex())) {
//                Map<String, String> fields = FieldsUtils.getFields(item.getFieldsIndex());
//                item.setExtendFields(fields);
//            }
//        });
        return R.ok();
    }
    /**
@@ -949,17 +1230,14 @@
    @Override
    public R getUnItemByContainer(Map<String, Object> params) {
        if (Cools.isEmpty(params.get("barcode")) && Cools.isEmpty(params.get("code"))) {
            throw new CoolException("容器号与组托档编码不能全为空");
            throw new CoolException("料箱码与组托档编码不能全为空");
        }
        //获取组拖未生成任务的组拖档
//        List<Short> asList = Arrays.asList(Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_DONE.val), Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_DONE.val));
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(!Cools.isEmpty(params.get("barcode")), WaitPakin::getBarcode, params.get("barcode"))
                .eq(!Cools.isEmpty(params.get("code")), WaitPakin::getCode, params.get("code"))
                .eq(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val));
        if (Objects.isNull(waitPakin)) {
            return R.error("未找到该容器码的组托明细,请检查组托状态");
            return R.error("未找到该料箱码的组托明细,请检查组托状态");
        }
        List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>()
                .eq(WaitPakinItem::getPakinId, waitPakin.getId()));
@@ -1019,10 +1297,14 @@
     */
    @Override
    public R getDeviceSites() {
        List<DeviceSite> sites = deviceSiteMapper.selectList(new LambdaQueryWrapper<DeviceSite>()
        // 先查全部再按 site 去重,避免 GROUP BY 与 only_full_group_by 冲突
        List<DeviceSite> all = deviceSiteMapper.selectList(new LambdaQueryWrapper<DeviceSite>()
                .select(DeviceSite::getId, DeviceSite::getSite, DeviceSite::getName)
                .eq(DeviceSite::getStatus, 1)
                .groupBy(DeviceSite::getSite, DeviceSite::getId, DeviceSite::getName));
                .eq(DeviceSite::getStatus, 1));
        List<DeviceSite> sites = all.stream()
                .collect(Collectors.toMap(DeviceSite::getSite, d -> d, (a, b) -> a))
                .values().stream()
                .collect(Collectors.toList());
        return R.ok(sites);
    }
@@ -1071,11 +1353,11 @@
                    .setMaktx(asnOrderItem.getMaktx())
                    .setFieldsIndex(asnOrderItem.getFieldsIndex())
                    .setBarcode(asnOrderItem.getTrackCode())
                    .setQty(asnOrderItem.getQty())
                    .setQty(QuantityUtils.roundToScale(asnOrderItem.getQty()))
                    .setStockUnit(asnOrderItem.getStockUnit())
                    .setPurUnit(asnOrderItem.getPurUnit())
                    .setPoCode(asnOrderItem.getPoCode())
                    .setAnfme(asnOrderItem.getAnfme())
                    .setAnfme(QuantityUtils.roundToScale(asnOrderItem.getAnfme()))
                    .setPurQty(asnOrderItem.getPurQty())
                    .setSplrBatch(asnOrderItem.getSplrBatch())
                    .setExtendFields(asnOrderItem.getExtendFields())
@@ -1106,7 +1388,7 @@
            if (Objects.isNull(stockItem)) {
                detlsDto.setStockQty(0.0);
            } else {
                Double anfme = Math.round((stockItem.getAnfme() + stockItem.getWorkQty()) * 10000) / 10000.0;
                Double anfme = QuantityUtils.add(stockItem.getAnfme(), stockItem.getWorkQty());
                detlsDto.setStockQty(anfme);
            }