25个文件已修改
2个文件已添加
2 文件已复制
4 文件已重命名
666 ■■■■ 已修改文件
rsf-admin/src/config/setting.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/ResourceContent.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/histories/asnOrderLog/AsnOrderLogList.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locItem/LocItemList.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/POItemModal.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/TaskList.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/checkOutBound/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/components/StaSelect.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/components/locItemInfoModal.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/outBound/OutBoundList.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/outBound/index.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/stockTransfer/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx 143 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItemWorking.java 5 ●●●● 补丁 | 查看 | 原始文档 | 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 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocItemService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 145 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/config/setting.js
@@ -25,7 +25,7 @@
export const ABORT_SIGNAL = false;
export const DEFAULT_PAGE_SIZE = 10;
export const DEFAULT_PAGE_SIZE = 15;
export const DEFAULT_ITEM_PAGE_SIZE = 10;
rsf-admin/src/i18n/en.js
@@ -993,6 +993,8 @@
                trackCode: "trackCode",
                unit: "unit",
                anfme: "anfme",
                qty: 'Qty',
                workQty: 'Work Qty',
                batch: "batch",
                splrBatch: "splrBatch",
                spec: "spec",
@@ -1119,6 +1121,7 @@
        siteInit: 'site init',
        batch: 'batch',
        pick: 'Pick',
        check: 'Check',
        confirm: 'confirm',
        cancel: "cancel",
        query: "Query",
rsf-admin/src/i18n/zh.js
@@ -1,5 +1,3 @@
import basContainer from "../page/basicInfo/basContainer";
import outBound from "../page/outWork/outBound";
import chineseMessages from "./core/chineseMessages";
const customChineseMessages = {
@@ -209,16 +207,24 @@
        basStation: '站点信息',
        basContainer: '容器管理',
        outBound: '出库作业',
        checkOutBound: '盘点出库',
        stockTransfer: '库存转移',
    },
    table: {        
        field: {
            stockTransfer: {
                orgLoc: '源库位',
                tarLoc: '目标库位',
                inputLoc: '输入库位'
            },
            outBound: {
                stockWithdrawal: '提取库存',
                withdrawal:'提取',
                outSta: '出库站',
                outSta: '出库/拣料站',
                outQty: '出库数量',
                anfme: '数量',
                createTask: '生成任务',
                checkSta: '盘点站'
                
            },
            basContainer: {
@@ -987,6 +993,7 @@
                matnrCode: "物料编码",
                trackCode: "跟踪码",
                workQty: '执行数',
                qty: '完成数',
                batch: "批次",
                splrBatch: "供应商批次",
                spec: "规格",
@@ -1118,6 +1125,7 @@
        batch: '批量操作',
        confirm: '确认',
        pick: '拣料',
        check: '盘点',
        bulkExport: "批量导出",
        selectSite: '选择站点',
        confirmSelect: '确认选择',
rsf-admin/src/page/ResourceContent.js
@@ -49,7 +49,9 @@
import basStation from './basicInfo/basStation';
import warehouseStock from './statistics/stockManage';
import basContainer from './basicInfo/basContainer';
import outBound from "./outWork/outBound";
import outBound from "./work/outBound";
import checkOutBound from "./work/checkOutBound";
import stockTransfer from "./work/stockTransfer";
const ResourceContent = (node) => {
    switch (node.component) {
@@ -145,6 +147,10 @@
            return basContainer;
        case 'outBound':
            return outBound;
        case 'checkOutBound':
            return checkOutBound;
        case 'stockTransfer':
            return stockTransfer;
        default:
            return {
                list: ListGuesser,
rsf-admin/src/page/histories/asnOrderLog/AsnOrderLogList.jsx
@@ -116,25 +116,21 @@
                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.asnOrderLog"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                empty={false}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <SelectColumnsButton preferenceKey='asnOrderLog' />
                        <MyExportButton />
                        {/* <MyExportButton /> */}
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='asnOrderLog'
                    bulkActionButtons={
                        <>
                            <MyExportButton />
                        </>
                    }
                    bulkActionButtons={false}
                    rowClick={'edit'}
                    expand={false}
                    expandSingle={true}
rsf-admin/src/page/locItem/LocItemList.jsx
@@ -175,6 +175,8 @@
                <TextField source="trackCode" label="table.field.locItem.trackCode" />,
                <TextField source="unit" label="table.field.locItem.unit" />,
                <NumberField source="anfme" label="table.field.locItem.anfme" />,
                <NumberField source="workQty" label="table.field.locItem.workQty" />,
                <NumberField source="qty" label="table.field.locItem.qty" />,
                <TextField source="splrBatch" label="table.field.locItem.splrBatch" />,
                <TextField source="fieldsIndex" label="table.field.locItem.fieldsIndex" />,
            ]
@@ -213,7 +215,7 @@
                    rowClick={false}
                    expand={false}
                    expandSingle={true}
                    omit={['id', 'createTime', 'locId', 'orderId', 'orderItemId', 'matnrId', 'splrBatch', 'workQty', 'qty', 'createBy', 'memo', 'fieldsIndex']}
                    omit={['id', 'createTime','spec', 'model', 'locId', 'orderId', 'trackCode', 'orderItemId', 'matnrId', 'splrBatch','createBy', 'memo', 'fieldsIndex']}
                >
                    {columns.map((column) => column)}
                </StyledDatagrid>}
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
@@ -706,7 +706,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50, 100]}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx
@@ -175,7 +175,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50]}
                pageSizeOptions={[15, 25, 50]}
            />
        </Box >
