From d40c85778470a7e8341f0fae023c41dec981f384 Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 13 五月 2025 20:41:25 +0800
Subject: [PATCH] 新增PO单生成收货单功能

---
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderController.java        |   16 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Purchase.java                      |    3 
 rsf-admin/src/page/orders/purchase/PurchaseList.jsx                                               |    4 
 rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx                                               |   64 ++-
 rsf-server/src/main/java/com/vincent/rsf/server/common/config/SysStockProperties.java             |    2 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java              |    1 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java               |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/PurchaseService.java              |    5 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/PurchaseController.java        |   13 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java                  |    8 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java     |  105 +++++
 rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx                                         |  213 +++++++++++++
 rsf-admin/src/page/orders/asnOrder/POItemModal.jsx                                                |  405 +++++++++++++++++++++++++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/POExceStatus.java                   |   19 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseServiceImpl.java     |    8 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseItemServiceImpl.java |   12 
 rsf-admin/src/i18n/zh.js                                                                          |    3 
 rsf-admin/src/i18n/en.js                                                                          |    1 
 rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx                                              |   14 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/PurchaseTemplate.java        |    5 
 rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java             |    1 
 rsf-server/src/main/resources/application-dev.yml                                                 |    2 
 22 files changed, 852 insertions(+), 58 deletions(-)

diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 56e1ae1..ba2d163 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -1046,6 +1046,7 @@
         complete: "complete",
         close: "close",
         asnCreate: "Create By Order",
+        poCreate: "Create By PO",
         createTask: "createTask",
         recover: "recover",
         createWave: "Create Wave",
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 1e4d55c..7991ead 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -596,7 +596,7 @@
                 spec: "瑙勬牸",
                 model: "鍨嬪彿",
                 matnrCode: "鐗╂枡缂栫爜",
-                anfme: "璁″垝鏁�",
+                anfme: "璁″垝鏁伴噺",
                 stockUnit: "鍗曚綅",
                 isptResult: "璐ㄦ缁撴灉",
                 purQty: "閲囪喘閲�",
@@ -1079,6 +1079,7 @@
         complete: "瀹岀粨",
         close: "鍏抽棴",
         asnCreate: "閫氳繃鍗曟嵁鍒涘缓",
+        poCreate: "閫氳繃PO鍗曞垱寤�",
         orderPrint: '鎵撳嵃鍗曟嵁',
         createTask: "涓嬪彂浠诲姟",
         createWave: "鐢熸垚娉㈡",
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx b/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx
new file mode 100644
index 0000000..5b99a52
--- /dev/null
+++ b/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx
@@ -0,0 +1,213 @@
+import { Dialog, DialogActions, DialogContent, DialogTitle, Box } from "@mui/material";
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    List,
+    DatagridConfigurable,
+    SearchInput,
+    TopToolbar,
+    Button,
+    SelectColumnsButton,
+    EditButton,
+    FilterButton,
+    CreateButton,
+    ExportButton,
+    BulkDeleteButton,
+    WrapperField,
+    Toolbar,
+    useRecordContext,
+    useTranslate,
+    useNotify,
+    useListContext,
+    FunctionField,
+    TextField,
+    NumberField,
+    DateField,
+    BooleanField,
+    ReferenceField,
+    TextInput,
+    DateTimeInput,
+    DateInput,
+    SelectInput,
+    NumberInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    DeleteButton,
+    Form,
+    SaveButton,
+    useRefresh,
+    useGetList,
+} from 'react-admin';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import { styled } from '@mui/material/styles';
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import { Grid, Stack, width } from "@mui/system";
+import request from '@/utils/request';
+import SaveIcon from '@mui/icons-material/Save';
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import POItemModal from "./POItemModal";
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+    '& .css-1vooibu-MuiSvgIcon-root': {
+        height: '.9em'
+    },
+    '& .RaDatagrid-row': {
+        cursor: 'auto'
+    },
+    '& .status': {
+        width: 90
+    },
+}));
+
+const AsnCreateByPoModal = (props) => {
+    const { open, setOpen, record } = props;
+    const translate = useTranslate();
+    const [params, setParams] = useState({});
+    const [item, setItem] = useState({});
+    const [poItemDialog, setPoItemDialog] = useState(false);
+    const [drawerVal, setDrawerVal] = useState(false);
+    const refresh = useRefresh();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+        }
+    };
+    // const CustomFilter = () => {
+    //     const { filterValues, setFilters, refetch } = useListContext('deliveryItem');
+    //     const [formValues, setFormValues] = useState(filterValues);
+    //     const handleChange = (event) => {
+    //         if (event.target == undefined || event.target == null) { return }
+    //         setFormValues(formValues => ({
+    //             ...formValues,
+    //             [event.target.name]: event.target.value
+    //         }));
+    //     };
+
+    //     const handleSubmit = (event) => {
+    //         setParams(formValues)
+    //     };
+
+    //     return (
+    //         <Box sx={{ width: '100%', margin: 1, marginBottom: 8, "& .MuiDialogActions-root": { padding: 0 } }}>
+    //             <Form>
+    //                 <Grid container rowSpacing={2} columnSpacing={2} sx={{ padding: 2 }}>
+    //                     <Stack>
+    //                         <TextInput
+    //                             source="condition"
+    //                             label="common.action.search"
+    //                             resettable
+    //                             defaultValue={params?.condition}
+    //                             onChange={handleChange} />
+    //                     </Stack>
+    //                 </Grid>
+    //                 <DialogActions>
+    //                     <Toolbar sx={{ width: '100%', justifyContent: 'end' }}  >
+    //                         <SaveButton onClick={handleSubmit} label={"toolbar.query"} />
+    //                     </Toolbar>
+    //                 </DialogActions>
+    //             </Form>
+    //         </Box>
+    //     );
+    // };
+    return (
+        <Box>
+            <Dialog
+                open={open}
+                onClose={handleClose}
+                aria-labelledby="form-dialog-title"
+                aria-hidden
+                fullWidth
+                disableRestoreFocus
+                maxWidth="lg"
+            >
+                <DialogTitle id="form-dialog-title" sx={{
+                    position: 'sticky',
+                    top: 0,
+                    backgroundColor: 'background.paper',
+                    zIndex: 1000
+                }}>
+                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                        <DialogCloseButton onClose={handleClose} />
+                    </Box>
+                </DialogTitle>
+                <Grid container rowSpacing={2} columnSpacing={2}>
+                    <DialogContent>
+                        <Grid item sx={24}>
+                            <List
+                                storeKey="selectPurchase"
+                                resource="purchase/filters"
+                                sx={{
+                                    flexGrow: 1,
+                                    marginTop: 8,
+                                    height: 500,
+                                    transition: (theme) =>
+                                        theme.transitions.create(['all'], {
+                                            duration: theme.transitions.duration.enteringScreen,
+                                        }),
+                                    marginRight: 0,
+                                }}
+                                // filters={<CustomFilter />}
+                                queryOptions={{ meta: { ...params } }}
+                                empty={false}
+                                sort={{ field: "create_time", order: "desc" }}
+                                actions={false}
+                                perPage={DEFAULT_PAGE_SIZE}
+                            >
+                                <StyledDatagrid
+                                    preferenceKey='selectPurchase'
+                                    bulkActionButtons={
+                                        <>
+                                            <ConfirmSelectButton
+                                                setOpen={setOpen}
+                                                setPoItemDialog={setPoItemDialog}
+                                                setItem={setItem}
+                                                mutationMode="pessimistic" />
+                                        </>
+                                    }
+                                    rowClick={false}
+                                    expand={false}
+                                    expandSingle={true}
+                                    omit={['id', 'createTime', 'createBy', 'channel', 'platCode', 'memo', 'channel', 'startTime', 'workQty', 'endTime']}
+                                >
+                                    <NumberField source="id" />
+                                    <TextField source="code" label="table.field.purchase.code" />
+                                    <TextField source="type$" label="table.field.purchase.type" />
+                                    <TextField source="wkType$" label="table.field.purchase.wkType" />
+                                    <TextField source="source" label="table.field.purchase.source" />
+                                    <NumberField source="anfme" label="table.field.purchase.anfme" />
+                                    <NumberField source="qty" label="table.field.purchase.qty" />
+                                    <TextField source="channel" label="table.field.purchase.channel" />
+                                    <TextField source="platCode" label="table.field.purchase.platCode" />
+                                    <DateField source="preArr" label="table.field.purchase.preArr" showTime />
+                                    <DateField source="startTime" label="table.field.purchase.startTime" showTime />
+                                    <DateField source="endTime" label="table.field.purchase.endTime" showTime />
+                                    <TextField source="project" label="table.field.purchase.project" />
+                                    <TextField source="memo" label="common.field.memo" sortable={false} />
+                                </StyledDatagrid>
+                            </List>
+                        </Grid>
+                    </DialogContent>
+                </Grid>
+            </Dialog >
+            <POItemModal open={poItemDialog} setOpen={setPoItemDialog} record={item} />
+        </Box>
+    )
+}
+
+export default AsnCreateByPoModal;
+
+
+const ConfirmSelectButton = ({ setOpen, setPoItemDialog, setItem }) => {
+    const { selectedIds, onUnselectItems } = useListContext();
+    const confirmSelect = async (event) => {
+        setItem(selectedIds[0])
+        onUnselectItems();
+        setPoItemDialog(true)
+        setOpen(false);
+    }
+
+    return (
+        <Button label={"toolbar.confirm"} variant="contained" color="primary" size="medium" startIcon={<SaveIcon />} onClick={confirmSelect} />
+    )
+}
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
index 063790b..4a6bec8 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
@@ -58,7 +58,8 @@
 import ImportButton from "../../components/ImportButton";
 import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined';
 import OrderPrintPreview from "./OrderPrintPreview";
