cbfbbc6ab15b0eac96b47e7a6214bc436e58dce2..7925e2cfcdcb39e9ac6793edd5362bbe369def5c
2025-05-22 skyouc
保存拣料入库流水
7925e2 对比 | 目录
2025-05-22 skyouc
库存出库任务联调
10dbf9 对比 | 目录
2025-05-22 zjj
#出库作业
706703 对比 | 目录
2025-05-22 skyouc
库存出库生成任务 优化
456f4f 对比 | 目录
28个文件已修改
1个文件已删除
1 文件已重命名
785 ■■■■■ 已修改文件
rsf-admin/src/i18n/en.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locItem/LocItemList.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/outWork/outBound/OutBoundList.jsx 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/outWork/outBound/StaSelect.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/outWork/outBound/locItemInfoModal.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/TaskList.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/WcsController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/WcsService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/DeviceSiteController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItem.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItemWorking.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Task.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/TaskLog.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/LocStsType.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/StaUseStatusType.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskStsType.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WarehType.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocItemService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js
@@ -987,6 +987,7 @@
                wkType: "wkType",
                aggType: "Agg Type",
                matnrId: "matnrId",
                wareArea: 'Warehouse Areas',
                maktx: "maktx",
                matnrCode: "matnrCode",
                trackCode: "trackCode",
@@ -1155,6 +1156,8 @@
        error: {
            stock: "Insufficient inventory to deliver !!",
            select_error_order: "Please Select Asn Orders",
            out_stock_qty: "The outbound quantity cannot be greater than the inventory quantity",
        }
    }
rsf-admin/src/i18n/zh.js
@@ -979,6 +979,7 @@
                orderItemId: "单据明细ID",
                wkType: "业务类型",
                aggType: "汇总类型",
                wareArea: '库区',
                matnrId: "物料ID",
                maktx: "物料名称",
                unit: '单位',
@@ -1152,6 +1153,8 @@
        error: {
            stock: "库存不足,无法提交!!", 
            select_error_order: "请选择通知单",
            out_stock_qty: "出库数量不能大于库存数量",
        }
    }
