From 273f2e5d3941b0e720e5eabd7dba9cfc042c3267 Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 17 六月 2025 17:04:53 +0800
Subject: [PATCH] 出库单生成波次功能开发

---
 rsf-admin/src/page/orders/wave/WaveEdit.jsx                                                   |    4 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java |   46 ++++---
 rsf-admin/src/page/orders/wave/WaveList.jsx                                                   |   26 +--
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java     |   16 ++
 rsf-admin/src/page/orders/outStock/OutStockPublic.jsx                                         |   46 ++++---
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java    |   10 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java     |    1 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java              |    9 +
 rsf-admin/src/page/orders/wave/WaveItemList.jsx                                               |   50 ++++++--
 rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java              |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java    |   47 +++++++
 rsf-admin/src/i18n/zh.js                                                                      |    5 
 rsf-admin/src/page/orders/outStock/OutOrderList.jsx                                           |   70 +++++++----
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java                      |    3 
 rsf-admin/src/i18n/en.js                                                                      |    6 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java        |   10 -
 rsf-admin/.env                                                                                |    2 
 17 files changed, 240 insertions(+), 117 deletions(-)

diff --git a/rsf-admin/.env b/rsf-admin/.env
index a3c69b2..a0bb09f 100644
--- a/rsf-admin/.env
+++ b/rsf-admin/.env
@@ -1,3 +1,3 @@
-VITE_BASE_IP=127.0.0.1
+VITE_BASE_IP=192.168.4.50
 # VITE_BASE_IP=47.76.147.249
 VITE_BASE_PORT=8080
diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 1d4627b..b36ae34 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -837,6 +837,7 @@
                 type: "type",
                 exceStatus: "exceStatus",
                 anfme: "anfme",
+                groupQty: 'Group Qty',
                 qty: "qty",
                 orderNum: "orderNum",
             },
@@ -1146,6 +1147,8 @@
         selectSite: 'Select Site',
         top: "top",
         resort: "sort",
+        start: 'Start',
+        pause: 'Pause',
         subzone: 'subzone',
         bindmatnr: 'bind matnr',
         bindloc: 'bind loc',
@@ -1160,6 +1163,7 @@
         orderPrint: 'Orders Print',
         quality: "quality",
         complete: "complete",
+        allComfirm: 'All Comfirm',
         verifyComfirm: 'Verify Comfirm',
         close: "close",
         asnCreate: "Create By Order",
@@ -1170,6 +1174,8 @@
         createWave: "Create Wave",
         order: 'Orders',
         modiftySite: 'Modify SiteNo',