-
+import CreateNewFolderOutlinedIcon from '@mui/icons-material/CreateNewFolderOutlined';
+import AsnCreateByPoModal from "./AsnCreateByPoModal";
 const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
   '& .css-1vooibu-MuiSvgIcon-root': {
     height: '.9em'
@@ -114,6 +115,7 @@
   const [createDialog, setCreateDialog] = useState(false);
   const [drawerVal, setDrawerVal] = useState(false);
   const [modalType, setmodalType] = useState(0);
+  const [poCreate, setPoCreate] = useState(false);
   const [printOrder, setPrintOrder] = useState(false);
   const [select, setSelect] = useState({});
   const invoiceRef = useRef();
@@ -141,6 +143,7 @@
           <TopToolbar>
             <FilterButton />
             <MyCreateButton onClick={() => { setCreateDialog(true); setmodalType(0) }} />
+            <CreateByPoButton setPoCreate={setPoCreate}/>
             <SelectColumnsButton preferenceKey='asnOrder' />
             <ImportButton value={'asnOrderItem'} />
             <MyExportButton />
@@ -186,8 +189,8 @@
             <MyButton setCreateDialog={setCreateDialog} setmodalType={setmodalType} />
             <InspectionButton />
             <CompleteButton />
-            <ODeleteButton  />
-            <PrintButton setPrintOrder={setPrintOrder} setSelect={setSelect}/>
+            <ODeleteButton />
+            <PrintButton setPrintOrder={setPrintOrder} setSelect={setSelect} />
             {/* <CloseButton /> */}
           </WrapperField>
         </StyledDatagrid>
@@ -198,10 +201,14 @@
         asnId={modalType}
         billReload={billReload}
       />
-      <OrderPrintPreview 
+      <OrderPrintPreview
         open={printOrder}
         setOpen={setPrintOrder}
         record={select}
+      />
+      <AsnCreateByPoModal
+        open={poCreate}
+        setOpen={setPoCreate}
       />
       <PageDrawer
         title='AsnOrder Detail'
@@ -214,9 +221,24 @@
 }
 export default AsnOrderList;
 
+//鎸塒O鍗曟柊寤�
+const CreateByPoButton = ({setPoCreate}) => {
+  const record = useRecordContext();
+
+  const createEvent = (event) => {
+    event.stopPropagation();
+    setPoCreate(true)
+  }
+  return (
+    <Button label={"toolbar.poCreate"} onClick={createEvent}>
+      <CreateNewFolderOutlinedIcon />
+    </Button>
+  )
+}
+
 
 //鎵撳嵃鎸夐挳