rsf-admin/src/page/locItem/LocItemList.jsx
@@ -160,6 +160,7 @@
            const arr = [
                <NumberField source="id" />,
                <NumberField source="locId" label="table.field.locItem.locId" />,
                <TextField source="wareArea" label="table.field.locItem.wareArea" />,
                <TextField source="locCode" label="table.field.locItem.locCode" />,
                <NumberField source="orderId" label="table.field.locItem.orderId" />,
                <TextField source="type$" label="table.field.locItem.type" />,
rsf-admin/src/page/outWork/outBound/OutBoundList.jsx
@@ -20,7 +20,8 @@
    useCreateController,
    useListContext,
    useRefresh,
    Edit,
    Edit,
    useRedirect,
} from 'react-admin';
import {
    Dialog,
@@ -59,13 +60,15 @@
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import StaSelect from "./StaSelect";
import { redirect } from "react-router";
import { number } from "prop-types";
const OutBoundList = () => {
const OutBoundList = () => {
    const [createDialog, setCreateDialog] = useState(false);
    const [tabelData, setTableData] = useState([]);
    const [selectedRows, setSelectedRows] = useState([]);
    const [sta,setSta] = useState("");
    const [sta, setSta] = useState("");
    const notify = useNotify();
    const tableRef = useRef();
    tableRef.current = useGridApiRef();
@@ -75,7 +78,7 @@
        const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
        setTableData(newTableData);
    }
    // 添加一个处理新数据的函数,设置outQty默认值
    const handleSetData = (newData) => {
        // 为新添加的数据设置outQty默认值为anfme的值
@@ -86,109 +89,126 @@
        setTableData([...tabelData, ...dataWithDefaultQty]);
    };
    return (
        <>
        <Card sx={{ p: 2, mb: 2, mt:2}}>
            <Grid container spacing={2}>
                <Grid item xs={12}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}>
                        <Typography variant="h6">
                            {translate('table.field.outBound.stockWithdrawal')}
                        </Typography>
                        <Stack direction='row' spacing={2}>
                            <Button
                                variant="contained"
                                color="primary"
                                startIcon={<AddIcon />}
                                onClick={() => setCreateDialog(true)}
                            >
                                {translate('table.field.outBound.withdrawal')}
                            </Button>
                        </Stack>
                    </Box>
            <Card sx={{ p: 2, mb: 2, mt: 2 }}>
                <Grid container spacing={2}>
                    <Grid item xs={12}>
                        <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}>
                            <Typography variant="h6">
                                {translate('table.field.outBound.stockWithdrawal')}
                            </Typography>
                            <Stack direction='row' spacing={2}>
                                <Button
                                    variant="contained"
                                    color="primary"
                                    startIcon={<AddIcon />}
                                    onClick={() => setCreateDialog(true)}
                                >
                                    {translate('table.field.outBound.withdrawal')}
                                </Button>
                            </Stack>
                        </Box>
                    </Grid>
                </Grid>
            </Grid>
        </Card>
        <Card sx={{ p: 2, mb: 2}}>
            <Form>
            <Grid container spacing={2}>
                <Grid item xs={12}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}>
                        <Typography  variant="h6" >
                            {translate('table.field.outBound.outSta')}
                         </Typography>
                        <Stack direction='row' spacing={2} minWidth={200}>
                            <StaSelect
                                source="sta"
                                label={translate("table.field.outBound.outSta")}
                                onChange={(e) => {
                                    setSta(e.target.value);
                                    console.log("站点已选择:", e.target.value);
                                }}
                                size="small"
                                type="1"
                            />
                        </Stack>
                        <Stack direction='row' spacing={2} minWidth={200}>
                            <SubmitButton
                                sta={sta}
                                data={tabelData}
                            />
                        </Stack>
                    </Box>
                </Grid>
            </Grid>
            </Form>
        </Card>
        <Card sx={{ mb: 2}}>
            <Box sx={{  }}>
                <ModalTable tabelData={tabelData} setTableData={setTableData}  selectedRows={selectedRows} setSelectedRows={setSelectedRows} tableRef={tableRef}></ModalTable>
            </Box>
        </Card>
        <LocItemInfoModal
            </Card>
            <Card sx={{ p: 2, mb: 2 }}>
                <Form>
                    <Grid container spacing={2}>
                        <Grid item xs={12}>
                            <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}>
                                <Typography variant="h6" >
                                    {translate('table.field.outBound.outSta')}
                                </Typography>
                                <Stack direction='row' spacing={2} minWidth={200}>
                                    <StaSelect
                                        source="sta"
                                        label={translate("table.field.outBound.outSta")}
                                        onChange={(e) => {
                                            setSta(e.target.value);
                                            console.log("站点已选择:", e.target.value);
                                        }}
                                        size="small"
                                        type="[101,103]"
                                    />
                                </Stack>
                                <Stack direction='row' spacing={2} minWidth={200}>
                                    <SubmitButton
                                        sta={sta}
                                        data={tabelData}
                                        setTableData={setTableData}
                                    />
                                </Stack>
                            </Box>
                        </Grid>
                    </Grid>
                </Form>
            </Card>
            <Card sx={{ mb: 2 }}>
                <Box sx={{}}>
                    <ModalTable tabelData={tabelData} setTableData={setTableData} selectedRows={selectedRows} setSelectedRows={setSelectedRows} tableRef={tableRef}></ModalTable>
                </Box>
            </Card>
            <LocItemInfoModal
                open={createDialog}
                setOpen={setCreateDialog}
                data={tabelData}
                setData={handleSetData}
            />
        </>
    )
}
export default OutBoundList;
const SubmitButton = (props) =>{
const SubmitButton = (props) => {
    const translate = useTranslate();
    const notify = useNotify();
    const { sta, data } = props;
    const check = ()=>{
        if(sta === "" || sta === undefined || sta === null){
    const redirect = useRedirect();
    const refresh = useRefresh();
    const { sta, data, setTableData } = props;
    const check = () => {
        if (sta === "" || sta === undefined || sta === null) {
            notify("请选择站点");
            return;
        }
        if(data.length === 0){
        if (data.length === 0) {
            notify("请选择物料");
            return;
        }
        http(sta,data);
        http(sta, data);
    }
    const http = async (sta, items) => {
        console.log(items);
    }
    const http = async (sta,data) => {
        console.log("提交数据",sta,data);
        const filter = items.filter(item => (item.outQty + item.workQty) > item.anfme);
        if (filter.length > 0) {
            notify(translate('toolbar.request.error.out_stock_qty'))
            return
        }
        const { data: { code, data, msg } } = await request.post(`/locItem/generate/task`, { siteNo: sta, items: items });
        if (code === 200) {
            notify(msg);
            refresh()
            setTableData([])
            redirect("/task")
        } else {
            notify(msg);
        }
    }
    return (
        <Button
            variant="contained"
            color="primary"
            onClick={check}
        <ConfirmButton
            variant="contained"
            color="primary"
            onConfirm={check}
            label={"table.field.outBound.createTask"}
        >
          {translate('table.field.outBound.createTask')}
        </Button>
        </ConfirmButton>
    )
}
const ModalTable = ({ tabelData, setTableData, selectedRows, setSelectedRows, tableRef }) => {
@@ -198,23 +218,32 @@
    const [columns, setColumns] = useState([
        {
            field: 'outQty',
            headerName: translate('table.field.outBound.outQty')+"*",
            headerName: translate('table.field.outBound.outQty') + "*",
            width: 100,
            editable: true,
            headerClassName: "custom",
            type: 'number',
            editable: true,
            headerClassName: "custom",
        },
        {
            field: 'anfme',
            headerName: translate('table.field.locItem.anfme'),
            type: 'number',
            width: 100,
            editable: false,
        },
        },
        {
            field: 'workQty',
            headerName: translate('table.field.locItem.workQty'),
            width: 100,
            type: 'number',
            editable: false,
        },
        {
            field: 'matnrCode',
            headerName: translate('table.field.locItem.matnrCode'),
            width: 130,
            editable: false,
        },
        },
        {
            field: 'maktx',
            headerName: translate('table.field.locItem.maktx'),
rsf-admin/src/page/outWork/outBound/StaSelect.jsx
@@ -29,7 +29,7 @@
    const http = async () => {
        setLoading(true);
        try {
            const res = await request.post('/deviceSite/page', {
            const res = await request.post('/selectStaList/page', {
                type: type,
                current: page,
                pageSize: perPage
rsf-admin/src/page/outWork/outBound/locItemInfoModal.jsx
@@ -44,7 +44,7 @@
    };
    const reset = () => {
        setFormData({
        setFormData({
        })
    }
@@ -129,7 +129,7 @@
                                onChange={handleChange}
                                size="small"
                            />
                        </Grid>
                        </Grid>
                    </Grid>
                </Box>
                <Box sx={{ mt: 2 }}>
@@ -172,9 +172,9 @@
        { field: 'maktx', headerName: translate('table.field.locItem.maktx'), width: 300 },
        { field: 'batch', headerName: translate('table.field.locItem.batch'), width: 100 },
        { field: 'anfme', headerName: translate('table.field.locItem.anfme'), width: 100 },
        { field: 'workQty', headerName: translate('table.field.locItem.workQty'), width: 100 },
        { field: 'unit', headerName: translate('table.field.locItem.unit'), width: 100 },
    ])
rsf-admin/src/page/task/TaskList.jsx
@@ -186,13 +186,19 @@
    const record = useRecordContext();
    const notify = useNotify();
    const refresh = useRefresh();
    const pickClick = () => {
    const pickClick = async () => {
        const { data: { code, data, msg } } = await request.post(`/task/pick/` + record.id);
        if (code === 200) {
            notify(msg);
            refresh();
        } else {
            notify(msg);
        }
    }
    return (
        record?.taskStatus == 103 ? <ConfirmButton label={"toolbar.pick"} startIcon={<ColorizeOutlinedIcon />} onConfirm={pickClick}/> : <></>
        record?.taskStatus == 198 ? <ConfirmButton label={"toolbar.pick"} startIcon={<ColorizeOutlinedIcon />} onConfirm={pickClick} /> : <></>
    )
}
@@ -219,7 +225,7 @@
        }
    }
    return (
        record?.taskStatus < 98 ? (<ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskAltIcon />} onConfirm={clickComplete} />) : (<></>)
        ((record?.taskStatus < 98) || (record?.taskType > 101 && record?.taskStatus < 198)) ? (<ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskAltIcon />} onConfirm={clickComplete} />) : (<></>)
    )
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/WcsController.java
@@ -81,8 +81,4 @@
        return R.ok();
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/WcsService.java
@@ -7,4 +7,6 @@
    InTaskMsgDto createInTask(TaskInParam param);
    void agvTaskPickUpComplete(TaskInParam param);
    InTaskMsgDto getLocNo(TaskInParam param);
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java
@@ -1,7 +1,5 @@
package com.vincent.rsf.server.api.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
@@ -9,8 +7,8 @@
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.service.AgvService;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.PakinIOStatus;
import com.vincent.rsf.server.manager.enums.StaUseStatusType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,7 +16,6 @@
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -56,7 +53,7 @@
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
                .eq(BasStation::getUseStatus,StaUseStatusType.TYPE_O.type)
                .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到接驳站点信息,请检查站点状态");
@@ -97,7 +94,7 @@
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
                .eq(BasStation::getUseStatus,StaUseStatusType.TYPE_F.type)
                .eq(BasStation::getUseStatus,LocStsType.LOC_STS_TYPE_F.type)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到接驳站点信息,请检查站点状态");
@@ -116,7 +113,7 @@
        taskService.generateAGVTasks(waitPakin,targetLoc,sta,loginUserId);
        basStation.setUseStatus(StaUseStatusType.TYPE_R.type);
        basStation.setUseStatus(LocStsType.LOC_STS_TYPE_R.type);
        if (!basStationService.updateById(basStation)){
            throw new CoolException("更新站点状态失败");
        }
@@ -136,7 +133,7 @@
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
                .eq(BasStation::getUseStatus,StaUseStatusType.TYPE_F.type)
                .eq(BasStation::getUseStatus,LocStsType.LOC_STS_TYPE_F.type)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到接驳站点信息,请检查站点状态");
@@ -152,7 +149,7 @@
            throw new CoolException("未找到组托数据,请检查状态");
        }
        basStation.setBarcode(null);
        basStation.setUseStatus(StaUseStatusType.TYPE_O.type);
        basStation.setUseStatus(LocStsType.LOC_STS_TYPE_O.type);
        if (!basStationService.updateById(basStation)){
            throw new CoolException("更新站点状态失败");
        }
@@ -169,7 +166,7 @@
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
                .eq(BasStation::getUseStatus,StaUseStatusType.TYPE_F.type)
                .eq(BasStation::getUseStatus,LocStsType.LOC_STS_TYPE_F.type)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到接驳站点信息,请检查站点状态");
@@ -219,7 +216,7 @@
        //验证基础信息
        BasStation basStation = checkStaStatus(barcode, sta);
        //更新站点状态
        basStation.setUseStatus(StaUseStatusType.TYPE_F.type);
        basStation.setUseStatus(LocStsType.LOC_STS_TYPE_F.type);
        basStation.setBarcode(barcode);
        if (!basStationService.updateById(basStation)){
            throw new CoolException("更新站点状态失败");
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -15,7 +15,7 @@
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
@@ -74,7 +74,7 @@
        task.setTaskStatus(TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD.id);
        taskService.updateById(task);
        basStation.setUseStatus(StaUseStatusType.TYPE_O.type);
        basStation.setUseStatus(LocStsType.LOC_STS_TYPE_O.type);
        basStation.setBarcode(null);
        basStationService.updateById(basStation);
@@ -164,8 +164,8 @@
                            String targetSite, String sourceSiteNo, Long loginUserId) {
        Task task = new Task();
        task.setTaskCode(ruleCode)
                .setTaskStatus(TaskStsType.GENERATE_IN.id.shortValue())
                .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue())
                .setTaskStatus(TaskStsType.GENERATE_IN.id)
                .setTaskType(TaskType.TASK_TYPE_IN.type)
                .setWarehType(WarehType.WAREHOUSE_TYPE_CRN.id)
                .setTargLoc(targetLoc)
                .setBarcode(barcode)
@@ -327,6 +327,7 @@
//        locNo.setWorkNo(ruleCode);
//        return locNo;
//    }
    @Override
    public InTaskMsgDto getLocNo(TaskInParam param) {
        String matnr = null;
        String batch = null;
@@ -363,6 +364,9 @@
            case "CTU": //ctu
                dto = getLocNoCtu(deviceBind, warehouseArea.getId(), param.getSourceStaNo(), matnr, batch, locTypeDto, 0, param.getIoType());
                break;
            default:
                dto = getLocNoCtu(deviceBind, warehouseArea.getId(), param.getSourceStaNo(), matnr, batch, locTypeDto, 0, param.getIoType());
                break;
        }
        return dto;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java
@@ -1,6 +1,5 @@
package com.vincent.rsf.server.manager.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -12,7 +11,7 @@
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.BasStation;
import com.vincent.rsf.server.manager.enums.StaUseStatusType;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.service.BasStationService;
import com.vincent.rsf.server.system.controller.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
@@ -114,7 +113,7 @@
        if (null != basStation.getContainerTypes() && !basStation.getContainerTypes().isEmpty()){
            basStation.setContainerType(basStation.getContainerTypes().toString());
        }
        if (null !=basStation.getUseStatus() && basStation.getUseStatus().equals(StaUseStatusType.TYPE_O.type)){
        if (null !=basStation.getUseStatus() && basStation.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)){
            basStation.setBarcode(null);
        }
        if (!basStationService.updateById(basStation)) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/DeviceSiteController.java
@@ -1,6 +1,8 @@
package com.vincent.rsf.server.manager.controller;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
@@ -38,6 +40,24 @@
        return R.ok().add(deviceSiteService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:deviceSite:list')")
    @PostMapping("/selectStaList/page")
    public R selectStaList(@RequestBody Map<String, Object> map) {
        List<String> longs = null;
        if (map.get("type") != null) {
            longs = JSONArray.parseArray(map.get("type").toString(), String.class);
            map.entrySet().removeIf(next -> next.getKey().equals("type"));
        }
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<DeviceSite, BaseParam> pageParam = new PageParam<>(baseParam, DeviceSite.class);
        QueryWrapper<DeviceSite> queryWrapper = pageParam.buildWrapper(true);
        queryWrapper.lambda().in(DeviceSite::getType, longs);
        PageParam<DeviceSite, BaseParam> page = deviceSiteService.page(pageParam, queryWrapper);
        return R.ok().add(page );
    }
    @PreAuthorize("hasAuthority('manager:deviceSite:list')")
    @PostMapping("/deviceSite/list")
    public R list(@RequestBody Map<String, Object> map) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java
@@ -12,10 +12,9 @@
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.entity.LocItem;
import com.vincent.rsf.server.manager.entity.WarehouseAreasItem;
import com.vincent.rsf.server.manager.service.LocItemService;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.system.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.LocStsType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -78,6 +77,15 @@
    }
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @PostMapping("/locItem/generate/task")
    public R generateTask(@RequestBody Map<String, Object> map) {
        if (Objects.isNull(map)) {
            return R.error("参数不能为空!!");
        }
        return locItemService.generateTask(map);
    }
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @PostMapping("/locItem/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(locItemService.list());
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java
@@ -14,9 +14,8 @@
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.BasStationServiceImpl;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.system.enums.LocStsType;
import com.vincent.rsf.server.system.service.impl.ConfigServiceImpl;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -37,6 +36,8 @@
    private WaitPakinService waitPakinService;
    @Autowired
    private LocService locService;
    @Autowired
    private ConfigServiceImpl configService;
    @PreAuthorize("hasAuthority('manager:task:list')")
@@ -130,8 +131,9 @@
        if (Objects.isNull(id)) {
            throw new CoolException("参数不能为空!!");
        }
        List<Short> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Integer> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getId, id).in(Task::getTaskStatus, longs));
        for (Task task : tasks) {
            task.setTaskStatus(task.getTaskType() < (short) 100 ? TaskStsType.COMPLETE_IN.id : TaskStsType.COMPLETE_OUT.id);
        }
@@ -154,7 +156,7 @@
            throw new CoolException("能数不能为空!!");
        }
        try {
            return taskService.pickTask(id);
            return R.ok(taskService.pickTask(id));
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
@@ -177,7 +179,7 @@
        if (Objects.isNull(id)) {
            throw new CoolException("参数不能为空!!");
        }
        List<Short> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Integer> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getId, id).in(Task::getTaskStatus, longs));
        if (tasks.isEmpty()) {
            throw new CoolException("任务已处执行状态不可一键置顶!!");
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItem.java
@@ -7,6 +7,8 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.server.manager.service.WarehouseAreasService;
import com.vincent.rsf.server.system.constant.DictTypeCode;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.service.DictDataService;
@@ -93,6 +95,10 @@
    @ApiModelProperty("项目号")
    private String projectCode;
    @ApiModelProperty("出库数量")
    @TableField(exist = false)
    private Double outQty;
    /**
     * 物料名称
@@ -285,6 +291,18 @@
//            null    // 备注
//    );
    public String getWareArea(){
        if (Cools.isEmpty(this.locId)){
            return "";
        }
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getById(this.locId);
        if (Objects.isNull(loc)) {
            return null;
        }
        return loc.getAreaId$();
    }
    public String getType$(){
        if (Cools.isEmpty(this.type)){
            return "";
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItemWorking.java
@@ -194,7 +194,6 @@
     * 是否删除 1: 是  0: 否  
     */
    @ApiModelProperty(value= "是否删除 1: 是  0: 否  ")
    @TableLogic
    private Integer deleted;
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Task.java
@@ -54,19 +54,19 @@
     * 任务状态
     */
    @ApiModelProperty(value= "任务状态")
    private Short taskStatus;
    private Integer taskStatus;
    @ApiModelProperty("上级任务ID")
    private Long parentId;
    @ApiModelProperty("仓库类型")
    private Short warehType;
    private Integer warehType;
    /**
     * 任务类型
     */
    @ApiModelProperty(value= "任务类型")
    private Short taskType;
    private Integer taskType;
    /**
     * 源库位
@@ -196,7 +196,7 @@
    public Task() {}
    public Task(String taskCode,Short taskStatus,Short taskType,String orgLoc,String targLoc,String barcode,String robotCode,Short exceStatus,String expDesc,Short sort,String expCode,Date startTime,Date endTime,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
    public Task(String taskCode,Integer taskStatus,Integer taskType,String orgLoc,String targLoc,String barcode,String robotCode,Short exceStatus,String expDesc,Short sort,String expCode,Date startTime,Date endTime,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.taskCode = taskCode;
        this.taskStatus = taskStatus;
        this.taskType = taskType;
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/TaskLog.java
@@ -62,13 +62,13 @@
     * 任务状态
     */
    @ApiModelProperty(value= "任务状态")
    private Short taskStatus;
    private Integer taskStatus;
    /**
     * 任务类型
     */
    @ApiModelProperty(value= "任务类型")
    private Short taskType;
    private Integer taskType;
    /**
     * 源库位
@@ -186,7 +186,7 @@
    public TaskLog() {}
    public TaskLog(Long taskId,String taskCode,Short taskStatus,Short taskType,String orgLoc,String targLoc,String barcode,String robotCode,Short exceStatus,String expDesc,Short sort,String expCode,Date startTime,Date endTime,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
    public TaskLog(Long taskId,String taskCode,Integer taskStatus,Integer taskType,String orgLoc,String targLoc,String barcode,String robotCode,Short exceStatus,String expDesc,Short sort,String expCode,Date startTime,Date endTime,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.taskId = taskId;
        this.taskCode = taskCode;
        this.taskStatus = taskStatus;
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/LocStsType.java
File was renamed from rsf-server/src/main/java/com/vincent/rsf/server/system/enums/LocStsType.java
@@ -1,4 +1,4 @@
package com.vincent.rsf.server.system.enums;
package com.vincent.rsf.server.manager.enums;
public enum LocStsType {
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/StaUseStatusType.java
File was deleted
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskStsType.java
@@ -41,14 +41,15 @@
    WAVE_SEED("198", "播种中"),
    COMPLETE_OUT("199", "出库完成"),
    UPDATED_OUT("200", "库存更新完成"),
    ;
    public Short id;
    public Integer id;
    public String desc;
    TaskStsType(String id, String desc) {
        this.id = Short.parseShort(id);
        this.id = Integer.parseInt(id);
        this.desc = desc;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java
@@ -21,11 +21,11 @@
    TASK_TYPE_CHECK_OUT("107", "盘点出库"),
    TASK_TYPE_EMPITY_OUT("110", "空板出库"),
    ;
    public Short type;
    public Integer type;
    public String desc;
    TaskType(String type, String desc) {
        this.type = Short.parseShort(type);
        this.type = Integer.parseInt(type);
        this.desc = desc;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WarehType.java
@@ -10,11 +10,11 @@
    WAREHOUSE_TYPE_CRN("5", "堆垛机库"),
    ;
    public Short id;
    public Integer id;
    public String desc;
    WarehType(String id, String desc) {
        this.id = Short.parseShort(id);
        this.id = Integer.parseInt(id);
        this.desc = desc;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -16,6 +16,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -48,21 +49,22 @@
    private LocService locService;
    @Autowired
    private ConfigService configService;
    /**
    * @author Ryan
    * @description 完成入库,更新库存
    * @param
    * @return
    * @time 2025/4/2 12:37
    */
     * @param
     * @return
     * @author Ryan
     * @description 完成入库,更新库存
     * @time 2025/4/2 12:37
     */
    @Scheduled(cron = "0/3 * * * * ?")
    @Transactional(rollbackFor = Exception.class)
//    @Transactional(rollbackFor = Exception.class)
    public void completeInStock() throws Exception {
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskStatus, TaskStsType.COMPLETE_IN.id));
        if (tasks.isEmpty()) {
            return;
        }
        taskService.completeTask(tasks);
        taskService.complateInTask(tasks);
    }
    /**
@@ -71,7 +73,7 @@
     * @description: 完成出库任务,更新库存
     * @version 1.0
     */
    @Scheduled(cron = "0/5 * * * * ?")
    @Scheduled(cron = "0/30 * * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void complateOutStock() throws Exception {
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskStatus, TaskStsType.COMPLETE_OUT.id));
@@ -82,12 +84,12 @@
    }
    /**
    * @author Ryan
    * @description 已完成任务加入历史档
    * @param
    * @return
    * @time 2025/4/3 12:54
    */
     * @param
     * @return
     * @author Ryan
     * @description 已完成任务加入历史档
     * @time 2025/4/3 12:54
     */
    @Scheduled(cron = "0 0/05 * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void taskLogUpdate() {
@@ -113,32 +115,37 @@
            return;
        }
        List<TaskLog> taskLogs = new ArrayList<>();
        Map<Long, List<TaskItem>> listMap = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getTaskId));
        tasks.forEach(task -> {
            TaskLog taskLog = new TaskLog();
            BeanUtils.copyProperties(task, taskLog);
            taskLog.setTaskId(task.getId()).setId(null);
            taskLogs.add(taskLog);
        });
        if (!taskLogService.saveBatch(taskLogs)) {
            throw new CoolException("任务历史档保存失败!!");
        }
        List<TaskItemLog >itemLogs = new ArrayList<>();
            taskLog.setTaskId(task.getId())
                    .setId(null);
            if (!taskLogService.save(taskLog)) {
                throw new CoolException("任务历史档保存失败!!");
            }
        taskItems.forEach(item -> {
            TaskItemLog itemLog = new TaskItemLog();
            BeanUtils.copyProperties(item, itemLog);
            itemLog.setId(null).setTaskItemId(item.getId());
            itemLogs.add(itemLog);
        });
            List<TaskItemLog> itemLogs = new ArrayList<>();
            for (TaskItem item : listMap.get(task.getId())) {
                TaskItemLog itemLog = new TaskItemLog();
                BeanUtils.copyProperties(item, itemLog);
                itemLog.setId(null)
                        .setTaskId(task.getId())
                        .setLogId(taskLog.getId())
                        .setTaskItemId(item.getId());
                itemLogs.add(itemLog);
            }
        if (!taskItemLogService.saveBatch(itemLogs)) {
            throw new CoolException("任务明细历史档保存失败!!");
        }
            if (!taskItemLogService.saveBatch(itemLogs)) {
                throw new CoolException("任务明细历史档保存失败!!");
            }
        });
        if (!taskService.removeByIds(list)) {
            throw new CoolException("原始任务删除失败!!");
        }
        List<Long> itemIds = taskItems.stream().map(TaskItem::getId).collect(Collectors.toList());
        if (!taskItemService.removeByIds(itemIds)) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocItemService.java