+        selectWave: 'Select Wave Rule',
+
     },
     request: {
         error: {
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 6df53d7..f3070a7 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -867,6 +867,7 @@
                 type: "鍗曟嵁绫诲瀷",
                 exceStatus: "鐘舵��",
                 anfme: "鏁伴噺",
+                groupQty: '鍝佺被鏁�',
                 qty: "瀹屾垚鏁伴噺",
                 orderNum: "鍗曟嵁鏁�",
             },
@@ -1140,6 +1141,8 @@
         continue: '缁х画鏀惰揣',
         batch: '鎵归噺鎿嶄綔',
         confirm: '纭',
+        start: '寮�濮嬩笅鍙�',
+        pause: '鏆傚仠',
         pick: '鎷f枡',
         check: '鐩樼偣',
         bulkExport: "鎵归噺瀵煎嚭",
@@ -1163,6 +1166,7 @@
         batchLocType: "鎵归噺搴撲綅绫诲瀷",
         batchPrint: "鎵归噺鎵撳嵃",
         verifyComfirm: '瀹℃牳纭',
+        allComfirm: '鍏ㄩ儴鎻愪氦',
         quality: "璐ㄦ",
         complete: "瀹岀粨",
         close: "鍏抽棴",
@@ -1174,6 +1178,7 @@
         createWave: "鐢熸垚娉㈡",
         recover: "缁х画鏀惰揣",
         modiftySite: '淇敼搴撳彛',
+        selectWave: '娉㈡瑙勫垯',
     },
     request: {
         error: {
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
index 955b074..1181459 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
@@ -39,26 +39,27 @@
   useUnselectAll,
   useRecordSelection,
 } from 'react-admin';
-import { Box, Typography, Card, Stack, Drawer } from '@mui/material';
 import { styled } from '@mui/material/styles';
-import MyCreateButton from "../../components/MyCreateButton";
-import BillStatusField from '../../components/BillStatusField';
-import ConfirmButton from '../../components/ConfirmButton';
 import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
-import EditIcon from '@mui/icons-material/Edit';
-import request from '@/utils/request';
+import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
+import { Box, Typography, Card, Stack, Drawer } from '@mui/material';
 import DictionarySelect from "../../components/DictionarySelect";
+import BillStatusField from '../../components/BillStatusField';
+import MyCreateButton from "../../components/MyCreateButton";
+import PageEditDrawer from "../../components/PageEditDrawer";
+import ConfirmButton from '../../components/ConfirmButton';
 import ImportButton from "../../components/ImportButton";
 import DetailsIcon from '@mui/icons-material/Details';
-import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
-import AddIcon from '@mui/icons-material/Add';
-import OutOrderModal from "./OutOrderModal";
+import AddTaskIcon from '@mui/icons-material/AddTask';
 import PublicIcon from '@mui/icons-material/Public';
 import SelectMatnrModal from "./SelectMatnrModal";
-import AddTaskIcon from '@mui/icons-material/AddTask';
-import PageEditDrawer from "../../components/PageEditDrawer";
-import OutStockPublic from "./OutStockPublic";
+import EditIcon from '@mui/icons-material/Edit';
 import OutOrderPreview from "./OutOrderPreview";
+import AddIcon from '@mui/icons-material/Add';
+import OutStockPublic from "./OutStockPublic";
+import OutOrderModal from "./OutOrderModal";
+import request from '@/utils/request';
+import OutStockWaveDialog from "./OutStockWaveDialog";
 
 const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
   '& .css-1vooibu-MuiSvgIcon-root': {
@@ -109,19 +110,38 @@
     dictTypeCode="sys_asn_exce_status"
     alwaysOn
   />,
-
 ]
 
 const OutOrderList = (props) => {
   const translate = useTranslate();
+  const refresh = useRefresh();
+
   const [createDialog, setCreateDialog] = useState(false);
   const [manualDialog, setManualDialog] = useState(false);
+  const [selectIds, setSelectIds] = useState([]);
   const [preview, setPreview] = useState(false);
+  const [waveRule, setWaveRule] = useState(false);
   const [drawerVal, setDrawerVal] = useState(false);
   const [modalType, setmodalType] = useState(0);
   const [select, setSelect] = useState(0);
   const billReload = useRef();
   const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || [];
+
+  //鑾峰彇娉㈡瑙勫垯
+  const closeDialog = async (value) => {
+    setWaveRule(false)
+    refresh()
+    console.log('=====>');
+    console.log(value);
+    console.log(selectIds);
+    // const res = await request.post(`/outStock/generate/wave`, { ids: selectIds });
+    // if (res?.data?.code === 200) {
+    //   notify(res.data.msg);
+    // } else {
+    //   notify(res.data.msg);
+    // }
+  }
+
   return (
     <Box display="flex">
       <List
@@ -152,7 +172,7 @@
         <StyledDatagrid
           sx={{ width: '100%' }}
           preferenceKey='outStock'
-          bulkActionButtons={<PublicTaskButton />}
+          bulkActionButtons={<PublicTaskButton setWaveRule={setWaveRule} setSelectIds={setSelectIds} />}
           rowClick={false}
           expandSingle={true}
           omit={['id', 'createTime', 'createBy', 'memo', 'rleStatus$']}
@@ -194,9 +214,10 @@
       <OutOrderModal
         open={createDialog}
         setOpen={setCreateDialog}
-        preview={preview} 
+        preview={preview}
         setPreview={setPreview}
       />
+      <OutStockWaveDialog open={waveRule} setOpen={setWaveRule} onClose={closeDialog} />
       <OutOrderPreview open={preview} setOpen={setPreview} />
       <PageEditDrawer
         title={"toolbar.publicWorking"}
@@ -211,24 +232,16 @@
 export default OutOrderList;
 
 
-const PublicTaskButton = () => {
+const PublicTaskButton = ({ setWaveRule, setSelectIds }) => {
   const record = useRecordContext();
   const { selectedIds, onUnselectItems } = useListContext();
   const notify = useNotify();
-  const refresh = useRefresh();
   const redirect = useRedirect();
 
-  const pubClick = async (event) => {
-    event.stopPropagation();
+  const pubClick = async () => {
     onUnselectItems();
-    const res = await request.post(`/outStock/generate/wave`, { ids: selectedIds });
-    if (res?.data?.code === 200) {
-      notify(res.data.msg);
-      redirect("/wave")
-    } else {
-      notify(res.data.msg);
-    }
-    refresh();
+    setWaveRule(true);
+    setSelectIds(selectedIds)
   }
 
   return (
@@ -236,7 +249,8 @@
       onClick={pubClick}
       label={"toolbar.createWave"}
       startIcon={<PublicIcon />}
-    />);
+    />
+  );
 }
 
 const MyButton = ({ setCreateDialog, setmodalType }) => {
diff --git a/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx b/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
index 60c2172..ce732be 100644
--- a/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
@@ -58,9 +58,11 @@
     '& .column-maktx': {
         width: 200
     },
-    '& .RaBulkActionsToolbar-toolbar': {
-        display: 'none'
-    }
+
+    mt: '60px'
+    // '& .RaBulkActionsToolbar-toolbar': {
+    //     display: 'none'
+    // }
 
 }));
 
@@ -88,19 +90,20 @@
     }, [selectedMatnr])
 
 