-const PrintButton = ({setPrintOrder, setSelect}) => {
+const PrintButton = ({ setPrintOrder, setSelect }) => {
   const record = useRecordContext();
   const printOrder = (event) => {
     event.stopPropagation();
@@ -225,9 +247,9 @@
   }
 
   return (
-      <Button label={"toolbar.print"} onClick={printOrder}>
-          <PrintOutlinedIcon />
-      </Button>
+    <Button label={"toolbar.print"} onClick={printOrder}>
+      <PrintOutlinedIcon />
+    </Button>
   )
 }
 
@@ -235,7 +257,7 @@
 const ODeleteButton = () => {
   const record = useRecordContext();
   return (
-    record.exceStatus === 0 ? <DeleteButton  mutationMode="pessimistic"/> : <></>
+    record.exceStatus === 0 ? <DeleteButton mutationMode="pessimistic" /> : <></>
   )
 
 }
@@ -251,15 +273,15 @@
   };
   return (
     record.exceStatus === 1 || record.exceStatus === 0 ?
-    <Button
-      color="primary"
-      startIcon={<EditIcon />}
-      onClick={(btn) => handleEditClick(btn)}
-      sx={{ ml: 1 }}
-      label={'ra.action.edit'}
-    >
-    </Button>
-    : <></>
+      <Button
+        color="primary"
+        startIcon={<EditIcon />}
+        onClick={(btn) => handleEditClick(btn)}
+        sx={{ ml: 1 }}
+        label={'ra.action.edit'}
+      >
+      </Button>
+      : <></>
   )
 }
 
@@ -284,7 +306,7 @@
   }
 
   return (
-      <ConfirmButton label={"toolbar.inspection"} color="secondary" startIcon={<ConstructionIcon />} onConfirm={inspection} />
+    <ConfirmButton label={"toolbar.inspection"} color="secondary" startIcon={<ConstructionIcon />} onConfirm={inspection} />
   )
 }
 
@@ -388,7 +410,7 @@
     // record.exceStatus === 1 && (record.anfme === record.qty ? <Button onClick={requestComplete} label={"toolbar.complete"} color="secondary">
     //   <TaskIcon />
     // </Button> : )
-    record.exceStatus === 1 ? <ConfirmButton label={"toolbar.complete"} color="secondary"  startIcon={<TaskIcon />} onConfirm={requestComplete} /> : <></>
+    record.exceStatus === 1 ? <ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskIcon />} onConfirm={requestComplete} /> : <></>
   )
 
 
@@ -410,6 +432,6 @@
   }
 
   return (
-    <ConfirmButton label={"toolbar.close"} color="error"  startIcon={<CloseIcon />} onConfirm={requestClose} />
+    <ConfirmButton label={"toolbar.close"} color="error" startIcon={<CloseIcon />} onConfirm={requestClose} />
   )
 }
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
index 6899c39..d046fdd 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
@@ -590,13 +590,13 @@
         //     flex: 1,
         //     editable: true,
         // },
