skyouc
3 天以前 687e4da4b6fb9147b12eb0cd5072e1dda02abc00
no message
7个文件已修改
1个文件已添加
190 ■■■■ 已修改文件
rsf-admin/src/page/orders/wave/WaveItemList.jsx 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/wave/WaveList.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WaveItem.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WaveItemExceStatus.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/DictTypeCode.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/wave/WaveItemList.jsx
@@ -34,20 +34,16 @@
    useGetRecordId,
    Button,
} from 'react-admin';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline';
import PlayArrowOutlinedIcon from '@mui/icons-material/PlayArrowOutlined';
import { Box, Typography, Card, Stack } from '@mui/material';
import ContentCreate from '@mui/icons-material/Create';
import PageDrawer from "../../components/PageDrawer";
import { styled } from '@mui/material/styles';
import WaveItemCreate from "./WaveItemCreate";
import EmptyData from "../../components/EmptyData";
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import PageDrawer from "../../components/PageDrawer";
import WaveItemEdit from "./WaveItemEdit";
import MyField from "../../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import ContentCreate from '@mui/icons-material/Create';
import PlayArrowOutlinedIcon from '@mui/icons-material/PlayArrowOutlined';
import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
@@ -58,7 +54,7 @@
    '& .column-name': {
    },
    '& .opt': {
        width: 200
        width: 140
    },
}));
@@ -126,7 +122,6 @@
                    bulkActionButtons={
                        <>
                            <BulkStartButton />
                            <BulkPauseButton />
                        </>
                    }
                    rowClick={(id, resource, record) => false}
@@ -153,6 +148,9 @@
                    <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} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <BulkPauseButton />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <WaveItemEdit