-    const handleRowClick = (id, resource, record) => {
-        setRowSelectedIds(prev =>
-            prev.includes(id)
-                ? prev.filter(item => item !== id)  // 鍙栨秷閫夋嫨
-                : [...prev, id]                     // 娣诲姞閫夋嫨
-        );
+    const ComfirmButton = () => {
+        const { selectedIds, data } = useListContext();
+        const handleRowClick = () => {
+            const ids = data.filter(item => selectedIds.includes(item.id)).map(item => item.id);
+            setRowSelectedIds(ids);
+            const mas = data.filter(item => selectedIds.includes(item.id)).map(item => item.matnrCode);
+            //璁剧疆搴撲綅淇℃伅绛涢�夋潯浠�
+            setSelectedMatnr(mas);
+        }
 
-        //璁剧疆搴撲綅淇℃伅绛涢�夋潯浠�
-        setSelectedMatnr(prev =>
-            prev.includes(record?.matnrCode)
-                ? prev.filter(item => item !== record?.matnrCode)  // 鍙栨秷閫夋嫨
-                : [...prev, record?.matnrCode]                     // 娣诲姞閫夋嫨
-        );
+        return (
+            <Button label="toolbar.confirm" size="medium" onClick={handleRowClick} />
+        )
+
     };
 
     const handleClickOpen = () => {
@@ -191,6 +194,7 @@
                                 filter={{ asnId: record?.id, deleted: 0 }}
                                 sort={{ field: "create_time", order: "desc" }}
                                 actions={false}
+                                pagination={false}
                                 perPage={DEFAULT_ITEM_PAGE_SIZE}
                             >
                                 <LinearProgress
@@ -199,9 +203,9 @@
                                 <StyledDatagrid
                                     storeKey={"outStockPublic"}
                                     preferenceKey='outStockItem'
-                                    bulkActionButtons={<></>}
-                                    rowClick={handleRowClick}
-                                    selectedIds={rowSelectedIds}
+                                    bulkActionButtons={<>
+                                        <ComfirmButton />
+                                    </>}
                                     omit={['id', 'splrName', 'qty', 'poCode',]}
                                 >
                                     <NumberField source="id" />
@@ -269,7 +273,8 @@
         { field: 'batch', headerName: '鎵规', width: 90 },
         { field: 'unit', headerName: '鍗曚綅', width: 60 },
         { field: 'outQty', headerName: '鍑哄簱鏁伴噺', width: 110, },
-        { field: 'anfme', headerName: '搴撳瓨鏁伴噺', width: 110,
+        {
+            field: 'anfme', headerName: '搴撳瓨鏁伴噺', width: 110,
             renderCell: (params) => (
                 <OutStockAnfme value={params.value} />
             )
@@ -449,11 +454,10 @@
     }
     return (
         <ConfirmButton
-            label="toolbar.confirm"
+            label="toolbar.allComfirm"
             variant="contained"
             size="medium"
             onConfirm={submit}
-            startIcon={<ConfirmationNumberOutlinedIcon />}
         />
     )
 }
diff --git a/rsf-admin/src/page/orders/wave/WaveEdit.jsx b/rsf-admin/src/page/orders/wave/WaveEdit.jsx
index 899a39f..689027f 100644
--- a/rsf-admin/src/page/orders/wave/WaveEdit.jsx
+++ b/rsf-admin/src/page/orders/wave/WaveEdit.jsx
@@ -55,7 +55,7 @@
                 <SimpleForm
                     shouldUnregister
                     warnWhenUnsavedChanges
-                    toolbar={<FormToolbar />}
+                    toolbar={false}
                     mode="onTouched"
                     defaultValues={{}}
                 // validate={(values) => { }}
@@ -143,3 +143,5 @@
 }
 
 export default WaveEdit;
+
+
diff --git a/rsf-admin/src/page/orders/wave/WaveItemList.jsx b/rsf-admin/src/page/orders/wave/WaveItemList.jsx
index 6dc7a54..5f675d1 100644
--- a/rsf-admin/src/page/orders/wave/WaveItemList.jsx
+++ b/rsf-admin/src/page/orders/wave/WaveItemList.jsx
@@ -46,7 +46,8 @@
 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'
@@ -72,10 +73,7 @@
     <TextInput source="matnrCode" label="table.field.waveItem.matnrCode" />,
     <TextInput source="batch" label="table.field.waveItem.batch" />,
     <TextInput source="splrBatch" label="table.field.waveItem.splrBatch" />,
-    <TextInput source="orderCode" label="table.field.waveItem.orderCode" />,
-    <NumberInput source="orderItemId" label="table.field.waveItem.orderItemId" />,
     <TextInput source="unit" label="table.field.waveItem.unit" />,
-    <TextInput source="trackCode" label="table.field.waveItem.trackCode" />,
     <TextInput source="fieldsIndex" label="table.field.waveItem.fieldsIndex" />,
     <NumberInput source="anfme" label="table.field.waveItem.anfme" />,
     <NumberInput source="workQty" label="table.field.waveItem.workQty" />,
@@ -125,27 +123,29 @@
             >
                 <StyledDatagrid
                     preferenceKey='waveItem'
-                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    bulkActionButtons= {
+                        <>
+                            <BulkStartButton />
+                            <BulkPauseButton />
+                        </>
+                    }
                     rowClick={(id, resource, record) => false}
                     expand={false}
                     expandSingle={false}
-                    omit={['id', 'createTime', 'matnrId', 'waveId', 'batch', 'orderItemId', 'batch', 'fieldsIndex', 'createBy', 'memo']}
+                    omit={['id', 'createTime', 'matnrId', 'waveId', 'batch', 'orderItemId', 'fieldsIndex', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
                     <NumberField source="waveId" label="table.field.waveItem.waveId" />
                     <TextField source="waveCode" label="table.field.waveItem.waveCode" />
                     <NumberField source="matnrId" label="table.field.waveItem.matnrId" />
-                    <TextField source="maktx" label="table.field.waveItem.matnrName" />
                     <TextField source="matnrCode" label="table.field.waveItem.matnrCode" />
+                    <TextField source="maktx" label="table.field.waveItem.matnrName" />
                     <TextField source="batch" label="table.field.waveItem.batch" />
                     <TextField source="splrBatch" label="table.field.waveItem.splrBatch" />
-                    <TextField source="orderCode" label="table.field.waveItem.orderCode" />
-                    <NumberField source="orderItemId" label="table.field.waveItem.orderItemId" />
-                    <TextField source="unit" label="table.field.waveItem.unit" />
-                    <TextField source="trackCode" label="table.field.waveItem.trackCode" />
-                    <TextField source="fieldsIndex" label="table.field.waveItem.fieldsIndex" />
                     <NumberField source="anfme" label="table.field.waveItem.anfme" />
+                    <TextField source="fieldsIndex" label="table.field.waveItem.fieldsIndex" />
                     <NumberField source="workQty" label="table.field.waveItem.workQty" />
+                    <TextField source="unit" label="table.field.waveItem.unit" />
                     <TextField source="updateBy$" label="common.field.updateBy" />
                     <DateField source="updateTime" label="common.field.updateTime" showTime />
                     <TextField source="createBy$" label="common.field.createBy" />
@@ -182,8 +182,30 @@
     }
 
     return (
-        <Button  label="ra.action.edit" onClick={editClick} startIcon={<ContentCreate />}/>
-
+        <Button label="ra.action.edit" onClick={editClick} startIcon={<ContentCreate />} />
     )
 
 }
+
+
+const BulkStartButton = () => {
+    const { data, selectedIds, onUnselectItems } = useListContext();
+
+    const startClick = () => {
+        onUnselectItems()
+    }
+    return (
+        <Button label="toolbar.start" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} variant="outlined" />
+    )
+}
+
+const BulkPauseButton = () => {
+    const { data, selectedIds, onUnselectItems } = useListContext();
+
+    const pauseClick = () => {
+        onUnselectItems()
+    }
+    return (
+        <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseCircleOutlineIcon />} variant="outlined" />
+    )
+}
\ No newline at end of file
diff --git a/rsf-admin/src/page/orders/wave/WaveList.jsx b/rsf-admin/src/page/orders/wave/WaveList.jsx
index eec93fe..a0fb5a4 100644
--- a/rsf-admin/src/page/orders/wave/WaveList.jsx
+++ b/rsf-admin/src/page/orders/wave/WaveList.jsx
@@ -35,21 +35,15 @@
     useRedirect,
     Button,
 } from 'react-admin';