-        {
-            field: 'purUnit',
-            headerName: translate('table.field.asnOrderItem.purUnit'),
-            minWidth: 100,
-            flex: 1,
-            editable: false,
-        },
+        // {
+        //     field: 'purUnit',
+        //     headerName: translate('table.field.asnOrderItem.purUnit'),
+        //     minWidth: 100,
+        //     flex: 1,
+        //     editable: false,
+        // },
     ])
 
     const action = {
diff --git a/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx b/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx
new file mode 100644
index 0000000..0e9ccc3
--- /dev/null
+++ b/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx
@@ -0,0 +1,405 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+    useListContext,
+    useRefresh,
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Stack,
+    Grid,
+    TextField,
+    Box,
+    Button,
+    Paper,
+    TableContainer,
+    Table,
+    TableHead,
+    TableBody,
+    TableRow,
+    TableCell,
+    Tooltip,
+    IconButton,
+    styled,
+    Select,
+    MenuItem
+
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import AsnWareModal from "./AsnWareModal";
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import _, { set } from 'lodash';
+import { DataGrid, useGridApiRef, GRID_DATE_COL_DEF, GRID_DATETIME_COL_DEF, getGridDateOperators, useGridApiContext } from '@mui/x-data-grid';
+import { LocalizationProvider, DatePicker, DateTimePicker } from '@mui/x-date-pickers';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import DictionarySelect from "../../components/DictionarySelect";
+import DictSelect from "../../components/DictSelect";
+import "./asnOrder.css";
+import { 'zhCN' as locale } from 'date-fns/locale';
+import { format, } from 'date-fns';
+import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
+
+const POItemModal = (props) => {
+    const { open, setOpen, billReload, record } = props;
+    const translate = useTranslate();
+    const notify = useNotify();
+    const refresh = useRefresh();
+    const [disabled, setDisabled] = useState(false)
+    const [createDialog, setCreateDialog] = useState(false);
+    const tableRef = useRef();
+
+    useEffect(() => {
+        if (open && record !== 0) {
+            requestGetBody()
+        }
+        setDisabled(false)
+    }, [open])
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+            refresh();
+            setTableData([])
+        }
+    };
+
+
+    const [tabelData, setTableData] = useState([]);
+
+    const resetData = () => {
+        setTableData([])
+    }
+
+    const setFinally = () => {
+        const rows = tableRef.current.state.editRows;
+        for (const key in rows) {
+            const find = tabelData.find(item => item.id === +key);
+            find.anfme = rows[key].anfme.value;
+        }
+        setTableData([...tabelData]);
+    }
+
+    const handleSubmit = async () => {
+        setFinally()
+        setDisabled(true)
+        setOpen(false)
+        const parmas = {
+            "purchaseId": record,
+            "items": tabelData,
+        }
+        console.log('--------->');
+        console.log(parmas);
+        // const res = await request.post(`/asnOrder/purchases/save`, parmas);
+        // if (res?.data?.code === 200) {
+        //     setOpen(false);
+        //     refresh();
+        //     resetData()
+        // } else {
+        //     notify(res.data.msg);
+        // }
+        setDisabled(false)
+    };
+
+    const requestGetBody = async () => {
+        const res = await request.post(`/purchaseItem/page`, { purchaseId: record });
+        if (res?.data?.code === 200) {
+            setTableData(res.data.data.records)
+        } else {
+            notify(res.data.msg);
+        }
+    }
+
+    const [selectedRows, setSelectedRows] = useState([]);
+
+    return (
+        <>
+            <Dialog
+                open={open}
+                onClose={handleClose}
+                aria-labelledby="form-dialog-title"
+                aria-hidden
+                fullWidth
+                disableRestoreFocus
+                maxWidth="xl"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+            >
+                <DialogTitle id="form-dialog-title" sx={{
+                    position: 'sticky',
+                    top: 0,
+                    backgroundColor: 'background.paper',
+                    zIndex: 1000
+                }}>
+                    {translate('create.title')}
+                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                        <DialogCloseButton onClose={handleClose} />
+                    </Box>
+                </DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    <Box sx={{ mt: 2 }}>
+                        <AsnOrderModalTable tabelData={tabelData}
+                            setTableData={setTableData}
+                            record={record}
+                            selectedRows={selectedRows}
+                            setSelectedRows={setSelectedRows}
+                            tableRef={tableRef} />
+                    </Box>
+                </DialogContent>
+                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                    <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
+                        <Button disabled={disabled} onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
+                            {translate('toolbar.confirm')}
+                        </Button>
+                    </Toolbar>
+                </DialogActions>
+            </Dialog>
+        </>
+    )
+}
+
+export default POItemModal;
+
+const SelectInputSplrNameEditCell = (params) => {
+    const [formData, setFormData] = useState([{}])
+    useEffect(() => {
+        getOptions();
+    }, []);
+    const getOptions = async () => {
+        const parmas = {
+            "type": "supplier"
+        }
+        const {
+            data: { code, data, msg },
+        } = await request.post("companys/page", parmas);
+        if (code === 200) {
+            setFormData(data.records)
+        } else {
+            notify(msg);
+        }
+    }
+
+    return (
+        <Select
+            value={params.value}
+            onChange={(e) => {
+                params.api.setEditCellValue({
+                    id: params.id,
+                    field: params.field,
+                    value: e.target.value,
+                })
+                // 鎵惧埌閫変腑鐨勪緵搴斿晢璁板綍
+                const selectedSupplier = formData.find(supplier => supplier.name === e.target.value);
+
+                // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁
+                if (selectedSupplier) {
+                    params.api.setEditCellValue({
+                        id: params.id,
+                        field: 'splrCode',
+                        value: selectedSupplier.id,
+                    });
+                }
+            }
+
+            }
+            fullWidth
+
+        >
+            {formData.map(e => {
+                return (
+                    <MenuItem value={e.name} children={e.name} key={e.id} />
+                );
+
+            })}
+
+        </Select>
+    );
+};
+
+const AsnOrderModalTable = ({ tabelData, setTableData, record, selectedRows, setSelectedRows, tableRef }) => {
+    const translate = useTranslate();
+    const notify = useNotify();
+
+    const [columns, setColumns] = useState([
+        {
+            field: 'matnrCode',
+            headerName: translate('table.field.asnOrderItem.matnrCode'),
+            width: 130,
+            editable: false,
+        },
+        {
+            field: 'matnrName',
+            headerName: translate('table.field.asnOrderItem.maktx'),
+            width: 250,
+            editable: false,
+        },
+        {
+            field: 'splrName',
+            headerName: translate('table.field.asnOrderItem.splrName') + "*",
+            minWidth: 150,
+            flex: 1,
+            editable: true,
+            renderEditCell: (params) => (
+                <SelectInputSplrNameEditCell {...params} />
+            ),
+            headerClassName: "custom",
+        },
+        {
+            field: 'platItemId',
+            headerName: translate('table.field.asnOrderItem.platItemId') + "*",
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+            headerClassName: "custom",
+        },
+        {
+            field: 'anfme',
+            headerName: translate('table.field.asnOrderItem.anfme') + "*",
+            type: 'number',
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+            valueFormatter: (val) => val < 0 ? 0 : val,
+            headerClassName: "custom",
+        },
+        {
+            field: 'unit',
+            headerName: translate('table.field.asnOrderItem.stockUnit'),
+            minWidth: 100,
+            flex: 1,
+            editable: false,
+        },
+    ])
+
+    const action = {
+        field: 'action',
+        headerName: '鎿嶄綔',
+        width: 70,
+        lockPosition: 'left',
+        renderCell: (params) => (
+            <Tooltip title="Delete">
+                <IconButton onClick={() => handleDelete(params.row)}>
+                    <Delete />
+                </IconButton>
+            </Tooltip>
+        ),
+    }
+
+    let cdata = useRef([]);
+
+
+    useEffect(() => {
+        getDynamicFields();
+    }, []);
+
+    useEffect(() => {
+        cdata.current = tabelData
+    }, [tabelData]);
+
+
+    const getDynamicFields = async () => {
+        const {
+            data: { code, data, msg },
+        } = await request.get("/fields/enable/list");
+        if (code === 200) {
+            const cols = data.map(el => ({
+                field: el.fields,
+                valueGetter: (value, row) => {
+                    if (value != null && value != undefined) {
+                        return value;
+                    }
+                    if (row.extendFields == null || row.extendFields[el.fields] == null) {
+                        return ''
+                    } else {
+                        return `${row.extendFields[el.fields] == null ? '' : row.extendFields[el.fields]}`;
+                    }
+                },
+                headerName: el.fieldsAlise,
+                minWidth: 100,
+                flex: 1,
+                editable: true
+            }))
+            setColumns([...columns, ...cols, action])
+        } else {
+            notify(msg);
+        }
+    }
+
+    const handleDelete = (row) => {
+        const newData = _.filter(cdata.current, (item) => item.id !== row.id);
+        setTableData(newData);
+    };
+
+
+    const processRowUpdate = (newRow, oldRow) => {
+        const rows = tabelData.map((r) =>
+            r.id === newRow.id ? { ...newRow } : r
+        )
+        setTableData(rows)
+
+        return newRow;
+    };
+
+
+    const handleSelectionChange = (ids) => {
+        setSelectedRows(ids)
+    };
+
+    tableRef.current = useGridApiRef();
+
+
+    return (
+        <div style={{ height: 400, width: '100%' }}>
+            <DataGrid
+                apiRef={tableRef}
+                rows={tabelData}
+                columns={columns}
+                disableRowSelectionOnClick
+                getRowId={(row) => row.id}
+                disableColumnFilter
+                disableColumnSelector
+                disableColumnSorting
+                disableMultipleColumnsSorting
+                processRowUpdate={processRowUpdate}
+                initialState={{
+                    pagination: {
+                        paginationModel: {
+                            pageSize: 25,
+                        },
+                    },
+                }}
+                pageSizeOptions={[10, 25, 50, 100]}
+                editMode="row"
+                checkboxSelection
+                onRowSelectionModelChange={handleSelectionChange}
+                selectionModel={selectedRows}
+                sx={{
+                    '& .MuiDataGrid-cell input': {
+                        border: '1px solid #ccc'
+                    },
+                }}
+            />
+        </div>
+    );
+};
+
diff --git a/rsf-admin/src/page/orders/purchase/PurchaseList.jsx b/rsf-admin/src/page/orders/purchase/PurchaseList.jsx
index 2a505de..fdfcc50 100644
--- a/rsf-admin/src/page/orders/purchase/PurchaseList.jsx
+++ b/rsf-admin/src/page/orders/purchase/PurchaseList.jsx
@@ -126,19 +126,19 @@
           rowClick={'edit'}
           expand={false}
           expandSingle={true}