rsf-admin/src/page/orders/asnOrder/POItemModal.jsx
@@ -394,7 +394,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50, 100]}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
@@ -595,7 +595,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50, 100]}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx
@@ -396,7 +396,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50, 100]}
                pageSizeOptions={[15, 25, 50, 100]}
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
                selectionModel={selectedRows}
rsf-admin/src/page/task/TaskList.jsx
@@ -44,6 +44,7 @@
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import ColorizeOutlinedIcon from '@mui/icons-material/ColorizeOutlined';
import GradingOutlinedIcon from '@mui/icons-material/GradingOutlined';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -161,6 +162,7 @@
                        <EditButton label="toolbar.detail" />
                        <DoneButton sx={{ padding: '1px', fontSize: '.75rem' }} ></DoneButton>
                        <CancelButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                        <CheckButton />
                        <PickButton />
                    </WrapperField>
                </StyledDatagrid>
@@ -177,6 +179,24 @@
export default TaskList;
const CheckButton = () => {
    const record = useRecordContext();
    const notify = useNotify();
    const refresh = useRefresh();
    const checkClick = async () => {
        const { data: { code, data, msg } } = await request.post(`/task/check/` + record.id);
        if (code === 200) {
            notify(msg);
            refresh();
        } else {
            notify(msg);
        }
    }
    return (record?.taskStatus == 198 && record?.taskType == 107 ? <ConfirmButton label={"toolbar.check"} startIcon={<GradingOutlinedIcon />} onConfirm={checkClick} /> : <></>)
}
/**
 * 拣料出库
@@ -198,7 +218,7 @@
    }
    return (
        record?.taskStatus == 198 ? <ConfirmButton label={"toolbar.pick"} startIcon={<ColorizeOutlinedIcon />} onConfirm={pickClick} /> : <></>
        record?.taskStatus == 198 && record?.taskType == 103 ? <ConfirmButton label={"toolbar.pick"} startIcon={<ColorizeOutlinedIcon />} onConfirm={pickClick} /> : <></>
    )
}
@@ -225,7 +245,7 @@
        }
    }
    return (
        ((record?.taskStatus < 98) || (record?.taskType > 101 && record?.taskStatus < 198)) ? (<ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskAltIcon />} onConfirm={clickComplete} />) : (<></>)
        ((record?.taskStatus < 98) || (record?.taskType >= 101 && record?.taskStatus < 199)) ? (<ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskAltIcon />} onConfirm={clickComplete} />) : (<></>)
    )
}
rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx
copy from rsf-admin/src/page/outWork/outBound/OutBoundList.jsx copy to rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx
File was copied from rsf-admin/src/page/outWork/outBound/OutBoundList.jsx
@@ -56,14 +56,14 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import request from '@/utils/request';
import LocItemInfoModal from "./locItemInfoModal";
import LocItemInfoModal from "../components/locItemInfoModal";
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import StaSelect from "./StaSelect";
import StaSelect from "../components/StaSelect";
import { redirect } from "react-router";
import { number } from "prop-types";
const OutBoundList = () => {
const CheckOutBoundList = () => {
    const [createDialog, setCreateDialog] = useState(false);
    const [tabelData, setTableData] = useState([]);
@@ -120,18 +120,18 @@
                        <Grid item xs={12}>
                            <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}>
                                <Typography variant="h6" >
                                    {translate('table.field.outBound.outSta')}
                                    {translate('table.field.outBound.checkSta')}
                                </Typography>
                                <Stack direction='row' spacing={2} minWidth={200}>
                                    <StaSelect
                                        source="sta"
                                        label={translate("table.field.outBound.outSta")}
                                        label={translate("table.field.outBound.checkSta")}
                                        onChange={(e) => {
                                            setSta(e.target.value);
                                            console.log("站点已选择:", e.target.value);
                                        }}
                                        size="small"
                                        type="[101,103]"
                                        type="[107]"
                                    />
                                </Stack>
                                <Stack direction='row' spacing={2} minWidth={200}>
@@ -162,7 +162,7 @@
    )
}
export default OutBoundList;
export default CheckOutBoundList;
const SubmitButton = (props) => {
    const translate = useTranslate();
@@ -182,14 +182,7 @@
        http(sta, data);
    }
    const http = async (sta, items) => {
        console.log(items);
        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 });
        const { data: { code, data, msg } } = await request.post(`/locItem/generate/task`, { siteNo: sta, items: items, type: 'check' });
        if (code === 200) {
            notify(msg);
            refresh()
@@ -217,12 +210,10 @@
    const [columns, setColumns] = useState([
        {
            field: 'outQty',
            headerName: translate('table.field.outBound.outQty') + "*",
            field: 'locCode',
            headerName: translate('table.field.locItem.locCode'),
            width: 100,
            type: 'number',
            editable: true,
            headerClassName: "custom",
            editable: false,
        },
        {
            field: 'anfme',
@@ -342,7 +333,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50, 100]}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
rsf-admin/src/page/work/checkOutBound/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import CheckOutBoundList from "./CheckOutBoundList";
export default {
    list: CheckOutBoundList,
    edit: EditGuesser,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-admin/src/page/work/components/StaSelect.jsx
rsf-admin/src/page/work/components/locItemInfoModal.jsx
rsf-admin/src/page/work/outBound/OutBoundList.jsx
File was renamed from rsf-admin/src/page/outWork/outBound/OutBoundList.jsx
@@ -56,10 +56,10 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import request from '@/utils/request';
import LocItemInfoModal from "./locItemInfoModal";
import LocItemInfoModal from "../components/locItemInfoModal";
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import StaSelect from "./StaSelect";
import StaSelect from "../components/StaSelect";
import { redirect } from "react-router";
import { number } from "prop-types";
@@ -189,7 +189,7 @@
            notify(translate('toolbar.request.error.out_stock_qty'))
            return
        }
        const { data: { code, data, msg } } = await request.post(`/locItem/generate/task`, { siteNo: sta, items: items });
        const { data: { code, data, msg } } = await request.post(`/locItem/check/task`, { siteNo: sta, items: items });
        if (code === 200) {
            notify(msg);
            refresh()
@@ -236,6 +236,12 @@
            headerName: translate('table.field.locItem.workQty'),
            width: 100,
            type: 'number',
            editable: false,
        },
        {
            field: 'locCode',
            headerName: translate('table.field.locItem.locCode'),
            width: 100,
            editable: false,
        },
        {
@@ -342,7 +348,7 @@
                        },
                    },
                }}
                pageSizeOptions={[10, 25, 50, 100]}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
rsf-admin/src/page/work/outBound/index.jsx
rsf-admin/src/page/work/stockTransfer/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import StockTransferList from "./stockTransferList";
export default {
    list: StockTransferList,
    edit: EditGuesser,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
copy from rsf-admin/src/page/outWork/outBound/OutBoundList.jsx copy to rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
File was copied from rsf-admin/src/page/outWork/outBound/OutBoundList.jsx
@@ -47,6 +47,7 @@
    MenuItem,
    Typography,
    Card,
    Autocomplete,
} from '@mui/material';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import ConfirmButton from "../../components/ConfirmButton";
@@ -56,14 +57,14 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import request from '@/utils/request';
import LocItemInfoModal from "./locItemInfoModal";
import LocItemInfoModal from "../components/locItemInfoModal";
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import StaSelect from "./StaSelect";
import StaSelect from "../components/StaSelect";
import { redirect } from "react-router";
import { number } from "prop-types";
const OutBoundList = () => {
const StockTransferList = () => {
    const [createDialog, setCreateDialog] = useState(false);
    const [tabelData, setTableData] = useState([]);
@@ -73,6 +74,35 @@
    const tableRef = useRef();
    tableRef.current = useGridApiRef();
    const translate = useTranslate();
    const [orgLoc, setOrgLoc] = useState([]);
    const [tarLoc, setTarLoc] = useState([]);
    const [tarLocList, setTarLocList] = useState([]);
    useEffect(() => {
        selectAreaNoUse();
    },[orgLoc])
    const selectAreaNoUse = async() =>{
        const {
            data: { code, data, msg },
        } = await request.post("/loc/areaNoUse/list",{
        });
        if (code === 200) {
            const newData = data.map((item) => {
                return {
                    label: item,
                    id: item
                }
            })
            console.log(newData);
            setTarLocList(newData);
        }
    }
    const handleDeleteItem = () => {
        const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
@@ -92,53 +122,39 @@
    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>
                    </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')}
                                    {translate('table.field.stockTransfer.inputLoc')}
                                </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>
                                <Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 1 }}>
                                    <Stack direction='row' spacing={2} minWidth={200}>
                                        <TextField
                                            label={translate("table.field.stockTransfer.orgLoc")}
                                            onChange={(event) => setOrgLoc(event.target.value)}
                                        />
                                    </Stack>
                                    <>{"——"}</>
                                    <Stack direction='row' spacing={2} minWidth={200}>
                                        <Autocomplete
                                            disablePortal
                                            options={tarLocList}
                                            renderInput={(params) => (
                                                <TextField {...params} label={translate("table.field.stockTransfer.tarLoc")} />
                                            )}
                                            onChange={(event, value) => setTarLoc(value)}
                                        />
                                    </Stack>
                                </Box>
                                <Stack direction='row' spacing={2} minWidth={200}>
                                    <SubmitButton
                                        sta={sta}
                                        data={tabelData}
                                        setTableData={setTableData}
                                        orgLoc={orgLoc}
                                        tarLoc={tarLoc}
                                    />
                                </Stack>
                            </Box>
@@ -162,38 +178,31 @@
    )
}
export default OutBoundList;
export default StockTransferList;
const SubmitButton = (props) => {
    const translate = useTranslate();
    const notify = useNotify();
    const redirect = useRedirect();
    const refresh = useRefresh();
    const { sta, data, setTableData } = props;
    const check = () => {
        if (sta === "" || sta === undefined || sta === null) {
    const { orgLoc, tarLoc } = props;
    const move = () => {
        console.log(orgLoc, tarLoc);
        if (orgLoc === "" || orgLoc === undefined || orgLoc === null) {
            notify("请选择站点");
            return;
        }
        if (data.length === 0) {
            notify("请选择物料");
        if (tarLoc === "" || tarLoc === undefined || tarLoc === null) {
            notify("请选择站点");
            return;
        }
        http(sta, data);
        }
        http(orgLoc, tarLoc?.id)
    }
    const http = async (sta, items) => {
        console.log(items);
        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 });
    const http = async (orgLoc, tarLoc) => {
        const { data: { code, data, msg } } = await request.post(`/locItem/move/task`, { orgLoc, tarLoc });
        if (code === 200) {
            notify(msg);
            refresh()
            setTableData([])
            redirect("/task")
        } else {
            notify(msg);
@@ -203,7 +212,7 @@
        <ConfirmButton
            variant="contained"
            color="primary"
            onConfirm={check}
            onConfirm={move}
            label={"table.field.outBound.createTask"}
        >
        </ConfirmButton>
@@ -217,12 +226,10 @@
    const [columns, setColumns] = useState([
        {
            field: 'outQty',
            headerName: translate('table.field.outBound.outQty') + "*",
            field: 'locCode',
            headerName: translate('table.field.locItem.locCode'),
            width: 100,
            type: 'number',
            editable: true,
            headerClassName: "custom",
            editable: false,
        },
        {
            field: 'anfme',
@@ -239,6 +246,12 @@
            editable: false,
        },
        {
            field: 'locCode',
            headerName: translate('table.field.locItem.locCode'),
            width: 100,
            editable: false,
        },
        {
            field: 'matnrCode',
            headerName: translate('table.field.locItem.matnrCode'),
            width: 130,
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocController.java
@@ -30,6 +30,7 @@
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;
@Api(tags = "库位信息")
@@ -58,6 +59,14 @@
    }
    @PreAuthorize("hasAuthority('manager:loc:list')")
    @PostMapping("/loc/areaNoUse/list")
    public R areaNoUselist(@RequestBody Map<String, Object> map) {
        List<Loc> list = locService.list();
        List<String> list1 = list.stream().map(obj -> obj.getCode()).collect(Collectors.toList());
        return R.ok(list1);
    }
    @PreAuthorize("hasAuthority('manager:loc:list')")
    @PostMapping({"/loc/many/{ids}", "/locs/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(locService.listByIds(Arrays.asList(ids)));
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java
@@ -15,6 +15,7 @@
import com.vincent.rsf.server.manager.service.LocItemService;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.manager.enums.LocStsType;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -76,7 +77,13 @@
        return R.ok().add(page);
    }
    /**
     * 生成库存出库任务
     * @param map
     * @return
     */
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @ApiOperation("生成库存出库任务")
    @PostMapping("/locItem/generate/task")
    public R generateTask(@RequestBody Map<String, Object> map) {
        if (Objects.isNull(map)) {
@@ -85,6 +92,37 @@
        return locItemService.generateTask(map);
    }
    /**
     * 生成移库任务
     * @param map
     * @return
     */
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @ApiOperation("生成移库任务")
    @PostMapping("/locItem/move/task")
    public R genMoveTask(@RequestBody Map<String, Object> map) {
        if (Objects.isNull(map)) {
            return R.error("参数不能为空!!");
        }
        return locItemService.genMoveTask(map);
    }
    /**
     * 生成盘点出库任务
     * @param map
     * @return
     */
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @ApiOperation("生成盘点出库任务")
    @PostMapping("/locItem/check/task")
    public R genStatisticalTask(@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) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java
@@ -100,7 +100,7 @@
        if (Objects.isNull(ids) || ids.length < 1) {
            return R.error("参数不能为空!!");
        }
       return taskService.removeTask(ids);
        return taskService.removeTask(ids);
//        return R.ok("Delete Success").add(ids);
    }