-import { Box, Typography, Card, Stack } from '@mui/material';
-import { styled } from '@mui/material/styles';
-import WaveCreate from "./WaveCreate";
-import WavePanel from "./WavePanel";
-import EmptyData from "../../components/EmptyData";
-import MyCreateButton from "../../components/MyCreateButton";
-import MyExportButton from '../../components/MyExportButton';
-import PageDrawer from "../../components/PageDrawer";
-import MyField from "../../components/MyField";
-import request from '@/utils/request';
 import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
-import * as Common from '@/utils/common';
+import { Box, Typography, Card, Stack } from '@mui/material';
+import ConfirmButton from "../../components/ConfirmButton";
+import PageDrawer from "../../components/PageDrawer";
 import PublicIcon from '@mui/icons-material/Public';
 import ItemToTaskModal from "./ItemToTaskModal";
-import ConfirmButton from "../../components/ConfirmButton";
+import { styled } from '@mui/material/styles';
+import request from '@/utils/request';
+import WaveCreate from "./WaveCreate";
 
 
 const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
@@ -143,6 +137,7 @@
                     <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="orderNum" label="table.field.wave.orderNum" />
                     <TextField source="updateBy$" label="common.field.updateBy" />
@@ -153,8 +148,7 @@
                     <TextField source="memo" label="common.field.memo" sortable={false} />
                     <WrapperField cellClassName="opt" label="common.field.opt">
                         <PublicTaskButton setSelectIds={setSelectIds} setDetailDialog={setDetailDialog} />
