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"; }