@@ -132,10 +132,12 @@
            throw new CoolException("参数不能为空!!");
        }
        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));
        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);
            task.setTaskStatus(task.getTaskType() < 100 ? TaskStsType.COMPLETE_IN.id : TaskStsType.COMPLETE_OUT.id);
        }
        if (!taskService.updateBatchById(tasks)) {
            return R.error("完成任务失败");
@@ -145,7 +147,7 @@
    }
    /**
     * 拣料出库
     * 拣料出库(用于测试拣料出库)
     * @return
     */
    @PreAuthorize("hasAuthority('manager:task:update')")
@@ -156,7 +158,26 @@
            throw new CoolException("能数不能为空!!");
        }
        try {
            return R.ok(taskService.pickTask(id));
            return R.ok(taskService.pickOrCheckTask(id, "pick"));
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
    }
    /**
     * 盘点出库(用于测试盘点出库)
     *
     * @return
     */
    @PreAuthorize("hasAuthority('manager:task:update')")
    @ApiOperation("盘点出库")
    @PostMapping("/task/check/{id}")
    public R checkTask(@PathVariable Long id) {
        if (Objects.isNull(id)) {
            throw new CoolException("能数不能为空!!");
        }
        try {
            return R.ok(taskService.pickOrCheckTask(id, "check"));
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItemWorking.java
@@ -43,9 +43,12 @@
    @ApiModelProperty(value= "主单ID")
    private Long locId;
    @ApiModelProperty("任务明细ID")
    @ApiModelProperty("任务ID")
    private Long taskId;
    @ApiModelProperty("库位明细ID")
    private Long locItemId;
    /**
     * 库位
     */
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskStsType.java
@@ -38,9 +38,10 @@
    WCS_EXECUTE_OUT_CONVEYOR("107", "RCS容器流动任务已下发"),
    GENERATE_WAVE_SEED("197", "等待容器到达"),
    WAVE_SEED("198", "播种中"),
    COMPLETE_OUT("199", "出库完成"),
    WAVE_SEED("199", "播种中/盘点中"),
    COMPLETE_OUT("198", "出库完成"),
    UPDATED_OUT("200", "库存更新完成"),
    ;
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java
@@ -16,7 +16,7 @@
    TASK_TYPE_MERGE_IN("54", "并板再入库"),
    TASK_TYPE_CHECK_IN("57", "盘点再入库"),
    TASK_TYPE_OUT("101", "出库"),
    TASK_TYPE_PICK_AGAIN_IN("103", "拣料出库"),
    TASK_TYPE_PICK_AGAIN_OUT("103", "拣料出库"),
    TASK_TYPE_MERGE_OUT("104", "并板出库"),
    TASK_TYPE_CHECK_OUT("107", "盘点出库"),
    TASK_TYPE_EMPITY_OUT("110", "空板出库"),
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -97,12 +97,12 @@
        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.ORDER_INOF_REPORT_PLAT));
        if (!Objects.isNull(config)) {
            if (Boolean.parseBoolean(config.getVal())) {
                queryWrapper.eq(Task::getTaskStatus, TaskStsType.REPORT_IN.id);
                queryWrapper.in(Task::getTaskStatus, TaskStsType.REPORT_IN.id);
            } else {
                queryWrapper.eq(Task::getTaskStatus, TaskStsType.UPDATED_IN.id);
                queryWrapper.in(Task::getTaskStatus, TaskStsType.UPDATED_IN.id, TaskStsType.UPDATED_OUT.id);
            }
        } else {
            queryWrapper.eq(Task::getTaskStatus, TaskStsType.UPDATED_IN.id);
            queryWrapper.in(Task::getTaskStatus, TaskStsType.UPDATED_IN.id, TaskStsType.UPDATED_OUT.id);
        }
        List<Task> tasks = taskService.list(queryWrapper);
        if (tasks.isEmpty()) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocItemService.java
