22个文件已修改
7个文件已添加
851 ■■■■ 已修改文件
rsf-admin/.env 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/loc/InitModal.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutOrderList.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutOrderModal.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/wave/WaveList.jsx 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/mcp/McpController.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaOutStockController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveItemController.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveOrderRelaController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocMastInitParam.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WaveOrderRela.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WaveExceStatus.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WaveItemExceStatus.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/WaveOrderRelaMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/WaveSchedules.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveOrderRelaService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveOrderRelaServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java 166 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/Shelves.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/WaveOrderRelaMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/.env
@@ -1,3 +1,3 @@
VITE_BASE_IP=192.168.4.12
VITE_BASE_IP=127.0.0.1
# VITE_BASE_IP=47.76.147.249
VITE_BASE_PORT=8080
rsf-admin/src/i18n/en.js
@@ -437,6 +437,7 @@
                col: "Col",
                lev: "Lev",
                channel: "Channel",
                startChannel: "startChannel",
                maxParts: "MaxParts",
                maxPack: "MaxPack",
                flagLabelMange: "FlagLabelMange",
rsf-admin/src/i18n/zh.js
@@ -445,6 +445,7 @@
                flagLogic: "虚拟库位",
                fucAtrrs: "功能属性",
                barcode: "容器码",
                startChannel: "起始巷道",
                unit: "单位",
                size: "长/宽/高",
                length: "长",
rsf-admin/src/page/basicInfo/loc/InitModal.jsx
@@ -235,6 +235,17 @@
                                    validate={[required()]}
                                />
                            </Grid>
                            <Grid item xs={4}>
                                <TextInput
                                    label={"table.field.loc.startChannel"}
                                    name="startChannel"
                                    value={formData.startChannel}
                                    onChange={(e) => handleChange(+e.target.value, 'startChannel')}
                                    size="small"
                                    type="number"
                                    validate={[required()]}
                                />
                            </Grid>
                        </Grid>
                    </Box>
                </DialogContent>
rsf-admin/src/page/orders/outStock/OutOrderList.jsx
@@ -222,7 +222,7 @@
        drawerVal={drawerVal}
        setDrawerVal={setDrawerVal}
      >
        <OutStockPublic record={select} open={drawerVal} setOpen={setDrawerVal} />
        <OutStockPublic record={select} open={drawerVal} setOpen={setDrawerVal}  setManualDialog={setManualDialog}/>
      </PageEditDrawer>
    </Box >
  )
rsf-admin/src/page/orders/outStock/OutOrderModal.jsx
@@ -96,10 +96,8 @@
    const translate = useTranslate();
    const [params, setParams] = useState({});
    const [select, setSelect] = useState([]);
    const [drawerVal, setDrawerVal] = useState(false);
    const refresh = useRefresh();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
@@ -253,7 +251,7 @@
                </DialogContent>
            </Grid>
            <Grid>
                <OutOrderPreview open={preview} setOpen={setPreview} selectedIds={select} />
                <OutOrderPreview open={preview} setOpen={setPreview} selectedIds={select} setCloseParent={setOpen} />
            </Grid>
        </Dialog >
    )
rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx
@@ -16,7 +16,7 @@
const OutOrderPreview = (props) => {
    const { open, setOpen, record, selectedIds } = props;
    const { open, setOpen, record, selectedIds, setCloseParent } = props;
    const translate = useTranslate();
    const gridRef = useGridApiRef();
    const [rows, setRows] = useState([]);
@@ -26,6 +26,7 @@
        if (reason !== "backdropClick") {
            // const res = await request.get(`/outStock/items/cancel/` + selectedIds);
            setOpen(false);
            setCloseParent(false)
        }
    };
@@ -66,7 +67,7 @@
                    </Grid>
                </Grid>
                <Toolbar sx={{ justifyContent: 'end' }}>
                    <ConfirmButton label="toolbar.confirm" variant="contained" size="large" gridRef={gridRef} setOpen={setOpen} />
                    <ConfirmButton label="toolbar.confirm" variant="contained" size="large" gridRef={gridRef} setOpen={setOpen} setCloseParent={setCloseParent}/>
                </Toolbar>
            </DialogContent>
        </Dialog>