-                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
-                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
+                        <EditButton label="toolbar.detail" sx={{ padding: '1px', fontSize: '.75rem' }} />
                     </WrapperField>
                 </StyledDatagrid>
             </List>
@@ -184,12 +178,12 @@
     const notify = useNotify();
     const refresh = useRefresh();
     const redirect = useRedirect();
-    
+
     const pubClick = async (event) => {
         setSelectIds(record);
         setDetailDialog(true);
     }
     return (
-        record?.exceStatus == 0 ? <ConfirmButton label={"toolbar.createTask"} startIcon={<PublicIcon /> } onConfirm={pubClick} size='small' /> : <></>
+        record?.exceStatus == 0 ? <ConfirmButton label={"toolbar.createTask"} startIcon={<PublicIcon />} onConfirm={pubClick} size='small' /> : <></>
     );
 }
\ No newline at end of file
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java
index d2d32ce..ba65995 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java
@@ -294,10 +294,14 @@
         if (Objects.isNull(params.get("outId"))) {
             return R.error("鍑哄簱鍙傛暟涓嶈兘涓虹┖锛侊紒");
         }
-
         List<OutStockToTaskParams> taskParams = JSONArray.parseArray(JSONArray.toJSONString(params.get("items")), OutStockToTaskParams.class);