@@ -185,28 +183,34 @@
    return (
        <Button label="ra.action.edit" onClick={editClick} startIcon={<ContentCreate />} />
    )
}
const BulkStartButton = () => {
    const { data, selectedIds, onUnselectItems } = useListContext();
    const startClick = () => {
        onUnselectItems()
    const waveId = useGetRecordId();
    const startClick = async () => {
        onUnselectItems();
        const { data: { code, data, msg } } = await request.post('/wave/selects/task', { wave: waveId, waveItem: selectedIds });
        if (code === 200) {
            notify(msg);
            setAutoExce(false)
        } else {
            notify(msg);
        }
    }
    return (
        <Button label="toolbar.start" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} variant="outlined" />
        <Button label="toolbar.publicWorking" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} variant="outlined" />
    )
}
const BulkPauseButton = () => {
    const { data, selectedIds, onUnselectItems } = useListContext();
    const record = useRecordContext();
    const pauseClick = () => {
        onUnselectItems()
        onUnselectItems();
    }
    return (
        <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseCircleOutlineIcon />} variant="outlined" />
        record?.exceStatus == 2 ? <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseCircleOutlineIcon />} /> : <></>
    )
}
rsf-admin/src/page/orders/wave/WaveList.jsx
@@ -95,18 +95,14 @@
    const [drawerVal, setDrawerVal] = useState(false);
    useEffect(() => {
        console.log('-------->');
        getConfig()
    }, [])
    const getConfig = async () => {
        const { data: { code, data, msg } } = await request.get('/config/flag/' + DEFAULT_WAVE_AUTO_EXCE);
        if (code === 200) {
            setAutoExce(data?.flag)
            notify(msg);
        } else {
            notify(msg);
        }
            setAutoExce(JSON.parse(data?.val))
        }
    }
    return (
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java
@@ -130,6 +130,16 @@
        return waveService.publicTask(map, getLoginUserId());
    }
    @PreAuthorize("hasAuthority('manager:wave:update')")
    @ApiOperation("选择明细下发任务")
    @PostMapping("/wave/selects/task")
    public R waveToTask(@RequestBody Map<String, Object> map) {
        if (Cools.isEmpty(map) || Cools.isEmpty(map.get("wave"))) {
            throw new CoolException("参数不能为空!!");
        }
        return waveService.waveToTask(map, getLoginUserId());
    }
    @PreAuthorize("hasAuthority('manager:wave:list')")
    @ApiOperation("波次出库任务预览")
    @PostMapping("/wave/locs/preview/page")
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WaveItem.java
@@ -5,7 +5,11 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.vincent.rsf.server.system.constant.DictTypeCode;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.service.DictDataService;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
@@ -21,6 +25,7 @@
import com.vincent.rsf.server.system.entity.User;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
@Data
@Accessors(chain = true)
@@ -259,6 +264,20 @@
//            null    // 备注
//    );
    public String getExceStatus$(){
        if (Cools.isEmpty(this.exceStatus)) {
            return null;
        }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictDatas = dictDataService.getOne(new LambdaQueryWrapper<DictData>()
                .eq(DictData::getDictTypeCode, DictTypeCode.SYS_WAVE_EXCE_STATUS)
                .eq(DictData::getValue, this.exceStatus));
        if (Objects.isNull(dictDatas) || Objects.isNull(dictDatas.getLabel())) {
            return null;
        }
        return dictDatas.getValue() + "." + dictDatas.getLabel();
    }
    public String getStatus$(){
        if (null == this.status){ return null; }
        switch (this.status){
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WaveItemExceStatus.java
New file
@@ -0,0 +1,28 @@
package com.vincent.rsf.server.manager.enums;
/**
* @author Ryan
* @description 波次明细执行状态
* @param
* @return
* @time 2025/6/19 14:18
*/
public enum WaveItemExceStatus {
    //波次执行状态
    WAVE_ITEM_EXCE_STATUS_UN("0", "未执行"),
    WAVE_EXCE_STATUS_ING("1", "执行中"),
    WAVE_EXCE_STATUS_SEED("2", "已下发"),
    WAVE_EXCE_STATUS_DONE("3", "完成"),
    ;
    WaveExceStatus(String val, String desc) {
        this.val = Short.parseShort(val);
        this.desc = desc;
    }
    public Short val;
    public String desc;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java
@@ -37,4 +37,14 @@
    * @time 2025/6/17 10:03
    */
    R cancelWave(List<Long> ids);
    /**
     * @param
     * @param loginUserId
     * @return
     * @author Ryan
     * @description 选择明细下发任务
     * @time 2025/4/25 16:24
     */
    R waveToTask(Map<String, Object> map, Long loginUserId);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java
@@ -1,5 +1,6 @@
package com.vincent.rsf.server.manager.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -61,14 +62,58 @@
        if (Objects.isNull(itemParams) || itemParams.isEmpty()) {
            throw new CoolException("参数不能为空!!");
        }
        List<WaveItem> items = JSONArray.parseArray(JSONArray.toJSONString(itemParams), WaveItem.class);
        String waveId = map.get("wave").toString();
        Wave waves = this.getById(Long.parseLong(waveId));
        if (Objects.isNull(waves)) {
            throw new CoolException("波次数据不存在!!");
        }
        List<WaveItem> waveItems = waveItemService.list(new LambdaQueryWrapper<WaveItem>().eq(WaveItem::getWaveId, waves.getId()));
        List<WaveItem> waveItems = waveItemService.list(new LambdaQueryWrapper<WaveItem>()
                .eq(WaveItem::getWaveId, waves.getId())
                .apply("anfme > work_qty"));
        if (waveItems.isEmpty()) {
            throw new CoolException("波次明细不存在!!");
        }
        /**生成出库任务*/
        try {
            generateOutTask(waveItems, loginUserId, waves);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new CoolException("出库任务生成失败!!!");
        }
        List<Long> orderIds = waveItems.stream().map(WaveItem::getOrderId).collect(Collectors.toList());
        /**修改出库单状态*/
        if (!asnOrderService.update(new LambdaUpdateWrapper<AsnOrder>()
                .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)
                .in(AsnOrder::getId, orderIds))) {
            throw new CoolException("出库单据状态修改失败!!");
        }
        return R.ok();
    }
    /**
     * 选择波次明细下发任务
     * @param map
     * @param loginUserId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R waveToTask(Map<String, Object> map, Long loginUserId) {
        if (Objects.isNull(map.get("waveItem"))) {
            throw new CoolException("参数不能为空!!");
        }
        String waveId = map.get("wave").toString();
        Wave waves = this.getById(Long.parseLong(waveId));
        if (Objects.isNull(waves)) {
            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("波次明细不存在!!");
        }
        /**生成出库任务*/
@@ -78,18 +123,7 @@
            log.error(e.getMessage());
            throw new CoolException("出库任务生成失败!!!");
        }
        //TODO 1. 根据波次明细生成出库任务
        // 2. 根据物料SKU寻找符合物料库位  {1. 根据物料编码,批次,动态字段 查询符合的库位,再根据库位中物料的数量选择最适合的库位 2. 判断当前订单是全拖出库还是拣料入库}
        // 3. 修改主单、波次执行数量
        // 4. 判断全仓出库或拣料出库
        List<Long> orderIds = waveItems.stream().map(WaveItem::getOrderId).collect(Collectors.toList());
        /**修改出库单状态*/
        if (!asnOrderService.update(new LambdaUpdateWrapper<AsnOrder>()
                .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)
                .in(AsnOrder::getId, orderIds))) {
            throw new CoolException("出库单据状态修改失败!!");
        }
        return R.ok();
        return null;
    }
    /**
@@ -113,6 +147,7 @@
            }
            List<Long> list = locItems.stream().map(LocItem::getLocId).collect(Collectors.toList());
            /**根据供应商批次,物料码, 动态字段查询指定的物料库存信息*/
            //TODO 这里需要要根据波次规则查找库存信息
            List<LocItem> items = locItemService.list(new LambdaQueryWrapper<LocItem>()
                    .eq(LocItem::getSplrBatch, param.getSplrBatch())
                    .in(LocItem::getLocId, list)
@@ -141,7 +176,7 @@
            List<LocItem> locItems = listMap.get(key);
            LocItem item1 = locItems.stream().findFirst().get();
            WaveItem waveItem = waveItemService.getById(item1.getSource());
            if (null == waveItem || Objects.isNull(waveItem)) {
            if (Objects.isNull(waveItem)) {
                throw new CoolException("数据错误:波次明细不存在!!");
            }
            //TODO 当前任务完成后,通过定时事件判断是全盘出库,还是拣料再入库
@@ -194,6 +229,7 @@
            taskItems.forEach(item -> {
                boolean update = waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
                        .eq(WaveItem::getId, item.getSource())
                                .set(WaveItem::getExceStatus, AsnExceStatus)
                        .set(WaveItem::getWorkQty, item.getAnfme()));
                if (!update) {
                    throw new CoolException("波次执行数量修改失败!!");
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/DictTypeCode.java
@@ -70,4 +70,9 @@
     */
    public final static String SYS_WAVE_RULE_CODE =  "sys_wave_rule_code";
    /**
     * 波次下发执行状态
     */
    public final static String SYS_WAVE_EXCE_STATUS =  "sys_wave_exce_status";
}