-          omit={['id', 'createTime', 'createBy','channel', 'platCode', 'memo', 'preArr', 'channel','startTime','workQty', 'endTime']}
+          omit={['id', 'createTime', 'createBy','channel', 'platCode', 'memo', 'channel','startTime','workQty', 'endTime']}
         >
           <NumberField source="id" />
           <TextField source="code" label="table.field.purchase.code" />
           <TextField source="type$" label="table.field.purchase.type" />
           <TextField source="wkType$" label="table.field.purchase.wkType" />
           <TextField source="source" label="table.field.purchase.source" />
-          <DateField source="preArr" label="table.field.purchase.preArr" showTime />
           <NumberField source="anfme" label="table.field.purchase.anfme" />
           <NumberField source="qty" label="table.field.purchase.qty" />
           {/* <NumberField source="workQty" label="table.field.purchase.workQty" /> */}
           <TextField source="channel" label="table.field.purchase.channel" />
           <TextField source="platCode" label="table.field.purchase.platCode" />
+          <DateField source="preArr" label="table.field.purchase.preArr" showTime />
           <DateField source="startTime" label="table.field.purchase.startTime" showTime />
           <DateField source="endTime" label="table.field.purchase.endTime" showTime />
           <TextField source="project" label="table.field.purchase.project" />
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/config/SysStockProperties.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/config/SysStockProperties.java
index 306fc3c..90bd960 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/config/SysStockProperties.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/config/SysStockProperties.java
@@ -15,8 +15,6 @@
 @Configuration
 @ConfigurationProperties(prefix = "stock")
 public class SysStockProperties {
-
-
     /**
      * wms鏄惁鍏佽鎵撳嵃璐х墿鏍囩, 榛樿鍙墦鍗�
      */
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderController.java
index d3c112c..9e5bcfc 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderController.java
@@ -221,6 +221,22 @@
         return asnOrderService.saveOrderAndItems(params, getLoginUserId());
     }
 
+    @PostMapping("/asnOrder/purchases/save")
+    @ApiOperation("鏍规嵁PO鍗曟柊寤烘敹璐у崟")
+    @PreAuthorize("hasAuthority('manager:asnOrder:save')")
+    public R orderCreateByPo(@RequestBody Map<String, Object> params) {
+        if (Objects.isNull(params.get("ids"))) {
+            return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+        }
+        String json = params.get("ids").toString();
+        List<Long> ids = JSONArray.parseArray(params.get("ids").toString(), Long.class);
+        if (ids.isEmpty()) {
+            return R.error("鍙傛暟涓嶈兘涓虹┖");
+        }
+        return asnOrderService.createByPo(ids);
+    }
+
+
     @ApiOperation("鍗曟嵁淇℃伅淇敼")
     @PostMapping("/asnOrder/items/update")
     @PreAuthorize("hasAuthority('manager:asnOrder:update')")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/PurchaseController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/PurchaseController.java
index a47d715..af7930d 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/PurchaseController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/PurchaseController.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.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.vincent.rsf.framework.common.Cools;
 import com.vincent.rsf.framework.common.R;
@@ -12,6 +13,7 @@
 import com.vincent.rsf.server.manager.entity.AsnOrderItem;
 import com.vincent.rsf.server.manager.entity.Purchase;
 import com.vincent.rsf.server.manager.entity.PurchaseItem;
+import com.vincent.rsf.server.manager.enums.POExceStatus;
 import com.vincent.rsf.server.manager.service.AsnOrderItemService;
 import com.vincent.rsf.server.manager.service.PurchaseItemService;
 import com.vincent.rsf.server.manager.service.PurchaseService;
@@ -48,6 +50,17 @@
     }
 
     @PreAuthorize("hasAuthority('manager:purchase:list')")