-
-        return  outStockService.genOutStockTask(taskParams, getLoginUserId(), Long.parseLong(params.get("outId").toString()));
+        List<OutStockToTaskParams> tasks = new ArrayList<>();
+        for (OutStockToTaskParams taskParam : taskParams) {
+            if (StringUtils.isNotBlank(taskParam.getLocCode())) {
+                tasks.add(taskParam);
+            }
+        }
+        return  outStockService.genOutStockTask(tasks, getLoginUserId(), Long.parseLong(params.get("outId").toString()));
     }
 
     /**
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java
index b527b50..7c95b75 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaveController.java
@@ -92,14 +92,12 @@
         if (Objects.isNull(ids)) {
             throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
         }
-        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().in(TaskItem::getSourceId, ids));
-        if (taskItems.isEmpty()) {
+        List<Long> list = Arrays.asList(ids);
+        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().in(TaskItem::getSourceId, list));
+        if (!taskItems.isEmpty()) {
             throw new CoolException("鏈夋湭瀹屾垚浠诲姟锛屼笉鍙墽琛屽垹闄ゆ搷浣滐紒锛�");
         }
-        if (!waveService.removeByIds(Arrays.asList(ids))) {
-            return R.error("Delete Fail");
-        }
-        return R.ok("Delete Success").add(ids);
+        return waveService.cancelWave(list);
     }
 
     @PreAuthorize("hasAuthority('manager:wave:list')")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java
index 31f8d53..cfd4a73 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java
@@ -80,6 +80,9 @@
     @ApiModelProperty(value= "鍗曟嵁鏁伴噺")
     private Integer orderNum;
 
+    @ApiModelProperty("鍝佺被鏁伴噺")
+    private Integer groupQty;
+
     /**
      * 鐘舵�� 1: 姝e父  0: 绂佺敤  
      */
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
index 7739a13..e7bb2da 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
@@ -28,9 +28,11 @@
     OUT_STOCK_STATUS_TASK_EXCE("11", "寰呭鐞�"),
     OUT_STOCK_STATUS_TASK_WAVE("11", "鐢熸垚娉㈡"),
     OUT_STOCK_STATUS_TASK_CREATE("13", "鐢熸垚宸ヤ綔妗�"),
-    OUT_STOCK_STATUS_TASK_WORKING("14", "浣滀笟涓�")
+    OUT_STOCK_STATUS_TASK_WORKING("14", "浣滀笟涓�"),
+    OUT_STOCK_STATUS_TASK_DONE("15", "宸插畬鎴�")
 
-            ;
+
+    ;
     AsnExceStatus(String val, String desc) {
         this.val = Short.parseShort(val);
         this.desc = desc;
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java
index 5692412..be17fde 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java
@@ -7,6 +7,7 @@
 import com.vincent.rsf.server.manager.entity.AsnOrderItemLog;
 import com.vincent.rsf.server.manager.entity.AsnOrderLog;
 import com.vincent.rsf.server.manager.enums.AsnExceStatus;
+import com.vincent.rsf.server.manager.enums.OrderType;
 import com.vincent.rsf.server.manager.service.AsnOrderItemLogService;
 import com.vincent.rsf.server.manager.service.AsnOrderItemService;
 import com.vincent.rsf.server.manager.service.AsnOrderLogService;
@@ -19,7 +20,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -54,10 +54,45 @@
     @Scheduled(cron = "0 0/05 * * * ?  ")
     @Transactional(rollbackFor = Exception.class)
     public void moveOrderToLog() {
-        List<AsnOrder> asnOrders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val));
+        List<AsnOrder> asnOrders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>()
+                        .eq(AsnOrder::getType, OrderType.ORDER_IN.type)
+                .eq(AsnOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val));
         if (asnOrders.isEmpty()) {
             return;
         }
+        moveOrderToLog(asnOrders, OrderType.ORDER_IN.type);
+    }
+
+
+    /**
+    * @author Ryan
+    * @description 鍑哄簱鍗曞畬鎴愬悗锛岀姸鎬佷慨鏀�
+    * @param
+    * @return
+    * @time 2025/6/16 08:35
+    */
+    @Scheduled(cron = "0/30 * * * * ?  ")
+    @Transactional(rollbackFor = Exception.class)
+    public void outStockComplete() {
+        List<AsnOrder> asnOrders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>()
+                        .eq(AsnOrder::getType, OrderType.ORDER_OUT.type)
+                .apply("anfme=work_qty")
+        );
+        if (asnOrders.isEmpty()) {
+            return;
+        }
+        moveOrderToLog(asnOrders, OrderType.ORDER_OUT.type);
+    }
+
+    /**
+     * @param
+     * @param type
+     * @return
+     * @author Ryan
+     * @description 娣诲姞鍘嗗彶鍗曟嵁
+     * @time 2025/6/16 08:56
+     */
+    private void moveOrderToLog(List<AsnOrder> asnOrders, String type) {
         Set<Long> longSet = asnOrders.stream().map(AsnOrder::getId).collect(Collectors.toSet());
         List<AsnOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<AsnOrderItem>().in(AsnOrderItem::getAsnId, longSet));
         if (orderItems.isEmpty()) {
@@ -66,6 +101,10 @@
 
         for (AsnOrder order : asnOrders) {
             AsnOrderLog orderLog = new AsnOrderLog();
+            if (type.equals(OrderType.ORDER_OUT.type)) {
+                order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val);
+                order.setQty(order.getWorkQty());
+            }
             BeanUtils.copyProperties(order, orderLog);
             orderLog.setId(null);
             orderLog.setAsnId(order.getId());
@@ -86,7 +125,7 @@
             });
 
             if (!asnOrderItemLogService.saveBatch(logs)) {
-                throw new CoolException("閫氱煡鍗曟槑缁嗗巻鍙叉。淇濆瓨澶辫触锛侊紒");
+                throw new CoolException("鍗曟嵁鏄庣粏鍘嗗彶妗d繚瀛樺け璐ワ紒锛�");
             }
         }
 