@@ -75,7 +76,7 @@
export default OutOrderPreview;
const ConfirmButton = ({ gridRef, setOpen }) => {
const ConfirmButton = ({ gridRef, setOpen, setCloseParent }) => {
    const refresh = useRefresh();
    const notify = useNotify();
    const confirm = async () => {
@@ -85,6 +86,7 @@
            notify(msg);
            refresh()
            setOpen(false)
            setCloseParent(false)
        } else {
            notify(msg);
        }
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
@@ -67,7 +67,7 @@
}));
const OutStockPublic = (props) => {
    const { record, open, setOpen } = props;
    const { record, open, setOpen, setManualDialog } = props;
    const notify = useNotify();
    const gridRef = useGridApiRef();
    const [rows, setRows] = useState([]);
@@ -103,7 +103,6 @@
        return (
            <Button label="toolbar.confirm" size="medium" onClick={handleRowClick} />
        )
    };
    const handleClickOpen = () => {
@@ -133,10 +132,8 @@
    };
    useEffect(() => {
        if (open) {
            getWaveRule()
        }
    }, [open, formData])
        getWaveRule()
    }, [open])
    const getWaveRule = async () => {
        if (formData.waveId == null && formData.waveId == undefined) {
@@ -144,7 +141,7 @@
        }
        const { data: { code, data, msg } } = await request.post('/outStock/order/getOutTaskItems', { ...formData });
        if (code === 200) {
            setRows(data)
            // setRows(data)
            setFetchRows(data)
        } else {
            notify(msg);
rsf-admin/src/page/orders/wave/WaveList.jsx
@@ -28,7 +28,8 @@
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_WAVE_AUTO_EXCE } from '@/config/setting';
import PlayArrowOutlinedIcon from '@mui/icons-material/PlayArrowOutlined';
import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline';
import { Box, Typography, Card, Stack } from '@mui/material';
import StopCircleOutlinedIcon from '@mui/icons-material/StopCircleOutlined';
import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material';
import ConfirmButton from "../../components/ConfirmButton";
import PageDrawer from "../../components/PageDrawer";
import PublicIcon from '@mui/icons-material/Public';
@@ -36,7 +37,7 @@
import { styled } from '@mui/material/styles';
import request from '@/utils/request';
import WaveCreate from "./WaveCreate";
import WavePannel from "./WavePanel"
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -48,7 +49,7 @@
    '& .column-name': {
    },
    '& .opt': {
        width: 260
        width: 200
    },
}));
@@ -102,12 +103,13 @@
        const { data: { code, data, msg } } = await request.get('/config/flag/' + DEFAULT_WAVE_AUTO_EXCE);
        if (code === 200) {
            setAutoExce(JSON.parse(data?.val))
        }
        }
    }
    return (
        <Box display="flex">
            <List
                queryOptions={{ refetchInterval: 5000 }}
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
@@ -122,8 +124,8 @@
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <BulkStartButton autoExce={autoExce} setAutoExce={setAutoExce} />
                        <BulkPauseButton autoExce={autoExce} setAutoExce={setAutoExce} />
                        <BulkAutoStartButton autoExce={autoExce} setAutoExce={setAutoExce} />
                        <BulkAutoPauseButton autoExce={autoExce} setAutoExce={setAutoExce} />
                        <FilterButton />
                        <SelectColumnsButton preferenceKey='wave' />
                    </TopToolbar>
@@ -132,28 +134,34 @@
            >
                <StyledDatagrid
                    preferenceKey='wave'
                    bulkActionButtons={false}
                    bulkActionButtons={
                        <>
                            <BulkStartButton />
                        </>
                    }
                    rowClick={(id, resource, record) => false}
                    expand={false}
                    expandSingle={false}
                    expand={<WavePannel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo', 'createBy$']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.wave.code" />
                    <TextField source="type$" label="table.field.wave.type" sortable={false} />
                    <TextField source="exceStatus$" label="table.field.wave.exceStatus" sortable={false} />
                    <NumberField source="anfme" label="table.field.wave.anfme" />
                    <NumberField source="groupQty" label="table.field.wave.groupQty" />
                    <NumberField source="qty" label="table.field.wave.qty" />
                    <NumberField source="workQty" label="table.field.wave.qty" />
                    <NumberField source="orderNum" label="table.field.wave.orderNum" />
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <TextField source="updateBy$" label="common.field.updateBy" />
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <TextField source="createBy$" label="common.field.createBy" />
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <CustomProcess source="progress" />
                    <TextField source="exceStatus$" label="table.field.wave.exceStatus" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <PublicTaskButton setSelectIds={setSelectIds} setDetailDialog={setDetailDialog} />
                        <PauseButton />
                        <ContinueButton />
                        <EditButton label="toolbar.detail" sx={{ padding: '1px', fontSize: '.75rem' }} />
                    </WrapperField>
                </StyledDatagrid>
@@ -179,6 +187,36 @@
export default WaveList;
const BulkStartButton = () => {
    const { data, selectedIds, onUnselectItems } = useListContext();
    // const waveId = useGetRecordId();
    const notify = useNotify();
    const refresh = useRefresh()
    const startClick = async () => {
        onUnselectItems();
        const { data: { code, data, msg } } = await request.post('/wave/selects/task', { ids: selectedIds });
        if (code === 200) {
            notify(msg);
            setAutoExce(false)
        } else {
            notify(msg);
        }
    }
    return (
        <Button label="toolbar.publicWorking" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} variant="outlined" />
    )
}
const CustomProcess = () => {
    const record = useRecordContext();
    const progress = (record.workQty / record.anfme) * 100
    return (
        <>
            <LinearProgress variant="determinate" value={progress} />
        </>
    )
}
const PublicTaskButton = ({ setSelectIds, setDetailDialog }) => {
    const record = useRecordContext();
    const notify = useNotify();
@@ -194,7 +232,7 @@
    );
}
const BulkStartButton = ({ autoExce, setAutoExce }) => {
const BulkAutoStartButton = ({ autoExce, setAutoExce }) => {
    const { data, selectedIds, onUnselectItems } = useListContext();
    const notify = useNotify();
    const startClick = async () => {
@@ -212,7 +250,7 @@
    )
}
const BulkPauseButton = ({ autoExce, setAutoExce }) => {
const BulkAutoPauseButton = ({ autoExce, setAutoExce }) => {
    const notify = useNotify();
    const { data, selectedIds, onUnselectItems } = useListContext();
@@ -229,4 +267,40 @@
    return (
        autoExce ? <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseCircleOutlineIcon />} /> : <></>
    )
}
const PauseButton = () => {
    const notify = useNotify()
    const refresh = useRefresh();
    const record = useRecordContext();
    const pauseClick = async () => {
        const { data: { code, data, msg } } = await request.post('/wave/pause/pub/' + record?.id);
        if (code === 200) {
            notify(msg);
        } else {
            notify(msg);
        }
        refresh()
    }
    return (
        record?.exceStatus == 1 ? <Button label="toolbar.pause" onClick={pauseClick} startIcon={<StopCircleOutlinedIcon />} /> : <></>
    )
}
const ContinueButton = () => {
    const notify = useNotify()
    const refresh = useRefresh();
    const record = useRecordContext();
    const continueClick = async () => {
        const { data: { code, data, msg } } = await request.post('/wave/continue/pub/' + record?.id);
        if (code === 200) {
            notify(msg);
        } else {
            notify(msg);
        }
        refresh()
    }
    return (
        record?.exceStatus == 2 ? <Button label="toolbar.continuePub" onClick={continueClick} startIcon={<PauseCircleOutlineIcon />} /> : <></>
    )
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/mcp/McpController.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.constant.Constants;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.controller.params.LocToTaskParams;
@@ -86,13 +87,13 @@
        }
        param.setType(Constants.TASK_TYPE_OUT_STOCK);
//        try {
//            locItemService.generateTask(TaskResouceType.TASK_RESOUCE_STOCK_TYPE.val, param, getLoginUserId());
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
        try {
            locItemService.generateTask(TaskResouceType.TASK_RESOUCE_STOCK_TYPE.val, param, getLoginUserId());
        } catch (Exception e) {
            throw new CoolException(e);
        }
        return R.ok(param);
        return R.ok();
    }
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaOutStockController.java
@@ -32,7 +32,7 @@
    @PreAuthorize("hasAuthority('manager:task:list')")
    @GetMapping("/saveOutTaskSts/{barcode}")
    @ApiOperation("快速拣货查询")
    @ApiOperation("快速拣货")
    public R saveOutTaskSts(@PathVariable String barcode) {
        return pdaOutStockService.saveOutTaskSts(barcode);
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java
@@ -193,7 +193,7 @@
                if (null == wave){
                    throw new CoolException("未找到容器号对应波次");
                }
                wave.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_DONE.val);
                wave.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_TASK.val);
                if (!waveService.updateById(wave)){
                    throw new CoolException("波次单更新状态失败");
                }
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -15,14 +15,14 @@
        generator.frontendPrefixPath = "rsf-admin/";
        generator.sqlOsType = SqlOsType.MYSQL;
        generator.url = "192.168.4.50:3306/rsf";
        generator.url = "127.0.0.1:3306/rsf";
        generator.username = "root";
        generator.password = "34821015";
