skyouc
1 天以前 646bfdde5c37f0b0d479bbcbc7503bc8482e67d6
可针对单个波次进行暂停,开始, 主单添加进度条
8个文件已修改
396 ■■■■■ 已修改文件
rsf-admin/src/page/orders/wave/WaveList.jsx 104 ●●●● 补丁 | 查看 | 原始文档 | 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/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/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/schedules/WaveSchedules.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java 166 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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/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/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/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/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/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();
    }