@@ -9,4 +9,7 @@
public interface LocItemService extends IService<LocItem> {
    R generateTask(Map<String, Object> map);
    R genMoveTask(Map<String, Object> map);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -21,7 +21,7 @@
    R removeTask(Long[] ids);
    Task pickTask(Long id) throws Exception;
    Task pickOrCheckTask(Long id, String oType) throws Exception;
    void complateInTask(List<Task> tasks) throws Exception;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -19,6 +19,7 @@
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.Synchronized;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -45,6 +46,7 @@
    /**
     * 库存出库生成出库任务
     * type: check 盘点, stock: 库存出库
     *
     * @param map
     * @return
@@ -53,6 +55,12 @@
    @Synchronized
    @Transactional(rollbackFor = Exception.class)
    public R generateTask(Map<String, Object> map) {
        String type;
        if (!Objects.isNull(map.get("type")) && StringUtils.isNotBlank(map.get("type").toString())) {
            type = map.get("type").toString();
        } else {
            type = "stock";
        }
        if (Objects.isNull(map.get("siteNo"))) {
            throw new CoolException("站点不能为空!");
        }
@@ -87,22 +95,29 @@
            }
            Double orgQty = locItems.stream().mapToDouble(LocItem::getAnfme).sum();
            Double workQty = locItems.stream().mapToDouble(LocItem::getWorkQty).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 (type.equals("stock")) {
                Double useQty  = Math.round((outQty + workQty) * 10000) / 10000.0;
                if (orgQty.compareTo(useQty) > 0) {
                    //拣料出库
                    task.setTaskType(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);
                } else {
                    //全板出库
                    task.setTaskType(TaskType.TASK_TYPE_OUT.type);
                }
            } else if (type.equals("check")) {
                //盘点出库
                task.setTaskType(TaskType.TASK_TYPE_CHECK_OUT.type);
            }
            if (!taskService.save(task)) {
                throw new CoolException("任务创建失败!!");
            }
@@ -129,7 +144,7 @@
                } else {
                    item.setWorkQty(qty);
                }
                if (! locItemService.updateById(item)) {
                if (!locItemService.updateById(item)) {
                    throw new CoolException("库存信息修改失败!!");
                }
            });
@@ -141,4 +156,79 @@
        return R.ok("任务生成完成!!");
    }
    /**
     * 生成移库任务
     * @param map
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R genMoveTask(Map<String, Object> map) {
        if (Objects.isNull(map.get("tarLoc")) || StringUtils.isBlank(map.get("tarLoc").toString())) {
            throw new CoolException("目标库位不能为空!");
        }
        if (Objects.isNull(map.get("orgLoc")) || StringUtils.isBlank(map.get("orgLoc").toString())) {
            throw new CoolException("源库位不能为空!");
        }
        Loc orgLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, map.get("orgLoc")));
        if (Objects.isNull(orgLoc)) {
            throw new CoolException("源库位不存在!!");
        }
        orgLoc.setUseStatus(LocStsType.LOC_STS_TYPE_R.type);
        if (!locService.updateById(orgLoc)) {
            throw new CoolException("目标库位预约失败!!");
        }
        Loc targetLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, map.get("tarLoc").toString()));
        if (Objects.isNull(targetLoc)) {
            throw new CoolException("目标库位不存在!!");
        }
        targetLoc.setUseStatus(LocStsType.LOC_STS_TYPE_S.type);
        if (!locService.updateById(targetLoc)) {
            throw new CoolException("目标库位预约失败!!");
        }
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null);
        Task task = new Task();
        task.setOrgLoc(orgLoc.getCode())
                .setTaskCode(ruleCode)
                .setTaskType(TaskType.TASK_TYPE_LOC_MOVE.type)
                .setTargLoc(targetLoc.getCode())
                .setTaskStatus(TaskStsType.GENERATE_IN.id)
                .setBarcode(orgLoc.getBarcode());
        if (!taskService.save(task)) {
            throw new CoolException("新建移库任务失败!!");
        }
        List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, orgLoc.getId()));
        if (locItems.isEmpty()) {
            throw new CoolException("库位明细不存在!!");
        }
        List<TaskItem> taskItems = new ArrayList<>();
        for (LocItem item : locItems) {
            TaskItem taskItem = new TaskItem();
            BeanUtils.copyProperties(item, taskItem);
            taskItem.setTaskId(task.getId())
                    .setAnfme(item.getAnfme())
                    .setBatch(item.getBatch())
                    .setOrderType(OrderType.ORDER_IN.type)
                    .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type));
            taskItems.add(taskItem);
        }
        if (!taskItemService.saveBatch(taskItems)) {
            throw new CoolException("任务明细生成失败!!");
        }
        return R.ok(task);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocServiceImpl.java
@@ -93,12 +93,21 @@
        }
        String join = StringUtils.join(param.getTypeIds(), ",");
        String[] split = warehouseAreas.getCode().split("\\.");
        if (split.length == 0){
            throw new CoolException("库区编码错误!!");
        }
        StringBuilder locStar = new StringBuilder();
        for (int i = 0; i < split.length; i++) {
            locStar.append(split[i]).append("-");
        }
        List<Loc> list = new ArrayList<>();
        for (int r = param.getStartRow(); r <= param.getEndRow(); r++) {
            for (int b = param.getStartBay(); b <= param.getEndBay(); b++) {
                for (int l = param.getStartLev(); l <= param.getEndLev(); l++) {
                    // 获取库位号
                    String locNo = String.format("%02d", r) + String.format("%03d", b) + String.format("%02d", l);
                    String locNo = locStar +  String.format("%d", r) + String.format("-%d", b) + String.format("-%d", l);
                    Loc loc = new Loc();
                    loc.setCode(locNo)
                            .setUseStatus("O")
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -390,11 +390,72 @@
            if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type)) {
                //1.入库
                complateInstock(task);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type)) {
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type) || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
                //53.拣料再入库
                //57.盘点再入库
                pickComplateInStock(task);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
                //移库
                moveInStock(task);
            }
        }
    }
    @Transactional(rollbackFor = Exception.class)
    public void moveInStock(Task task) {
        if (Objects.isNull(task)) {
            return;
        }
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()));
        if (Objects.isNull(loc)) {
            throw new CoolException("目标库位不存在!");
        }
        Loc orgLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getOrgLoc()));
        if (Objects.isNull(orgLoc)) {
            throw new CoolException("目标库位不存在!");
        }
        if (!loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_S.type)) {
            throw new CoolException("当前库位状态不处于S.入库预约,不可执行入库操作!");
        }
        if (!orgLoc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_R.type)) {
            throw new CoolException("当前库位状态不处于R.出库预约,不可执行入库操作!");
        }
        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId()));
        if (taskItems.isEmpty()) {
            throw new CoolException("任务明细不存在!!");
        }
        try {
            //更新库位明细
            saveLocItem(taskItems, task.getId());
        } catch (Exception e) {
            throw new CoolException("库位明细更新失败!!");
        }
//        /**对任务明细按组拖明细进行分组*/
//        try {
//            //保存库存明细
//            saveStockItems(taskItems, null, null, pakinItem.getWkType(), pakinItem.getType());
//        } catch (Exception e) {
//            log.error("<UNK>", e);
//            throw new CoolException(e.getMessage());
//        }
        /**修改库位状态为F.在库*/
        if (!locService.update(new LambdaUpdateWrapper<Loc>().set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type).eq(Loc::getCode, task.getTargLoc()))) {
            throw new CoolException("库位状态修改失败!!");
        }
        if (!locService.update(new LambdaUpdateWrapper<Loc>().set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type).eq(Loc::getCode, task.getOrgLoc()))) {
            throw new CoolException("库位状态修改失败!!");
        }
        if (!this.update(new LambdaUpdateWrapper<Task>().eq(Task::getId, task.getId()).set(Task::getTaskStatus, TaskStsType.UPDATED_IN.id))) {
            throw new CoolException("任务状态修改失败!!");
        }
    }