@@ -1,8 +1,12 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.manager.entity.LocItem;
import java.util.Map;
public interface LocItemService extends IService<LocItem> {
    R generateTask(Map<String, Object> map);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -21,5 +21,7 @@
    R removeTask(Long[] ids);
    R pickTask(Long id) throws Exception;
    Task pickTask(Long id) throws Exception;
    void complateInTask(List<Task> tasks) throws Exception;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -1,12 +1,144 @@
package com.vincent.rsf.server.manager.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.entity.Task;
import com.vincent.rsf.server.manager.entity.TaskItem;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.mapper.LocItemMapper;
import com.vincent.rsf.server.manager.entity.LocItem;
import com.vincent.rsf.server.manager.service.LocItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.server.manager.service.TaskItemService;
import com.vincent.rsf.server.manager.service.TaskService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.Synchronized;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service("locItemService")
public class LocItemServiceImpl extends ServiceImpl<LocItemMapper, LocItem> implements LocItemService {
    @Autowired
    private LocService locService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private TaskItemService taskItemService;
    @Autowired
    private LocItemService locItemService;
    /**
     * 库存出库生成出库任务
     *
     * @param map
     * @return
     */
    @Override
    @Synchronized
    @Transactional(rollbackFor = Exception.class)
    public R generateTask(Map<String, Object> map) {
        if (Objects.isNull(map.get("siteNo"))) {
            throw new CoolException("站点不能为空!");
        }
        if (Objects.isNull(map.get("items"))) {
            throw new CoolException("明细不能为空!");
        }
        String siteNo = map.get("siteNo").toString();
        List<LocItem> items = JSONArray.parseArray(JSONArray.toJSONString(map.get("items")), LocItem.class);
        Map<Long, List<LocItem>> listMap = items.stream().collect(Collectors.groupingBy(LocItem::getLocId));
        listMap.keySet().forEach(key -> {
            Task task = new Task();
            Loc loc = locService.getById(key);
            if (Objects.isNull(loc)) {
                throw new CoolException("数据错误:所选库存信息不存在!!");
            }
            loc.setUseStatus(LocStsType.LOC_STS_TYPE_R.type);
            if (!locService.updateById(loc)) {
                throw new CoolException("库位状态更新失败!!");
            }
            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null);
            task.setOrgLoc(loc.getCode())
                    .setTaskCode(ruleCode)
                    .setTargSite(siteNo)
                    .setTaskStatus(TaskStsType.GENERATE_OUT.id)
                    .setBarcode(loc.getBarcode());
            List<LocItem> locItems = this.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, key));
            if (locItems.isEmpty()) {
                throw new CoolException("数据错误:所选库存明细不存在!!");
            }
            Double orgQty = locItems.stream().mapToDouble(LocItem::getAnfme).sum();
            List<LocItem> locItemList = listMap.get(key);
            Double outQty = locItemList.stream().mapToDouble(LocItem::getOutQty).sum();
            Task serviceOne = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, loc.getBarcode()));
            if (!Objects.isNull(serviceOne)) {
                throw new CoolException("托盘任务执行中,不能重复创建!");
            }
            if (orgQty.compareTo(outQty) > 0) {
                //拣料出库
                task.setTaskType(TaskType.TASK_TYPE_PICK_AGAIN_IN.type);
            } else {
                //全板出库
                task.setTaskType(TaskType.TASK_TYPE_OUT.type);
            }
            if (!taskService.save(task)) {
                throw new CoolException("任务创建失败!!");
            }
            List<TaskItem> taskItems = new ArrayList<>();
            listMap.get(key).forEach(item -> {
                TaskItem taskItem = new TaskItem();
                BeanUtils.copyProperties(item, taskItem);
                taskItem.setTaskId(task.getId())
                        .setAnfme(item.getOutQty())
                        .setBatch(item.getBatch())
                        .setOrderType(OrderType.ORDER_OUT.type)
                        .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type));
                taskItems.add(taskItem);
                Double qty = Math.round((item.getWorkQty() + item.getOutQty()) * 10000) / 10000.0;
                LocItem locItem = locItemService.getById(item.getId());
                if (Objects.isNull(locItem)) {
                    throw new CoolException("库存信息不存在!");
                }
                if (locItem.getAnfme().compareTo(qty) < 0) {
                    Double minusQty = Math.round((locItem.getAnfme() - locItem.getWorkQty()) * 10000) / 10000.0;
                    item.setWorkQty(minusQty);
                } else {
                    item.setWorkQty(qty);
                }
                if (! locItemService.updateById(item)) {
                    throw new CoolException("库存信息修改失败!!");
                }
            });
            if (!taskItemService.saveBatch(taskItems)) {
                throw new CoolException("任务明细生成失败!!");
            }
        });
        return R.ok("任务生成完成!!");
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -4,19 +4,21 @@
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.server.api.controller.params.TaskInParam;
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
import com.vincent.rsf.server.api.service.WcsService;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.utils.LocUtils;
import com.vincent.rsf.server.manager.controller.params.GenerateTaskParams;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.LocType;
import com.vincent.rsf.server.manager.mapper.TaskMapper;
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.LocType;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.Synchronized;
import org.apache.commons.lang3.StringUtils;
@@ -69,6 +71,8 @@
    private TaskService taskService;
    @Autowired
    private LocItemWorkingService locItemWorkingService;
    @Autowired
    private WcsService wcsService;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -98,8 +102,8 @@
            }
            Task task = new Task();
            task.setTaskCode(ruleCode)
                    .setTaskStatus(TaskStsType.GENERATE_IN.id.shortValue())
                    .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue())
                    .setTaskStatus(TaskStsType.GENERATE_IN.id)
                    .setTaskType(TaskType.TASK_TYPE_IN.type)
                    .setWarehType(WarehType.WAREHOUSE_TYPE_AGV.id)
                    .setTargLoc(targetLoc)
                    .setOrgSite(orgSta)