//        generator.url="47.97.1.152:51433;databasename=jkasrs";
//        generator.username="sa";
//        generator.password="Zoneyung@zy56$";
        generator.table = "man_wave_rule";
        generator.table = "man_wave_order_rela";
        generator.tableDesc = "波次策略";
        generator.packagePath = "com.vincent.rsf.server.manager";
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java
@@ -1,6 +1,7 @@
package com.vincent.rsf.server.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
@@ -15,6 +16,8 @@
import com.vincent.rsf.server.manager.entity.TaskItem;
import com.vincent.rsf.server.manager.entity.Wave;
import com.vincent.rsf.server.manager.entity.WaveItem;
import com.vincent.rsf.server.manager.enums.WaveExceStatus;
import com.vincent.rsf.server.manager.enums.WaveItemExceStatus;
import com.vincent.rsf.server.manager.service.TaskItemService;
import com.vincent.rsf.server.manager.service.WaveService;
import com.vincent.rsf.server.system.controller.BaseController;
@@ -134,7 +137,7 @@
    @ApiOperation("选择明细下发任务")
    @PostMapping("/wave/selects/task")
    public R waveToTask(@RequestBody Map<String, Object> map) {
        if (Cools.isEmpty(map) || Cools.isEmpty(map.get("wave"))) {
        if (Cools.isEmpty(map) || Cools.isEmpty(map.get("ids"))) {
            throw new CoolException("参数不能为空!!");
        }
        return waveService.waveToTask(map, getLoginUserId());
@@ -154,7 +157,25 @@
        return R.ok().add(pageResult);
    }
    @PreAuthorize("hasAuthority('manager:waveItem:update')")
    @ApiOperation("暂停下发任务")
    @PostMapping("/wave/pause/pub/{id}")
    public R pausePublicTask(@PathVariable Long id) {
        waveService.update(new LambdaUpdateWrapper<Wave>()
                .eq(Wave::getId, id)
                .set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_PAUSE.val));
        return R.ok();
    }
    @PreAuthorize("hasAuthority('manager:waveItem:update')")
    @ApiOperation("继续下发任务")
    @PostMapping("/wave/continue/pub/{id}")
    public R continuePublicTask(@PathVariable Long id) {
        waveService.update(new LambdaUpdateWrapper<Wave>()
                .eq(Wave::getId, id)
                .set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val));
        return R.ok();
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveItemController.java
@@ -109,26 +109,4 @@
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(waveItemService.list(), WaveItem.class), response);
    }
    @PreAuthorize("hasAuthority('manager:waveItem:update')")
    @ApiOperation("暂停下发任务")
    @PostMapping("/waveItem/pause/pub/{id}")
    public R pausePublicTask(@PathVariable Long id) {
         waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                 .eq(WaveItem::getId, id)
                 .set(WaveItem::getExceStatus, WaveItemExceStatus.WAVE_ITEM_EXCE_PAUSE.val));
         return R.ok();
    }
    @PreAuthorize("hasAuthority('manager:waveItem:update')")
    @ApiOperation("继续下发任务")
    @PostMapping("/waveItem/continue/pub/{id}")
    public R continuePublicTask(@PathVariable Long id) {
        waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                .eq(WaveItem::getId, id)
                .set(WaveItem::getExceStatus, WaveItemExceStatus.WAVE_EXCE_STATUS_ING.val));
        return R.ok();
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveOrderRelaController.java
New file
@@ -0,0 +1,110 @@
package com.vincent.rsf.server.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.common.annotation.OperationLog;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.WaveOrderRela;
import com.vincent.rsf.server.manager.service.WaveOrderRelaService;
import com.vincent.rsf.server.system.controller.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
@RestController
public class WaveOrderRelaController extends BaseController {
    @Autowired
    private WaveOrderRelaService waveOrderRelaService;
    @PreAuthorize("hasAuthority('manager:waveOrderRela:list')")
    @PostMapping("/waveOrderRela/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<WaveOrderRela, BaseParam> pageParam = new PageParam<>(baseParam, WaveOrderRela.class);
        return R.ok().add(waveOrderRelaService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:list')")
    @PostMapping("/waveOrderRela/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(waveOrderRelaService.list());
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:list')")
    @PostMapping({"/waveOrderRela/many/{ids}", "/waveOrderRelas/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(waveOrderRelaService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:list')")
    @GetMapping("/waveOrderRela/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(waveOrderRelaService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:save')")
    @OperationLog("Create 波次策略")
    @PostMapping("/waveOrderRela/save")
    public R save(@RequestBody WaveOrderRela waveOrderRela) {
        waveOrderRela.setCreateBy(getLoginUserId());
        waveOrderRela.setCreateTime(new Date());
        waveOrderRela.setUpdateBy(getLoginUserId());
        waveOrderRela.setUpdateTime(new Date());
        if (!waveOrderRelaService.save(waveOrderRela)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(waveOrderRela);
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:update')")
    @OperationLog("Update 波次策略")
    @PostMapping("/waveOrderRela/update")
    public R update(@RequestBody WaveOrderRela waveOrderRela) {
        waveOrderRela.setUpdateBy(getLoginUserId());
        waveOrderRela.setUpdateTime(new Date());
        if (!waveOrderRelaService.updateById(waveOrderRela)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(waveOrderRela);
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:remove')")
    @OperationLog("Delete 波次策略")
    @PostMapping("/waveOrderRela/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!waveOrderRelaService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:list')")
    @PostMapping("/waveOrderRela/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<WaveOrderRela> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(WaveOrderRela::getId, condition);
        }
        waveOrderRelaService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getId()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('manager:waveOrderRela:list')")
    @PostMapping("/waveOrderRela/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(waveOrderRelaService.list(), WaveOrderRela.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocMastInitParam.java
@@ -54,5 +54,9 @@
    @NotBlank(message = "巷道")
    private Integer channel;
    @ApiModelProperty("起始巷道")
    @NotBlank(message = "起始巷道")
    private Integer startChannel;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WaveOrderRela.java
New file
@@ -0,0 +1,93 @@
package com.vincent.rsf.server.manager.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.entity.User;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("man_wave_order_rela")
public class WaveOrderRela implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * ID
     */
    @ApiModelProperty(value= "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 波次ID
     */
    @ApiModelProperty(value= "波次ID")
    private Long waveId;
    /**
     * 波次明细ID
     */
    @ApiModelProperty(value= "波次明细ID")
    private Long waveItemId;
    /**
     * 订单ID
     */
    @ApiModelProperty(value= "订单ID")
    private Long orderId;
    /**
     * 订单明细ID
     */
    @ApiModelProperty(value= "订单明细ID")
    private Long orderItemId;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    private String memo;
    public WaveOrderRela() {}
    public WaveOrderRela(Long waveId,Long waveItemId,Long orderId,Long orderItemId,String memo) {
        this.waveId = waveId;
        this.waveItemId = waveItemId;
        this.orderId = orderId;
        this.orderItemId = orderItemId;
        this.memo = memo;
    }
//    WaveOrderRela waveOrderRela = new WaveOrderRela(
//            null,    // 波次ID
//            null,    // 波次明细ID
//            null,    // 订单ID
//            null,    // 订单明细ID
//            null    // 备注
//    );
    public Boolean getStatusBool(){
        if (null == this.status){ return null; }
        switch (this.status){
            case 1:
                return true;
            case 0:
                return false;
            default:
                return null;
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WaveExceStatus.java
@@ -10,12 +10,12 @@
public enum WaveExceStatus {
    //波次执行状态
    WAVE_EXCE_STATUS_INIT("0", "初始化"),
    WAVE_EXCE_STATUS_EXCING("1", "执行中"),
    WAVE_EXCE_STATUS_TASK("2", "生成任务"),
    WAVE_EXCE_STATUS_DONE("3", "任务完成"),
    ;
    WAVE_EXCE_STATUS_INIT("0", "等待执行"),
    WAVE_EXCE_STATUS_EXCING("1", "正在执行"),
    WAVE_EXCE_STATUS_PAUSE("2", "暂停执行"),
    WAVE_EXCE_STATUS_TASK("3", "执行完成"),
    ;
    WaveExceStatus(String val, String desc) {
        this.val = Short.parseShort(val);
        this.desc = desc;
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WaveItemExceStatus.java
@@ -18,6 +18,7 @@
    WAVE_EXCE_STATUS_DONE("4", "任务完成"),
    ;
    // 终止,     等待执行, 正在执行,执行完成
    WaveItemExceStatus(String val, String desc) {
        this.val = Short.parseShort(val);
        this.desc = desc;
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/WaveOrderRelaMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.WaveOrderRela;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface WaveOrderRelaMapper extends BaseMapper<WaveOrderRela> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/WaveSchedules.java
@@ -25,12 +25,12 @@
import java.util.stream.Collectors;
/**
* @author Ryan
* @description 波次定时任务
* @param
* @return
* @time 2025/6/23 13:49
*/
 * @param
 * @author Ryan
 * @description 波次定时任务
 * @return
 * @time 2025/6/23 13:49
 */
@Component
public class WaveSchedules {
@@ -48,12 +48,12 @@
    /**
    * @author Ryan
    * @description 自动下发波次任务
    * @param
    * @return
    * @time 2025/6/23 13:52
    */
     * @param
     * @return
     * @author Ryan
     * @description 自动下发波次任务
     * @time 2025/6/23 13:52
     */
    @Scheduled(cron = "0/15 * * * * ?")
//    @Transactional(rollbackFor = Exception.class)
    public void autoGenerateTask() {
@@ -61,36 +61,26 @@
        if (Objects.isNull(config) || !Boolean.parseBoolean(config.getVal())) {
            return;
        }
//        List<Wave> list = waveService.list(new LambdaQueryWrapper<Wave>()
//                        .select(Wave::getId)
//                        .in(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_INIT.val
//                                , WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val));
//        if (list.isEmpty()) {
//            return;
//        }
//        List<Long> longs = list.stream().map(Wave::getId).collect(Collectors.toList());
        List<WaveItem> waveItems = waveItemService.list(new LambdaQueryWrapper<WaveItem>()
                .in(WaveItem::getExceStatus, Arrays.asList(WaveItemExceStatus.WAVE_ITEM_EXCE_STATUS_UN.val
                        , WaveItemExceStatus.WAVE_EXCE_STATUS_ING.val)));
        waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                .set(WaveItem::getExceStatus, WaveItemExceStatus.WAVE_EXCE_STATUS_ING.val)
                .apply("anfme > work_qty")
        );
        if (waveItems.isEmpty()) {
        List<Wave> list = waveService.list(new LambdaQueryWrapper<Wave>()
                .select(Wave::getId)
                .in(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_INIT.val
                        , WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val));
        if (list.isEmpty()) {
            return;
        }
        List<Long> longs = list.stream().map(Wave::getId).collect(Collectors.toList());
        waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                .in(WaveItem::getWaveId, longs)
                .set(WaveItem::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val)
                .apply("anfme > work_qty"));
        Long loginUserId = SystemAuthUtils.getLoginUserId();
        Map<Long, List<WaveItem>> listMap = waveItems.stream().collect(Collectors.groupingBy(WaveItem::getWaveId));
        listMap.keySet().forEach(waveId -> {
            List<Long> itemIds = listMap.get(waveId).stream().map(WaveItem::getId).collect(Collectors.toList());
            Map<String, Object> params = new HashMap<>();
            params.put("wave", waveId);
            params.put("waveItem", itemIds);
            waveService.waveToTask(params, loginUserId);
        });
        Map<String, Object> params = new HashMap<>();
        params.put("ids", longs);
        waveService.waveToTask(params, loginUserId);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveOrderRelaService.java
New file
@@ -0,0 +1,8 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.server.manager.entity.WaveOrderRela;
public interface WaveOrderRelaService extends IService<WaveOrderRela> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocServiceImpl.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.controller.params.LocMastInitParam;
@@ -11,6 +12,7 @@
import com.vincent.rsf.server.manager.mapper.LocTypeRelaMapper;
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.utils.Shelves;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -106,8 +108,20 @@
        List<Loc> list = new ArrayList<>();
        Integer chanl = 0; //默认第一巷道
        for (int r = param.getStartRow(); r <= param.getEndRow(); r++) {
            if (r % param.getChannel() == 1) {
                chanl ++;
            try{
                Shelves shelves = new Shelves(param.getEndRow() - param.getStartRow() + 1, param.getChannel(),param.getStartRow());
                for (List<Integer> node : shelves.nodes){
                    if (node.contains(r)) {
                        if (!Cools.isEmpty(param.getStartChannel()) && param.getStartChannel() > 0){
                            chanl = shelves.nodes.indexOf(node) + param.getStartChannel();
                        }else {
                            chanl = shelves.nodes.indexOf(node) + 1;
                        }
                        break;
                    }
                }
            }catch (Exception e){
                throw new CoolException("解析巷道号失败");
            }
            for (int b = param.getStartBay(); b <= param.getEndBay(); b++) {
                for (int l = param.getStartLev(); l <= param.getEndLev(); l++) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -193,6 +193,8 @@
                    .setId(null)
                    .setUpdateBy(loginUserId)
                    .setCreateBy(loginUserId)
                    .setCreateTime(new Date())
                    .setUpdateTime(new Date())
                    .setPoCode(delivery.getCode());
            if (!this.save(order)) {
                throw new CoolException("主单保存失败!!");
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveOrderRelaServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.WaveOrderRelaMapper;
import com.vincent.rsf.server.manager.entity.WaveOrderRela;
import com.vincent.rsf.server.manager.service.WaveOrderRelaService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("waveOrderRelaService")
public class WaveOrderRelaServiceImpl extends ServiceImpl<WaveOrderRelaMapper, WaveOrderRela> implements WaveOrderRelaService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java
@@ -110,7 +110,6 @@
        return R.ok();
    }
    /**
     * 选择波次明细下发任务
     *
@@ -121,99 +120,94 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R waveToTask(Map<String, Object> map, Long loginUserId) {
        if (Objects.isNull(map.get("waveItem"))) {
        if (Objects.isNull(map.get("ids"))) {
            throw new CoolException("参数不能为空!!");
        }
        String waveId = map.get("wave").toString();
        Wave waves = this.getById(Long.parseLong(waveId));
        List<Long> WaveIds = JSONArray.parseArray(JSON.toJSONString(map.get("ids")), Long.class);
        List<Wave> waves = waveService.listByIds(WaveIds);
        if (Objects.isNull(waves)) {
            throw new CoolException("波次数据不存在!!");
            throw new CoolException("数据错误: 波次不存在!!");
        }
        List<Long> waveItems = JSONArray.parseArray(JSON.toJSONString(map.get("waveItem")), Long.class);
        if (waveItems.isEmpty()) {
            throw new CoolException("波次明细不能为空!!");
        }
        List<WaveItem> items = waveItemService.listByIds(waveItems);
        if (items.isEmpty()) {
            throw new CoolException("波次明细不存在!!");
        }
        if (!waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                .set(WaveItem::getExceStatus, WaveItemExceStatus.WAVE_EXCE_STATUS_ING.val)
                .in(WaveItem::getId, waveItems))) {
            throw new CoolException("执行状态修改失败!!");
        }
        WaveRule waveRule = waveRuleService.getOne(new LambdaQueryWrapper<WaveRule>()
                .eq(WaveRule::getType, WaveRuleType.First_In_First_Out.type));
        if (Cools.isEmpty(waveRule)) {
            throw new CoolException("未找到当前策略");
        }
        List<WaveToLocParams> params = new ArrayList<>();
        for (WaveItem item : items) {
            WaveToLocParams locParams = new WaveToLocParams();
            BeanUtils.copyProperties(item, locParams);
            locParams.setBatch(item.getSplrBatch())
                    .setItemId(item.getId())
                    .setWaveId(item.getWaveId());
            params.add(locParams);
        }
        List<OrderOutItemDto> results = LocManageUtil.getOutOrderList(params, waveRule);
        if (results.isEmpty()) {
            Wave wave = waveService.getById(waveId);
            if (Objects.isNull(wave)) {
                throw new CoolException("<UNK>");
        for (Wave wave : waves) {
            List<WaveItem> items = waveItemService.list(new LambdaQueryWrapper<WaveItem>().eq(WaveItem::getWaveId, wave.getId()));
            if (items.isEmpty()) {
                throw new CoolException("波次明细不存在!!");
            }
            wave.setUpdateBy(loginUserId).setUpdateTime(new Date());
            if (wave.getAnfme().compareTo(wave.getWorkQty()) == 0) {
                wave.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_TASK.val);
            } else {
                wave.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val);
            }
            waveService.updateById(wave);
            return R.ok();
        }
        try {
            /**生成出库任务*/
            generateOutTask(results, loginUserId, waves);
        } catch (Exception e) {
            log.error("UNK", e);
            throw new CoolException(e.getMessage());
        }
        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>()
                .in(TaskItem::getSource, waveItems));
        if (Cools.isEmpty(taskItems)) {
            throw new CoolException("暂无合适库存信息!!");
        }
        for (TaskItem item : taskItems) {
            WaveItem waveItem = waveItemService.getById(item.getSource());
            Double workQty = Math.round((waveItem.getWorkQty() + item.getAnfme()) * 10000) / 10000.0;
            waveItem.setWorkQty(workQty);
            if (workQty.compareTo(waveItem.getAnfme()) < 0) {
                waveItem.setExceStatus(WaveItemExceStatus.WAVE_EXCE_STATUS_ING.val);
            } else {
                waveItem.setExceStatus(WaveItemExceStatus.WAVE_EXCE_STATUS_PUBD.val);
            }
            List<Long> ids = items.stream().map(WaveItem::getId).collect(Collectors.toList());
            if (!waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                    .set(WaveItem::getExceStatus, WaveItemExceStatus.WAVE_EXCE_STATUS_PUBD.val)
                    .setSql("work_qty = work_qty + " + item.getAnfme())
                    .set(WaveItem::getUpdateBy, loginUserId)
                    .set(WaveItem::getUpdateTime, new Date())
                    .eq(WaveItem::getId, item.getSource()))) {
                throw new CoolException("下发执行异常,请稍候重试!");
                    .set(WaveItem::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val)
                    .in(WaveItem::getId, ids))) {
                throw new CoolException("执行状态修改失败!!");
            }
            WaveRule waveRule = waveRuleService.getOne(new LambdaQueryWrapper<WaveRule>()
                    .eq(WaveRule::getType, WaveRuleType.First_In_First_Out.type));
            if (Cools.isEmpty(waveRule)) {
                throw new CoolException("未找到当前策略");
            }
            List<WaveToLocParams> params = new ArrayList<>();
            for (WaveItem item : items) {
                WaveToLocParams locParams = new WaveToLocParams();
                BeanUtils.copyProperties(item, locParams);
                locParams.setBatch(item.getSplrBatch())
                        .setItemId(item.getId())
                        .setWaveId(item.getWaveId());
                params.add(locParams);
            }
            List<OrderOutItemDto> results = LocManageUtil.getOutOrderList(params, waveRule);
            if (results.isEmpty()) {
                wave.setUpdateBy(loginUserId).setUpdateTime(new Date());
                if (wave.getAnfme().compareTo(wave.getWorkQty()) == 0) {
                    wave.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_TASK.val);
                } else {
                    wave.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val);
                }
                waveService.updateById(wave);
                return R.ok();
            }
            try {
                /**生成出库任务*/
                generateOutTask(results, loginUserId, wave);
            } catch (Exception e) {
                log.error("UNK", e);
                throw new CoolException(e.getMessage());
            }
            List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>()
                    .in(TaskItem::getSource, ids));
            if (Cools.isEmpty(taskItems)) {
                throw new CoolException("暂无合适库存信息!!");
            }
            for (TaskItem item : taskItems) {
                WaveItem waveItem = waveItemService.getById(item.getSource());
                Double workQty = Math.round((waveItem.getWorkQty() + item.getAnfme()) * 10000) / 10000.0;
                waveItem.setWorkQty(workQty);
                if (workQty.compareTo(waveItem.getAnfme()) < 0) {
                    waveItem.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_EXCING.val);
                } else {
                    waveItem.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_TASK.val);
                }
                if (!waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                        .set(WaveItem::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_TASK.val)
                        .setSql("work_qty = work_qty + " + item.getAnfme())
                        .set(WaveItem::getUpdateBy, loginUserId)
                        .set(WaveItem::getUpdateTime, new Date())
                        .eq(WaveItem::getId, item.getSource()))) {
                    throw new CoolException("下发执行异常,请稍候重试!");
                }
            }
            if (!waveService.update(new LambdaUpdateWrapper<Wave>()
                    .set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_TASK.val)
                    .set(Wave::getWorkQty, taskItems.stream().mapToDouble(TaskItem::getAnfme).sum())
                    .set(Wave::getUpdateBy, loginUserId)
                    .set(Wave::getUpdateTime, new Date())
                    .eq(Wave::getId, wave.getId()))) {
                throw new CoolException("波次状态修改失败!!");
            }
        }
        if (!waveService.update(new LambdaUpdateWrapper<Wave>()
                .set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_TASK.val)
                .set(Wave::getWorkQty, taskItems.stream().mapToDouble(TaskItem::getAnfme).sum())
                .set(Wave::getUpdateBy, loginUserId)
                .set(Wave::getUpdateTime, new Date())
                .eq(Wave::getId, waveId))) {
            throw new CoolException("波次状态修改失败!!");
        }
        return R.ok();
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/Shelves.java
New file
@@ -0,0 +1,132 @@
package com.vincent.rsf.server.manager.utils;
import com.alibaba.fastjson.JSON;
import com.vincent.rsf.framework.common.Arith;
import com.vincent.rsf.framework.exception.CoolException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
 * <strong>立库货架实体类</strong>
 * Created by vincent on 2020/6/11
 */
public class Shelves {
    // 货架排数量
    public final int size;
    // 货架组数量
    public final int group;
    // 偏移量[default:0]
    public final int offset;
    // 货架实例节点集合
    public List<List<Integer>> nodes;
    public Shelves(int size, int group) {
        this(size, group, 0);
    }
    /**
     * @param size 货架单排总数
     * @param group 货架组数量
     * @param offset 序列号偏移量
     */
    public Shelves(int size, int group, int offset) {
        this.size = size;
        this.group = group;
        this.offset = offset-1;
        init();
    }
    /**
     * 初始化方法【私有】
     */
    private void init(){
        if (group == 0 || size%group != 0) {
            throw new RuntimeException("shelves init fail!");
        }
        nodes = new ArrayList<>();
        for (int g = 1; g <= this.group; g++){
            int unit = size/group;
            List<Integer> node = new ArrayList<>();
            for (int i = (g-1)*unit+1+offset ; i <= g*unit+offset; i++){
                node.add(i);
            }
            nodes.add(node);
        }
    }
    /**
     * 开始计算 =======>>>
     *
     *          货架命中规则如下:
     *              安装位置:   [1]  [2]  |  [3]  [4]  --------  [5] [6]  |  [7] [8]
     *                  命中顺序:      1 -> 5 -> 4 -> 8 -> 2 -> 6 -> 3 -> 7 -> 1 ...
     *
     *          1.该规则适不限制货架数量,总数与组别在构造器中设置
     *          2.如有序列号起始问题,用偏移量规避即可
     *
     * @param curSeq 当前货架号
     * @return 规则命中货架号
     */
    public int start(int curSeq){
        Iterator<List<Integer>> iterator = nodes.iterator();
        while (iterator.hasNext()){
            List<Integer> node = iterator.next();
            if (node.contains(curSeq)) {
                int idx = node.indexOf(curSeq);
                // 是否为末尾货架
                if (iterator.hasNext()) {
                    return iterator.next().get(idx);
                } else {
                    List<Integer> first = nodes.get(0);
                    int val = first.get(idx);
                    int res = size / group + 1 + offset - val;
                    // 反向命中货架时不再是对立下标(相对于巷道)
                    if (res < val) {
                        // 轮询所有货架后重新开始定位
                        if (val - res - offset == 1) {
                            return first.get(0);
                        }
                        res = res + 1;
                    }
                    return res + offset;
                }
            }
        }
        return -1;
    }
    public Integer get(Integer curRow) {
        for (List<Integer> node : nodes){
            if (node.contains(curRow)) {
                return nodes.indexOf(node) + 1;
            }
        }
        throw new CoolException("货排检索系统报错, node:" + JSON.toJSONString(nodes) + ", curRow:" + curRow);
    }
    public static void main(String[] args) throws InterruptedException {
        double remainder = Arith.divides(1,16 - 1, 16);
        System.out.println(remainder);
        System.out.println((int) remainder);
//        Shelves shelves = new Shelves(8,2);
//        System.out.println(shelves.nodes.toString());
//        int start = 1;
//        while (true) {
//            System.out.println(start);
//            start = shelves.start(start);
//            Thread.sleep(500L);
//        }
    }
}
rsf-server/src/main/resources/mapper/manager/WaveOrderRelaMapper.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.vincent.rsf.server.manager.mapper.WaveOrderRelaMapper">
</mapper>