@@ -97,4 +136,6 @@
             throw new CoolException("鍘熷崟鎹垹闄ゅけ璐ワ紒锛�");
         }
     }
+
+
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java
index c9cc4f7..55a559b 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WaveService.java
@@ -28,4 +28,13 @@
      * @time 2025/4/27 11:08
      */
     List<WaveItem> mergeWavePreview(Long waveId);
+
+    /**
+    * @author Ryan
+    * @description 鍙栨秷娉㈡锛屼慨鏀硅鍗曚俊鎭�
+    * @param
+    * @return
+    * @time 2025/6/17 10:03
+    */
+    R cancelWave(List<Long> ids);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
index 849a6fd..46d5648 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -279,13 +279,13 @@
         if (Objects.isNull(ids) || ids.isEmpty()) {
             throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
         }
-        List<AsnOrder> orders = this.list(new LambdaQueryWrapper<AsnOrder>()
-                .in(AsnOrder::getId, ids)
-                .eq(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val));
+        List<AsnOrder> orders = this.list(new LambdaQueryWrapper<AsnOrder>().in(AsnOrder::getId, ids));
         if (orders.isEmpty()) {
             throw new CoolException("褰撳墠鍗曟嵁鐘舵�佷笉鑳芥墽琛屾尝娆$敓鎴愭搷浣滐紒锛�");
         }
-        double sum = orders.stream().mapToDouble(AsnOrder::getAnfme).sum();
+        Double sum = orders.stream().mapToDouble(AsnOrder::getAnfme).sum();
+        Double workQty = orders.stream().mapToDouble(AsnOrder::getWorkQty).sum();
+        Double anfme = Math.round((sum - workQty) * 10000) / 10000.0;
         Wave wave = new Wave();
         String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_WAVE_TYPE, null);
         if (Objects.isNull(ruleCode) || StringUtils.isBlank(ruleCode)) {
@@ -295,7 +295,7 @@
                 .setType(Short.parseShort("1"))
                 .setCode(ruleCode)
                 .setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_INIT.val)
-                .setAnfme(sum);
+                .setAnfme(anfme);
         if (!waveService.save(wave)) {
             throw new CoolException("娉㈡淇濆瓨澶辫触锛侊紒");
         }
@@ -306,13 +306,13 @@
         if (orderItems.isEmpty()) {
             throw new CoolException("鍗曟嵁涓嶅瓨鍦紒锛�");
         }
-
+        //鍚堝苟鐗╂枡锛岀敓鎴愭尝娆℃槑缁�
         List<WaveItem> waveItems = mergeWave(orderItems, wave);
         if (!waveItemService.saveBatch(waveItems)) {
             throw new CoolException("娉㈡鏄庣粏淇濆瓨澶辫触锛侊紒");
         }
         double sum1 = waveItems.stream().mapToDouble(WaveItem::getAnfme).sum();
-        wave.setAnfme(sum1);
+        wave.setAnfme(sum1).setGroupQty(waveItems.size());
         if (!waveService.saveOrUpdate(wave)) {
             throw new CoolException("涓诲崟淇敼澶辫触锛侊紒");
         }
@@ -325,14 +325,17 @@
             throw new CoolException("鍑哄簱鍗曟墽琛屾暟閲忎慨鏀瑰け璐ワ紒锛�");
         }
 