+    @PostMapping("/purchase/filters/page")
+    public R filterPage(@RequestBody Map<String, Object> map) {
+        BaseParam baseParam = buildParam(map, BaseParam.class);
+        PageParam<Purchase, BaseParam> pageParam = new PageParam<>(baseParam, Purchase.class);
+        QueryWrapper<Purchase> wrapper = pageParam.buildWrapper(true);
+        wrapper.ne("exce_status", POExceStatus.PO_EXCE_STATUS_ALL_DONE.val);
+        return R.ok().add(purchaseService.page(pageParam, wrapper));
+    }
+
+
+    @PreAuthorize("hasAuthority('manager:purchase:list')")
     @PostMapping("/purchase/list")
     public R list(@RequestBody Map<String, Object> map) {
         return R.ok().add(purchaseService.list());
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Purchase.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Purchase.java
index d9ba537..68331a1 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Purchase.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Purchase.java
@@ -108,6 +108,9 @@
     @ApiModelProperty(value = "鏀惰揣閬撳彛")
     private String channel;
 
+    @ApiModelProperty("鎵ц鐘舵��")
+    private Short exceStatus;
+
     /**
      * erp鍗曞彿
      */
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/PurchaseTemplate.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/PurchaseTemplate.java
index aeaf704..975acfa 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/PurchaseTemplate.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/PurchaseTemplate.java
@@ -29,13 +29,13 @@
 
     @Excel(name = "鍗曟嵁绫诲瀷")
     @ApiModelProperty(value= "鍗曟嵁绫诲瀷")
-    @ExcelComment(value = "type", example = "閲囪喘鍏ュ簱鍗�")
+    @ExcelComment(value = "type", example = "鍏ュ簱鍗�")
     private String type;
 
 
     @Excel(name = "涓氬姟绫诲瀷")
     @ApiModelProperty(value= "涓氬姟绫诲瀷")
-    @ExcelComment(value = "wkType", example = "澶栬喘鏀惰揣")
+    @ExcelComment(value = "wkType", example = "閲囪喘鍏ュ簱鍗�")
     private String wkType;
 
     @Excel(name = "椤圭洰鍚嶇О")
@@ -131,6 +131,7 @@
     @ExcelComment(value = "splrBatch", example = "20250401")
     private String splrBatch;
 
+
     @Excel(name = "棰勮閫佽揪鏃堕棿")
     @ApiModelProperty("棰勮閫佽揪鏃堕棿")
     @ExcelComment(value = "arrTime", example = "2025-05-21")
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 5d43cc8..6566eb2 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
@@ -9,7 +9,7 @@
  */
 public enum AsnExceStatus {
 
-    //璐ㄦ鐘舵��
+    //ASN鎵ц鐘舵�佺姸鎬�
     ASN_EXCE_STATUS_UN_EXCE("0", "鏈墽琛�"),
     ASN_EXCE_STATUS_EXCE_ING("1", "鎵ц涓�"),
     ASN_EXCE_STATUS_RECEIPT_DONE("2", "鏀惰揣瀹屾垚"),
@@ -17,6 +17,12 @@
     ASN_EXCE_STATUS_TASK_CANCEL("4", "鍙栨秷"),
     ASN_EXCE_STATUS_TASK_CLOSE("5", "宸插叧闂�"),
 
+    //PO鍗曟墽琛岀姸鎬�
+    PO_EXCE_STATUS_UN_EXCE("0", "鏈墽琛�"),
+    PO_EXCE_STATUS_EXCE_ING("1", "鎵ц涓�"),
+    PO_EXCE_STATUS_SECTION_DONE("3", "閮ㄥ垎瀹屾垚"),
+    PO_EXCE_STATUS_ALL_DONE("3", "宸插畬鎴�"),
+
 
     OUT_STOCK_STATUS_TASK_INIT("11", "鍒濆鍖�"),
     OUT_STOCK_STATUS_TASK_EXCE("12", "寰呭鐞�"),
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/POExceStatus.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/POExceStatus.java
new file mode 100644
index 0000000..318da31
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/POExceStatus.java
@@ -0,0 +1,19 @@
+package com.vincent.rsf.server.manager.enums;
+
+
+public enum POExceStatus {
+    PO_EXCE_STATUS_UN_EXCE("0", "鏈墽琛�"),
+    PO_EXCE_STATUS_EXCE_ING("1", "鎵ц涓�"),
+    PO_EXCE_STATUS_SECTION_DONE("3", "閮ㄥ垎瀹屾垚"),
+    PO_EXCE_STATUS_ALL_DONE("3", "宸插畬鎴�"),
+    ;
+
+    POExceStatus(String val, String desc) {
+        this.val = Short.parseShort(val);
+        this.desc = desc;
+    }
+
+    public Short val;
+    public String desc;
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
index 626dbd8..a3ce17e 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
@@ -11,6 +11,7 @@
 import com.vincent.rsf.server.manager.controller.params.WarehouseAreaParam;
 import com.vincent.rsf.server.manager.entity.*;
 import com.vincent.rsf.server.manager.enums.AsnExceStatus;
+import com.vincent.rsf.server.manager.enums.POExceStatus;
 import com.vincent.rsf.server.manager.enums.PakinIOStatus;
 import com.vincent.rsf.server.manager.enums.WarehouseAreasType;
 import com.vincent.rsf.server.manager.service.*;
@@ -203,7 +204,7 @@
             return;
         }
         //鑾峰彇鏈敓鎴怉SN鍗曟嵁
-        List<Purchase> purchases = purchaseService.list(new LambdaQueryWrapper<Purchase>().eq(Purchase::getStatus, 0));
+        List<Purchase> purchases = purchaseService.list(new LambdaQueryWrapper<Purchase>().eq(Purchase::getExceStatus, 0));
         //PO鍗曚负绌猴紝鐩存帴璺冲嚭褰撳墠浠诲姟
         if (purchases.isEmpty()) {
             return;
@@ -266,7 +267,8 @@
             }
 
             //浠诲姟鎵ц瀹屾垚锛屼慨鏀瑰凡瀹屾垚鏁伴噺鍜孭O鍗曟墽琛岀姸鎬�
-            purchase.setQty(purchase.getAnfme()).setStatus(1);
+            purchase.setQty(purchase.getAnfme())
+                    .setExceStatus(POExceStatus.PO_EXCE_STATUS_EXCE_ING.val);
 
             if (!purchaseService.saveOrUpdate(purchase)) {
                 throw new CoolException("PO鍗曟墽琛屽畬鎴愬悗锛屼繚瀛樺け璐ワ紒锛�");
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java
index 2132c30..060bd61 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java
@@ -25,4 +25,5 @@
 
     R closeOrder(Long id);
 
+    R  createByPo(List<Long> ids);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/PurchaseService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/PurchaseService.java
index a9ed4df..bdcb10e 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/PurchaseService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/PurchaseService.java
@@ -1,8 +1,13 @@
 package com.vincent.rsf.server.manager.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.vincent.rsf.server.api.entity.dto.PoItemsDto;
 import com.vincent.rsf.server.manager.entity.Purchase;
+
+import java.util.List;
+import java.util.Set;
 
 public interface PurchaseService extends IService<Purchase> {
 
+    List<PoItemsDto> poList(Set<Long> asnIds);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
index 7ab439d..d1aa2c0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
@@ -8,19 +8,14 @@
 import com.vincent.rsf.server.api.entity.dto.PoItemsDto;
 import com.vincent.rsf.server.api.service.ReceiveMsgService;
 import com.vincent.rsf.server.api.service.ReportMsgService;
+import com.vincent.rsf.server.common.utils.DateUtils;
 import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams;
 import com.vincent.rsf.server.manager.controller.params.BatchUpdateParam;
-import com.vincent.rsf.server.manager.entity.AsnOrderItem;
-import com.vincent.rsf.server.manager.entity.AsnOrderItemLog;
-import com.vincent.rsf.server.manager.entity.AsnOrderLog;
+import com.vincent.rsf.server.manager.entity.*;
 import com.vincent.rsf.server.manager.enums.AsnExceStatus;
+import com.vincent.rsf.server.manager.enums.POExceStatus;
 import com.vincent.rsf.server.manager.mapper.AsnOrderMapper;
-import com.vincent.rsf.server.manager.entity.AsnOrder;
-import com.vincent.rsf.server.manager.mapper.PurchaseMapper;
-import com.vincent.rsf.server.manager.service.AsnOrderItemLogService;
-import com.vincent.rsf.server.manager.service.AsnOrderItemService;
-import com.vincent.rsf.server.manager.service.AsnOrderLogService;
-import com.vincent.rsf.server.manager.service.AsnOrderService;
+import com.vincent.rsf.server.manager.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.vincent.rsf.server.system.constant.SerialRuleCode;
 import com.vincent.rsf.server.system.mapper.SerialRuleMapper;
@@ -49,8 +44,7 @@
     private ReceiveMsgService receiveMsgService;
     @Autowired
     private ReportMsgService reportMsgService;
-    @Resource
-    private PurchaseMapper purchaseMapper;
+
     @Autowired
     private AsnOrderItemService asnOrderItemService;
     @Autowired
@@ -59,6 +53,12 @@
     private AsnOrderItemLogService asnOrderItemLogService;
     @Resource
     private SerialRuleMapper serialRuleMapper;
+    @Autowired
+    private MatnrService matnrService;
+    @Autowired
+    private PurchaseService purchaseService;
+    @Autowired
+    private PurchaseItemService purchaseItemService;
 
     @Override
     public boolean notifyInspect(List<AsnOrder> orders) {
@@ -69,7 +69,7 @@
         if (asnIds.isEmpty()) {
             throw new CoolException("ASN鍗曟嵁涓嶈兘涓虹┖锛侊紒");
         }
-        List<PoItemsDto> items = purchaseMapper.poList(asnIds);
+        List<PoItemsDto> items = purchaseService.poList(asnIds);
         if (items.isEmpty()) {
             throw new CoolException("鐗╂枡鎵�灞為噰璐崟鎹笉瀛樺湪锛侊紒");
         }
@@ -247,6 +247,87 @@
     }
 
     /**
+     * @author Ryan
+     * @date 2025/5/13
+     * @description: 鏍规嵁PO鍗曞垱寤篈SN鍗�
+     * @version 1.0
+     */
+    @Override
+    public R createByPo(List<Long> ids) {
+        //鑾峰彇鏈敓鎴怉SN鍗曟嵁
+        List<Purchase> purchases = purchaseService.list(new LambdaQueryWrapper<Purchase>().in(Purchase::getId, ids));
+        //鐢熸垚ASN鍗曟嵁
+        purchases.forEach(purchase -> {
+            if (!Objects.isNull(purchase.getStartTime())) {
+                //鍒ゆ柇璧峰鏃堕棿鏄惁澶т簬褰撳墠鏃堕棿
+                if (DateUtils.compareDate(new Date(), purchase.getStartTime())) {
+                    return;
+                }
+            }
+            List<PurchaseItem> items = purchaseItemService.list(new LambdaQueryWrapper<PurchaseItem>().eq(PurchaseItem::getPurchaseId, purchase.getId()));
+            if (items.isEmpty()) {
+                throw new CoolException("瀛愬垪琛ㄦ暟鎹负绌猴紝璇锋煡璇O鍗曟槸鍚︽纭綍鍏ワ紒锛�");
+            }
+            AsnOrder order = new AsnOrder();
+            //鏍规嵁缂栫爜瑙勫垯鐢熸垚ASN鍗曞彿
+            String code = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, purchase);
+            order.setAnfme(purchase.getAnfme())
+                    .setCode(code)
+                    .setArrTime(purchase.getPreArr())
+                    .setQty(purchase.getQty())
+                    .setPoId(purchase.getId())
+                    .setPoCode(purchase.getCode());
+            if (!this.save(order)) {
+                throw new CoolException("ASN鍗曟嵁淇濆瓨澶辫触锛侊紒");
+            }
+            List<AsnOrderItem> orderItems = new ArrayList<>();
+            items.forEach(item -> {
+                AsnOrderItem orderItem = new AsnOrderItem();
+                Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, item.getMatnrCode()));
+                if (Objects.isNull(matnr)) {
+                    throw new CoolException("鏁版嵁閿欒锛氬綋鍓嶇墿鏂欎笉瀛樺湪!!");
+                }
+                String trackCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_LABEL_CODE, item);
+                if (StringUtils.isBlank(trackCode)) {
+                    throw new CoolException("鍗曟嵁璺熻釜鐮佺敓鎴愬け璐ワ細璇锋鏌ャ�宻ys_asn_mantr_label銆嶆槸鍚﹂厤缃畬鎴愶紒锛�");
+                }
+//                String barcode = code + matnr.getCode();
+                orderItem.setAnfme(item.getAnfme())
+                        .setAsnId(order.getId())
+                        .setQty(item.getAnfme())
+                        .setSplrName(item.getSplrName())
+                        .setAsnCode(code)
+                        .setSplrBatch(item.getSplrBatch())
+                        .setSplrCode(item.getSplrCode())
+                        .setPoDetlId(item.getId())
+                        .setPlatItemId(item.getPlatItemId())
+                        .setTrackCode(trackCode)
+                        .setPoCode(purchase.getCode())
+                        .setPurQty(item.getAnfme())
+                        .setPurUnit(item.getUnit())
+                        .setMatnrCode(matnr.getCode())
+                        .setMaktx(matnr.getName())
+                        .setMatnrId(matnr.getId());
+                orderItems.add(orderItem);
+            });
+            if (!asnOrderItemService.saveBatch(orderItems)) {
+                throw new CoolException(("Asn鍗曟嵁鏄庣粏淇濆瓨澶辫触锛侊紒"));
+            }
+
+            //浠诲姟鎵ц瀹屾垚锛屼慨鏀瑰凡瀹屾垚鏁伴噺鍜孭O鍗曟墽琛岀姸鎬�
+            purchase.setQty(purchase.getAnfme())
+                    .setExceStatus(POExceStatus.PO_EXCE_STATUS_EXCE_ING.val);
+
+            if (!purchaseService.saveOrUpdate(purchase)) {
+                throw new CoolException("PO鍗曟墽琛屽畬鎴愬悗锛屼繚瀛樺け璐ワ紒锛�");
+            }
+        });
+
+
+        return null;
+    }
+
+    /**
      * @param
      * @return
      * @author Ryan
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseItemServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseItemServiceImpl.java
index 29370c0..f9b7e40 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseItemServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseItemServiceImpl.java
@@ -96,25 +96,25 @@
                 if (StringUtils.isBlank(purchaseTemplate.getMatnrCode())) {
                     throw new CoolException(purchaseTemplate.getPoCode() + "锛氱墿鏂欑紪鐮佷笉鑳戒负绌猴紒锛�");
                 }
-                Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, template.getMatnrCode()));
+                Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, purchaseTemplate.getMatnrCode()));
                 if (Objects.isNull(matnr)) {
-                    throw new CoolException(template.getMatnrCode() + "鐗╂枡涓嶅瓨鍦紒锛�");
+                    throw new CoolException(purchaseTemplate.getMatnrCode() + "鐗╂枡涓嶅瓨鍦紒锛�");
                 }
                 item.setMatnrName(matnr.getName())
                         .setMatnrCode(matnr.getCode())
-                        .setPlatItemId(template.getPlatItemId())
-                        .setAnfme(template.getAnfme())
+                        .setPlatItemId(purchaseTemplate.getPlatItemId())
+                        .setAnfme(purchaseTemplate.getAnfme())
                         .setPurchaseId(purchase.getId())
                         .setUnit(matnr.getUnit())
                         .setNromQty(matnr.getNromNum())
-                        .setSplrBatch(template.getSplrBatch())
+                        .setSplrBatch(purchaseTemplate.getSplrBatch())
                         .setCreateBy(loginUserId)
                         .setUpdateBy(loginUserId);
 
                 if (StringUtils.isNotBlank(purchaseTemplate.getSplrCode())) {
                     Companys companys = companysService.getOne(new LambdaQueryWrapper<Companys>()
                             .eq(Companys::getType, CompanysType.COMPANYS_TYPE_SUPPLIER.val)
-                            .eq(Companys::getCode, template.getSplrCode()));
+                            .eq(Companys::getCode, purchaseTemplate.getSplrCode()));
                     if (!Objects.isNull(companys)) {
                         item.setSplrCode(companys.getCode()).setSplrName(companys.getName());
                     } else {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseServiceImpl.java
index 3a5edea..9cadbf2 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/PurchaseServiceImpl.java
@@ -1,12 +1,20 @@
 package com.vincent.rsf.server.manager.service.impl;
 
+import com.vincent.rsf.server.api.entity.dto.PoItemsDto;
 import com.vincent.rsf.server.manager.mapper.PurchaseMapper;
 import com.vincent.rsf.server.manager.entity.Purchase;
 import com.vincent.rsf.server.manager.service.PurchaseService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+import java.util.Set;
+
 @Service("purchaseService")
 public class PurchaseServiceImpl extends ServiceImpl<PurchaseMapper, Purchase> implements PurchaseService {
 
+    @Override
+    public List<PoItemsDto> poList(Set<Long> asnIds) {
+        return this.baseMapper.poList(asnIds);
+    }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java
index 615ca93..129af7b 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java
@@ -8,7 +8,6 @@
  */
 public class GlobalConfigCode {
 
-
     public final static String EXECUTION = "Execution";
 
     /**鐩存帴缁勬墭*/
diff --git a/rsf-server/src/main/resources/application-dev.yml b/rsf-server/src/main/resources/application-dev.yml
index efd3d05..203032b 100644
--- a/rsf-server/src/main/resources/application-dev.yml
+++ b/rsf-server/src/main/resources/application-dev.yml
@@ -89,7 +89,7 @@
   #鏄惁鍏佽鎵撳嵃璐х墿鏍囩锛� 榛樿鍏佽鎵撳嵃锛屼篃鍙敱渚涘簲鍟嗘彁渚涙爣绛�
   flagPrinter: false
   #鏄惁鑷姩鐢熸垚ASN鍗曪紙榛樿锛氭槸锛夛紝涓恒�庡惁銆忓垯寮�鍚疨O鍗曟墜鍔ㄧ敓鎴怉SN鍗曞姛鑳�
-  flagAutoAsn: true
+  flagAutoAsn: false
   #璐ㄦ鍔熻兘 鏄惁鏍¢獙涓婃灦锛堥粯璁わ細鏄級锛屾槸鍚︽牎楠屾敹璐э紙榛樿锛氬惁锛�
   inspect:
     #鍒ゆ柇鏄悗妫�楠屽悎鏍煎悗锛屾墠鍏佽涓婃灦

--
Gitblit v1.9.1