@@ -184,8 +188,8 @@
            }
            Task task = new Task();
            task.setTaskCode(ruleCode)
                    .setTaskStatus(TaskStsType.COMPLETE_IN.id.shortValue())
                    .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue())
                    .setTaskStatus(TaskStsType.COMPLETE_IN.id)
                    .setTaskType(TaskType.TASK_TYPE_IN.type)
                    .setWarehType(WarehType.WAREHOUSE_TYPE_PLAT.id)
                    .setTargLoc(targetLoc)
                    .setBarcode(pakin.getBarcode())
@@ -291,8 +295,8 @@
            }
            Task task = new Task();
            task.setTaskCode(ruleCode)
                    .setTaskStatus(TaskStsType.GENERATE_IN.id.shortValue())
                    .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue())
                    .setTaskStatus(TaskStsType.GENERATE_IN.id)
                    .setTaskType(TaskType.TASK_TYPE_IN.type)
                    .setTargLoc(targetLoc)
                    .setBarcode(pakin.getBarcode())
                    .setOrgSite(deviceSite.getSite())
@@ -373,6 +377,28 @@
    }
    /**
     * 入库任务
     *
     * @param tasks
     * @throws Exception
     */
    @Synchronized
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complateInTask(List<Task> tasks) throws Exception {
        for (Task task : tasks) {
            if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type)) {
                //1.入库
                complateInstock(task);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type)) {
                //53.拣料再入库
                pickComplateInStock(task);
            }
        }
    }
    /**
     * 完成任务 更新库位明细信息,将单据库存更新到单据库存表
     *
     * @param tasks
@@ -384,25 +410,14 @@
    public void completeTask(List<Task> tasks) throws Exception {
        for (Task task : tasks) {
            //出库任务
            if (task.getTaskType() < TaskType.TASK_TYPE_OUT.type) {
                if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type)) {
                    //1.入库
                    complateInstock(task);
                } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type)) {
                    //53.拣料再入库
                    pickComplateInStock(task);
                }
            } else {
                //出库任务
                if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) {
                    //全托出库
                    complateOutStock(task);
                } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_IN.type)) {
                    //拣料出库
                    pickTask(task.getId());
                    //移除原始库存
                    complateOutStock(task);
                }
            if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) {
                //全托出库
                complateOutStock(task);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_IN.type)) {
                //拣料出库
//                Task seviceOne = pickTask(task.getId());
                //移除原始库存
                complateOutStock(task);
            }
        }
    }
@@ -439,11 +454,7 @@
        for (TaskItem taskItem : taskItems) {
            LocItem locItem = new LocItem();
            LocItemWorking locWorking = locItemWorkingService.getOne(new LambdaQueryWrapper<LocItemWorking>()
                    .eq(LocItemWorking::getTaskId, taskItem.getTaskId())
                    .eq(LocItemWorking::getLocCode, task.getTargLoc())
                    .eq(LocItemWorking::getMatnrId, taskItem.getMatnrId())
                    .eq(StringUtils.isNoneBlank(taskItem.getFieldsIndex()), LocItemWorking::getFieldsIndex, taskItem.getFieldsIndex())
                    .eq(StringUtils.isNotBlank(taskItem.getBatch()), LocItemWorking::getBatch, taskItem.getBatch()));
                    .eq(LocItemWorking::getTaskId, taskItem.getTaskId()));
            if (Objects.isNull(locWorking)) {
                throw new CoolException("数据错误,作业中库存数据丢失!!");
            }
@@ -458,12 +469,22 @@
            items.add(locItem);
        }
        TaskItem taskItem = taskItems.stream().findFirst().get();
        saveStockItems(taskItems, null, null, taskItem.getWkType(), taskItem.getOrderType());
        if (!locItemService.saveBatch(items)) {
            throw new CoolException("作业库存回写失败!!");
        }
        if (!locItemWorkingService.remove(new LambdaQueryWrapper<LocItemWorking>().eq(LocItemWorking::getTaskId, task.getId()))) {
            throw new CoolException("作业中库存删除失败!!");
        }
        task.setTaskStatus(TaskStsType.UPDATED_IN.id);
        if (!taskService.updateById(task)) {
            throw new CoolException("任务状态修改失败!!");
        }
    }
@@ -476,7 +497,7 @@
     */
    @Override
    public R removeTask(Long[] ids) {
        List<Short> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Integer> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Task> tasks = this.list(new LambdaQueryWrapper<Task>().in(Task::getId, ids).in(Task::getTaskStatus, longs));
        if (tasks.isEmpty()) {
            throw new CoolException("任务已处执行状态不可取消!!");
@@ -507,7 +528,7 @@
                if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type) || task.getTaskType().equals(TaskType.TASK_TYPE_EMPITY_IN.type)) {
                    basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                            .eq(BasStation::getStationName, task.getOrgSite())
                            .eq(BasStation::getUseStatus, StaUseStatusType.TYPE_R.type)
                            .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_R.type)
                    );
                } else if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)
                        || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_IN.type)