-        double sum2 = orderItems.stream().mapToDouble(AsnOrderItem::getWorkQty).sum();
-        if (!this.update(new LambdaUpdateWrapper<AsnOrder>()
-                .set(AsnOrder::getWaveId, wave.getId())
-                .set(AsnOrder::getWorkQty, sum2)
-                .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val)
-                .in(AsnOrder::getId, ids))) {
-            throw new CoolException("鎵ц鐘舵�佷慨鏀逛慨鏀瑰け璐ワ紒锛�");
+        for (AsnOrder order : orders) {
+            Double wkQty = Math.round((order.getWorkQty() + order.getAnfme()) * 10000) / 10000.0;
+            if (!this.update(new LambdaUpdateWrapper<AsnOrder>()
+                    .set(AsnOrder::getWaveId, wave.getId())
+                    .set(AsnOrder::getWorkQty, wkQty)
+                    .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val)
+                    .in(AsnOrder::getId, ids))) {
+                throw new CoolException("鎵ц鐘舵�佷慨鏀逛慨鏀瑰け璐ワ紒锛�");
+            }
         }
+
         return R.ok("鎿嶄綔瀹屾垚锛侊紒");
     }
 
@@ -442,12 +445,14 @@
             throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
         }
         //浼樺厛鐢熸垚娴呭簱浣嶄换鍔�
-        List<OutStockToTaskParams> Items = params.stream().sorted(Comparator.comparing(OutStockToTaskParams::getLocCode).thenComparing(item -> {
+        List<OutStockToTaskParams> Items = params.stream()
+                .sorted(Comparator.comparing(OutStockToTaskParams::getLocCode)
+                        .thenComparing(item -> {
             return LocUtils.isShallowLoc(item.getLocCode()) ? 1 : 0;
         }).reversed()).collect(Collectors.toList());
 
         for (OutStockToTaskParams param : Items) {
-            if (Objects.isNull(param)) {
+            if (Objects.isNull(param) || StringUtils.isBlank(param.getLocCode())) {
                 continue;
             }
             Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, param.getLocCode()).eq(Loc::getBarcode, param.getBarcode()));
@@ -697,12 +702,11 @@
     private List<WaveItem> mergeWave(List<AsnOrderItem> orderItems, Wave wave) {
         List<WaveItem> items = new ArrayList<>();
         orderItems.forEach(order -> {
+            Double anfme = Math.round((order.getAnfme() - order.getWorkQty()) * 10000) / 10000.0;
             WaveItem item = new WaveItem();
             BeanUtils.copyProperties(order, item);
-            item.setOrderItemId(order.getId())
-                    .setId(null)
-                    .setOrderCode(order.getAsnCode())
-                    .setOrderId(order.getAsnId())
+                item.setId(null)
+                    .setAnfme(anfme)
                     .setMatnrId(order.getMatnrId())
                     .setMaktx(order.getMaktx())
                     .setWaveId(wave.getId())
@@ -735,7 +739,7 @@
                         p1.getUpdateBy(),
                         p1.getMemo()
                 ),
-                WaveItem::getSplrBatch, WaveItem::getMatnrCode, WaveItem::getFieldsIndex
+                WaveItem::getSplrBatch, WaveItem::getMatnrId, WaveItem::getFieldsIndex
         );
 
         return waveItems;
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
index 816bc4d..3430a52 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -1047,7 +1047,6 @@
                     if (Objects.isNull(orderItem)) {
                         throw new CoolException("鍗曟嵁鏄庣粏涓嶅瓨鍦紒锛�");
                     }
-
                     try {
                         saveOutStockItem(maps.get(key), orderItem, null, loginUserId);
                     } catch (Exception e) {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java
index 8e0e9d8..97f2276 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java
@@ -43,6 +43,8 @@
     private LocItemService locItemService;
     @Autowired
     private LocService locService;
+    @Autowired
+    private OutStockService outStockService;
 
     /**
      * @param
@@ -239,6 +241,20 @@
     }
 
     /**
+    * @author Ryan
+    * @description 鍙栨秷娉㈡
+    * @param
+    * @return
+    * @time 2025/6/17 10:04
+    */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R cancelWave(List<Long> ids) {
+        
+        return null;
+    }
+
+    /**
      * @param
      * @param waveItems
      * @return

--
Gitblit v1.9.1