From c3bd7262ff89c7594ec368f76ea910e6212769af Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 29 四月 2025 13:53:03 +0800
Subject: [PATCH] 1. 出库单新增修改优化
---
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java | 49 +
rsf-admin/src/page/orders/outStock/AsnWareModal.jsx | 249 ++++++++
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java | 4
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java | 40
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java | 4
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java | 25
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java | 2
rsf-admin/src/page/orders/outStock/OutOrderCreate.jsx | 83 -
rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx | 613 +++++++++++++++++++++
rsf-admin/src/page/components/DictSelect.jsx | 1
rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx | 1
rsf-admin/src/page/orders/wave/ItemToTaskModal.jsx | 7
rsf-admin/src/page/orders/outStock/AsnOrderModal.jsx | 643 ++++++++++++++++++++++
rsf-admin/src/i18n/zh.js | 1
rsf-admin/src/page/orders/outStock/OutOrderList.jsx | 15
rsf-admin/src/i18n/en.js | 1
16 files changed, 1,656 insertions(+), 82 deletions(-)
diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 37cd4e3..596f515 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -56,6 +56,7 @@
expand: 'Expand',
expandAll: 'Expand All',
collapse: 'Collapse',
+ newAddMats: 'New Mats',
collapseAll: 'Collapse All',
scope: 'Assign',
import: {
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 8f6d2d3..0c681ce 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -56,6 +56,7 @@
expand: '灞曞紑',
expandAll: '鍏ㄩ儴灞曞紑',
collapse: '鎶樺彔',
+ newAddMats: '鏂板鐗╂枡',
collapseAll: '鍏ㄩ儴鎶樺彔',
scope: '鏉冮檺',
inputPlaceholder: '绔欑偣鍙~澶氫釜锛屼腑闂翠互鑻辨枃閫楀彿鍖哄垎锛�,锛�',
diff --git a/rsf-admin/src/page/components/DictSelect.jsx b/rsf-admin/src/page/components/DictSelect.jsx
index 72c9d76..d42a8ee 100644
--- a/rsf-admin/src/page/components/DictSelect.jsx
+++ b/rsf-admin/src/page/components/DictSelect.jsx
@@ -44,6 +44,7 @@
<Select
labelId="demo-select-small-label"
value={validValue}
+ variant="filled"
onChange={handleChange}
size='small'
>
diff --git a/rsf-admin/src/page/orders/outStock/AsnOrderModal.jsx b/rsf-admin/src/page/orders/outStock/AsnOrderModal.jsx
new file mode 100644
index 0000000..6c2dc38
--- /dev/null
+++ b/rsf-admin/src/page/orders/outStock/AsnOrderModal.jsx
@@ -0,0 +1,643 @@
+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 ConfirmButton from "../../components/ConfirmButton";
+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 } from '@mui/x-data-grid';
+import DictionarySelect from "../../components/DictionarySelect";
+import DictSelect from "../../components/DictSelect";
+import "./asnOrder.css";
+
+const AsnOrderModal = (props) => {
+ const { open, setOpen, asnId, billReload } = 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 && asnId !== 0) {
+ requestGetHead()
+ requestGetBody()
+ }
+ setDisabled(false)
+ }, [open])
+
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ refresh();
+ setFormData({ type: '', wkType: '' })
+ setTableData([])
+ }
+ };
+
+ const [formData, setFormData] = useState({
+ type: '',
+ wkType: '',
+ poCode: '',
+ logisNo: '',
+ arrTime: ''
+ });
+
+ const [tabelData, setTableData] = useState([]);
+
+
+ const handleChange = (value, name) => {
+ setFormData((prevData) => ({
+ ...prevData,
+ [name]: value
+ }));
+ console.log(formData);
+ };
+
+ const resetData = () => {
+ setFormData({
+ type: '',
+ wkType: '',
+ poCode: '',
+ logisNo: '',
+ arrTime: ''
+ })
+ setTableData([])
+ }
+
+ const setFinally = () => {
+ const rows = tableRef.current.state.editRows;
+ for (const key in rows) {
+ const find = tabelData.find(item => item.matnrId === +key);
+ find.anfme = rows[key].anfme.value;
+ }
+ setTableData([...tabelData]);
+ }
+
+ const handleSubmit = async () => {
+ setFinally()
+ setDisabled(true)
+
+ if (asnId === 0) {
+ const parmas = {
+ "orders": formData,
+ "items": tabelData,
+ }
+
+ const res = await request.post(`/asnOrder/items/save`, parmas);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ billReload?.current()
+ resetData()
+ } else {
+ notify(res.data.msg);
+ }
+ } else {
+ const parmas = {
+ "orders": formData,
+ "items": tabelData,
+ }
+ const res = await request.post(`/asnOrder/items/update`, parmas);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ billReload?.current()
+ resetData()
+ } else {
+ notify(res.data.msg);
+ }
+ }
+ setDisabled(false)
+
+ };
+
+
+ const handleDelete = async () => {
+ const res = await request.post(`/asnOrder/remove/${asnId}`);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ } else {
+ notify(res.data.msg);
+ }
+ };
+
+ const requestGetHead = async () => {
+ const res = await request.get(`/asnOrder/${asnId}`);
+ if (res?.data?.code === 200) {
+ setFormData(res.data.data)
+ } else {
+ notify(res.data.msg);
+ }
+ }
+
+ const requestGetBody = async () => {
+ const res = await request.post(`/asnOrderItem/page`, { asnId });
+ if (res?.data?.code === 200) {
+ setTableData(res.data.data.records)
+ } else {
+ notify(res.data.msg);
+ }
+ }
+
+ const [selectedRows, setSelectedRows] = useState([]);
+
+
+
+ const handleDeleteItem = () => {
+ const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
+ setTableData(newTableData);
+ }
+
+ return (
+ <>
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ aria-hidden
+ fullWidth
+ disableRestoreFocus
+ maxWidth="lg" // '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={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+ <Form defaultValues={formData}>
+ <Grid container spacing={2}>
+ <Grid item md={3}>
+ <DictSelect
+ label={translate("table.field.asnOrder.type")}
+ value={formData.type}
+ onChange={(e) => handleChange(e.target.value, 'type')}
+ dictTypeCode="sys_order_type"
+ required
+ />
+ </Grid>
+ <Grid item md={3}>
+ <DictSelect
+ label={translate("table.field.asnOrder.wkType")}
+ value={formData.wkType}
+ onChange={(e) => handleChange(e.target.value, 'wkType')}
+ dictTypeCode="sys_business_type"
+ required
+ />
+ </Grid>
+ <Grid item md={3}>
+ <TextField
+ label={translate("table.field.asnOrder.poCode")}
+ value={formData.poCode}
+ onChange={(e) => handleChange(e.target.value, 'poCode')}
+ />
+ </Grid>
+ <Grid item md={3}>
+ <TextField
+ label={translate("table.field.asnOrder.logisNo")}
+ value={formData.logisNo}
+ onChange={(e) => handleChange(e.target.value, 'logisNo')}
+ />
+ </Grid>
+
+ <Grid item md={3}>
+ {/* <TextField
+ label={translate("table.field.asnOrder.arrTime")}
+ value={formData.arrTime}
+ onChange={(e) => handleChange(e.target.value, 'arrTime')}
+ /> */}
+ <DateInput
+ source="arrTime"
+ label="table.field.asnOrder.arrTime"
+ value={formData.arrTime}
+ onChange={(e) => handleChange(e.target.value, 'arrTime')}
+ />
+
+ </Grid>
+ </Grid>
+ </Form>
+ </Box>
+
+ <Box sx={{ mt: 2 }}>
+ <Stack direction="row" spacing={2}>
+ <Button variant="contained" onClick={() => setCreateDialog(true)}>鏂板鐗╂枡</Button>
+ {/* {asnId !== '' && <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDelete} />} */}
+ <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDeleteItem} />
+ </Stack>
+ </Box>
+ <Box sx={{ mt: 2 }}>
+ <AsnOrderModalTable tabelData={tabelData} setTableData={setTableData} asnId={asnId} selectedRows={selectedRows} setSelectedRows={setSelectedRows} tableRef={tableRef}></AsnOrderModalTable>
+ </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>
+
+ <AsnWareModal
+ open={createDialog}
+ setOpen={setCreateDialog}
+ data={tabelData}
+ setData={setTableData}
+ />
+ </>
+ )
+}
+
+export default AsnOrderModal;
+
+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)
+ console.log(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 SelectInputSplrCodeEditCell = (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)
+ console.log(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.id === e.target.value);
+
+ // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁
+ if (selectedSupplier) {
+ params.api.setEditCellValue({
+ id: params.id,
+ field: 'splrName',
+ value: selectedSupplier.name,
+ });
+ }
+ }
+
+ }
+ fullWidth
+
+ >
+ {formData.map(e => {
+ return(
+ <MenuItem value={e.id} children={e.name} key={e.id} />
+ );
+
+ })}
+
+ </Select>
+ );
+ };
+
+
+
+
+const AsnOrderModalTable = ({ tabelData, setTableData, asnId, selectedRows, setSelectedRows, tableRef }) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+
+ const [columns, setColumns] = useState([
+
+ {
+ field: 'maktx',
+ headerName: translate('table.field.asnOrderItem.maktx'),
+ width: 250,
+ editable: false,
+ },
+ {
+ field: 'matnrCode',
+ headerName: translate('table.field.asnOrderItem.matnrCode'),
+ width: 130,
+ editable: false,
+ },
+ {
+ 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: 'splrCode',
+ headerName: translate('table.field.asnOrderItem.splrCode')+"*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrCodeEditCell {...params} />
+ ),
+ headerClassName: "custom",
+ },
+ {
+ field: 'splrName',
+ headerName: translate('table.field.asnOrderItem.splrName')+"*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrNameEditCell {...params} />
+ ),
+ headerClassName: "custom",
+ },
+ // {
+ // field: 'packName',
+ // headerName: translate('table.field.asnOrderItem.packName'),
+ // minWidth: 100,
+ // flex: 1,
+ // editable: true,
+ // },
+ // {
+ // field: 'poDetlId',
+ // headerName: translate('table.field.asnOrderItem.poDetlId'),
+ // minWidth: 100,
+ // flex: 1,
+ // },
+ {
+ field: 'poCode',
+ headerName: translate('table.field.asnOrderItem.poDetlCode')+"*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ headerClassName: "custom",
+ },
+
+ {
+ field: 'stockUnit',
+ headerName: translate('table.field.asnOrderItem.stockUnit'),
+ minWidth: 100,
+ flex: 1,
+ editable: false,
+ },
+ // {
+ // field: 'purQty',
+ // headerName: translate('table.field.asnOrderItem.purQty'),
+ // minWidth: 100,
+ // flex: 1,
+ // editable: true,
+ // },
+ {
+ field: 'purUnit',
+ headerName: translate('table.field.asnOrderItem.purUnit'),
+ 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,
+ headerName: el.fieldsAlise,
+ minWidth: 100,
+ flex: 1,
+ editable: false
+ }))
+ setColumns([...columns, ...cols, action])
+ } else {
+ notify(msg);
+ }
+ }
+
+
+
+ const handleDelete = (row) => {
+ const newData = _.filter(cdata.current, (item) => item.matnrId !== row.matnrId);
+ setTableData(newData);
+ };
+
+
+ const processRowUpdate = (newRow, oldRow) => {
+ const rows = tabelData.map((r) =>
+ r.matnrId === newRow.matnrId ? { ...newRow } : r
+ )
+ setTableData(rows)
+ // setTableData((prevData) =>
+ // prevData.map((r) =>
+ // r.matnrId === newRow.matnrId ? { ...newRow } : r
+ // )
+
+ // );
+
+ 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.matnrId}
+ 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/outStock/AsnWareModal.jsx b/rsf-admin/src/page/orders/outStock/AsnWareModal.jsx
new file mode 100644
index 0000000..8f3788b
--- /dev/null
+++ b/rsf-admin/src/page/orders/outStock/AsnWareModal.jsx
@@ -0,0 +1,249 @@
+import React, { useState, useEffect } from "react";
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Stack,
+ Grid,
+ TextField,
+ Box,
+ Button,
+ Paper,
+ styled
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import { useTranslate, useNotify, useRefresh } from 'react-admin';
+import request from '@/utils/request';
+import { DataGrid } from '@mui/x-data-grid';
+import SaveIcon from '@mui/icons-material/Save';
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+const AsnWareModal = (props) => {
+ const { open, setOpen, data, setData } = props;
+
+ const translate = useTranslate();
+ const notify = useNotify();
+ const refresh = useRefresh();
+
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+
+ const [formData, setFormData] = useState({});
+ const [tableData, setTableData] = useState([]);
+ const [dyFields, setDyFields] = useState([]);
+ const [selectedRows, setSelectedRows] = useState([]);
+
+ const handleChange = (e) => {
+ const { name, value } = e.target;
+ setFormData(() => ({
+ [name]: value
+ }));
+ };
+
+ const reset = () => {
+ setFormData({
+ name: '',
+ code: '',
+ groupId: 0
+ })
+ }
+
+ const handleSubmit = () => {
+ const hasarr = data.map(el => +el.matnrId)
+ const selectedData = selectedRows.filter(item => !hasarr.includes(item)).map(id => (tableData.find(row => row.id === id)));
+ const value = selectedData.map((el => {
+ const dynamicFields = dyFields.reduce((acc, item) => {
+ acc[item.fields] = el['extendFields']?.[item.fields] || '';
+ return acc;
+ }, {});
+ return {
+ matnrId: el.id,
+ maktx: el.name,
+ matnrCode: el.code,
+ stockUnit: el.stockUnit || '',
+ purUnit: el.purchaseUnit || '',
+ ...dynamicFields
+ }
+ }))
+ setData([...data, ...value]);
+ setOpen(false);
+ reset();
+ };
+
+ const getData = async () => {
+ const res = await request.post(`/matnr/page`, {
+ ...formData,
+ current: 1,
+ pageSize: 100,
+ orderBy: "create_time desc"
+ });
+ if (res?.data?.code === 200) {
+ setTableData(res.data.data.records);
+ } else {
+ notify(res.data.msg);
+ }
+ };
+
+ useEffect(() => {
+ getData();
+ }, [open]);
+
+ const handleSearch = () => {
+ getData()
+ };
+
+ return (
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ 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>
+ <DialogContent sx={{ mt: 2 }}>
+ <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+ <Grid container spacing={2}>
+ <Grid item md={4}>
+ <TextField
+ label={translate('table.field.matnr.name')}
+ name="name"
+ value={formData.name}
+ onChange={handleChange}
+ size="small"
+ />
+ </Grid>
+ <Grid item md={4}>
+ <TextField
+ label={translate('table.field.matnr.code')}
+ name="code"
+ value={formData.code}
+ onChange={handleChange}
+ size="small"
+ />
+ </Grid>
+ <Grid item md={4}>
+ <TreeSelectInput
+ label="table.field.matnr.groupId"
+ value={formData.groupId}
+ resource={'matnrGroup'}
+ source="groupId"
+ name="groupId"
+ onChange={handleChange}
+ />
+ </Grid>
+ </Grid>
+ </Box>
+ <Box sx={{ mt: 2 }}>
+ <Stack direction="row" spacing={2}>
+ <Button variant="contained" onClick={handleSearch}>鎼滅储</Button>
+ </Stack>
+ </Box>
+ <Box sx={{ mt: 2, height: 400, width: '100%' }}>
+ <AsnWareModalTable
+ tableData={tableData}
+ setTableData={setTableData}
+ dyFields={dyFields}
+ setDyFields={setDyFields}
+ selectedRows={selectedRows}
+ setSelectedRows={setSelectedRows}
+ />
+ </Box>
+ </DialogContent>
+ <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+ <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
+ <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
+ {translate('toolbar.confirm')}
+ </Button>
+ </Box>
+ </DialogActions>
+ </Dialog>
+ );
+};
+
+export default AsnWareModal;
+
+const AsnWareModalTable = ({ tableData, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+
+ const [columns, setColumns] = useState([
+ // { field: 'id', headerName: 'ID', width: 100 },
+ { field: 'name', headerName: translate('table.field.matnr.name'), width: 300 },
+ { field: 'code', headerName: translate('table.field.matnr.code'), width: 200 },
+ { field: 'groupId$', headerName: translate('table.field.matnr.groupId'), width: 100 },
+ { field: 'spec', headerName: translate('table.field.matnr.spec'), width: 100 },
+ { field: 'model', headerName: translate('table.field.matnr.model'), width: 100 },
+ { field: 'weight', headerName: translate('table.field.matnr.weight'), width: 100 },
+
+ { field: 'describle', headerName: translate('table.field.matnr.describle'), width: 100 },
+ { field: 'nromNum', headerName: translate('table.field.matnr.nromNum'), width: 100 },
+ { field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 },
+ { field: 'purchaseUnit', headerName: translate('table.field.matnr.purUnit'), width: 100 },
+ { field: 'stockUnit', headerName: translate('table.field.matnr.stockUnit'), width: 100 },
+ { field: 'stockLeval$', headerName: translate('table.field.matnr.stockLevel'), width: 100, sortable: false },
+ ])
+
+
+
+ const handleSelectionChange = (ids) => {
+ setSelectedRows(ids)
+
+ };
+
+ useEffect(() => {
+ getDynamicFields();
+ }, []);
+
+ 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,
+ headerName: el.fieldsAlise,
+ minWidth: 100,
+ flex: 1,
+ editable: el.unique,
+ valueGetter: (value, row) => {
+ return row.extendFields?.[el.fields] || '';
+ },
+ }))
+ setDyFields(data)
+ setColumns([...columns, ...cols])
+ } else {
+ notify(msg);
+ }
+ }
+
+ return (
+ <div style={{ height: 400, width: '100%' }}>
+ <DataGrid
+ size="small"
+ rows={tableData}
+ columns={columns}
+ checkboxSelection
+ onRowSelectionModelChange={handleSelectionChange}
+ selectionModel={selectedRows}
+ disableColumnMenu={true}
+ disableColumnSorting
+ disableMultipleColumnsSorting
+ />
+ </div>
+ );
+};
\ No newline at end of file
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderCreate.jsx b/rsf-admin/src/page/orders/outStock/OutOrderCreate.jsx
index 25a8314..40fba47 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderCreate.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderCreate.jsx
@@ -27,6 +27,8 @@
useList,
ListContextProvider,
useListContext,
+ Button,
+ useRecordContext,
} from 'react-admin';
import {
Dialog,
@@ -43,7 +45,8 @@
import StatusSelectInput from "../../components/StatusSelectInput";
import OutOrderItemList from "./OutOrderItemList";
import MemoInput from "../../components/MemoInput";
-
+import AddIcon from '@mui/icons-material/Add';
+import SelectMatnrModal from "./SelectMatnrModal";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
'& .css-1vooibu-MuiSvgIcon-root': {
@@ -67,6 +70,7 @@
const translate = useTranslate();
const notify = useNotify();
const [drawerVal, setDrawerVal] = useState(false);
+ const [matCreate, setMatCreate] = useState(false);
const handleClose = (event, reason) => {
if (reason !== "backdropClick") {
@@ -120,7 +124,7 @@
</DialogTitle>
<DialogContent sx={{ mt: 2 }}>
<>
- <Grid container rowSpacing={2} columnSpacing={2}>
+ <Grid container>
<Grid item xs={12} display="flex" gap={1}>
<TextInput
label="table.field.asnOrder.poCode"
@@ -154,12 +158,13 @@
source="anfme"
validate={required()}
/>
+
+ </Grid>
+ <Grid item xs={12} display="flex" gap={1}>
<NumberInput
label="table.field.asnOrder.qty"
source="qty"
/>
- </Grid>
- <Grid item xs={12} display="flex" gap={1}>
<TextInput
label="table.field.asnOrder.logisNo"
source="logisNo"
@@ -179,64 +184,15 @@
/>
</Grid>
</Grid>
+ <SelectMatnrModal open={matCreate} setOpen={setMatCreate} />
<DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
<Toolbar sx={{ width: '100%', justifyContent: 'end' }} >
+ <AddOutOrderButton setMatCreate={setMatCreate} />
<SaveButton />
</Toolbar>
</DialogActions>
-
<Box>
- <ListContextProvider
- // resource="waveItem脧"
- value={listContext}
- sx={{
- flexGrow: 1,
- transition: (theme) =>
- theme.transitions.create(['all'], {
- duration: theme.transitions.duration.enteringScreen,
- }),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
- }}
- title={"menu.waveItem"}
- empty={false}
- sort={{ field: "create_time", order: "desc" }}
- filters={false}
- actions={(
- <TopToolbar>
- <SelectColumnsButton preferenceKey='waveItem' />
- </TopToolbar>
- )}
- perPage={DEFAULT_PAGE_SIZE}
- >
- <StyledDatagrid
- preferenceKey='waveItem'
- bulkActionButtons={false}
- rowClick={(id, resource, record) => false}
- expand={false}
- expandSingle={false}
- omit={['id', 'createTime', 'matnrId', 'waveId', 'batch', 'orderItemId', 'unit', 'batch', 'trackCode', 'fieldsIndex', 'createBy', 'memo']}
- >
- <NumberField source="id" />
- <NumberField source="waveId" label="table.field.waveItem.waveId" />
- <TextField source="waveCode" label="table.field.waveItem.waveCode" />
- <TextField source="orderCode" label="table.field.waveItem.orderCode" />
- <NumberField source="matnrId" label="table.field.waveItem.matnrId" />
- <TextField source="matnrCode" label="table.field.waveItem.matnrCode" />
- <TextField source="batch" label="table.field.waveItem.batch" />
- <TextField source="splrBatch" label="table.field.waveItem.splrBatch" />
- <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" />
- <NumberField source="workQty" label="table.field.waveItem.workQty" />
- <NumberField source="qty" label="table.field.waveItem.qty" />
- <NumberField source="stockQty" label="table.field.waveItem.stockQty" />
- <WrapperField cellClassName="opt" label="table.field.waveItem.stockLocs">
- {/* <TagsField /> */}
- </WrapperField>
- </StyledDatagrid>
- </ListContextProvider>
+
</Box>
</>
</DialogContent>
@@ -248,3 +204,18 @@
}
export default OutOrderCreate;
+
+
+const AddOutOrderButton = (setMatCreate) => {
+ const record = useRecordContext();
+ const addMats = (event) => {
+ event.stopPropagation();
+ setMatCreate(true)
+ }
+
+ return (
+ <Button label={"common.action.newAddMats"} onClick={addMats} variant="contained" sx={{ padding: '0.6em', marginRight: '1em' }}>
+ <AddIcon />
+ </Button>
+ );
+}
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
index 23ed27e..2b181eb 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
@@ -56,6 +56,7 @@
import AddIcon from '@mui/icons-material/Add';
import OutOrderModal from "./OutOrderModal";
import PublicIcon from '@mui/icons-material/Public';
+import SelectMatnrModal from "./SelectMatnrModal";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
'& .css-1vooibu-MuiSvgIcon-root': {
@@ -139,7 +140,7 @@
<TopToolbar>
<FilterButton />
<CreateByOrderButton setCreateDialog={setCreateDialog} />
- <MyCreateButton onClick={() => { setManualDialog(true) }} />
+ <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} />
<SelectColumnsButton preferenceKey='outStock' />
<ImportButton value={'asnOrderItem'} />
{/* <MyExportButton /> */}
@@ -173,12 +174,19 @@
<BillStatusField cellClassName="status" source="exceStatus" label="table.field.outStock.exceStatus" />
<TextField source="memo" label="common.field.memo" sortable={false} />
<WrapperField cellClassName="opt" label="common.field.opt" >
+ <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} />
<EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton>
<CancelButton />
</WrapperField>
</StyledDatagrid>
</List>
- <OutOrderCreate
+ {/* <OutOrderCreate
+ open={manualDialog}
+ setOpen={setManualDialog}
+ /> */}
+ <SelectMatnrModal
+ asnId={modalType}
+ billReload={billReload}
open={manualDialog}
setOpen={setManualDialog}
/>
@@ -190,8 +198,7 @@
title='AsnOrder Detail'
drawerVal={drawerVal}
setDrawerVal={setDrawerVal}
- >
- </PageDrawer>
+ />
</Box >
)
}
diff --git a/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx b/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
new file mode 100644
index 0000000..7e0652b
--- /dev/null
+++ b/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
@@ -0,0 +1,613 @@
+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 ConfirmButton from "../../components/ConfirmButton";
+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 } from '@mui/x-data-grid';
+import DictionarySelect from "../../components/DictionarySelect";
+import DictSelect from "../../components/DictSelect";
+import "./asnOrder.css";
+
+const SelectMatnrModal = (props) => {
+ const { open, setOpen, asnId, billReload } = 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 && asnId !== 0) {
+ requestGetHead()
+ requestGetBody()
+ }
+ setDisabled(false)
+ }, [open])
+
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ refresh();
+ setFormData({ type: '', wkType: '' })
+ setTableData([])
+ }
+ };
+
+ const [formData, setFormData] = useState({
+ type: '',
+ wkType: '',
+ poCode: '',
+ logisNo: '',
+ arrTime: ''
+ });
+
+ const [tabelData, setTableData] = useState([]);
+
+ const handleChange = (value, name) => {
+ setFormData((prevData) => ({
+ ...prevData,
+ [name]: value
+ }));
+ console.log(formData);
+ };
+
+ const resetData = () => {
+ setFormData({
+ type: '',
+ wkType: '',
+ poCode: '',
+ logisNo: '',
+ arrTime: ''
+ })
+ setTableData([])
+ }
+
+ const setFinally = () => {
+ const rows = tableRef.current.state.editRows;
+ for (const key in rows) {
+ const find = tabelData.find(item => item.matnrId === +key);
+ find.anfme = rows[key].anfme.value;
+ }
+ setTableData([...tabelData]);
+ }
+
+ const handleSubmit = async () => {
+ setFinally()
+ setDisabled(true)
+
+ if (asnId === 0) {
+ const parmas = {
+ "orders": formData,
+ "items": tabelData,
+ }
+
+ const res = await request.post(`/asnOrder/items/save`, parmas);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ billReload?.current()
+ resetData()
+ } else {
+ notify(res.data.msg);
+ }
+ } else {
+ const parmas = {
+ "orders": formData,
+ "items": tabelData,
+ }
+ const res = await request.post(`/asnOrder/items/update`, parmas);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ billReload?.current()
+ resetData()
+ } else {
+ notify(res.data.msg);
+ }
+ }
+ setDisabled(false)
+
+ };
+
+
+ const handleDelete = async () => {
+ const res = await request.post(`/asnOrder/remove/${asnId}`);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ } else {
+ notify(res.data.msg);
+ }
+ };
+
+ const requestGetHead = async () => {
+ const res = await request.get(`/asnOrder/${asnId}`);
+ if (res?.data?.code === 200) {
+ setFormData(res.data.data)
+ } else {
+ notify(res.data.msg);
+ }
+ }
+
+ const requestGetBody = async () => {
+ const res = await request.post(`/asnOrderItem/page`, { asnId });
+ if (res?.data?.code === 200) {
+ setTableData(res.data.data.records)
+ } else {
+ notify(res.data.msg);
+ }
+ }
+
+ const [selectedRows, setSelectedRows] = useState([]);
+
+ const handleDeleteItem = () => {
+ const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
+ setTableData(newTableData);
+ }
+
+ return (
+ <>
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ aria-hidden
+ fullWidth
+ disableRestoreFocus
+ maxWidth="lg" // '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={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+ <Form defaultValues={formData}>
+ <Grid container spacing={2}>
+ {/* <Grid item md={2}>
+ <DictSelect
+ label={translate("table.field.asnOrder.type")}
+ value={formData.type}
+ onChange={(e) => handleChange(e.target.value, 'type')}
+ dictTypeCode="sys_order_type"
+ required
+ />
+ </Grid> */}
+ <Grid item md={2}>
+ <DictSelect
+ label={translate("table.field.asnOrder.wkType")}
+ value={formData.wkType}
+ variant="filled"
+ onChange={(e) => handleChange(e.target.value, 'wkType')}
+ dictTypeCode="sys_business_type"
+ required
+ />
+ </Grid>
+ <Grid item md={2}>
+ <TextField
+ label={translate("table.field.asnOrder.poCode")}
+ value={formData.poCode}
+ variant="filled"
+ size='small'
+ onChange={(e) => handleChange(e.target.value, 'poCode')}
+ />
+ </Grid>
+ <Grid item md={2}>
+ <TextField
+ label={translate("table.field.asnOrder.logisNo")}
+ value={formData.logisNo}
+ variant="filled"
+ size='small'
+ onChange={(e) => handleChange(e.target.value, 'logisNo')}
+ />
+ </Grid>
+ <Grid item md={2}>
+ <DateInput
+ source="arrTime"
+ label="table.field.asnOrder.arrTime"
+ size='small'
+ variant="filled"
+ value={formData.arrTime}
+ onChange={(e) => handleChange(e.target.value, 'arrTime')}
+ />
+ </Grid>
+ </Grid>
+ </Form>
+ </Box>
+
+ <Box sx={{ mt: 2 }}>
+ <Stack direction="row" spacing={2}>
+ <Button variant="contained" onClick={() => setCreateDialog(true)}>鏂板鐗╂枡</Button>
+ {/* {asnId !== '' && <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDelete} />} */}
+ <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDeleteItem} />
+ </Stack>
+ </Box>
+ <Box sx={{ mt: 2 }}>
+ <AsnOrderModalTable tabelData={tabelData} setTableData={setTableData} asnId={asnId} selectedRows={selectedRows} setSelectedRows={setSelectedRows} tableRef={tableRef}></AsnOrderModalTable>
+ </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>
+ <AsnWareModal
+ open={createDialog}
+ setOpen={setCreateDialog}
+ data={tabelData}
+ setData={setTableData}
+ />
+ </>
+ )
+}
+
+export default SelectMatnrModal;
+
+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)
+ console.log(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 SelectInputSplrCodeEditCell = (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)
+ console.log(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.id === e.target.value);
+
+ // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁
+ if (selectedSupplier) {
+ params.api.setEditCellValue({
+ id: params.id,
+ field: 'splrName',
+ value: selectedSupplier.name,
+ });
+ }
+ }}
+ fullWidth
+
+ >
+ {formData.map(e => {
+ return (
+ <MenuItem value={e.id} children={e.name} key={e.id} />
+ );
+
+ })}
+
+ </Select>
+ );
+};
+
+
+
+
+const AsnOrderModalTable = ({ tabelData, setTableData, asnId, selectedRows, setSelectedRows, tableRef }) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+
+ const [columns, setColumns] = useState([
+ {
+ field: 'maktx',
+ headerName: translate('table.field.asnOrderItem.maktx'),
+ width: 250,
+ editable: false,
+ },
+ {
+ field: 'matnrCode',
+ headerName: translate('table.field.asnOrderItem.matnrCode'),
+ width: 130,
+ editable: false,
+ },
+ {
+ 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: 'splrCode',
+ headerName: translate('table.field.asnOrderItem.splrCode') + "*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrCodeEditCell {...params} />
+ ),
+ headerClassName: "custom",
+ },
+ {
+ field: 'splrName',
+ headerName: translate('table.field.asnOrderItem.splrName') + "*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrNameEditCell {...params} />
+ ),
+ headerClassName: "custom",
+ },
+ // {
+ // field: 'packName',
+ // headerName: translate('table.field.asnOrderItem.packName'),
+ // minWidth: 100,
+ // flex: 1,
+ // editable: true,
+ // },
+ // {
+ // field: 'poDetlId',
+ // headerName: translate('table.field.asnOrderItem.poDetlId'),
+ // minWidth: 100,
+ // flex: 1,
+ // },
+ {
+ field: 'poCode',
+ headerName: translate('table.field.asnOrderItem.poDetlCode') + "*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ headerClassName: "custom",
+ },
+
+ {
+ field: 'stockUnit',
+ headerName: translate('table.field.asnOrderItem.stockUnit'),
+ minWidth: 100,
+ flex: 1,
+ editable: false,
+ },
+ // {
+ // field: 'purQty',
+ // headerName: translate('table.field.asnOrderItem.purQty'),
+ // minWidth: 100,
+ // flex: 1,
+ // editable: true,
+ // },
+ {
+ field: 'purUnit',
+ headerName: translate('table.field.asnOrderItem.purUnit'),
+ 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,
+ headerName: el.fieldsAlise,
+ minWidth: 100,
+ flex: 1,
+ editable: false
+ }))
+ setColumns([...columns, ...cols, action])
+ } else {
+ notify(msg);
+ }
+ }
+
+
+ const handleDelete = (row) => {
+ const newData = _.filter(cdata.current, (item) => item.matnrId !== row.matnrId);
+ setTableData(newData);
+ };
+
+
+ const processRowUpdate = (newRow, oldRow) => {
+ const rows = tabelData.map((r) =>
+ r.matnrId === newRow.matnrId ? { ...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.matnrId}
+ 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/wave/ItemToTaskModal.jsx b/rsf-admin/src/page/orders/wave/ItemToTaskModal.jsx
index 2f81a39..d37edc4 100644
--- a/rsf-admin/src/page/orders/wave/ItemToTaskModal.jsx
+++ b/rsf-admin/src/page/orders/wave/ItemToTaskModal.jsx
@@ -150,7 +150,7 @@
</DialogContent>
<DialogActions>
<Toolbar sx={{ width: '100%', justifyContent: 'end' }} >
- <GenerateTaskButton record={[record?.id]} dataSource={data} />
+ <GenerateTaskButton record={record?.id} dataSource={data} />
</Toolbar>
</DialogActions>
</Dialog>
@@ -165,7 +165,10 @@
const notify = useNotify();
const redirect = useRedirect();
const generateTask = async () => {
- const res = await request.post(`/wave/public/task`, { wave: record, waveItem: dataSource });
+ const params = {wave: record, waveItem: dataSource}
+ console.log('---------->');
+ console.log(record);
+ const res = await request.post(`/wave/public/task`, { wave: record?.record, waveItem: record?.dataSource });
if (res?.data?.code === 200) {
notify(res.data.msg);
redirect("/task")
diff --git a/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx b/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx
index 86a989a..cf5d60c 100644
--- a/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx
+++ b/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx
@@ -116,7 +116,6 @@
const translate = useTranslate();
const [createDialog, setCreateDialog] = useState(false);
const [drawerVal, setDrawerVal] = useState(false);
- const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_ware_areas_type')) || [];
return (
<Box display="flex">
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java
index 56b1756..ddef2aa 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java
@@ -8,7 +8,7 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
-@Component
+//@Component
public class CustomParameterFilter extends OncePerRequestFilter {
@Override
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 2efff1c..058422e 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
@@ -13,6 +13,7 @@
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.utils.ExcelUtil;
+import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams;
import com.vincent.rsf.server.manager.entity.AsnOrder;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.excel.AsnOrderTemplate;
@@ -214,4 +215,28 @@
List<Long> ids = (List<Long>) params.get("ids");
return outStockService.generateWaves(ids);
}
+
+ @PostMapping("/outStock/items/save")
+ @ApiOperation("淇濆瓨涓诲崟鍙婃槑缁�")
+ @PreAuthorize("hasAuthority('manager:outStock:save')")
+ public R orderAndItem(@RequestBody AsnOrderAndItemsParams params) throws Exception {
+ if (Objects.isNull(params)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ return outStockService.saveOrderAndItems(params, getLoginUserId());
+ }
+
+ @ApiOperation("鍗曟嵁淇℃伅淇敼")
+ @PostMapping("/outStock/items/update")
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ public R orderAndrItemUpdate(@RequestBody AsnOrderAndItemsParams params) throws Exception {
+ if (Objects.isNull(params)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ return outStockService.updateOrderItem(params, getLoginUserId());
+ }
+
+
+
+
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
index aa19574..919b81a 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -126,4 +126,8 @@
}
}
+
+
+
+
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java
index 22fcc64..71a70bd 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java
@@ -16,4 +16,8 @@
R genOutStock(List<Long> ids);
R generateWaves(List<Long> ids);
+
+ R saveOrderAndItems(AsnOrderAndItemsParams params, Long loginUserId);
+
+ R updateOrderItem(AsnOrderAndItemsParams params, Long loginUserId);
}
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 ddc4991..20dc185 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
@@ -310,6 +310,55 @@
}
/**
+ * @author Ryan
+ * @description 淇濆瓨鍑哄簱涓诲崟鍙婃槑缁�
+ * @param
+ * @return
+ * @time 2025/4/29 13:47
+ */
+ @Override
+ public R saveOrderAndItems(AsnOrderAndItemsParams params, Long loginUserId) {
+ if (Objects.isNull(params.getOrders())) {
+ throw new CoolException("涓诲崟淇℃伅涓嶈兘涓虹┖");
+ }
+ AsnOrder orders = params.getOrders();
+ if (Objects.isNull(orders)) {
+ throw new CoolException("鍗曟嵁涓嶈兘涓虹┖锛侊紒");
+ }
+ String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, orders);
+ if (Objects.isNull(ruleCode) || StringUtils.isBlank(ruleCode)) {
+ throw new CoolException("缂栫爜瑙勫垯閿欒锛氳妫�鏌ャ�孲YS_OUT_STOCK_CODE銆嶆槸鍚﹁缃纭紒锛�");
+ }
+ orders.setCode(ruleCode)
+ .setUpdateBy(loginUserId)
+ .setCreateBy(loginUserId);
+ if (!this.save(orders)) {
+ throw new CoolException("涓诲崟淇濆瓨澶辫触锛侊紒");
+ }
+ if (params.getItems().isEmpty()) {
+ throw new CoolException("鏀惰揣閫氱煡鍗曟槑缁嗕笉鑳戒负瀵掗鑺傦紒锛�");
+ }
+
+// svaeOrUpdateOrderItem(params,loginUserId);
+
+
+
+ return null;
+ }
+
+ /**
+ * @author Ryan
+ * @description 淇敼涓诲崟鍙婃槑缁�
+ * @param
+ * @return
+ * @time 2025/4/29 13:47
+ */
+ @Override
+ public R updateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) {
+ return null;
+ }
+
+ /**
* @param
* @param wave
* @return
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 f070e5f..73b2acd 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
@@ -1,6 +1,7 @@
package com.vincent.rsf.server.manager.service.impl;
import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -17,6 +18,7 @@
import com.vincent.rsf.server.manager.utils.OptimalAlgorithmUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,6 +28,7 @@
import java.util.*;
import java.util.stream.Collectors;
+@Slf4j
@Service("waveService")
public class WaveServiceImpl extends ServiceImpl<WaveMapper, Wave> implements WaveService {
@@ -59,39 +62,40 @@
if (Objects.isNull(itemParams) || itemParams.isEmpty()) {
throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
}
- Wave wave = (Wave) map.get("wave");
- Wave waves = this.getById(new LambdaQueryWrapper<Wave>().in(Wave::getId, wave.getId()));
+ List<WaveItem> items = JSONArray.parseArray(JSONArray.toJSONString(itemParams), WaveItem.class);
+ String waveId = map.get("wave").toString();
+ Wave waves = this.getById(Long.parseLong(waveId));
if (Objects.isNull(waves)) {
throw new CoolException("娉㈡鏁版嵁涓嶅瓨鍦紒锛�");
}
- List<Long> list = itemParams.stream().map(WaveItem::getWaveId).collect(Collectors.toList());
- List<WaveItem> waveItems = waveItemService.list(new LambdaQueryWrapper<WaveItem>().in(WaveItem::getWaveId, list));
+// List<Long> list = itemParams.stream().map(WaveItem::getWaveId).collect(Collectors.toList());
+ List<WaveItem> waveItems = waveItemService.list(new LambdaQueryWrapper<WaveItem>().eq(WaveItem::getWaveId, waves.getId()));
if (waveItems.isEmpty()) {
throw new CoolException("娉㈡鏄庣粏涓嶅瓨鍦紒锛�");
}
/**鐢熸垚鍑哄簱浠诲姟*/
try {
- generateOutTask(itemParams, loginUserId, wave);
+ generateOutTask(items, loginUserId, waves);
} catch (Exception e) {
- throw new CoolException("搴撲綅鑾峰彇澶辫触锛侊紒锛�");
+ log.error(e.getMessage());
+ throw new CoolException("鍑哄簱浠诲姟鐢熸垚澶辫触锛侊紒锛�");
}
//TODO 1. 鏍规嵁娉㈡鏄庣粏鐢熸垚鍑哄簱浠诲姟
// 2. 鏍规嵁鐗╂枡SKU瀵绘壘绗﹀悎鐗╂枡搴撲綅 {1. 鏍规嵁鐗╂枡缂栫爜锛屾壒娆★紝鍔ㄦ�佸瓧娈� 鏌ヨ绗﹀悎鐨勫簱浣嶏紝鍐嶆牴鎹簱浣嶄腑鐗╂枡鐨勬暟閲忛�夋嫨鏈�閫傚悎鐨勫簱浣� 2. 鍒ゆ柇褰撳墠璁㈠崟鏄叏鎷栧嚭搴撹繕鏄嫞鏂欏叆搴搣
// 3. 淇敼涓诲崟銆佹尝娆℃墽琛屾暟閲�
// 4. 鍒ゆ柇鍏ㄤ粨鍑哄簱鎴栨嫞鏂欏嚭搴�
List<Long> orderIds = waveItems.stream().map(WaveItem::getOrderId).collect(Collectors.toList());
-
- List<AsnOrder> orders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>().in(AsnOrder::getId, orderIds));
+// List<AsnOrder> orders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>().in(AsnOrder::getId, orderIds));
/**淇敼鍑哄簱鍗曠姸鎬�*/
- if (!asnOrderService.update(new LambdaQueryWrapper<AsnOrder>()
- .eq(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)
- .in(AsnOrder::getId, orders))) {
+ if (!asnOrderService.update(new LambdaUpdateWrapper<AsnOrder>()
+ .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)
+ .in(AsnOrder::getId, orderIds))) {
throw new CoolException("鍑哄簱鍗曟嵁鐘舵�佷慨鏀瑰け璐ワ紒锛�");
}
- /**淇敼娉㈡鍗曟嵁鎵ц鐘舵��*/
- if (!this.update(new LambdaUpdateWrapper<Wave>().set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_TASK).eq(Wave::getId, wave.getId()))) {
- throw new CoolException("娉㈡鐘舵�佷慨鏀瑰け璐ワ紒锛�");
- }
+// /**淇敼娉㈡鍗曟嵁鎵ц鐘舵��*/
+// if (!this.update(new LambdaUpdateWrapper<Wave>().set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_TASK).eq(Wave::getId, waves.getId()))) {
+// throw new CoolException("娉㈡鐘舵�佷慨鏀瑰け璐ワ紒锛�");
+// }
return R.ok();
}
@@ -113,7 +117,7 @@
if (locItems.isEmpty()) {
continue;
}
- List<Long> list = locItems.stream().map(LocItem::getId).collect(Collectors.toList());
+ List<Long> list = locItems.stream().map(LocItem::getLocId).collect(Collectors.toList());
/**鏍规嵁渚涘簲鍟嗘壒娆★紝鐗╂枡鐮侊紝 鍔ㄦ�佸瓧娈垫煡璇㈡寚瀹氱殑鐗╂枡搴撳瓨淇℃伅*/
List<LocItem> items = locItemService.list(new LambdaQueryWrapper<LocItem>()
.eq(LocItem::getSplrBatch, param.getSplrBatch())
@@ -185,7 +189,7 @@
/**淇敼娉㈡鎵ц鏁伴噺*/
taskItems.forEach(item -> {
boolean update = waveItemService.update(new LambdaUpdateWrapper<WaveItem>()
- .eq(WaveItem::getWaveId, item.getSource())
+ .eq(WaveItem::getId, item.getSource())
.set(WaveItem::getWorkQty, item.getAnfme()));
if (!update) {
throw new CoolException("娉㈡鎵ц鏁伴噺淇敼澶辫触锛侊紒");
@@ -195,7 +199,7 @@
List<WaveItem> waveItems = waveItemService.list(new LambdaQueryWrapper<WaveItem>().eq(WaveItem::getWaveId, wave.getId()));
double sum = waveItems.stream().mapToDouble(WaveItem::getWorkQty).sum();
/**娉㈡涓诲崟淇℃伅淇敼*/
- if (!update(new LambdaUpdateWrapper<Wave>()
+ if (!this.update(new LambdaUpdateWrapper<Wave>()
.eq(Wave::getId, wave.getId())
.set(Wave::getWorkQty, sum)
.set(Wave::getExceStatus, WaveExceStatus.WAVE_EXCE_STATUS_TASK.val))) {
--
Gitblit v1.9.1