@@ -413,10 +474,11 @@
            if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) {
                //全托出库
                complateOutStock(task);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_IN.type)) {
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)) {
                //拣料出库
//                Task seviceOne = pickTask(task.getId());
                //移除原始库存
                complateOutStock(task);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_OUT.type)) {
                //盘点出库
                complateOutStock(task);
            }
        }
@@ -454,28 +516,37 @@
        for (TaskItem taskItem : taskItems) {
            LocItem locItem = new LocItem();
            LocItemWorking locWorking = locItemWorkingService.getOne(new LambdaQueryWrapper<LocItemWorking>()
                    .eq(LocItemWorking::getTaskId, taskItem.getTaskId()));
                    .eq(LocItemWorking::getTaskId, taskItem.getTaskId())
                    .eq(StringUtils.isNotBlank(taskItem.getBatch()), LocItemWorking::getBatch, taskItem.getBatch())
                    .eq(StringUtils.isNotBlank(taskItem.getFieldsIndex()), LocItemWorking::getFieldsIndex, taskItem.getFieldsIndex())
                    .eq(LocItemWorking::getMatnrId, taskItem.getMatnrId()));
            if (Objects.isNull(locWorking)) {
                throw new CoolException("数据错误,作业中库存数据丢失!!");
            }
            if (locWorking.getAnfme().compareTo(taskItem.getAnfme()) >= 0) {
                locWorking.setAnfme(Math.round((locWorking.getAnfme() - taskItem.getAnfme()) * 10000) / 10000.0);
            if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
                locWorking.setWorkQty(0.0);
                locWorking.setAnfme(taskItem.getAnfme());
            } else {
                continue;
                if (locWorking.getAnfme().compareTo(taskItem.getAnfme()) >= 0) {
                    locWorking.setWorkQty(0.0);
                    locWorking.setAnfme(Math.round((locWorking.getAnfme() - taskItem.getAnfme()) * 10000) / 10000.0);
                } else {
                    continue;
                }
            }
            BeanUtils.copyProperties(locWorking, locItem);
            locItem.setLocCode(loc.getCode()).setLocId(loc.getId()).setId(null);
            items.add(locItem);
        }
        TaskItem taskItem = taskItems.stream().findFirst().get();
        saveStockItems(taskItems, null, null, taskItem.getWkType(), taskItem.getOrderType());
        if (!locItemService.saveBatch(items)) {
            throw new CoolException("作业库存回写失败!!");
        }
        TaskItem taskItem = taskItems.stream().findFirst().get();
        //保存入出库流水
        saveStockItems(taskItems, null, null, taskItem.getWkType(), taskItem.getOrderType());
        if (!locItemWorkingService.remove(new LambdaQueryWrapper<LocItemWorking>().eq(LocItemWorking::getTaskId, task.getId()))) {
            throw new CoolException("作业中库存删除失败!!");
@@ -531,7 +602,7 @@
                            .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)
                        || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                        || task.getTaskType().equals(TaskType.TASK_TYPE_MERGE_OUT.type)
                        || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_OUT.type)
                        || task.getTaskType().equals(TaskType.TASK_TYPE_EMPITY_OUT.type)
