09fc8e2e0c0718be6b920c73f50f7cb9ded38f04..e877563a0916d1bec2472bbbed04ab17f0921ec4
21 小时以前 chen.lin
删除调试代码
e87756 对比 | 目录
22 小时以前 chen.lin
过滤器还原
8c1d59 对比 | 目录
22 小时以前 chen.lin
测试代码删除
42f8a4 对比 | 目录
22 小时以前 chen.lin
过滤器还原
cd5e1d 对比 | 目录
22 小时以前 chen.lin
库位转移,优化查询速度
209878 对比 | 目录
23 小时以前 chen.lin
还原
39373c 对比 | 目录
昨天 1
lsh#
5ce79f 对比 | 目录
昨天 chen.lin
盘点流程
11514b 对比 | 目录
昨天 1
lsh#
18b895 对比 | 目录
15个文件已修改
510 ■■■■ 已修改文件
rsf-admin/src/page/components/StickyDataTable.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx 127 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/exception/GlobalExceptionHandler.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckDiffItemController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckOrderType.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/StickyDataTable.jsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
import React, { useMemo, useRef, useEffect } from 'react';
import { DataTable, useDataTableDataContext, useTranslate } from 'react-admin';
import { TableFooter, TableRow, TableCell } from '@mui/material';
@@ -218,7 +218,21 @@
        };
    }, [bulkActionsOffsetY]);
    const containerRef = useRef(null);
    useEffect(() => {
        const el = containerRef.current;
        if (!el) return;
        const clearExpandIconAriaHidden = () => {
            el.querySelectorAll('.RaDataTable-expandIcon').forEach((btn) => btn.removeAttribute('aria-hidden'));
        };
        clearExpandIconAriaHidden();
        const mo = new MutationObserver(clearExpandIconAriaHidden);
        mo.observe(el, { attributes: true, attributeFilter: ['aria-hidden'], subtree: true });
        return () => mo.disconnect();
    }, []);
    return (
        <span ref={containerRef} style={{ display: 'contents' }}>
        <DataTable {...props} foot={footerComponent} sx={dataTableStyles}>
            {/* {processedChildren} */}
            {processedChildren
@@ -234,6 +248,7 @@
                ))
            }
        </DataTable>
        </span>
    );
};
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
@@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useWatch, useFormContext } from "react-hook-form";
import {
    CreateBase,
@@ -78,57 +78,101 @@
    const [orgLoc, setOrgLoc] = useState("");
    const [tarLoc, setTarLoc] = useState("");
    const [tarLocList, setTarLocList] = useState([]);
    const [tarLocTotal, setTarLocTotal] = useState(0);
    const [tarLocLoading, setTarLocLoading] = useState(false);
    const tarLocPageRef = useRef(1);
    const tarLocQueryRef = useRef("");
    const debounceRef = useRef(null);
    const PAGE_SIZE = 50;
    useEffect(() => {
        if (orgLoc === "" || orgLoc.length < 7) {
            return;
        }
        selectLocItem().then((is) => {
        selectLocItem().then((is) => {
            if (is) {
                selectAreaNoUse();
                setTarLocList([]);
                setTarLocTotal(0);
                setTarLoc(null);
            }
        });
    },[orgLoc])
    }, [orgLoc]);
    const selectLocItem = async() =>{
    const selectLocItem = async () => {
        const {
            data: { code, data, msg },
        } = await request.post("/locItem/useO/page",{
        } = await request.post("/locItem/useO/page", {
            locCode: orgLoc,
            current: 1,
            pageSize: 100,
            orderBy: "create_time desc"
        });
        if (code === 200) {
            if(data.total !== 0) {
                setTableData(data.records);
            if (data.total !== 0) {
                setTableData(data.records);
                return true;
            }
        }
        return false;
    }
        return false;
    };
    const selectAreaNoUse = async() =>{
        const {
            data: { code, data, msg },
        } = await request.post("/loc/areaNoUse/list",{
            locCode: orgLoc
        });
        if (code === 200) {
            const newData = data.map((item) => {
                return {
                    label: item,
                    id: item
    const loadAreaNoUsePage = useCallback(async (current = 1, q = "", append = false) => {
        if (!orgLoc || orgLoc.length < 7) return;
        setTarLocLoading(true);
        try {
            const { data: { code, data: pageData } } = await request.post("/loc/areaNoUse/page", {
                locCode: orgLoc,
                current,
                pageSize: PAGE_SIZE,
                q: q || undefined
            });
            if (code === 200 && pageData) {
                const { records = [], total = 0 } = pageData;
                const options = (records || []).map((item) => ({ label: item, id: item }));
                if (append) {
                    setTarLocList((prev) => [...prev, ...options]);
                } else {
                    setTarLocList(options);
                }
            })
            setTarLocList(newData);
                setTarLocTotal(total);
                tarLocPageRef.current = current;
                tarLocQueryRef.current = q;
            }
        } finally {
            setTarLocLoading(false);
        }
    }, [orgLoc]);
    }
    const handleTarLocOpen = useCallback(() => {
        if (orgLoc && orgLoc.length >= 7) {
            tarLocPageRef.current = 1;
            tarLocQueryRef.current = "";
            loadAreaNoUsePage(1, "", false);
        }
    }, [orgLoc, loadAreaNoUsePage]);
    const handleTarLocInputChange = useCallback((e, value) => {
        if (debounceRef.current) clearTimeout(debounceRef.current);
        if (!orgLoc || orgLoc.length < 7) return;
        debounceRef.current = setTimeout(() => {
            loadAreaNoUsePage(1, value ?? "", false);
            debounceRef.current = null;
        }, 300);
    }, [orgLoc, loadAreaNoUsePage]);
    const handleTarLocListboxScroll = useCallback((e) => {
        const el = e.target;
        if (!el || tarLocLoading) return;
        const { scrollTop, scrollHeight, clientHeight } = el;
        if (scrollTop + clientHeight >= scrollHeight - 10) {
            const loaded = tarLocList.length;
            if (loaded < tarLocTotal) {
                const nextPage = Math.floor(loaded / PAGE_SIZE) + 1;
                loadAreaNoUsePage(nextPage, tarLocQueryRef.current, true);
            }
        }
    }, [tarLocLoading, tarLocList.length, tarLocTotal, loadAreaNoUsePage]);
    const handleDeleteItem = () => {
@@ -170,10 +214,17 @@
                                        <Autocomplete
                                            disablePortal
                                            options={tarLocList}
                                            loading={tarLocLoading}
                                            filterOptions={(opts) => opts}
                                            onOpen={handleTarLocOpen}
                                            onInputChange={handleTarLocInputChange}
                                            renderInput={(params) => (
                                                <TextField {...params} label={translate("table.field.stockTransfer.tarLoc")} />
                                            )}
                                            onChange={(event, value) => setTarLoc(value)}
                                            ListboxProps={{
                                                onScroll: handleTarLocListboxScroll
                                            }}
                                        />
                                    </Stack>
                                </Box>
@@ -219,10 +270,10 @@
            notify("请输入源库位");
            return;
        }
        // if (tarLoc === "" || tarLoc === undefined || tarLoc === null) {
        //     notify("请输入目标库位");
        //     return;
        // }
        if (tarLoc === "" || tarLoc === undefined || tarLoc === null) {
            notify("请输入目标库位");
            return;
        }
        if (tabelData.length === 0) {
            notify("源库位明细无,请检查库位状态");
            return;
@@ -276,12 +327,12 @@
        //     type: 'number',
        //     editable: false,
        // },
        {
            field: 'locCode',
            headerName: translate('table.field.locItem.locCode'),
            width: 100,
            editable: false,
        },
        // {
        //     field: 'tarLoc',
        //     headerName: translate('table.field.stockTransfer.tarLoc'),
        //     width: 100,
        //     editable: false,
        // },
        {
            field: 'matnrCode',
            headerName: translate('table.field.locItem.matnrCode'),
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java
@@ -92,16 +92,20 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveCheckDiff(SaveCheckDiffParams params, Long loginUserId) {
        if (params.getCheckDiffItems() == null || params.getCheckDiffItems().isEmpty()) {
            throw new CoolException("盘点明细不能为空");
        }
        Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.getContainer()).last("limit 1"));
        if (null == task) {
            throw new CoolException("数据错误,未找到容器码对应盘点任务");
        }
        CheckDiff checkDiff = checkDiffService.getById(params.getCheckId());
        if (null == checkDiff) {
            return R.error("未找到盘点差异单");
        }
        if (checkDiff.getExceStatus().equals(CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_END.val)) {
            return R.error("该盘点单已完成");
        }
        Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.getContainer()).last("limit 1"));
        if (null == task) {
            throw new CoolException("数据错误,未找到容器码对应盘点任务");
        }
        for (CheckDiffItem ckDiffItem : params.getCheckDiffItems()) {
            CheckDiffItem diffItem = new CheckDiffItem();
@@ -244,7 +248,6 @@
        if (checkDiffItems.isEmpty()) {
            throw new CoolException("此条码不在当前盘点单中");
        }
        return R.ok(Cools.add("checkDiffItems",checkDiffItems).add("checkDiff",checkDiff));
        return R.ok(Cools.add("checkDiffItems", checkDiffItems).add("checkDiff", checkDiff));
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -523,8 +523,7 @@
                    || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_EMPTY_IN.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_MERGE_IN.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
                    || task.getTaskType().equals(TaskType.TASK_TYPE_MERGE_IN.type)) {
                /**修改出库站点状态*/
                BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                        .eq(BasStation::getStationName, task.getOrgSite()));
@@ -556,6 +555,10 @@
//                        throw new CoolException("站点状态修改失败!!");
//                    }
//                }
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)){
                //查询步骤  清楚源库位或者中间站点数据
                //待修改  先默认清除源库位
            }
            /**取箱完成, 修改任务状态*/
        } else if (params.getEventType().equals(CallBackEvent.CALL_BACK_EVENT_END.event)) {
@@ -1080,6 +1083,12 @@
                flowStepInstanceService.updateById(flowStepInstance);
                taskService.updateById(task);
                // 盘点再入库任务经 WCS 上报变为 100(库存更新完成)时,同步将盘点差异单置为已审核
                if (TaskType.TASK_TYPE_CHECK_IN.type.equals(task.getTaskType())
                        && flowStepInstance.getWmsNextTaskStatus() != null
                        && flowStepInstance.getWmsNextTaskStatus().equals(TaskStsType.UPDATED_IN.id)) {
                    taskService.markCheckDiffApprovedWhenCheckInDone(task);
                }
                if (flowStepInstance.getWmsNextTaskStatus() != 9999) {
                    FlowStepInstance nextFlowStepInstance = flowStepInstanceService.getOne(new LambdaQueryWrapper<FlowStepInstance>()
                            .eq(FlowStepInstance::getStatus, (short)0)
rsf-server/src/main/java/com/vincent/rsf/server/common/exception/GlobalExceptionHandler.java
@@ -81,6 +81,18 @@
    @ResponseBody
    @ExceptionHandler(RuntimeException.class)
    public R runtimeExceptionHandler(RuntimeException e, HttpServletResponse response) {
        CommonUtil.addCrossHeaders(response);
        Throwable cause = e.getCause();
        if (cause instanceof CoolException) {
            return R.error(cause.getMessage());
        }
        logger.error(e.getMessage(), e);
        return R.error(Constants.RESULT_ERROR_MSG);
    }
    @ResponseBody
    @ExceptionHandler(Throwable.class)
    public R exceptionHandler(Throwable e, HttpServletResponse response) {
        logger.error(e.getMessage(), e);
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckDiffItemController.java
@@ -93,18 +93,21 @@
        if (!diffItems.isEmpty()) {
            Map<Integer, List<CheckDiffItem>> listMap = diffItems.stream().collect(Collectors.groupingBy(CheckDiffItem::getExceStatus));
            List<CheckDiffItem> checkDiffItems = listMap.get(CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_END.val);
            if (diffItems.size() == checkDiffItems.size()) {
            if (checkDiffItems != null && diffItems.size() == checkDiffItems.size()) {
                if (!checkDiffService.update(new LambdaUpdateWrapper<CheckDiff>()
                        .eq(CheckDiff::getId, checkDiffItem.getCheckId())
                        .set(CheckDiff::getExceStatus, CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_END.val))) {
                    throw new CoolException("盘点单状态更新失败!!");
                }
                if (!checkOrderService.update(new LambdaUpdateWrapper<WkOrder>().eq(WkOrder::getId, checkDiffItem.getCheckId())
                        .set(WkOrder::getExceStatus, CheckExceStatus.CHECK_ORDER_STATUS_EXCE_DONE.val))) {
                    throw new CoolException("盘点单执行状态修改失败!!");
                // 仅在有单时更新盘点单(WkOrder)执行状态;无单盘点无盘点单,不更新
                CheckDiff checkDiff = checkDiffService.getById(checkDiffItem.getCheckId());
                if (checkDiff != null && checkDiff.getOrderId() != null) {
                    if (!checkOrderService.update(new LambdaUpdateWrapper<WkOrder>()
                            .eq(WkOrder::getId, checkDiff.getOrderId())
                            .set(WkOrder::getExceStatus, CheckExceStatus.CHECK_ORDER_STATUS_EXCE_DONE.val))) {
                        throw new CoolException("盘点单执行状态修改失败!!");
                    }
                }
            } else {
                if (!checkDiffService.update(new LambdaUpdateWrapper<CheckDiff>()
                        .eq(CheckDiff::getId, checkDiffItem.getCheckId())
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocController.java
@@ -78,6 +78,47 @@
        return R.ok(list1);
    }
    /** 同库区空闲库位分页,支持按库位号前缀过滤;用于下拉滚动分页或输入前缀实时加载 */
    @PreAuthorize("hasAuthority('manager:loc:list')")
    @PostMapping("/loc/areaNoUse/page")
    public R areaNoUsePage(@RequestBody Map<String, Object> map) {
        String locCode = (String) map.get("locCode");
        int current = map.get("current") != null ? Integer.parseInt(String.valueOf(map.get("current"))) : 1;
        int pageSize = map.get("pageSize") != null ? Integer.parseInt(String.valueOf(map.get("pageSize"))) : 50;
        if (Cools.isEmpty(locCode)) {
            Page<String> emptyPage = new Page<>(current, pageSize);
            emptyPage.setRecords(Collections.emptyList());
            emptyPage.setTotal(0L);
            return R.ok().add(emptyPage);
        }
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locCode).last("LIMIT 1"));
        if (loc == null) {
            Page<String> emptyPage = new Page<>(current, pageSize);
            emptyPage.setRecords(Collections.emptyList());
            emptyPage.setTotal(0L);
            return R.ok().add(emptyPage);
        }
        String q = map.get("q") != null ? String.valueOf(map.get("q")).trim() : null;
        if (StringUtils.isBlank(q) && map.get("condition") != null) {
            q = String.valueOf(map.get("condition")).trim();
        }
        LambdaQueryWrapper<Loc> wrapper = new LambdaQueryWrapper<Loc>()
                .select(Loc::getCode)
                .eq(Loc::getAreaId, loc.getAreaId())
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                .orderByAsc(Loc::getCode);
        if (StringUtils.isNotBlank(q)) {
            wrapper.likeRight(Loc::getCode, q);
        }
        Page<Loc> page = new Page<>(current, pageSize);
        Page<Loc> result = locService.page(page, wrapper);
        List<String> records = result.getRecords().stream().map(Loc::getCode).collect(Collectors.toList());
        Page<String> pageOut = new Page<>(current, pageSize);
        pageOut.setRecords(records);
        pageOut.setTotal(result.getTotal());
        return R.ok().add(pageOut);
    }
    @PreAuthorize("hasAuthority('manager:loc:list')")
    @PostMapping({"/loc/many/{ids}", "/locs/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.constant.Constants;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.common.annotation.OperationLog;
@@ -137,6 +138,8 @@
        try {
            locItemService.generateTask(TaskResouceType.TASK_RESOUCE_CHECK_TYPE.val, map, getLoginUserId());
        } catch (CoolException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java
@@ -335,9 +335,9 @@
//    );
    public BigDecimal getAbleQty(){
        BigDecimal anfmeDec = new BigDecimal(this.anfme.toString());
        BigDecimal workQtyDec = new BigDecimal(this.workQty.toString());
        BigDecimal qtyDec = new BigDecimal(this.qty.toString());
        BigDecimal anfmeDec = this.anfme != null ? new BigDecimal(this.anfme.toString()) : BigDecimal.ZERO;
        BigDecimal workQtyDec = this.workQty != null ? new BigDecimal(this.workQty.toString()) : BigDecimal.ZERO;
        BigDecimal qtyDec = this.qty != null ? new BigDecimal(this.qty.toString()) : BigDecimal.ZERO;
        return anfmeDec.subtract(workQtyDec).subtract(qtyDec);
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckOrderType.java
@@ -14,6 +14,7 @@
    CHECK_ORDER_TYPE_DIFF("4", "差异盘点"),
    CHECK_ORDER_TYPE_CIRCLE("5", "循环盘点"),
    CHECK_ORDER_TYPE_TIMER("6", "定期盘点"),
    CHECK_ORDER_TYPE_NORM("7", "标准盘点"),
    ;
    CheckOrderType(String type, String desc) {
@@ -37,6 +38,8 @@
            return CheckOrderType.CHECK_ORDER_TYPE_CIRCLE.type;
        } else if (desc.equals(CheckOrderType.CHECK_ORDER_TYPE_TIMER.desc)) {
            return CheckOrderType.CHECK_ORDER_TYPE_TIMER.type;
        } else if (desc.equals(CheckOrderType.CHECK_ORDER_TYPE_NORM.desc)) {
            return CheckOrderType.CHECK_ORDER_TYPE_NORM.type;
        }
        return null;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -484,7 +484,7 @@
//    @Scheduled(cron = "0/3 * * * * ?")
    public void completeInStock() throws Exception {
        try{
            List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskStatus, TaskStsType.COMPLETE_IN.id).select(Task::getId));
            List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().select(Task::getId).eq(Task::getTaskStatus, TaskStsType.COMPLETE_IN.id));
            if (tasks.isEmpty()) {
                return;
            }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -25,6 +25,11 @@
    void complateInTask(List<Task> tasks) throws Exception;
    /**
     * 盘点再入库完成后,将关联的盘点差异单置为已审核(有单按 orderId,无单按 出库任务号 orderCode)
     */
    void markCheckDiffApprovedWhenCheckInDone(Task checkInTask);
    Task taskToTop(Long id, Long loginUserId) throws Exception;
    Task operateComplete(Long id, Long loginUserId);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -1,6 +1,7 @@
package com.vincent.rsf.server.manager.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.controller.erp.params.TaskInParam;
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
@@ -53,6 +54,10 @@
    private BasStationService basStationService;
    @Autowired
    private LocItemWorkingService locItemWorkingService;
    @Autowired
    private CheckDiffService checkDiffService;
    @Autowired
    private CheckDiffItemService checkDiffItemService;
    /**
@@ -367,6 +372,63 @@
            if (!taskItemService.saveBatch(taskItems)) {
                throw new CoolException("任务明细生成失败!!");
            }
            // 无单盘点:提取出库时即生成盘点差异单,便于 PDA 按差异单校验
            if (map.getType().equals(Constants.TASK_TYPE_OUT_CHECK)) {
                Date now = new Date();
                double sumAnfme = taskItems.stream().mapToDouble(ti -> ti.getAnfme() != null ? ti.getAnfme() : 0).sum();
                CheckDiff checkDiff = new CheckDiff();
                checkDiff.setOrderCode(task.getTaskCode())
                        .setOrderId(null)
                        .setCheckType(0)
                        .setExceStatus(CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_INIT.val)
                        .setAnfme(sumAnfme)
                        .setCheckQty(0D)
                        .setStatus(1)
                        .setDeleted(0)
                        .setTenantId(task.getTenantId())
                        .setCreateBy(loginUserId)
                        .setCreateTime(now)
                        .setUpdateBy(loginUserId)
                        .setUpdateTime(now);
                if (loc.getAreaId() != null) {
                    checkDiff.setAreaId(loc.getAreaId()).setAreaName(loc.getAreaId$());
                }
                if (!checkDiffService.save(checkDiff)) {
                    throw new CoolException("无单盘点差异单创建失败!!");
                }
                List<CheckDiffItem> diffItems = new ArrayList<>();
                for (TaskItem ti : taskItems) {
                    CheckDiffItem diffItem = new CheckDiffItem();
                    diffItem.setCheckId(checkDiff.getId())
                            .setOrderCode(task.getTaskCode())
                            .setTaskId(task.getId())
                            .setTaskItemId(ti.getId())
                            .setBarcode(task.getBarcode())
                            .setAnfme(ti.getAnfme() != null ? ti.getAnfme() : 0D)
                            .setCheckQty(ti.getAnfme() != null ? ti.getAnfme() : 0D)
                            .setMatnrCode(ti.getMatnrCode())
                            .setMaktx(ti.getMaktx())
                            .setBatch(ti.getBatch())
                            .setSpec(ti.getSpec())
                            .setModel(ti.getModel())
                            .setExceStatus(CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_INIT.val)
                            .setStatus(1)
                            .setDeleted(0)
                            .setTenantId(task.getTenantId())
                            .setCreateBy(loginUserId)
                            .setCreateTime(now)
                            .setUpdateBy(loginUserId)
                            .setUpdateTime(now);
                    diffItems.add(diffItem);
                }
                if (!checkDiffItemService.saveBatch(diffItems)) {
                    throw new CoolException("无单盘点差异明细创建失败!!");
                }
                taskItemService.update(new LambdaUpdateWrapper<TaskItem>()
                        .set(TaskItem::getSourceCode, task.getTaskCode())
                        .eq(TaskItem::getTaskId, task.getId()));
            }
        });
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -1049,7 +1049,7 @@
                    .eq(LocItemWorking::getTaskId, taskItem.getTaskId())
                    .eq(LocItemWorking::getFieldsIndex, taskItem.getFieldsIndex())
                    .eq(StringUtils.isNotEmpty(taskItem.getBatch()), LocItemWorking::getBatch, taskItem.getBatch())
                    .eq(LocItemWorking::getMatnrId, taskItem.getMatnrId()));
                    .eq(LocItemWorking::getMatnrId, taskItem.getMatnrId()).last("limit 1"));
            if (Objects.isNull(locWorking)) {
               continue;
            }
@@ -1132,7 +1132,39 @@
        if (!taskService.updateById(task)) {
            throw new CoolException("任务状态修改失败!!");
        }
        // 盘点再入库任务结束:将关联的盘点差异单置为已审核
        if (TaskType.TASK_TYPE_CHECK_IN.type.equals(task.getTaskType())) {
            markCheckDiffApprovedWhenCheckInDone(task);
        }
    }
    /**
     * 盘点再入库完成后,将关联的盘点差异单置为已审核(有单按 orderId,无单按 出库任务号 orderCode)
     */
    @Override
    public void markCheckDiffApprovedWhenCheckInDone(Task checkInTask) {
        List<TaskItem> items = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, checkInTask.getId()).last("limit 1"));
        Long orderId = items.isEmpty() ? null : items.get(0).getOrderId();
        CheckDiff checkDiff = null;
        if (orderId != null && !orderId.equals(0L)) {
            checkDiff = checkDiffService.getOne(new LambdaQueryWrapper<CheckDiff>().eq(CheckDiff::getOrderId, orderId).last("limit 1"));
        } else {
            Task outTask = taskService.getOne(new LambdaQueryWrapper<Task>()
                    .eq(Task::getBarcode, checkInTask.getBarcode())
                    .eq(Task::getTaskType, TaskType.TASK_TYPE_CHECK_OUT.type)
                    .last("limit 1"));
            if (outTask != null) {
                checkDiff = checkDiffService.getOne(new LambdaQueryWrapper<CheckDiff>()
                        .eq(CheckDiff::getOrderCode, outTask.getTaskCode())
                        .and(w -> w.isNull(CheckDiff::getOrderId).or().eq(CheckDiff::getOrderId, 0))
                        .last("limit 1"));
            }
        }
        if (checkDiff != null && !CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_END.val.equals(checkDiff.getExceStatus())) {
            checkDiffService.update(new LambdaUpdateWrapper<CheckDiff>()
                    .eq(CheckDiff::getId, checkDiff.getId())
                    .set(CheckDiff::getExceStatus, CheckDiffExceStatus.CHECK_DIFF_EXCE_STATUS_END.val));
        }
    }
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java
@@ -243,82 +243,133 @@
                                .apply("JSON_CONTAINS(container_type, {0}) = 1", containerType.getContainerType().toString())//容器类型
                                .eq(BasStationArea::getDeleted, 0));
//                                .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", null)//区域包含站点集
                        if (basStationAreas.isEmpty()){
                            throw new CoolException("未找到符合条件站点!!!请检查库区配置!!!");
                        }
                        List<String> targSiteAreaList = new ArrayList<>();
                        for (BasStationArea basStationArea : basStationAreas) {
                            if (basStationArea.getStationAliasStaNo().isEmpty()){
                                continue;
                        if (!basStationAreas.isEmpty()){
                            List<String> targSiteAreaList = new ArrayList<>();
                            for (BasStationArea basStationArea : basStationAreas) {
                                if (basStationArea.getStationAliasStaNo().isEmpty()){
                                    continue;
                                }
                                targSiteAreaList.add(basStationArea.getId().toString());
                            }
                            targSiteAreaList.add(basStationArea.getId().toString());
                        }
                        if (targSiteAreaList.isEmpty()){
                            throw new CoolException("未找到符合条件站点!!!请检查库区配置!!!");
                        }
                        int count = 0;
                        for (BasStationArea basStationArea : basStationAreas) {
                            count++;
                            if (!basStationArea.getStationAliasStaNo().isEmpty()) {
                            if (targSiteAreaList.isEmpty()){
                                throw new CoolException("未找到符合条件站点!!!请检查库区配置!!!");
                            }
                            int count = 0;
                            for (BasStationArea basStationArea : basStationAreas) {
                                count++;
                                if (!basStationArea.getStationAliasStaNo().isEmpty()) {
                                    List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                                    for (String site : basStationArea.getStationAliasStaNo()) {
                                        OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                        staListDto.setStaNo(site);
                                        staListDto.setStaName(site);
                                        maps.add(staListDto);
                                    }
                                    orderOutItemDto.setStaNos(maps);
                                    //获取满足条件站点
                                    Set<String> stationSet = new HashSet<>(basStationArea.getStationAliasStaNo());
//                                Set<String> stationSet = basStationArea.getStationAlias().stream().collect(Collectors.toSet());
//                                Set<String> stationSet = deviceSites.stream().map(DeviceSite::getSite).collect(Collectors.toSet());
                                    //已使用站点
                                    Set<String> stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet());
                                    if (stas.size() == maps.size()) {
                                        stations = new ArrayList<>();
                                        stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet());
                                    }
                                    BasStationService basStationService = SpringUtils.getBean(BasStationService.class);
                                    BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                            .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                                            .in(BasStation::getStationName, stationSet)
                                            .notIn(!stas.isEmpty(), BasStation::getStationName, stas)
                                            .last("LIMIT 1"));
                                    if (!Objects.isNull(basStation)) {
                                        stations.add(basStation);
                                    }
                                    if (count == basStationAreas.size()) {
                                        if (!Objects.isNull(basStation)) {
                                            orderOutItemDto.setTargSiteAreaNow(basStationArea.getStationAreaId());
                                            orderOutItemDto.setSiteNo(basStation.getStationName());
//                                        throw new CoolException("站點不存在!!");
                                        } else if (!stas.isEmpty()) {
                                            orderOutItemDto.setTargSiteAreaNow(basStationArea.getStationAreaId());
                                            orderOutItemDto.setSiteNo(basStationArea.getStationAliasStaNo().get(0));
                                        } else {
                                            throw new CoolException("未找到符合条件站点!!!请检查库区或者路径配置!!!");
                                        }
                                    } else {
                                        if (Objects.isNull(basStation)) {
                                            continue;
//                                        throw new CoolException("站點不存在!!");
                                        }
                                        orderOutItemDto.setTargSiteAreaNow(basStationArea.getStationAreaId());
                                        orderOutItemDto.setSiteNo(basStation.getStationName());
                                    }
                                }
                                orderOutItemDto.setSource(item.getItemId().toString())
                                        .setTargSiteAreaList(targSiteAreaList)
                                        .setSourceId(item.getWaveId().toString());
                                list.add(orderOutItemDto);
                                locList.add(loc);
                                issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                                break;
                            }
                        } else {
                            List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                    .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
                                    .eq(!Objects.isNull(loc.getAreaId()), DeviceSite::getAreaIdStart, loc.getAreaId())
                                    .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                            );
                            if (!deviceSites.isEmpty()) {
                                List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                                for (String site : basStationArea.getStationAliasStaNo()) {
                                for (DeviceSite sta : deviceSites) {
                                    OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                    staListDto.setStaNo(site);
                                    staListDto.setStaName(site);
                                    staListDto.setStaNo(sta.getSite());
                                    staListDto.setStaName(sta.getSite());
                                    maps.add(staListDto);
                                }
                                orderOutItemDto.setStaNos(maps);
                                //获取满足条件站点
                                Set<String> stationSet = new HashSet<>(basStationArea.getStationAliasStaNo());
//                                Set<String> stationSet = basStationArea.getStationAlias().stream().collect(Collectors.toSet());
//                                Set<String> stationSet = deviceSites.stream().map(DeviceSite::getSite).collect(Collectors.toSet());
                                Set<String> stationSet = deviceSites.stream().map(DeviceSite::getSite).collect(Collectors.toSet());
                                //已使用站点
                                Set<String> stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet());
                                if (stas.size() == maps.size()) {
                                    stations = new ArrayList<>();
                                    stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet());
                                }
                                BasStationService basStationService = SpringUtils.getBean(BasStationService.class);
                                BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                        .apply("cross_zone_area != '[]'")  // 不是空数组
                                        .apply("container_type != '[]'")
                                        .apply("JSON_CONTAINS(cross_zone_area, {0}) = 1", loc.getAreaId().toString())//可执行库区区区域id
                                        .apply("JSON_CONTAINS(container_type, {0}) = 1", containerType.getContainerType().toString())//容器类型
                                        .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                                        .in(BasStation::getStationName, stationSet)
                                        .notIn(!stas.isEmpty(), BasStation::getStationName, stas)
                                        .last("LIMIT 1"));
                                if (!Objects.isNull(basStation)) {
                                if (Objects.isNull(basStation)) {
                                    throw new CoolException("站點不存在!!");
                                }
                                if (basStation.getType()!=0){
                                    stations.add(basStation);
                                }
                                if (count == basStationAreas.size()) {
                                    if (!Objects.isNull(basStation)) {
                                        orderOutItemDto.setTargSiteAreaNow(basStationArea.getStationAreaId());
                                        orderOutItemDto.setSiteNo(basStation.getStationName());
//                                        throw new CoolException("站點不存在!!");
                                    } else if (!stas.isEmpty()) {
                                        orderOutItemDto.setTargSiteAreaNow(basStationArea.getStationAreaId());
                                        orderOutItemDto.setSiteNo(basStationArea.getStationAliasStaNo().get(0));
                                    } else {
                                        throw new CoolException("未找到符合条件站点!!!请检查库区或者路径配置!!!");
                                    }
                                } else {
                                    if (Objects.isNull(basStation)) {
                                        continue;
//                                        throw new CoolException("站點不存在!!");
                                    }
                                    orderOutItemDto.setTargSiteAreaNow(basStationArea.getStationAreaId());
                                    orderOutItemDto.setSiteNo(basStation.getStationName());
                                }
                                orderOutItemDto.setSiteNo(basStation.getStationName());
                            } else {
                                throw new CoolException("未找到符合条件站点!!!请检查路径管理!!!");
                            }
                            orderOutItemDto.setSource(item.getItemId().toString())
                                    .setTargSiteAreaList(targSiteAreaList)
                                    .setTargSiteAreaList(new ArrayList<>())
                                    .setSourceId(item.getWaveId().toString());
                            list.add(orderOutItemDto);
                            locList.add(loc);
                            locList.add(loc);
                            issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                            break;
                        }
//                         if (true){
////                            throw new CoolException("未找到符合条件站点!!!请检查库区配置!!!");
//                        }
                    }
                }
            }
@@ -343,7 +394,7 @@
                return container;
            }
        }
        return null;
        throw new CoolException("容器码:"+barcode+"异常==>未找到匹配的规则");
    }
}