@@ -517,13 +538,13 @@
                ) {
                    basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                            .eq(BasStation::getStationName, task.getTargLoc())
                            .eq(BasStation::getUseStatus, StaUseStatusType.TYPE_R.type)
                            .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_R.type)
                    );
                }
                if (null == basStation) {
                    throw new CoolException("站点状态错误!!");
                }
                basStation.setUseStatus(StaUseStatusType.TYPE_F.type);
                basStation.setUseStatus(LocStsType.LOC_STS_TYPE_F.type);
                if (!basStationService.updateById(basStation)) {
                    throw new CoolException("更新站点状态失败!!");
                }
@@ -544,7 +565,7 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R pickTask(Long id) throws Exception {
    public Task pickTask(Long id) throws Exception {
        Task task = this.getById(id);
        if (Objects.isNull(task)) {
            throw new CoolException("当前任务不存在!!");
@@ -559,41 +580,38 @@
            throw new CoolException("没有空库位!!");
        }
        List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId()));
        if (locItems.isEmpty()) {
            throw new CoolException("库位明细不存在!!");
        }
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, task);
        //更新任务主单
        task.setTaskCode(ruleCode)
                .setTaskType(TaskType.TASK_TYPE_PICK_IN.type)
                .setBarcode(task.getBarcode())
                .setTaskStatus(TaskStsType.GENERATE_IN.id);
        //TODO 后续需根据仓库类型查找新库位,原始库位置空闲状态 {
        // TaskInParam param = new TaskInParam();
        //        param.setSourceStaNo(Integer.parseInt(task.getOrgSite()))
        //                .setIoType(Integer.parseInt(TaskType.TASK_TYPE_IN.type + ""));
        ////                .setLocType1(LocType.LOC_TYPE_LOW.type);}
        TaskInParam param = new TaskInParam();
        param.setSourceStaNo(Integer.parseInt(task.getTargSite()))
                .setIoType(Integer.parseInt(TaskType.TASK_TYPE_PICK_IN.type + ""))
                .setLocType1(Integer.parseInt(loc.getType()));
        InTaskMsgDto locInfo = wcsService.getLocNo(param);
        if (Objects.isNull(locInfo)) {
            throw new CoolException("获取库位失败!!");
        }
        task.setTargLoc(locInfo.getLocNo());
        if (!this.updateById(task)) {
            throw new CoolException("任务状态更新失败!!");
        }
        List<LocItemWorking> workings = new ArrayList<>();
        for (LocItem item : locItems) {
            LocItemWorking working = new LocItemWorking();
            BeanUtils.copyProperties(item, working);
            working.setId(null).setTaskId(task.getId());
            workings.add(working);
        Loc one = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()));
        if (Objects.isNull(one)) {
            throw new CoolException("目标库位不存在!!");
        }
        one.setUseStatus(LocStsType.LOC_STS_TYPE_S.type);
        if (!locItemWorkingService.saveBatch(workings)) {
            throw new CoolException("临时库存保存失败!!");
        if (!locService.updateById(one)) {
            throw new CoolException("库位预约入库失败!!");
        }
        return R.ok("拣货成功!!");
        return task;
    }
    /**
@@ -620,6 +638,24 @@
        if (taskItems.isEmpty()) {
            throw new CoolException("任务明细不存在!!");
        }
        List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId()));
        if (locItems.isEmpty()) {
            throw new CoolException("库位明细不存在!!");
        }
        List<LocItemWorking> workings = new ArrayList<>();
        for (LocItem item : locItems) {
            LocItemWorking working = new LocItemWorking();
            BeanUtils.copyProperties(item, working);
            working.setId(null).setTaskId(task.getId());
            workings.add(working);
        }
        if (!locItemWorkingService.saveBatch(workings)) {
            throw new CoolException("临时库存保存失败!!");
        }
        try {
            //更新库位明细
            subtractLocItem(loc);
@@ -656,12 +692,26 @@
        }
        /**修改为库位状态为O.空库*/
        if (!locService.update(new LambdaUpdateWrapper<Loc>().set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type).eq(Loc::getCode, loc.getId()))) {
        if (!locService.update(new LambdaUpdateWrapper<Loc>()
                .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                .eq(Loc::getId, loc.getId()))) {
            throw new CoolException("库位状态修改失败!!");
        }
        if (!this.update(new LambdaUpdateWrapper<Task>().eq(Task::getId, task.getId()).set(Task::getTaskStatus, TaskStsType.UPDATED_OUT.id))) {
            throw new CoolException("任务状态修改失败!!");
        if (!task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_IN.type)) {
            if (!this.update(new LambdaUpdateWrapper<Task>()
                    .eq(Task::getId, task.getId())
                    .set(Task::getTaskStatus, TaskStsType.UPDATED_OUT.id))) {
                throw new CoolException("库存状态更新失败!!");
            }
        } else {
            if (!this.update(new LambdaUpdateWrapper<Task>()
                    .eq(Task::getId, task.getId())
                    .set(Task::getTaskStatus, TaskStsType.WAVE_SEED.id))) {
                throw new CoolException("库存状态更新失败!!");
            }
        }
    }
    /**
@@ -763,7 +813,7 @@
            List<TaskItem> items = orderMap.get(key);
            try {
                //保存库存明细
                saveStockItems(items, pakinItem);
                saveStockItems(items, pakinItem.getId(), pakinItem.getAsnCode(), pakinItem.getWkType(), pakinItem.getType());
                //移出收货区库存, 修改组托状态
                removeReceiptStock(pakinItem);
            } catch (Exception e) {
@@ -850,19 +900,19 @@
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveStockItems(List<TaskItem> items, WaitPakinItem order) throws Exception {
    public void saveStockItems(List<TaskItem> items, Long id, String code, Short wkType, String type) throws Exception {
        Stock stock = new Stock();
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_STOCK_CODE, null);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("当前业务:" + SerialRuleCode.SYS_STOCK_CODE + ",编码规则不存在!!");
        }
        double sum = items.stream().mapToDouble(TaskItem::getAnfme).sum();
        stock.setSourceId(order.getId())
        stock.setSourceId(id)
                .setCode(ruleCode)
                .setSourceCode(order.getAsnCode())
                .setSourceCode(code)
                .setAnfme(sum)
                .setWkType(order.getWkType())
                .setType(order.getType());
                .setWkType(wkType)
                .setType(type);
        if (!stockService.save(stock)) {
            throw new CoolException("库存保存失败!!");
        }
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java
@@ -2,13 +2,11 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.DeviceSite;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.service.DeviceSiteService;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.server.system.enums.LocStsType;
import org.apache.commons.lang3.StringUtils;
import com.vincent.rsf.server.manager.enums.LocStsType;
import java.util.Objects;