@@ -565,13 +636,26 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Task pickTask(Long id) throws Exception {
    public Task pickOrCheckTask(Long id, String oType) throws Exception {
        Task task = this.getById(id);
        if (Objects.isNull(task)) {
            throw new CoolException("当前任务不存在!!");
        }
        if (!task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_IN.type)) {
            throw new CoolException("非拣料出库 ,不可执行此操作!!");
        Integer type;
        if (oType.equals("check")) {
            //盘点入库
            type = TaskType.TASK_TYPE_CHECK_IN.type;
            if (!task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_OUT.type)) {
                throw new CoolException("非盘点出库 ,不可执行此操作!!");
            }
        } else {
            //拣料入库
            type = TaskType.TASK_TYPE_PICK_IN.type;
            if (!task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)) {
                throw new CoolException("非拣料出库 ,不可执行此操作!!");
            }
        }
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
@@ -583,13 +667,14 @@
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, task);
        //更新任务主单
        task.setTaskCode(ruleCode)
                .setTaskType(TaskType.TASK_TYPE_PICK_IN.type)
                .setTaskType(type)
                .setBarcode(task.getBarcode())
                .setTaskStatus(TaskStsType.GENERATE_IN.id);
        //TODO 根据物料的库位类型生成新的库位
        TaskInParam param = new TaskInParam();
        param.setSourceStaNo(Integer.parseInt(task.getTargSite()))
                .setIoType(Integer.parseInt(TaskType.TASK_TYPE_PICK_IN.type + ""))
                .setIoType(type)
                .setLocType1(Integer.parseInt(loc.getType()));
        InTaskMsgDto locInfo = wcsService.getLocNo(param);
@@ -648,7 +733,7 @@
        for (LocItem item : locItems) {
            LocItemWorking working = new LocItemWorking();
            BeanUtils.copyProperties(item, working);
            working.setId(null).setTaskId(task.getId());
            working.setId(null).setTaskId(task.getId()).setLocItemId(item.getId());
            workings.add(working);
        }
@@ -660,6 +745,7 @@
            //更新库位明细
            subtractLocItem(loc);
        } catch (Exception e) {
            log.error("<UNK>", e);
            throw new CoolException(e.getMessage());
        }
@@ -698,18 +784,19 @@
            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 (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type) || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_OUT.type)) {
            if (!this.update(new LambdaUpdateWrapper<Task>()
                    .eq(Task::getId, task.getId())
                    .set(Task::getTaskStatus, TaskStsType.WAVE_SEED.id))) {
                throw new CoolException("库存状态更新失败!!");
            }
        } else {
            if (!this.update(new LambdaUpdateWrapper<Task>()
                    .eq(Task::getId, task.getId())
                    .set(Task::getTaskStatus, TaskStsType.UPDATED_OUT.id))) {
                throw new CoolException("库存状态更新失败!!");
            }
        }
    }
@@ -877,6 +964,7 @@
        if (Objects.isNull(task)) {
            throw new CoolException("任务不存在!!");
        }
        List<LocItem> locItems = new ArrayList<>();
        items.forEach(taskItem -> {
            Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()), false);
@@ -900,7 +988,8 @@
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveStockItems(List<TaskItem> items, Long id, String code, Short wkType, String type) 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)) {
rsf-server/src/main/resources/application-dev.yml
@@ -14,7 +14,7 @@
    driver-class-name: com.mysql.jdbc.Driver
#    url: jdbc:mysql://47.76.147.249:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    url: jdbc:mysql://192.168.4.50:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    url: jdbc:mysql://127.0.0.1:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
#    username: rsf
    password: 34821015
    type: com.alibaba.druid.pool.DruidDataSource