From f1f08a7174e53f375b341c9bd4be50f637db2c2e Mon Sep 17 00:00:00 2001
From: 1 <1@123>
Date: 星期一, 02 三月 2026 16:48:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/devlop-phyz' into devlop-phyz
---
rsf-admin/src/page/orders/preparation/PreparationOrderItemEdit.jsx | 195 +++
rsf-admin/src/page/orders/preparation/preparation.css | 5
rsf-admin/src/page/orders/preparation/PreparationOrderCreate.jsx | 221 +++
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatPreparationController.java | 338 ++++
rsf-admin/src/page/orders/preparation/PreparationStockWaveDialog.jsx | 64 +
rsf-admin/src/page/orders/preparation/PreparationSelectMatnrModal.jsx | 587 ++++++++++
rsf-admin/src/page/orders/preparation/PreparationOrderEdit.jsx | 182 +++
/dev/null | 120 --
rsf-admin/src/page/orders/preparation/PreparationStockPublic.jsx | 17
rsf-admin/src/page/orders/preparation/index.jsx | 10
rsf-admin/src/page/orders/preparation/PreparationOrderModal.jsx | 282 ++++
rsf-admin/src/page/orders/outStock/OutOrderList.jsx | 163 +-
rsf-admin/src/page/orders/preparation/PreparationOrderList.jsx | 386 ++++++
rsf-admin/src/page/orders/preparation/PreparationOrderPreview.jsx | 149 ++
rsf-admin/src/page/orders/preparation/PreparationOrderItemCreate.jsx | 198 +++
rsf-admin/src/page/orders/preparation/PreparationStockSiteDialog.jsx | 54
rsf-admin/src/page/orders/preparation/PreparationMatnrInfoModal.jsx | 270 ++++
rsf-admin/src/page/orders/preparation/PreparationOrderItemList.jsx | 206 +++
18 files changed, 3,194 insertions(+), 253 deletions(-)
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
index a2ccae7..1f8ce47 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
@@ -2,11 +2,10 @@
import { useLocation, useNavigate } from 'react-router-dom';
import {
List,
- DatagridConfigurable,
SearchInput,
TopToolbar,
Toolbar,
- SelectColumnsButton,
+ ColumnsButton,
EditButton,
FilterButton,
CreateButton,
@@ -42,8 +41,10 @@
import { styled } from '@mui/material/styles';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
-import { Box, Typography, Card, Stack, Drawer } from '@mui/material';
+import { Box, Typography, Card, Stack, Drawer, LinearProgress } from '@mui/material';
import DictionarySelect from "../../components/DictionarySelect";
+import StickyDataTable from "../../components/StickyDataTable";
+import useTableLayout from '@/utils/useTableLayout';
import BillStatusField from '../../components/BillStatusField';
import MyCreateButton from "../../components/MyCreateButton";
import PageEditDrawer from "../../components/PageEditDrawer";
@@ -62,25 +63,93 @@
import OutOrderModal from "./OutOrderModal";
import request from '@/utils/request';
-const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
- '& .css-1vooibu-MuiSvgIcon-root': {
- height: '.9em'
- },
- '& .RaDatagrid-row': {
- cursor: 'auto'
- },
- '& .column-name': {
- },
- '& .opt': {
- width: 420
- },
- '& .wkType': {
- width: 110
- },
- '& .status': {
- width: 90
- },
-}));
+const ListContent = ({ drawerVal, setDrawerVal, setWaveRule, setSelectIds, setSelect }) => {
+ const { isLoading } = useListContext();
+ const { boxMaxWidth, boxMaxHeight } = useTableLayout(drawerVal);
+
+ const omittedFields = ['id', 'code', 'createTime', 'createBy$', 'memo', 'rleStatus$', 'logisNo', 'updateBy$', 'workQty', 'updateTime', 'type$'];
+
+ return (
+ <Box sx={{
+ position: 'relative',
+ maxHeight: boxMaxHeight,
+ maxWidth: boxMaxWidth,
+ overflowX: 'auto',
+ overflowY: 'auto',
+ '& .MuiTableCell-root': {
+ whiteSpace: 'nowrap',
+ },
+ '& .css-1vooibu-MuiSvgIcon-root': {
+ height: '.9em'
+ },
+ '& .RaDatagrid-row': {
+ cursor: 'auto'
+ },
+ '& .column-name': {
+ },
+ '& .opt': {
+ width: 420
+ },
+ '& .wkType': {
+ width: 110
+ },
+ '& .status': {
+ width: 90
+ },
+ }}>
+ {isLoading && (
+ <LinearProgress
+ sx={{
+ height: "2px",
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ }}
+ />
+ )}
+ <StickyDataTable
+ storeKey='outStock'
+ bulkActionButtons={<PublicTaskButton setWaveRule={setWaveRule} setSelectIds={setSelectIds} />}
+ rowClick={false}
+ hiddenColumns={omittedFields}
+ >
+ <NumberField source="id" />
+ <TextField source="code" label="table.field.outStock.code" />
+ <TextField source="poCode" label="table.field.outStock.poCode" />
+ <TextField source="type$" label="table.field.outStock.type" />
+ <TextField cellClassName="wkType" source="wkType$" label="table.field.outStock.wkType" />
+ <NumberField source="anfme" label="table.field.outStock.anfme" />
+ <NumberField source="workQty" label="table.field.outStock.workQty" />
+ <NumberField source="qty" label="table.field.outStock.qty" />
+ <TextField source="logisNo" label="table.field.outStock.logisNo" />
+ <TextField source="rleStatus$" label="table.field.outStock.rleStatus" sortable={false} />
+ <TextField source="updateBy$" label="common.field.updateBy" />
+ <DateField source="updateTime" label="common.field.updateTime" showTime />
+ <TextField source="createBy$" label="common.field.createBy" />
+ <DateField source="createTime" label="common.field.createTime" showTime />
+ <TextField source="memo" label="common.field.memo" sortable={false} />
+
+ {/* 閾跺骇鏂板 */}
+ <TextField source="saleOrgName" label="閿�鍞粍缁�" />
+ <TextField source="saleUserName" label="閿�鍞憳" />
+ <DateField source="businessTime" label="鍑哄簱鏃ユ湡" />
+ <TextField source="customerId" label="瀹㈡埛缂栫爜" />
+ <TextField source="customerName" label="瀹㈡埛" />
+ <TextField source="stockOrgName" label="table.field.outStock.stockOrgName" />
+
+ <BillStatusField cellClassName="status" source="exceStatus" label="table.field.outStock.exceStatus" />
+ <WrapperField cellClassName="opt" label="common.field.opt" >
+ {/* <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} /> */}
+ <EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton>
+ <CancelButton />
+ <CompleteButton />
+ <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} />
+ </WrapperField>
+ </StickyDataTable>
+ </Box>
+ )
+}
const filters = [
<SearchInput source="condition" alwaysOn />,
@@ -162,53 +231,19 @@
<FilterButton />
<CreateByOrderButton setCreateDialog={setCreateDialog} />
<MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} />
- <SelectColumnsButton preferenceKey='outStock' />
+ <ColumnsButton storeKey='outStock' />
<ImportButton value={'outStockItem'} />
</TopToolbar>
)}
perPage={DEFAULT_PAGE_SIZE}
>
- <StyledDatagrid
- sx={{ width: '100%' }}
- preferenceKey='outStock'
- bulkActionButtons={<PublicTaskButton setWaveRule={setWaveRule} setSelectIds={setSelectIds} />}
- rowClick={false}
- expandSingle={true}
- omit={['id', 'code', 'createTime', 'createBy$', 'memo', 'rleStatus$', 'logisNo', 'updateBy$', 'workQty', 'updateTime', 'type$']}
- >
- <NumberField source="id" />
- <TextField source="code" label="table.field.outStock.code" />
- <TextField source="poCode" label="table.field.outStock.poCode" />
- <TextField source="type$" label="table.field.outStock.type" />
- <TextField cellClassName="wkType" source="wkType$" label="table.field.outStock.wkType" />
- <NumberField source="anfme" label="table.field.outStock.anfme" />
- <NumberField source="workQty" label="table.field.outStock.workQty" />
- <NumberField source="qty" label="table.field.outStock.qty" />
- <TextField source="logisNo" label="table.field.outStock.logisNo" />
- <TextField source="rleStatus$" label="table.field.outStock.rleStatus" sortable={false} />
- <TextField source="updateBy$" label="common.field.updateBy" />
- <DateField source="updateTime" label="common.field.updateTime" showTime />
- <TextField source="createBy$" label="common.field.createBy" />
- <DateField source="createTime" label="common.field.createTime" showTime />
- <TextField source="memo" label="common.field.memo" sortable={false} />
-
- {/* 閾跺骇鏂板 */}
- <TextField source="saleOrgName" label="閿�鍞粍缁�" />
- <TextField source="saleUserName" label="閿�鍞憳" />
- <DateField source="businessTime" label="鍑哄簱鏃ユ湡" />
- <TextField source="customerId" label="瀹㈡埛缂栫爜" />
- <TextField source="customerName" label="瀹㈡埛" />
- <TextField source="stockOrgName" label="table.field.outStock.stockOrgName" />
-
- <BillStatusField cellClassName="status" source="exceStatus" label="table.field.outStock.exceStatus" />
- <WrapperField cellClassName="opt" label="common.field.opt" >
- {/* <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} /> */}
- <EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton>
- <CancelButton />
- <CompleteButton />
- <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} />
- </WrapperField>
- </StyledDatagrid>
+ <ListContent
+ drawerVal={drawerVal}
+ setDrawerVal={setDrawerVal}
+ setWaveRule={setWaveRule}
+ setSelectIds={setSelectIds}
+ setSelect={setSelect}
+ />
</List>
{/* <OutOrderCreate
open={manualDialog}
diff --git a/rsf-admin/src/page/orders/preparation/MatPreparationItemList.jsx b/rsf-admin/src/page/orders/preparation/MatPreparationItemList.jsx
deleted file mode 100644
index 1f3317e..0000000
--- a/rsf-admin/src/page/orders/preparation/MatPreparationItemList.jsx
+++ /dev/null
@@ -1,216 +0,0 @@
-import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
-import { useFetcher, useNavigate } from 'react-router-dom';
-import {
- List,
- DatagridConfigurable,
- SearchInput,
- TopToolbar,
- SelectColumnsButton,
- FilterButton,
- useTranslate,
- TextField,
- NumberField,
- DateField,
- BooleanField,
- ReferenceField,
- TextInput,
- useRefresh,
- DateInput,
- useNotify,
- SelectInput,
- useListContext,
- NumberInput,
- useGetRecordId,
-} from 'react-admin';
-import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
-import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material';
-import MyCreateButton from "../components/MyCreateButton";
-import PageDrawer from "../components/PageDrawer";
-import { styled } from '@mui/material/styles';
-// import TaskItemCreate from "./TaskItemCreate";
-import request from '@/utils/request';
-
-const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
- '& .css-1vooibu-MuiSvgIcon-root': {
- height: '.9em'
- },
- '& .RaDatagrid-row': {
- cursor: 'auto',
- maring: '1em'
- },
- '& .column-name': {
- },
- '& .opt': {
- width: 220
- },
-}));
-
-const filters = [
- <SearchInput source="condition" alwaysOn />,
- // <DateInput label='common.time.after' source="timeStart" />,
- // <DateInput label='common.time.before' source="timeEnd" />,
- // <NumberInput source="taskId" label="table.field.taskItem.taskId" />,
- // <NumberInput source="orderId" label="table.field.taskItem.orderId" />,
- // <NumberInput source="orderType" label="table.field.taskItem.orderType" />,
- // <NumberInput source="orderItemId" label="table.field.taskItem.orderItemId" />,
- <NumberInput source="matnrId" label="table.field.taskItem.matnrId" />,
- <TextInput source="maktx" label="table.field.taskItem.maktx" />,
- <TextInput source="matnrCode" label="table.field.taskItem.matnrCode" />,
- <TextInput source="unit" label="table.field.taskItem.unit" />,
- <NumberInput source="anfme" label="table.field.taskItem.anfme" />,
- <TextInput source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />,
- <TextInput source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />,
- <TextInput source="projectCode" label="table.field.asnOrderItem.projectCode" />,
- <TextInput source="batch" label="table.field.taskItem.batch" />,
- <TextInput source="spec" label="table.field.taskItem.spec" />,
- <TextInput source="model" label="table.field.taskItem.model" />,
- <TextInput label="common.field.memo" source="memo" />,
- <SelectInput
- label="common.field.status"
- source="status"
- choices={[
- { id: '1', name: 'common.enums.statusTrue' },
- { id: '0', name: 'common.enums.statusFalse' },
- ]}
- resettable
- />,
-]
-
-const MatPreparationItemList = () => {
- const translate = useTranslate();
- const [createDialog, setCreateDialog] = useState(false);
- const [drawerVal, setDrawerVal] = useState(false);
- const recordId = useGetRecordId();
-
- return (
- <Box display="flex">
- <List
- resource="preparationItem"
- sx={{
- flexGrow: 1,
- transition: (theme) =>
- theme.transitions.create(['all'], {
- duration: theme.transitions.duration.enteringScreen,
- }),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
- }}
- title={"menu.preparationItem"}
- empty={false}
- pagination={false}
- filters={filters}
- filter={{ taskId: recordId }}
- sort={{ field: "create_time", order: "desc" }}
- actions={(
- <TopToolbar>
- <FilterButton />
- {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */}
- <SelectColumnsButton preferenceKey='preparationItem' />
- {/* <MyExportButton /> */}
- </TopToolbar>
- )}
- perPage={DEFAULT_PAGE_SIZE}
- >
- <DynamicFields />
- </List>
- <TaskItemCreate
- open={createDialog}
- setOpen={setCreateDialog} />
- <PageDrawer
- title='PreparationItem Detail'
- drawerVal={drawerVal}
- setDrawerVal={setDrawerVal}
- >
- </PageDrawer>
- </Box>
- )
-}
-
-export default MatPreparationItemList;
-
-
-const DynamicFields = (props) => {
- const translate = useTranslate();
- const notify = useNotify();
- const [columns, setColumns] = useState([]);
- const { isLoading } = useListContext();
- const refresh = useRefresh();
- useEffect(() => {
- getDynamicFields();
- }, []);
-
- const getDynamicFields = async () => {
- const { data: { code, data, msg }, } = await request.get("/fields/enable/list");
- if (code == 200) {
- const arr = [
- <TextField source="matnrCode" label="鐗╂枡缂栫爜" />,
- <TextField source="maktx" label="鐗╂枡鍚嶇О" />,
- <TextField source="spec" label="瑙勬牸" />,
- <TextField source="unit" label="鍗曚綅" />,
- <TextField source="anfme" label="鏁伴噺" />,
-
-
- // <NumberField source="id" />,
- // // <NumberField source="taskId" label="table.field.taskItem.taskId" />,
- // // <NumberField source="orderId" label="table.field.taskItem.orderId" />,
- // // <NumberField source="orderType$" label="table.field.taskItem.orderType" />,
- // // <NumberField source="wkType$" label="table.field.taskItem.wkType" />,
- // <NumberField source="orderItemId" label="table.field.taskItem.orderItemId" />,
- // <NumberField source="matnrId" label="table.field.taskItem.matnrId" />,
- // <TextField source="maktx" label="table.field.taskItem.maktx" />,
- // <TextField source="matnrCode" label="table.field.taskItem.matnrCode" />,
- // <TextField source="unit" label="table.field.taskItem.unit" />,
- // <NumberField source="anfme" label="table.field.taskItem.anfme" />,
- // <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />,
- // <TextField source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />,
- // <TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />,
- // <TextField source="batch" label="table.field.taskItem.batch" />,
- // <TextField source="isptResult$" label="table.field.taskItem.isptResult" />,
- // <TextField source="spec" label="table.field.taskItem.spec" />,
- // <TextField source="model" label="table.field.taskItem.model" />,
- ]
- const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />)
- const lastArr = [
- <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
- <TextField source="nickname" />
- </ReferenceField>,
- <DateField source="updateTime" label="common.field.updateTime" showTime />,
- <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
- <TextField source="nickname" />
- </ReferenceField>,
- <DateField source="createTime" label="common.field.createTime" showTime />,
- <BooleanField source="statusBool" label="common.field.status" sortable={false} />,
- <TextField source="memo" label="common.field.memo" sortable={false} />,
- ]
- setColumns([...arr, ...fields, ...lastArr]);
- } else {
- notify(msg);
- }
- }
-
- return (
- <Box sx={{ position: 'relative', minHeight: "60vh", }}>
- {isLoading && (
- <LinearProgress
- sx={{
- height: "2px",
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- }}
- />
- )}
- {columns.length > 0 &&
- <StyledDatagrid
- preferenceKey='preparationItem'
- bulkActionButtons={false}
- rowClick={false}
- // expand={() => <TaskItemPanel />}
- expandSingle={true}
- omit={['id', 'createTime', 'createBy', 'memo', 'taskId', 'orderId', 'orderItemId', 'matnrId', 'platWorkCode', 'projectCode','statusBool']}
- >
- {columns.map((column) => column)}
- </StyledDatagrid>}
- </Box>
- )
-}
diff --git a/rsf-admin/src/page/orders/preparation/MatPreparationList.jsx b/rsf-admin/src/page/orders/preparation/MatPreparationList.jsx
deleted file mode 100644
index 58580fc..0000000
--- a/rsf-admin/src/page/orders/preparation/MatPreparationList.jsx
+++ /dev/null
@@ -1,422 +0,0 @@
-import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
-import { useNavigate } from 'react-router-dom';
-import request from '@/utils/request';
-
-import {
- List,
- DatagridConfigurable,
- SearchInput,
- TopToolbar,
- SelectColumnsButton,
- FilterButton,
- BulkDeleteButton,
- WrapperField,
- useRecordContext,
- useTranslate,
- useNotify,
- useRefresh,
- TextField,
- NumberField,
- DateField,
- AutocompleteInput,
- BooleanField,
- TextInput,
- DateInput,
- SelectInput,
- NumberInput,
- Button,
- EditButton,
-} from 'react-admin';
-import { Box, Typography, Card, Stack, Drawer } from '@mui/material';
-import { styled } from '@mui/material/styles';
-import SwapVertIcon from '@mui/icons-material/SwapVert';
-import AlignVerticalTopIcon from '@mui/icons-material/AlignVerticalTop';
-import TaskAltIcon from '@mui/icons-material/TaskAlt';
-import CancelIcon from '@mui/icons-material/Cancel';
-import PageDrawer from "../../components/PageDrawer";
-import MatPreparationPanel from "./MatPreparationPanel";
-import MyField from "../../components/MyField";
-import ConfirmButton from "../../components/ConfirmButton";
-import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, AUTO_RUN_CHECK_ORDERS } from '@/config/setting';
-import PlayArrowOutlinedIcon from '@mui/icons-material/PlayArrowOutlined';
-import PauseIcon from '@mui/icons-material/Pause';
-import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline';
-import * as Common from '@/utils/common';
-import ColorizeOutlinedIcon from '@mui/icons-material/ColorizeOutlined';
-import GradingOutlinedIcon from '@mui/icons-material/GradingOutlined';
-
-const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
- '& .css-1vooibu-MuiSvgIcon-root': {
- height: '.9em'
- },
- '& .RaDatagrid-row': {
- cursor: 'auto'
- },
- '& .column-name': {
- },
- '& .opt': {
- width: 248
- },
- '& .MuiTableCell-root': {
- whiteSpace: 'nowrap',
- overflow: 'visible',
- textOverflow: 'unset'
- }
-
-}));
-
-
-const MatPreparationList = (props) => {
- const translate = useTranslate();
- const refresh = useRefresh();
- const [drawerVal, setDrawerVal] = useState(false);
- const [autoExce, setAutoExce] = useState(false);
- const dict = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_warehouse_type')) || [];
-
- useEffect(() => {
- // getConfig()
- }, [])
-
- // const getConfig = async () => {
- // const { data: { code, data, msg } } = await request.get('/config/flag/' + AUTO_RUN_CHECK_ORDERS);
- // if (code === 200) {
- // setAutoExce(JSON.parse(data?.val))
- // }
- // }
-
- // useEffect(() => {
- // const interval = setInterval(() => {
- // refresh();
- // }, 5000); // 姣�5绉掑埛鏂颁竴娆�
-
- // return () => clearInterval(interval); // 娓呴櫎瀹氭椂鍣�
- // }, [refresh])
-
- const filters = [
- <SearchInput source="condition" alwaysOn />,
- // <DateInput label='common.time.after' source="timeStart" />,
- // <DateInput label='common.time.before' source="timeEnd" />,
- <TextInput source="orderCode" label="table.field.preparation.orderCode" />,
- <NumberInput source="orderStatus" label="table.field.preparation.orderStatus" />,
- <DateInput source="orderTime" label="table.field.preparation.orderTime" />,
- <NumberInput source="anfme" label="table.field.preparation.anfme" />,
-
- // <AutocompleteInput choices={dict} optionText='label' optionValue="value" source="warehType" label="table.field.task.warehType" />,
- // <TextInput source="orgLoc" label="table.field.task.orgLoc" />,
- // <TextInput source="orgSite" label="table.field.task.orgSite" />,
- // <TextInput source="targLoc" label="table.field.task.targLoc" />,
- // <TextInput source="targSite" label="table.field.task.targSite" />,
- // <TextInput source="barcode" label="table.field.task.barcode" />,
- // <TextInput source="robotCode" label="table.field.task.robotCode" />,
- // <NumberInput source="exceStatus" label="table.field.task.exceStatus" />,
- // <TextInput source="expDesc" label="table.field.task.expDesc" />,
- // <NumberInput source="sort" label="table.field.task.sort" />,
- // <TextInput source="expCode" label="table.field.task.expCode" />,
- // <DateInput source="startTime" label="table.field.task.startTime" />,
- // <DateInput source="endTime" label="table.field.task.endTime" />,
- // <TextInput label="common.field.memo" source="memo" />,
- // <SelectInput
- // label="common.field.status"
- // source="status"
- // choices={[
- // { id: '1', name: 'common.enums.statusTrue' },
- // { id: '0', name: 'common.enums.statusFalse' },
- // ]}
- // resettable
- // />,
- ]
-
- return (
- <Box display="flex">
- <List
- queryOptions={{ refetchInterval: 5000 }}
- sx={{
- flexGrow: 1,
- transition: (theme) =>
- theme.transitions.create(['all'], {
- duration: theme.transitions.duration.enteringScreen,
- }),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
- }}
- title={"menu.preparation"}
- empty={false}
- filters={filters}
- sort={{ field: "sort", order: "desc" }}
- actions={(
- <TopToolbar>
- {/* <BulkAutoStartButton autoExce={autoExce} setAutoExce={setAutoExce}/> */}
- <BulkAutoPauseButton autoExce={autoExce} setAutoExce={setAutoExce} />
- <FilterButton />
- <SelectColumnsButton preferenceKey='preparation' />
- </TopToolbar>
- )}
- perPage={DEFAULT_PAGE_SIZE}
- >
- <StyledDatagrid
- preferenceKey='preparation'
- bulkActionButtons={false}
- rowClick={false}
- expand={<MatPreparationPanel />}
- expandSingle={true}
- omit={['id', 'sort', 'createTime', 'createBy$', 'memo', 'robotCode', 'exceStatus', 'expDesc', 'expCode', 'status','warehType$']}
- >
- <NumberField source="id" />
- <TextField source="taskCode" label="澶囨枡鍙�" />
- <NumberField source="status" label="table.field.task.exceStatus" />
- <DateField source="startTime" label="table.field.task.startTime" />
- <NumberField source="sort" label="鏁伴噺" />
- {/* table.field.task.sort */}
-
- {/* <TextField source="taskCode" label="table.field.task.taskCode" />
- <NumberField source="taskStatus$" label="table.field.task.taskStatus" />
- <NumberField source="taskType$" label="table.field.task.taskType" />
- <NumberField source="warehType$" label="table.field.task.warehType" />
- <TextField source="orgLoc" label="table.field.task.orgLoc" />
- <TextField source="orgSite" label="table.field.task.orgSite" />
- <TextField source="targLoc" label="table.field.task.targLoc" />
- <TextField source="targSite" label="table.field.task.targSite" />
- <TextField source="barcode" label="table.field.task.barcode" />
- <TextField source="robotCode" label="table.field.task.robotCode" />
- <NumberField source="exceStatus" label="table.field.task.exceStatus" />
- <TextField source="expDesc" label="table.field.task.expDesc" />
- <NumberField source="sort" label="table.field.task.sort" />
- <TextField source="expCode" label="table.field.task.expCode" />
- <TextField source="updateBy$" label="common.field.updateBy" />
- <TextField source="createBy$" label="common.field.createBy" />
- <DateField source="updateTime" label="common.field.updateTime" showTime />
- <DateField source="createTime" label="common.field.createTime" showTime />
- <TextField source="memo" label="common.field.memo" sortable={false} /> */}
- <WrapperField cellClassName="opt" label="common.field.opt" onClick={(e) => e.stopPropagation()} >
- <EditButton label="toolbar.detail" />
- <DoneButton title="杞崲" label="杞崲" sx={{ padding: '1px', fontSize: '.75rem' }} ></DoneButton>
- <CancelButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
- <CheckButton />
- <PickButton />
- {/* <SetTopButton /> */}
- </WrapperField>
- </StyledDatagrid>
- </List>
- <PageDrawer
- title='Preparation Detail'
- drawerVal={drawerVal}
- setDrawerVal={setDrawerVal}
- >
- </PageDrawer>
- </Box>
- )
-}
-
-export default MatPreparationList;
-
-/**
- * 鐩樼偣
- * @returns te
- */
-const CheckButton = () => {
- const record = useRecordContext();
- const notify = useNotify();
- const refresh = useRefresh();
-
- const checkClick = async () => {
- const { data: { code, data, msg } } = await request.post(`/task/check/` + record.id);
- if (code === 200) {
- notify(msg);
- refresh();
- } else {
- notify(msg);
- }
- }
-
- return (record?.taskStatus == 199 && record?.taskType == 107 ? <ConfirmButton label={"toolbar.check"} startIcon={<GradingOutlinedIcon />} onConfirm={checkClick} /> : <></>)
-}
-
-/**鑷姩涓嬪彂浠诲姟**/
-const BulkAutoStartButton = ({ autoExce, setAutoExce }) => {
- const notify = useNotify();
- const startClick = async () => {
- setAutoExce(true)
- const { data: { code, data, msg } } = await request.post('/config/byFlag', { val: true, flag: 'AUTO_RUN_CHECK_ORDERS' });
- if (code === 200) {
- notify(msg);
- } else {
- notify(msg);
- }
- }
- return (
- !autoExce ? <Button label="toolbar.autoStartLocs" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} /> : <></>
- )
-}
-
-const BulkAutoPauseButton = ({ autoExce, setAutoExce }) => {
- const notify = useNotify();
- const pauseClick = async () => {
- const { data: { code, data, msg } } = await request.post('/config/byFlag', { val: false, flag: 'AUTO_RUN_CHECK_ORDERS' });
- if (code === 200) {
- notify(msg);
- setAutoExce(false)
- } else {
- notify(msg);
- }
- }
- return (
- autoExce ? <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseIcon />} /> : <></>
- )
-}
-
-
-/**
- * 鎷f枡鍑哄簱
- * @returns
- */
-const PickButton = () => {
- const record = useRecordContext();
- const notify = useNotify();
- const refresh = useRefresh();
-
- const pickClick = async () => {
- const { data: { code, data, msg } } = await request.post(`/task/pick/` + record.id);
- if (code === 200) {
- notify(msg);
- refresh();
- } else {
- notify(msg);
- }
- }
-
- return (
- record?.taskStatus == 199 && record?.taskType == 103 ? <ConfirmButton label={"toolbar.pick"} startIcon={<ColorizeOutlinedIcon />} onConfirm={pickClick} /> : <></>
- )
-}
-
-
-/**
- * 瀹屾垚鎿嶄綔
- * @returns
- */
-const DoneButton = (props) => {
- const record = useRecordContext();
- const notify = useNotify();
- const refresh = useRefresh();
- const clickComplete = () => {
- completeTask(record)
- };
- //瀹屾垚浠诲姟
- const completeTask = async (row) => {
- const { data: { code, data, msg } } = await request.post(`task/complete/` + row.id);
- if (code === 200) {
- notify(msg);
- refresh();
- } else {
- notify(msg);
- }
- }
- return (
- ((record?.taskStatus < 98) || (record?.taskType >= 101 && record?.taskStatus < 198)) || (record?.taskType == 11 && record?.taskStatus == 101) ? (<ConfirmButton label={"杞崲"} color="secondary" startIcon={<TaskAltIcon />} onConfirm={clickComplete} />) : (<></>)
- )
-}
-
-/**
- * 鍙栨秷鎸夐挳
- * @returns
- */
-const CancelButton = () => {
- const record = useRecordContext();
- const notify = useNotify();
- const refresh = useRefresh();
- const clickCancel = () => {
- cancleTask(record)
- };
- //鍙栨秷浠诲姟
- const cancleTask = async (row) => {
- const { data: { code, data, msg } } = await request.post(`/task/remove/` + row.id);
- if (code === 200) {
- notify(msg);
- refresh();
- } else {
- notify(msg);
- }
- }
- return (
- (record.taskStatus == 1 || record.taskStatus == 101) && (record.taskType == 1 || record.taskType == 101 || record.taskType == 10 || record.taskType == 107 || record.taskType == 103 || record.taskType == 11) ?
- <ConfirmButton
- onConfirm={clickCancel}
- startIcon={<CancelIcon />}
- label={"toolbar.cancel"}>
- </ConfirmButton>
- :
- <></>
- )
-}
-/**
- * 缃《鎿嶄綔
- * @returns
- */
-const SetTopButton = () => {
- const record = useRecordContext();
- const notify = useNotify();
- const refresh = useRefresh();
- const clickTop = (event) => {
- event.stopPropagation();
- topTask(record)
- };
- //缃《浠诲姟
- const topTask = async (row) => {
- const { data: { code, data, msg } } = await request.post(`/task/top/` + row.id);
- if (code === 200) {
- notify(msg);
- refresh();
- } else {
- notify(msg);
- }
- }
- return (
- (record.taskStatus == 1 || record.taskStatus == 101) && (record.taskType == 1 || record.taskType == 101 || record.taskType == 10 || record.taskType == 103 || record.taskType == 11) ?
- <Button
- onClick={clickTop}
- label="toolbar.top">
- <AlignVerticalTopIcon />
- </Button>
- :
- <></>
- )
-}
-
-/**
- * 鎵归噺鍙栨秷
- * @returns
- */
-const BulkCancelButton = () => {
- const record = useRecordContext();
- const clickCancel = () => {
- cancleTask([record])
- };
- //鍙栨秷浠诲姟
- const cancleTask = async (row) => { }
- return (
- <Button
- onClick={clickCancel}
- label="toolbar.cancel">
- <CancelIcon />
- </Button>
- )
-}
-
-/**
- * 鎵归噺鎺掑簭
- * @returns
- */
-const BulkResortButton = () => {
- const record = useRecordContext();
- const bulkResort = () => {
- resortTask([record])
- };
- //鎵归噺鎺掑簭
- const resortTask = async (row) => { }
- return (
- <Button
- onClick={bulkResort}
- label="toolbar.resort">
- <SwapVertIcon />
- </Button>
- )
-}
diff --git a/rsf-admin/src/page/orders/preparation/MatPreparationPanel.jsx b/rsf-admin/src/page/orders/preparation/MatPreparationPanel.jsx
deleted file mode 100644
index 3892186..0000000
--- a/rsf-admin/src/page/orders/preparation/MatPreparationPanel.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import React, { useState, useRef, useEffect, useMemo } from "react";
-import { Box } from '@mui/material';
-import {
- List,
- DatagridConfigurable,
- useRecordContext,
- useTranslate,
- TextField,
- NumberField,
- DateField,
- BooleanField,
- ReferenceField,
-} from 'react-admin';
-import { styled } from '@mui/material/styles';
-import PageDrawer from "../../components/PageDrawer";
-import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
-import * as Common from '@/utils/common';
-
-const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
- '& .css-1vooibu-MuiSvgIcon-root': {
- height: '.9em'
- },
- '& .RaDatagrid-row': {
- cursor: 'auto'
- },
- '& .column-name': {
- },
- '& .opt': {
- width: 200
- },
- // 娣诲姞鍒楀鏍峰紡
- '& .col-code': {
- width: 120,
- minWidth: 120,
- maxWidth: 150,
- },
- '& .col-name': {
- width: 180,
- minWidth: 150,
- maxWidth: 250,
- },
- '& .col-spec': {
- width: 120,
- minWidth: 120,
- maxWidth: 200,
- },
- '& .col-unit': {
- width: 80,
- minWidth: 60,
- maxWidth: 100,
- },
- '& .col-quantity': {
- width: 100,
- minWidth: 80,
- maxWidth: 120,
- },
-}));
-
-const MatPreparationPanel = () => {
- const record = useRecordContext();
- const translate = useTranslate();
- const [createDialog, setCreateDialog] = useState(false);
- const [drawerVal, setDrawerVal] = useState(false);
- return (
- <>
- <Box display="flex">
- <List resource="preparationItem"
- sx={{
- flexGrow: 1,
- transition: (theme) =>
- theme.transitions.create(['all'], {
- duration: theme.transitions.duration.enteringScreen,
- }),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
- }}
- filter={{ taskId: record.id }}
- // title={"menu.taskItem"}
- pagination={false}
- empty={false}
- actions={false}
- >
- <StyledDatagrid
- preferenceKey='preparationItem'
- bulkActionButtons={false}
- rowClick={false}
- expandSingle
- omit={['id', 'taskId', 'createTime', 'createBy$', 'memo', 'taskId', 'orderId', 'orderItemId', 'matnrId']}
- >
- <TextField source="matnrCode" label="鐗╂枡缂栫爜" cellClassName="col-code" />,
- <TextField source="maktx" label="鐗╂枡鍚嶇О" cellClassName="col-name" />,
- {/* <TextField source="spec" label="瑙勬牸" cellClassName="col-spec" />, */}
- {/* <TextField source="unit" label="鍗曚綅" cellClassName="col-unit" />, */}
- <TextField source="anfme" label="鏁伴噺" cellClassName="col-quantity" />,
- {/* <NumberField source="id" />
- <NumberField source="taskId" label="table.field.taskItem.taskId" />
- <NumberField source="orderId" label="table.field.preparationItem.orderId" />
- <NumberField source="orderType$" label="table.field.preparationItem.orderType" />
- <TextField source="sourceCode" label="table.field.taskItem.sourceCode" />
- <NumberField source="orderItemId" label="table.field.preparationItem.orderItemId" />
- <NumberField source="matnrId" label="table.field.preparationItem.matnrId" />
- <TextField source="maktx" label="table.field.preparationItem.maktx" />
- <TextField source="matnrCode" label="table.field.preparationItem.matnrCode" />
- <TextField source="unit" label="table.field.preparationItem.unit" />
- <NumberField source="anfme" label="table.field.preparationItem.anfme" />
- <TextField source="batch" label="table.field.preparationItem.batch" />
- <TextField source="spec" label="table.field.preparationItem.spec" />
- <TextField source="model" label="table.field.preparationItem.model" /> */}
- {/* <TextField source="updateBy$" label="common.field.updateBy"/>
- <TextField source="createBy$" label="common.field.createBy"/>
- <DateField source="updateTime" label="common.field.updateTime" showTime />
- <DateField source="createTime" label="common.field.createTime" showTime />
- <TextField source="memo" label="common.field.memo" sortable={false} /> */}
- </StyledDatagrid>
- </List>
- </Box>
- </>
- );
-};
-
-export default MatPreparationPanel;
diff --git a/rsf-admin/src/page/orders/preparation/PreparationMatnrInfoModal.jsx b/rsf-admin/src/page/orders/preparation/PreparationMatnrInfoModal.jsx
new file mode 100644
index 0000000..e51d215
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationMatnrInfoModal.jsx
@@ -0,0 +1,270 @@
+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 { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+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 MatnrInfoModal = (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 [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE });
+ const [rowCount, setRowCount] = useState(0);
+ const [isLoading, setIsLoading] = useState(false);
+ const handleChange = (e) => {
+ const { name, value } = e.target;
+ setFormData(() => ({
+ [name]: value
+ }));
+ };
+
+ const reset = () => {
+ setFormData({
+ name: null,
+ code: null,
+ groupId: null
+ })
+ }
+
+ 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 () => {
+ setIsLoading(true)
+ console.log(page);
+ const res = await request.post(`/matnr/page`, {
+ ...formData,
+ current: page?.page,
+ pageSize: page?.pageSize,
+ orderBy: "create_time desc"
+ });
+ if (res?.data?.code === 200) {
+ setTableData(res.data.data.records);
+ setRowCount(res.data?.data?.total);
+
+ } else {
+ notify(res.data.msg);
+ }
+ setIsLoading(false)
+
+ };
+
+ useEffect(() => {
+ getData();
+ }, [open, page]);
+
+ 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
+ }}>
+ {translate("common.action.newAddMats")}
+ <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}
+ page={page}
+ rowCount={rowCount}
+ setPage={setPage}
+ isLoading={isLoading}
+ 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 MatnrInfoModal;
+
+const AsnWareModalTable = ({ tableData, setTableData, page, isLoading, pageSize, setPage, rowCount, 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
+ rowCount={rowCount}
+ paginationMode="server"
+ paginationModel={page}
+ onPaginationModelChange={setPage}
+ loading={isLoading}
+ slotProps={{
+ loadingOverlay: {
+ variant: 'linear-progress',
+ noRowsVariant: 'linear-progress',
+ },
+ }}
+ />
+ </div>
+ );
+};
\ No newline at end of file
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderCreate.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderCreate.jsx
new file mode 100644
index 0000000..ed3d15d
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderCreate.jsx
@@ -0,0 +1,221 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ CreateBase,
+ useTranslate,
+ TextInput,
+ NumberInput,
+ BooleanInput,
+ TextField,
+ WrapperField,
+ NumberField,
+ DateInput,
+ TopToolbar,
+ SelectColumnsButton,
+ DatagridConfigurable,
+ SaveButton,
+ SelectInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ Toolbar,
+ required,
+ useDataProvider,
+ useNotify,
+ Form,
+ useCreateController,
+ useGetList,
+ useList,
+ ListContextProvider,
+ useListContext,
+ Button,
+ useRecordContext,
+} from 'react-admin';
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Stack,
+ Grid,
+ Box,
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import { styled } from '@mui/material/styles';
+import StatusSelectInput from "../../components/StatusSelectInput";
+import OutOrderItemList from "./PreparationOrderItemList";
+import MemoInput from "../../components/MemoInput";
+import AddIcon from '@mui/icons-material/Add';
+import SelectMatnrModal from "./PreparationSelectMatnrModal";
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+ '& .css-1vooibu-MuiSvgIcon-root': {
+ height: '.9em'
+ },
+ '& .RaDatagrid-row': {
+ cursor: 'auto'
+ },
+ '& .column-name': {
+ },
+ '& .opt': {
+ width: 200
+ },
+}));
+
+
+const OutOrderCreate = (props) => {
+ const { open, setOpen, record } = props;
+ const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_order_type')) || [];
+ const business = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || [];
+ const translate = useTranslate();
+ const notify = useNotify();
+ const [drawerVal, setDrawerVal] = useState(false);
+ const [matCreate, setMatCreate] = useState(false);
+
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+
+ const handleSuccess = async (data) => {
+ setOpen(false);
+ notify('common.response.success');
+ };
+
+ const handleError = async (error) => {
+ notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+ };
+
+ const { data, total, isPending, error, refetch, meta } = useGetList('/wave/locs/preview', { filter: { waveId: record?.id } });
+ const listContext = useList({ data, isPending });
+
+ return (
+ <>
+ <CreateBase
+ record={{}}
+ transform={(data) => {
+ return data;
+ }}
+ mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+ >
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ fullWidth
+ disableRestoreFocus
+ maxWidth="xl" // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+ >
+ <Form
+ resource="outStock"
+ >
+ <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 }}>
+ <>
+ <Grid container>
+ <Grid item xs={12} display="flex" gap={1}>
+ <TextInput
+ label="table.field.asnOrder.poCode"
+ source="poCode"
+ parse={v => v}
+ />
+ <NumberInput
+ label="table.field.asnOrder.poId"
+ source="poId"
+ />
+ {/* <AutocompleteInput
+ choices={dicts}
+ optionText="label"
+ label="table.field.asnOrder.type"
+ source="type"
+ optionValue="value"
+ validate={required()}
+ parse={v => v}
+ /> */}
+ <AutocompleteInput
+ choices={business}
+ optionText="label"
+ label="table.field.asnOrder.wkType"
+ source="wkType"
+ optionValue="value"
+ validate={required()}
+ parse={v => v}
+ />
+ <NumberInput
+ label="table.field.asnOrder.anfme"
+ source="anfme"
+ validate={required()}
+ />
+
+ </Grid>
+ <Grid item xs={12} display="flex" gap={1}>
+ <NumberInput
+ label="table.field.asnOrder.qty"
+ source="qty"
+ />
+ <TextInput
+ label="table.field.asnOrder.logisNo"
+ source="logisNo"
+ parse={v => v}
+ />
+ <DateInput
+ label="table.field.asnOrder.arrTime"
+ source="arrTime"
+ />
+ <SelectInput
+ label="table.field.asnOrder.rleStatus"
+ source="rleStatus"
+ choices={[
+ { id: 0, name: ' 姝e父' },
+ { id: 1, name: ' 宸查噴鏀�' },
+ ]}
+ />
+ </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>
+
+ </Box>
+ </>
+ </DialogContent>
+ </Form>
+ </Dialog>
+ </CreateBase>
+ </>
+ )
+}
+
+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/preparation/PreparationOrderEdit.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderEdit.jsx
new file mode 100644
index 0000000..cfbb930
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderEdit.jsx
@@ -0,0 +1,182 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ Edit,
+ SimpleForm,
+ useTranslate,
+ TextInput,
+ DateInput,
+ SelectInput,
+ AutocompleteInput,
+ SaveButton,
+ Toolbar,
+ required,
+ DeleteButton,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography } from '@mui/material';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import EditBaseAside from "../../components/EditBaseAside";
+import CustomerTopToolBar from "../../components/EditTopToolBar";
+import OutOrderItemList from "./PreparationOrderItemList";
+
+
+const PreparationOrderEdit = () => {
+ const translate = useTranslate();
+ const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_order_type')) || [];
+ const business = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || [];
+
+ return (
+ <>
+ <Edit
+ redirect="list"
+ mutationMode={EDIT_MODE}
+ actions={<CustomerTopToolBar />}
+ aside={<EditBaseAside />}
+ >
+ <SimpleForm
+ shouldUnregister
+ warnWhenUnsavedChanges
+ toolbar={false}
+ mode="onTouched"
+ defaultValues={{}}
+ >
+ <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}
+ sx={{
+ "& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled": {
+ bgcolor: 'white',
+ WebkitTextFillColor: "rgba(0, 0, 0)"
+ },
+
+ "& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled": {
+ bgcolor: 'white',
+ WebkitTextFillColor: "rgba(0, 0, 0)"
+ },
+ "& .MuiFilledInput-root.MuiInputBase-sizeSmall": {
+ bgcolor: 'white',
+ }
+ }}
+ >
+ <Grid item xs={24} md={12} >
+ <Typography variant="h6" gutterBottom>
+ {translate('common.edit.title.main')}
+ </Typography>
+ <Stack direction='row' gap={2}>
+ {/* <TextInput
+ label="table.field.outStock.code"
+ source="code"
+ readOnly
+ parse={v => v}
+ /> */}
+ <TextInput
+ label="table.field.outStock.poCode"
+ source="poCode"
+ readOnly
+ parse={v => v}
+ />
+ {/* <AutocompleteInput
+ choices={dicts}
+ optionText="label"
+ label="table.field.outStock.type"
+ source="type"
+ optionValue="value"
+ parse={v => v}
+ readOnly
+ /> */}
+ <TextInput
+ label="table.field.outStock.wkType"
+ source="wkType$"
+ readOnly
+ parse={v => v}
+ />
+ {/* <AutocompleteInput
+ choices={business}
+ optionText="label"
+ label="table.field.outStock.wkType"
+ source="wkType$"
+ optionValue="value"
+ parse={v => v}
+ readOnly
+ /> */}
+ <TextInput
+ label="table.field.outStock.saleDate"
+ source="businessTime"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStock.anfme"
+ source="anfme"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStock.qty"
+ source="qty"
+ readOnly
+ parse={v => v}
+ />
+ </Stack>
+ <Stack direction='row' gap={2}>
+ {/* 閾跺骇鏂板 */}
+ <TextInput
+ label="table.field.outStock.saleOrgName"
+ source="saleOrgName"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStock.saleUserName"
+ source="saleUserName"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStock.customerId"
+ source="customerId"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStock.customerName"
+ source="customerName"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStock.stockOrgName"
+ source="stockOrgName"
+ readOnly
+ parse={v => v}
+ />
+ {/* <TextInput
+ label="table.field.outStock.logisNo"
+ source="logisNo"
+ readOnly
+ parse={v => v}
+ /> */}
+ {/* <DateInput
+ label="table.field.outStock.arrTime"
+ source="arrTime"
+ readOnly
+ /> */}
+ {/* <SelectInput
+ label="table.field.outStock.rleStatus"
+ source="rleStatus"
+ readOnly
+ choices={[
+ { id: 0, name: ' 姝e父' },
+ { id: 1, name: ' 宸查噴鏀�' },
+ ]}
+ validate={required()}
+ /> */}
+ </Stack>
+ </Grid>
+ </Grid>
+ </SimpleForm>
+ </Edit >
+ <OutOrderItemList />
+ </>
+ )
+}
+
+export default PreparationOrderEdit;
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderItemCreate.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderItemCreate.jsx
new file mode 100644
index 0000000..e478b47
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderItemCreate.jsx
@@ -0,0 +1,198 @@
+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,
+} from 'react-admin';
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Stack,
+ Grid,
+ Box,
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import MemoInput from "../../components/MemoInput";
+
+const OutOrderItemCreate = (props) => {
+ const { open, setOpen, record } = props;
+ const translate = useTranslate();
+ const notify = useNotify();
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+
+ const handleSuccess = async (data) => {
+ setOpen(false);
+ notify('common.response.success');
+ };
+
+ const handleError = async (error) => {
+ notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+ };
+
+ return (
+ <>
+ <CreateBase
+ resource="outStockItem"
+ record={{}}
+ transform={(data) => {
+ return data;
+ }}
+ mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+ >
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ fullWidth
+ disableRestoreFocus
+ maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+ >
+ <Form>
+ <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 }}>
+ <Grid>
+ <Grid item xs={6} display="flex" gap={2}>
+ <NumberInput
+ label="table.field.outStockItem.orderId"
+ source="orderId"
+ readOnly
+ hidden
+ defaultValue={record?.id}
+ />
+ <TextInput
+ label="table.field.outStockItem.orderCode"
+ source="orderCode"
+ readOnly
+ defaultValue={record?.code}
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.poDetlId"
+ source="poDetlId"
+ parse={v => v}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.outStockItem.matnrId"
+ source="matnrId"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.maktx"
+ source="maktx"
+ parse={v => v}
+ />
+ <NumberInput
+ label="table.field.outStockItem.anfme"
+ source="anfme"
+ validate={required()}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.outStockItem.stockUnit"
+ source="stockUnit"
+ parse={v => v}
+ />
+ <NumberInput
+ label="table.field.outStockItem.purQty"
+ source="purQty"
+ validate={required()}
+ />
+ <TextInput
+ label="table.field.outStockItem.purUnit"
+ source="purUnit"
+ parse={v => v}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <NumberInput
+ label="table.field.outStockItem.qty"
+ source="qty"
+ />
+ <TextInput
+ label="table.field.outStockItem.splrCode"
+ source="splrCode"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.splrName"
+ source="splrName"
+ parse={v => v}
+ />
+
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.outStockItem.qrcode"
+ source="qrcode"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.barcode"
+ source="barcode"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.packName"
+ source="packName"
+ parse={v => v}
+ />
+ </Grid>
+
+ <Grid item xs={4} display="flex" gap={1}>
+ <StatusSelectInput />
+ </Grid>
+ <Grid item xs={4} display="flex" gap={1}>
+ <Stack direction="column" spacing={1}>
+ <MemoInput />
+ </Stack>
+ </Grid>
+ </Grid>
+ </DialogContent>
+ <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+ <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} >
+ <SaveButton />
+ </Toolbar>
+ </DialogActions>
+ </Form>
+ </Dialog>
+ </CreateBase>
+ </>
+ )
+}
+
+export default OutOrderItemCreate;
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderItemEdit.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderItemEdit.jsx
new file mode 100644
index 0000000..1ae87ac
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderItemEdit.jsx
@@ -0,0 +1,195 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ Edit,
+ SimpleForm,
+ FormDataConsumer,
+ useTranslate,
+ TextInput,
+ NumberInput,
+ BooleanInput,
+ DateInput,
+ SelectInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ SaveButton,
+ Toolbar,
+ Labeled,
+ NumberField,
+ required,
+ Form,
+ useRecordContext,
+ useGetOne,
+ DeleteButton,
+ EditBase,
+ ReferenceField,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import EditBaseAside from "../../components/EditBaseAside";
+import CustomerTopToolBar from "../../components/EditTopToolBar";
+import MemoInput from "../../components/MemoInput";
+import StatusSelectInput from "../../components/StatusSelectInput";
+
+const FormToolbar = () => {
+ const { getValues } = useFormContext();
+
+ return (
+ <Toolbar sx={{ justifyContent: 'end' }}>
+ <SaveButton />
+ <DeleteButton mutationMode="optimistic" />
+ </Toolbar>
+ )
+}
+
+const OutOrderItemEdit = (props) => {
+ const { open, setOpen, record } = props;
+ const translate = useTranslate();
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+ const { data, isPending, } = useGetOne('outStockItem', { id: record?.id });
+ if (data == null || data == undefined) { return }
+
+ return (
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ fullWidth
+ disableRestoreFocus
+ maxWidth="md"
+ >
+ <DialogTitle id="form-dialog-title" sx={{
+ position: 'sticky',
+ top: 0,
+ backgroundColor: 'background.paper',
+ zIndex: 1000
+ }}
+ >
+ {translate('update.title')}
+ <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+ <DialogCloseButton onClose={handleClose} />
+ </Box>
+ </DialogTitle>
+ <DialogContent sx={{ mt: 2 }}>
+ <EditBase
+ id={record?.id}
+ resource="outStockItem"
+ mutationMode={EDIT_MODE}
+ actions={<CustomerTopToolBar />}
+ >
+ <Form
+ shouldUnregister
+ warnWhenUnsavedChanges
+ mode="onTouched"
+ defaultValues={{}}
+ >
+ <Grid container width={{ xs: '100%', xl: '100%' }}>
+ <Grid item xs={24} md={14}>
+ <Stack direction='row' gap={2}>
+ <NumberInput
+ label="table.field.outStockItem.orderId"
+ source="orderId"
+ readOnly
+ />
+ <TextInput
+ label="table.field.outStockItem.orderCode"
+ source="orderCode"
+ readOnly
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.poDetlId"
+ source="poDetlId"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.poDetlCode"
+ source="poDetlCode"
+ parse={v => v}
+ />
+ </Stack>
+ <Stack direction='row' gap={2}>
+ <TextInput
+ label="table.field.outStockItem.matnrId"
+ source="matnrId"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.maktx"
+ source="maktx"
+ parse={v => v}
+ />
+ <NumberInput
+ label="table.field.outStockItem.anfme"
+ source="anfme"
+ validate={required()}
+ />
+ <TextInput
+ label="table.field.outStockItem.stockUnit"
+ source="stockUnit"
+ parse={v => v}
+ />
+ </Stack>
+ <Stack direction='row' gap={2}>
+ <NumberInput
+ label="table.field.outStockItem.purQty"
+ source="purQty"
+ validate={required()}
+ />
+ <TextInput
+ label="table.field.outStockItem.purUnit"
+ source="purUnit"
+ parse={v => v}
+ />
+ <NumberInput
+ label="table.field.outStockItem.qty"
+ source="qty"
+ readOnly
+ />
+ <ReferenceInput source="splrName" label="table.field.outStockItem.splrName" reference="companys" filter={{type: 'supplier'}}>
+ <AutocompleteInput optionText="name" label="table.field.outStockItem.splrName" />
+ </ReferenceInput>
+ </Stack>
+ <Stack direction='row' gap={2}>
+ <TextInput
+ label="table.field.outStockItem.qrcode"
+ source="qrcode"
+ parse={v => v}
+ />
+ <TextInput
+ label="table.field.outStockItem.barcode"
+ source="trackCode"
+ parse={v => v}
+ readOnly
+ />
+ <TextInput
+ label="table.field.outStockItem.packName"
+ source="packName"
+ parse={v => v}
+ />
+ </Stack>
+ </Grid>
+ </Grid>
+ <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+ <Toolbar sx={{ width: '100%', justifyContent: 'end' }} >
+ <SaveButton type="button" mutationOptions={{
+ onSuccess: () => {
+ setOpen(false)
+ }
+ }} />
+ </Toolbar>
+ </DialogActions>
+ </Form>
+ </EditBase >
+ </DialogContent>
+ </Dialog>
+ )
+}
+
+export default OutOrderItemEdit;
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderItemList.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderItemList.jsx
new file mode 100644
index 0000000..72298b8
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderItemList.jsx
@@ -0,0 +1,206 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useNavigate, useLocation } from 'react-router-dom';
+import {
+ List,
+ DatagridConfigurable,
+ SearchInput,
+ TopToolbar,
+ SelectColumnsButton,
+ EditButton,
+ FilterButton,
+ CreateButton,
+ ExportButton,
+ BulkDeleteButton,
+ WrapperField,
+ useRecordContext,
+ useTranslate,
+ useNotify,
+ useListContext,
+ FunctionField,
+ TextField,
+ NumberField,
+ DateField,
+ BooleanField,
+ ReferenceField,
+ TextInput,
+ DateTimeInput,
+ DateInput,
+ SelectInput,
+ NumberInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ DeleteButton,
+ Button,
+ useEditContext,
+ useGetRecordId,
+ useRefresh,
+ useGetOne
+} from 'react-admin';
+import { Box, Typography, Card, Stack, Dialog, DialogActions, DialogTitle, LinearProgress } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import OutOrderItemCreate from "./PreparationOrderItemCreate";
+import PageDrawer from "../../components/PageDrawer";
+import request from '@/utils/request';
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
+import OutOrderItemEdit from "./PreparationOrderItemEdit";
+import { fetchOutOrderItemColumns } from "../config/orderItemColumns";
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+ '& .css-1vooibu-MuiSvgIcon-root': {
+ height: '.9em',
+ },
+ '& .RaDatagrid-row': {
+ cursor: 'auto'
+ },
+ '& .column-name': {
+ },
+ '& .opt': {
+ width: 200
+ },
+ '& .MuiTableCell-root': {
+ whiteSpace: 'nowrap',
+ overflow: 'visible',
+ textOverflow: 'unset'
+ }
+
+}));
+
+const filters = [
+ <SearchInput source="condition" alwaysOn />,
+ <NumberInput source="orderId" label="table.field.outStockItem.orderId" />,
+ <TextInput source="orderCode" label="table.field.outStockItem.orderCode" alwaysOn />,
+ <TextInput source="poDetlId" label="table.field.outStockItem.poDetlId" />,
+ <TextInput source="matnrId" label="table.field.outStockItem.matnrId" />,
+ <TextInput source="maktx" label="table.field.outStockItem.maktx" alwaysOn />,
+ <TextInput source="matnrCode" label="table.field.outStockItem.matnrCode" alwaysOn />,
+ <NumberInput source="anfme" label="table.field.outStockItem.anfme" />,
+ <TextInput source="stockUnit" label="table.field.outStockItem.stockUnit" />,
+ <NumberInput source="purQty" label="table.field.outStockItem.purQty" />,
+ <TextInput source="purUnit" label="table.field.outStockItem.purUnit" />,
+ <NumberInput source="qty" label="table.field.outStockItem.qty" />,
+ <TextInput source="splrCode" label="table.field.outStockItem.splrCode" />,
+ <TextInput source="splrName" label="table.field.outStockItem.splrName" />,
+ <TextInput source="qrcode" label="table.field.outStockItem.qrcode" />,
+ <TextInput source="trackCode" label="table.field.outStockItem.barcode" />,
+ <TextInput source="packName" label="table.field.outStockItem.packName" />,
+ <TextInput label="common.field.memo" source="memo" />,
+ <SelectInput
+ label="common.field.status"
+ source="status"
+ choices={[
+ { id: '1', name: 'common.enums.statusTrue' },
+ { id: '0', name: 'common.enums.statusFalse' },
+ ]}
+ resettable
+ />,
+]
+
+const OutOrderItemList = () => {
+ const translate = useTranslate();
+ const [createDialog, setCreateDialog] = useState(false);
+ const [editDialog, setEditDialog] = useState(false);
+ const [drawerVal, setDrawerVal] = useState(false);
+ const [select, setSelect] = useState({});
+ const asnId = useGetRecordId();
+ const { data: dicts, isPending, error } = useGetOne('outStock', { id: asnId });
+
+ return (
+ <>
+ <Box display="flex">
+ <List
+ resource="outStockItem"
+ storeKey='outStockItem'
+ sx={{
+ flexGrow: 1,
+ transition: (theme) =>
+ theme.transitions.create(['all'], {
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ }}
+ title={"menu.outStockItem"}
+ empty={false}
+ filter={{ orderId: asnId, deleted: 0 }}
+ filters={filters}
+ sort={{ field: "create_time", order: "desc" }}
+ actions={(
+ <TopToolbar>
+ <FilterButton />
+ <SelectColumnsButton preferenceKey='outStockItem' />
+ </TopToolbar>
+ )}
+ perPage={DEFAULT_ITEM_PAGE_SIZE}
+ >
+ <DynamicFields />
+ </List>
+ <OutOrderItemCreate
+ open={createDialog}
+ setOpen={setCreateDialog}
+ record={dicts}
+ />
+ <OutOrderItemEdit
+ open={editDialog}
+ setOpen={setEditDialog}
+ record={select}
+ />
+ <PageDrawer
+ title={false}
+ drawerVal={drawerVal}
+ setDrawerVal={setDrawerVal}
+ >
+ </PageDrawer>
+ </Box>
+ </>
+ )
+}
+OutOrderItemList.Context = React.createContext()
+
+export default OutOrderItemList;
+
+
+const DynamicFields = (props) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+ const [columns, setColumns] = useState([]);
+ const { isLoading } = useListContext();
+ const refresh = useRefresh();
+ useEffect(() => {
+ getDynamicFields();
+ }, []);
+
+ const getDynamicFields = async () => {
+ const result = await fetchOutOrderItemColumns();
+ if (result.success) {
+ setColumns(result.columns);
+ } else {
+ notify(result.msg);
+ }
+ }
+
+ return (
+ <Box sx={{ position: 'relative', minHeight: "60vh", }}>
+ {isLoading && (
+ <LinearProgress
+ sx={{
+ height: "2px",
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ }}
+ />
+ )}
+ {columns.length > 0 &&
+ <StyledDatagrid
+ preferenceKey='outStockItem'
+ bulkActionButtons={false}
+ rowClick={(id, resource, record) => false}
+ omit={['id', 'orderId', 'orderCode', 'poDetlId', 'poDetlCode', 'platOrderCode', 'matnrId', 'spec', 'model', 'purQty', 'purUnit',
+ 'qrcode', 'trackCode', 'splrCode', 'projectCode', 'workQty', 'createBy', 'createTime', 'createBy$', 'sourceWareHouseId', 'splrName', 'supplierName']}
+ >
+ {columns.map((column) => column)}
+ </StyledDatagrid>}
+ </Box>
+ )
+}
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderList.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderList.jsx
new file mode 100644
index 0000000..8f3a8ff
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderList.jsx
@@ -0,0 +1,386 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useLocation, useNavigate } from 'react-router-dom';
+import {
+ List,
+ SearchInput,
+ TopToolbar,
+ Toolbar,
+ ColumnsButton,
+ FilterButton,
+ EditButton,
+ CreateButton,
+ ExportButton,
+ BulkDeleteButton,
+ useDataProvider,
+ WrapperField,
+ useRecordContext,
+ useTranslate,
+ useNotify,
+ useRefresh,
+ useListContext,
+ FunctionField,
+ TextField,
+ NumberField,
+ DateField,
+ BooleanField,
+ ReferenceField,
+ TextInput,
+ DateTimeInput,
+ DateInput,
+ SelectInput,
+ NumberInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ DeleteButton,
+ Button,
+ useRedirect,
+ useUnselectAll,
+ useRecordSelection,
+} from 'react-admin';
+import { styled } from '@mui/material/styles';
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
+import { Box, Typography, Card, Stack, Drawer, LinearProgress } from '@mui/material';
+import DictionarySelect from "../../components/DictionarySelect";
+import StickyDataTable from "../../components/StickyDataTable";
+import useTableLayout from '@/utils/useTableLayout';
+import BillStatusField from '../../components/BillStatusField';
+import MyCreateButton from "../../components/MyCreateButton";
+import PageEditDrawer from "../../components/PageEditDrawer";
+import ConfirmButton from '../../components/ConfirmButton';
+import ImportButton from "../../components/ImportButton";
+import DetailsIcon from '@mui/icons-material/Details';
+import OutStockWaveDialog from "./PreparationStockWaveDialog";
+import AddTaskIcon from '@mui/icons-material/AddTask';
+import PublicIcon from '@mui/icons-material/Public';
+import SelectMatnrModal from "./PreparationSelectMatnrModal";
+import EditIcon from '@mui/icons-material/Edit';
+import TaskIcon from '@mui/icons-material/Task';
+import OutOrderPreview from "./PreparationOrderPreview";
+import AddIcon from '@mui/icons-material/Add';
+import OutStockPublic from "./PreparationStockPublic";
+import OutOrderModal from "./PreparationOrderModal";
+import request from '@/utils/request';
+
+const ListContent = ({ drawerVal, setDrawerVal, setWaveRule, setSelectIds, setSelect }) => {
+ const { isLoading } = useListContext();
+ const { boxMaxWidth, boxMaxHeight } = useTableLayout(drawerVal);
+
+ const omittedFields = ['id', 'code', 'createTime', 'createBy$', 'memo', 'rleStatus$', 'logisNo', 'updateBy$', 'workQty', 'updateTime', 'type$'];
+
+ return (
+ <Box sx={{
+ position: 'relative',
+ maxHeight: boxMaxHeight,
+ maxWidth: boxMaxWidth,
+ overflowX: 'auto',
+ overflowY: 'auto',
+ '& .MuiTableCell-root': {
+ whiteSpace: 'nowrap',
+ },
+ '& .css-1vooibu-MuiSvgIcon-root': {
+ height: '.9em'
+ },
+ '& .RaDatagrid-row': {
+ cursor: 'auto'
+ },
+ '& .column-name': {
+ },
+ '& .opt': {
+ width: 420
+ },
+ '& .wkType': {
+ width: 110
+ },
+ '& .status': {
+ width: 90
+ },
+ }}>
+ {isLoading && (
+ <LinearProgress
+ sx={{
+ height: "2px",
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ }}
+ />
+ )}
+ <StickyDataTable
+ storeKey='outStock'
+ bulkActionButtons={<PublicTaskButton setWaveRule={setWaveRule} setSelectIds={setSelectIds} />}
+ rowClick={false}
+ hiddenColumns={omittedFields}
+ >
+ <NumberField source="id" />
+ <TextField source="code" label="table.field.outStock.code" />
+ <TextField source="poCode" label="table.field.outStock.poCode" />
+ <TextField source="type$" label="table.field.outStock.type" />
+ <TextField cellClassName="wkType" source="wkType$" label="table.field.outStock.wkType" />
+ <NumberField source="anfme" label="table.field.outStock.anfme" />
+ <NumberField source="workQty" label="table.field.outStock.workQty" />
+ <NumberField source="qty" label="table.field.outStock.qty" />
+ <TextField source="logisNo" label="table.field.outStock.logisNo" />
+ <TextField source="rleStatus$" label="table.field.outStock.rleStatus" sortable={false} />
+ <TextField source="updateBy$" label="common.field.updateBy" />
+ <DateField source="updateTime" label="common.field.updateTime" showTime />
+ <TextField source="createBy$" label="common.field.createBy" />
+ <DateField source="createTime" label="common.field.createTime" showTime />
+ <TextField source="memo" label="common.field.memo" sortable={false} />
+
+ {/* 閾跺骇鏂板 */}
+ <TextField source="saleOrgName" label="閿�鍞粍缁�" />
+ <TextField source="saleUserName" label="閿�鍞憳" />
+ <DateField source="businessTime" label="鍑哄簱鏃ユ湡" />
+ <TextField source="customerId" label="瀹㈡埛缂栫爜" />
+ <TextField source="customerName" label="瀹㈡埛" />
+ <TextField source="stockOrgName" label="table.field.outStock.stockOrgName" />
+
+ <BillStatusField cellClassName="status" source="exceStatus" label="table.field.outStock.exceStatus" />
+ <WrapperField cellClassName="opt" label="common.field.opt" >
+ {/* <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} /> */}
+ <EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton>
+ <CancelButton />
+ <CompleteButton />
+ <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} />
+ </WrapperField>
+ </StickyDataTable>
+ </Box>
+ )
+}
+
+const filters = [
+ <SearchInput source="condition" alwaysOn />,
+ <TextInput source="code" label="table.field.outStock.code" alwaysOn />,
+ <TextInput source="poCode" label="table.field.outStock.poCode" />,
+ <NumberInput source="poId" label="table.field.outStock.poId" />,
+
+ <NumberInput source="anfme" label="table.field.outStock.anfme" />,
+ <NumberInput source="qty" label="table.field.outStock.qty" />,
+ <TextInput source="logisNo" label="table.field.outStock.logisNo" />,
+ <DateInput source="arrTime" label="table.field.outStock.arrTime" />,
+ <SelectInput source="rleStatus" label="table.field.outStock.rleStatus"
+ choices={[
+ { id: 0, name: ' 姝e父' },
+ { id: 1, name: ' 宸查噴鏀�' },
+ ]}
+ />,
+
+ <TextInput label="common.field.memo" source="memo" />,
+ <DictionarySelect
+ label='table.field.outStock.exceStatus'
+ name="exceStatus"
+ dictTypeCode="sys_asn_exce_status"
+ alwaysOn
+ />,
+]
+
+const PreparationOrderList = (props) => {
+
+ const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || [];
+ const [createDialog, setCreateDialog] = useState(false);
+ const [manualDialog, setManualDialog] = useState(false);
+ const [drawerVal, setDrawerVal] = useState(false);
+ const [waveRule, setWaveRule] = useState(false);
+ const [selectIds, setSelectIds] = useState([]);
+ const [preview, setPreview] = useState(false);
+ const [modalType, setmodalType] = useState(0);
+ const [select, setSelect] = useState(0);
+ const translate = useTranslate();
+ const refresh = useRefresh();
+ const notify = useNotify();
+ const billReload = useRef();
+
+ //鑾峰彇娉㈡瑙勫垯
+ const closeDialog = async (value) => {
+ setWaveRule(false)
+ const res = await request.post(`/outStock/generate/wave`, { ids: selectIds, waveRuleId: value.id });
+ if (res?.data?.code === 200) {
+ notify(res.data.msg);
+ } else {
+ notify(res.data.msg);
+ }
+ refresh()
+ }
+
+ return (
+ <Box display="flex">
+ <List
+ resource="preparation"
+ sx={{
+ flexGrow: 1,
+ transition: (theme) =>
+ theme.transitions.create(['all'], {
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ }}
+ title={"menu.outStock"}
+ empty={false}
+ filters={filters}
+ filter={{ deleted: 0, type: 'out', wkType: 23 }}
+ sort={{ field: "create_time", order: "desc" }}
+ actions={(
+ <TopToolbar>
+ <FilterButton />
+ <CreateByOrderButton setCreateDialog={setCreateDialog} />
+ <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} />
+ <ColumnsButton storeKey='outStock' />
+ <ImportButton value={'outStockItem'} />
+ </TopToolbar>
+ )}
+ perPage={DEFAULT_PAGE_SIZE}
+ >
+ <ListContent
+ drawerVal={drawerVal}
+ setDrawerVal={setDrawerVal}
+ setWaveRule={setWaveRule}
+ setSelectIds={setSelectIds}
+ setSelect={setSelect}
+ />
+ </List>
+ {/* <OutOrderCreate
+ open={manualDialog}
+ setOpen={setManualDialog}
+ /> */}
+ <SelectMatnrModal
+ asnId={modalType}
+ billReload={billReload}
+ open={manualDialog}
+ setOpen={setManualDialog}
+ />
+ <OutOrderModal
+ open={createDialog}
+ setOpen={setCreateDialog}
+ preview={preview}
+ setPreview={setPreview}
+ />
+ <OutStockWaveDialog open={waveRule} setOpen={setWaveRule} onClose={closeDialog} />
+ <OutOrderPreview open={preview} setOpen={setPreview} />
+ <PageEditDrawer
+ title={"toolbar.publicWorking"}
+ drawerVal={drawerVal}
+ setDrawerVal={setDrawerVal}
+ >
+ <OutStockPublic record={select} open={drawerVal} setOpen={setDrawerVal} />
+ </PageEditDrawer>
+ </Box >
+ )
+}
+export default PreparationOrderList;
+
+
+const PublicTaskButton = ({ setWaveRule, setSelectIds }) => {
+ const record = useRecordContext();
+ const { selectedIds, onUnselectItems } = useListContext();
+ const notify = useNotify();
+ const redirect = useRedirect();
+
+ const pubClick = async () => {
+ onUnselectItems();
+ setWaveRule(true);
+ setSelectIds(selectedIds)
+ }
+
+ return (
+ <Button
+ onClick={pubClick}
+ label={"toolbar.createWave"}
+ startIcon={<PublicIcon />}
+ />
+ );
+}
+
+//瀹屾垚鍗曟嵁
+const CompleteButton = () => {
+ const record = useRecordContext();
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const requestComplete = async () => {
+ const { data: { code, data, msg } } = await request.get(`/outStock/complete/${record.id}`);
+ if (code === 200) {
+ notify(msg);
+ refresh()
+ } else {
+ notify(msg);
+ }
+ }
+
+ return (
+ // record.exceStatus === 1 && (record.anfme === record.qty ? <Button onClick={requestComplete} label={"toolbar.complete"} color="secondary">
+ // <TaskIcon />
+ // </Button> : )
+ record.exceStatus != 15 ? <ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskIcon />} onConfirm={requestComplete} /> : <></>
+ )
+}
+
+const MyButton = ({ setCreateDialog, setmodalType }) => {
+ const record = useRecordContext();
+ const handleEditClick = (btn) => {
+ btn.stopPropagation();
+ const id = record.id;
+ setmodalType(id);
+ setCreateDialog(true);
+ };
+ return (
+ <Button
+ color="primary"
+ startIcon={<EditIcon />}
+ onClick={(btn) => handleEditClick(btn)}
+ sx={{ ml: 1 }}
+ label={'ra.action.edit'}
+ >
+ </Button>
+ )
+}
+
+const CreateByOrderButton = ({ setCreateDialog }) => {
+ const record = useRecordContext();
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const createByOrder = async (event) => {
+ event.stopPropagation();
+ setCreateDialog(true);
+ }
+
+ return (
+ <Button onClick={createByOrder} label={'toolbar.asnCreate'}> <AddIcon /> </Button>
+ )
+}
+
+const CancelButton = () => {
+ const record = useRecordContext();
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const cancelOrder = async () => {
+ const { data: { code, data, msg } } = await request.get(`/outStock/cancel/${record?.id}`);
+ if (code === 200) {
+ notify(msg);
+ refresh()
+ } else {
+ notify(msg);
+ }
+ }
+
+ return (
+ record?.exceStatus == 10 ? <ConfirmButton label={"toolbar.cancel"} startIcon={<CancelOutlinedIcon />} onConfirm={cancelOrder} size={"small"} /> : <></>
+ )
+}
+
+//涓嬪彂鎵ц
+const PublicButton = ({ setDrawerVal, setSelect }) => {
+ const record = useRecordContext();
+ const refresh = useRefresh();
+ const taskEvent = () => {
+ setDrawerVal(true)
+ setSelect(record)
+ refresh();
+ }
+
+ return (
+ record.workQty < record.anfme ? <Button label={"toolbar.publicWorking"} startIcon={<AddTaskIcon />} onClick={taskEvent} size={"small"} /> : <></>
+ )
+}
+
+
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderModal.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderModal.jsx
new file mode 100644
index 0000000..6e43095
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderModal.jsx
@@ -0,0 +1,282 @@
+import { Dialog, DialogActions, DialogContent, DialogTitle, Box, LinearProgress } from "@mui/material";
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ List,
+ DatagridConfigurable,
+ SearchInput,
+ TopToolbar,
+ Toolbar,
+ Button,
+ SelectColumnsButton,
+ EditButton,
+ FilterButton,
+ CreateButton,
+ ExportButton,
+ BulkDeleteButton,
+ WrapperField,
+ useRecordContext,
+ useTranslate,
+ useNotify,
+ useListContext,
+ FunctionField,
+ TextField,
+ NumberField,
+ DateField,
+ BooleanField,
+ ReferenceField,
+ TextInput,
+ DateTimeInput,
+ DateInput,
+ SelectInput,
+ NumberInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ DeleteButton,
+ SimpleForm,
+ Form,
+ SaveButton,
+ useRefresh,
+ useGetList,
+} from 'react-admin';
+
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import EditableTextField from "../../components/EditableTextField";
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import { Grid, margin, Stack, width } from "@mui/system";
+import SaveIcon from '@mui/icons-material/Save';
+import OutOrderPreview from "./PreparationOrderPreview";
+import { styled } from '@mui/material/styles';
+import request from '@/utils/request';
+
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+ '& .css-1vooibu-MuiSvgIcon-root': {
+ height: '.9em'
+ },
+ '& .RaDatagrid-row': {
+ cursor: 'auto'
+ },
+ '& .status': {
+ width: 90
+ },
+}));
+
+const StyledForm = styled(Form)(({ theme }) => ({
+ width: '100%',
+ marginBottom: '45px',
+
+ '& .MuiGrid-root': {
+ margin: '0 10px'
+ }
+}));
+
+
+const filters = [
+ <SearchInput source="condition" alwaysOn />,
+ <DateInput label='common.time.after' source="timeStart" />,
+ <DateInput label='common.time.before' source="timeEnd" />,
+ <TextInput source="code" label="table.field.delivery.code" />,
+ <TextInput source="platId" label="table.field.delivery.platId" />,
+ <TextInput source="type" label="table.field.delivery.type" />,
+ <TextInput source="wkType" label="table.field.delivery.wkType" />,
+ <TextInput source="source" label="table.field.delivery.source" />,
+ <SelectInput
+ label="common.field.status"
+ source="status"
+ choices={[
+ { id: '1', name: 'common.enums.statusTrue' },
+ { id: '0', name: 'common.enums.statusFalse' },
+ ]}
+ resettable
+ />,
+]
+
+const OutOrderModal = (props) => {
+ const { open, setOpen, preview, setPreview, record } = props;
+ const [drawerVal, setDrawerVal] = useState(false);
+ const [params, setParams] = useState({});
+ const [select, setSelect] = useState([]);
+ const translate = useTranslate();
+ const refresh = useRefresh();
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+
+ const CustomFilter = () => {
+ const { filterValues, setFilters, refetch } = useListContext();
+ 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 (
+ <StyledForm>
+ <Grid container rowSpacing={3} columnSpacing={3} >
+ <Stack>
+ <TextInput
+ source="condition"
+ label="common.action.search"
+ resettable
+ defaultValue={params?.condition}
+ onChange={handleChange} />
+ </Stack>
+ <Stack>
+ <TextInput
+ source="deliveryCode"
+ label="table.field.deliveryItem.deliveryCode"
+ defaultValue={params?.deliveryCode}
+ onChange={handleChange}
+ resettable
+ />
+ </Stack>
+ <Stack>
+ <TextInput
+ source="maktx"
+ label="table.field.deliveryItem.matnrName"
+ defaultValue={params?.maktx}
+ onChange={handleChange}
+ resettable
+ />
+ </Stack>
+ <Stack>
+ <TextInput
+ source="matnrCode"
+ label="table.field.deliveryItem.matnrCode"
+ defaultValue={params?.matnrCode}
+ resettable
+ onChange={handleChange} />
+ </Stack>
+ <Stack>
+ <TextInput
+ source="splrName"
+ label="table.field.deliveryItem.splrName"
+ defaultValue={params?.splrName}
+ resettable
+ onChange={handleChange} />
+ </Stack>
+ </Grid>
+ <DialogActions>
+ <Toolbar sx={{ width: '100%', justifyContent: 'end' }} >
+ <SaveButton onClick={handleSubmit} label={"toolbar.query"} />
+ </Toolbar>
+ </DialogActions>
+ </StyledForm>
+ );
+ };
+ return (
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ aria-hidden
+ fullWidth
+ disableRestoreFocus
+ maxWidth="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>
+ <Grid container rowSpacing={2} columnSpacing={2}>
+ <DialogContent>
+ <Grid item>
+ <List
+ resource="/deliveryItem/filters"
+ sx={{
+ flexGrow: 1,
+ transition: (theme) =>
+ theme.transitions.create(['all'], {
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ }}
+ filters={<CustomFilter />}
+ queryOptions={{ meta: { ...params } }}
+ empty={false}
+ sort={{ field: "create_time", order: "desc" }}
+ actions={(
+ <TopToolbar>
+ <></>
+ </TopToolbar>
+ )}
+ perPage={DEFAULT_PAGE_SIZE}
+ >
+ <Box sx={{ position: 'relative', minHeight: "60vh", }}>
+ <LinearProgress
+ sx={{ height: "2px", position: 'absolute', top: 0, left: 0, right: 0, }}
+ />
+ <StyledDatagrid
+ preferenceKey='deliveryItem'
+ bulkActionButtons={<AddOutStockButton setOpen={setOpen} setPreview={setPreview} setSelect={setSelect} />}
+ rowClick={(id, resource, record) => false}
+ expand={false}
+ expandSingle={true}
+ omit={['id', 'createTime', 'createBy', 'memo', 'startTime', 'endTime', 'updateBy', 'createTime']}
+ >
+ <NumberField source="id" />
+ <TextField source="deliveryCode" label="table.field.deliveryItem.deliveryCode" />
+ <TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" />
+ <TextField source="maktx" label="table.field.deliveryItem.matnrName" />
+ <TextField source="unit" label="table.field.deliveryItem.unit" />
+ <NumberField source="anfme" label="table.field.deliveryItem.anfme" />
+ <NumberField source="workQty" label="table.field.outStockItem.workQty" />
+ <TextField source="splrName" label="table.field.deliveryItem.splrName" />
+ <TextField source="splrBatch" label="table.field.deliveryItem.splrBatch" />
+ <TextField source="updateBy$" label="common.field.updateBy" />
+ <DateField source="updateTime" label="common.field.updateTime" showTime />
+ <TextField source="createBy$" label="common.field.createBy" />
+ <DateField source="createTime" label="common.field.createTime" showTime />
+ <BooleanField source="statusBool" label="common.field.status" sortable={false} />
+ <TextField source="memo" label="common.field.memo" sortable={false} />
+ </StyledDatagrid>
+ </Box>
+ </List>
+ </Grid>
+ </DialogContent>
+ </Grid>
+ <Grid>
+ <OutOrderPreview open={preview} setOpen={setPreview} selectedIds={select} setCloseParent={setOpen} />
+ </Grid>
+ </Dialog >
+ )
+}
+
+export default OutOrderModal;
+
+const AddOutStockButton = (props) => {
+ const { setOpen, setPreview, setSelect } = props;
+ const { selectedIds, onUnselectItems } = useListContext();
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const confirm = async (event) => {
+ setPreview(true)
+ setSelect(selectedIds);
+ onUnselectItems();
+ // refresh();
+ }
+
+ return (
+ <Button label={"toolbar.confirmSelect"} onClick={confirm}>
+ <CheckCircleIcon />
+ </Button>
+ )
+}
\ No newline at end of file
diff --git a/rsf-admin/src/page/orders/preparation/PreparationOrderPreview.jsx b/rsf-admin/src/page/orders/preparation/PreparationOrderPreview.jsx
new file mode 100644
index 0000000..6acbd99
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationOrderPreview.jsx
@@ -0,0 +1,149 @@
+import { Dialog, DialogActions, DialogContent, DialogTitle, Box, LinearProgress, Grid, } from "@mui/material";
+import React, { useState, useRef, useEffect, useMemo, memo } from "react";
+import {
+ Toolbar,
+ Button,
+ useTranslate,
+ useNotify,
+ useRefresh,
+ useGetList,
+} from 'react-admin';
+import request from '@/utils/request';
+import { styled } from '@mui/material/styles';
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import { DataGrid, useGridApiContext, GridActionsCellItem, useGridApiRef } from '@mui/x-data-grid';
+import DialogCloseButton from "../../components/DialogCloseButton";
+
+
+const OutOrderPreview = (props) => {
+ const { open, setOpen, record, selectedIds, setCloseParent } = props;
+ const translate = useTranslate();
+ const gridRef = useGridApiRef();
+ const [rows, setRows] = useState([]);
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const handleClose = async (event, reason) => {
+ if (reason !== "backdropClick") {
+ // const res = await request.get(`/outStock/items/cancel/` + selectedIds);
+ setOpen(false);
+ setCloseParent(false)
+ }
+ };
+
+ if (!selectedIds) { return }
+
+ const { data, isLoading, error } = useGetList('/deliveryItem/edit', {
+ pagination: { page: 1, perPage: 1000 },
+ filter: { deleted: 0, ids: selectedIds }
+ });
+
+ return (
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ aria-hidden
+ fullWidth
+ maxWidth="lg"
+ >
+ <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>
+ <Grid container xl={12}>
+ <Grid item xl={12}>
+ <Box display="flex" sx={{ height: 400, width: '100%', '& .RaConfigurable-root': { width: '100%' } }}>
+ <LinearProgress sx={{ height: "2px", position: 'absolute', top: 0, left: 0, right: 0, }} />
+ <OrderPreview rows={data} gridRef={gridRef} />
+ </Box >
+ </Grid>
+ </Grid>
+ <Toolbar sx={{ justifyContent: 'end' }}>
+ <ConfirmButton label="toolbar.confirm" variant="contained" size="large" gridRef={gridRef} setOpen={setOpen} setCloseParent={setCloseParent} />
+ </Toolbar>
+ </DialogContent>
+ </Dialog>
+ )
+}
+
+export default OutOrderPreview;
+
+const ConfirmButton = ({ gridRef, setOpen, setCloseParent }) => {
+ const refresh = useRefresh();
+ const notify = useNotify();
+ const confirm = async () => {
+ const items = gridRef.current?.getSortedRows();
+ const { data: { code, msg } } = await request.post(`/outStock/generate/orders`, { ids: items });
+ if (code === 200) {
+ notify(msg);
+ refresh()
+ setOpen(false)
+ setCloseParent(false)
+ } else {
+ notify(msg);
+ }
+ }
+
+ return (
+ <Button label="toolbar.confirm" variant="contained" size="large" onClick={confirm} />
+ )
+}
+
+const OrderPreview = ({ rows, gridRef }) => {
+ gridRef.current = useGridApiRef();
+
+ const columns = [
+ { field: 'matnrCode', headerName: '鐗╂枡缂栫爜', width: 110 },
+ { field: 'maktx', headerName: '鐗╂枡鍚嶇О', width: 190 },
+ {
+ field: 'anfme', headerName: '鍑哄簱鏁伴噺', width: 110, type: 'number', editable: true,
+ valueGetter: (value, row) => {
+ return row.anfme - row.workQty - row.qty;
+ },
+ preProcessEditCellProps: (params) => {
+ const hasError = !params.props.value || params.props.value.trim() === '';
+ return {
+ ...params.props,
+ error: hasError,
+ message: hasError ? '璁″垝鏁伴噺涓嶈兘涓虹┖锛侊紒' : '',
+ };
+ },
+ },
+ {
+ field: 'workQty', headerName: '鍓╀綑鏁伴噺', width: 110, type: 'number',
+ valueGetter: (value, row) => {
+ return row.anfme - row.workQty - row.qty;
+ },
+ },
+ { field: 'unit', headerName: '鍗曚綅', width: 110 },
+ { field: 'splrBatch', headerName: '鎵规', width: 110 },
+ { field: 'splrName', headerName: '渚涘簲鍟�', width: 110 },
+ { field: 'updateTime', headerName: '鏇存柊鏃堕棿', width: 110 },
+ { field: 'updateBy$', headerName: '鏇存柊浜哄憳', width: 110 },
+ ]
+
+ return (
+ <DataGrid
+ storeKey={"outOrderItemPreview"}
+ rows={rows}
+ columns={columns}
+ apiRef={gridRef}
+ disableRowSelectionOnClick
+ hideFooterPagination={true} // 闅愯棌鍒嗛〉鎺т欢
+ hideFooter={true}
+ onRowSelectionModelChange={(ids) => {
+ setSelectedIds(ids)
+ }}
+ />
+ )
+}
+
+
diff --git a/rsf-admin/src/page/orders/preparation/PreparationSelectMatnrModal.jsx b/rsf-admin/src/page/orders/preparation/PreparationSelectMatnrModal.jsx
new file mode 100644
index 0000000..c15d5dc
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationSelectMatnrModal.jsx
@@ -0,0 +1,587 @@
+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 { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import DialogCloseButton from "../../components/DialogCloseButton";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import DictionarySelect from "../../components/DictionarySelect";
+import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
+import ConfirmButton from "../../components/ConfirmButton";
+import { Add, Edit, Delete } from '@mui/icons-material';
+import DictSelect from "../../components/DictSelect";
+import SaveIcon from '@mui/icons-material/Save';
+import MatnrInfoModal from "./PreparationMatnrInfoModal";
+import request from '@/utils/request';
+import "./preparation.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
+ }));
+ };
+
+ 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(`/outStock/items/save`, parmas);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ resetData()
+ } else {
+ notify(res.data.msg);
+ }
+ } else {
+ const parmas = {
+ "orders": formData,
+ "items": tabelData,
+ }
+ const res = await request.post(`/outStock/items/update`, parmas);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ resetData()
+ } else {
+ notify(res.data.msg);
+ }
+ }
+ setDisabled(false)
+
+ };
+
+
+ const handleDelete = async () => {
+ const res = await request.post(`/outStock/remove/${asnId}`);
+ if (res?.data?.code === 200) {
+ setOpen(false);
+ refresh();
+ } else {
+ notify(res.data.msg);
+ }
+ };
+
+ const requestGetHead = async () => {
+ const res = await request.get(`/outStock/${asnId}`);
+ if (res?.data?.code === 200) {
+ setFormData(res.data.data)
+ } else {
+ notify(res.data.msg);
+ }
+ }
+
+ const requestGetBody = async () => {
+ const res = await request.post(`/outStockItem/page`, { orderId: 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.outStock.wkType")}
+ value={formData.wkType}
+ variant="filled"
+ group='2'
+ onChange={(e) => handleChange(e.target.value, 'wkType')}
+ dictTypeCode="sys_business_type"
+ required
+ />
+ </Grid>
+ <Grid item md={2}>
+ <TextField
+ label={translate("table.field.outStock.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.outStock.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.outStock.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>
+ <MatnrInfoModal
+ 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)
+ } 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)
+ } 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.outStockItem.maktx'),
+ width: 250,
+ editable: false,
+ },
+ {
+ field: 'matnrCode',
+ headerName: translate('table.field.outStockItem.matnrCode'),
+ width: 130,
+ editable: false,
+ },
+ {
+ field: 'anfme',
+ headerName: translate('table.field.outStockItem.anfme') + "*",
+ type: 'number',
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ valueFormatter: (val) => val < 0 ? 0 : val,
+ headerClassName: "custom",
+ },
+ {
+ field: 'splrCode',
+ headerName: translate('table.field.outStockItem.splrCode') + "*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrCodeEditCell {...params} />
+ ),
+ headerClassName: "custom",
+ },
+ {
+ field: 'splrName',
+ headerName: translate('table.field.outStockItem.splrName') + "*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrNameEditCell {...params} />
+ ),
+ headerClassName: "custom",
+ },
+ {
+ field: 'splrBatch',
+ headerName: translate('table.field.outStockItem.splrBatch'),
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ },
+ {
+ field: 'poCode',
+ headerName: translate('table.field.outStockItem.poDetlCode'),
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ },
+ {
+ field: 'stockUnit',
+ headerName: translate('table.field.outStockItem.stockUnit'),
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ },
+ ])
+
+ 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: el.unique,
+ valueGetter: (value, row) => {
+ return row.extendFields?.[el.fields] || '';
+ },
+ }))
+ 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 ? row.matnrId : row.id}
+ disableColumnFilter
+ disableColumnSelector
+ disableColumnSorting
+ disableMultipleColumnsSorting
+ processRowUpdate={processRowUpdate}
+ initialState={{
+ pagination: {
+ paginationModel: {
+ pageSize: 25,
+ },
+ },
+ }}
+ pageSizeOptions={[10, 20, 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/preparation/MatPreparationPublic.jsx b/rsf-admin/src/page/orders/preparation/PreparationStockPublic.jsx
similarity index 95%
rename from rsf-admin/src/page/orders/preparation/MatPreparationPublic.jsx
rename to rsf-admin/src/page/orders/preparation/PreparationStockPublic.jsx
index c40f37d..f962a5c 100644
--- a/rsf-admin/src/page/orders/preparation/MatPreparationPublic.jsx
+++ b/rsf-admin/src/page/orders/preparation/PreparationStockPublic.jsx
@@ -47,7 +47,7 @@
import CloseSharpIcon from '@mui/icons-material/CloseSharp';
import ConfirmButton from '../../components/ConfirmButton';
import { Delete, Edit, Add } from '@mui/icons-material';
-// import OutStockSiteDialog from "./OutStockSiteDialog";
+import OutStockSiteDialog from "./PreparationStockSiteDialog";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
'& .css-1vooibu-MuiSvgIcon-root': {
@@ -67,7 +67,7 @@
}));
-const MatPerparationPublic = (props) => {
+const OutStockPublic = (props) => {
const { record, open, setOpen, setManualDialog } = props;
const notify = useNotify();
const gridRef = useGridApiRef();
@@ -201,19 +201,14 @@
sx={{ height: "2px", position: 'absolute', top: 0, left: 0, right: 0, }}
/>
<StyledDatagrid
- storeKey={"matPerparationPublic"}
+ storeKey={"outStockPublic"}
preferenceKey='outStockItem'
bulkActionButtons={<>
<ComfirmButton />
</>}
omit={['id', 'splrName', 'qty', 'poCode',]}
>
- <TextField source="matnrCode" label="鐗╂枡缂栫爜" />,
- <TextField source="maktx" label="鐗╂枡鍚嶇О" />,
- <TextField source="spec" label="瑙勬牸" />,
- <TextField source="unit" label="鍗曚綅" />,
- <TextField source="anfme" label="鏁伴噺" />,
- {/* <NumberField source="id" />
+ <NumberField source="id" />
<TextField source="asnCode" label="table.field.outStockItem.orderCode" />
<TextField source="poCode" label="table.field.outStockItem.poCode" />
<TextField source="matnrCode" label="table.field.outStockItem.matnrCode" />
@@ -222,7 +217,7 @@
<NumberField source="workQty" label="table.field.outStockItem.workQty" />
<NumberField source="qty" label="table.field.outStockItem.qty" />
<TextField source="stockUnit" label="table.field.outStockItem.stockUnit" />
- <TextField source="splrName" label="table.field.outStockItem.splrName" /> */}
+ <TextField source="splrName" label="table.field.outStockItem.splrName" />
</StyledDatagrid>
</List>
</Card>
@@ -483,6 +478,6 @@
)
}
-export default MatPerparationPublic;
+export default OutStockPublic;
diff --git a/rsf-admin/src/page/orders/preparation/PreparationStockSiteDialog.jsx b/rsf-admin/src/page/orders/preparation/PreparationStockSiteDialog.jsx
new file mode 100644
index 0000000..e0b0ced
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationStockSiteDialog.jsx
@@ -0,0 +1,54 @@
+import { Box, Card, Grid, List, LinearProgress, Select, MenuItem, ListItemText, ListItemAvatar, Avatar, ListItemButton, Dialog, DialogTitle, ListItem } from "@mui/material";
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
+import { Delete, Edit, Add } from '@mui/icons-material';
+import request from '@/utils/request';
+import { useTranslate } from "react-admin";
+
+const OutStockSiteDialog = (props) => {
+ const translate = useTranslate();
+ const { onClose, selectedValue, open } = props;
+ const [siteNos, setSiteNos] = useState([]);
+
+ const handleClose = () => {
+ onClose(selectedValue);
+ }
+
+ const handleListItemClick = (value) => {
+ onClose(value);
+ }
+
+ useEffect(() => {
+ getSiteNos()
+ }, [open])
+
+
+ const getSiteNos = async () => {
+ const { data: { code, data, msg } } = await request.get('/outStock/tasks/sites');
+ if (code === 200) {
+ setSiteNos(data);
+ } else {
+ notify(msg);
+ }
+ }
+
+ return (
+ <Dialog
+ onClose={handleClose}
+ open={open}
+ >
+ <DialogTitle>{translate("toolbar.modiftySite")}</DialogTitle>
+ <List sx={{ pt: 0 }}>
+ {siteNos.map((site) => (
+ <ListItem disableGutters key={site?.id}>
+ <ListItemButton onClick={() => handleListItemClick(site)}>
+ <ListItemText primary={site.site} />
+ </ListItemButton>
+ </ListItem>
+ ))}
+ </List>
+ </Dialog>
+ );
+}
+
+export default OutStockSiteDialog;
\ No newline at end of file
diff --git a/rsf-admin/src/page/orders/preparation/PreparationStockWaveDialog.jsx b/rsf-admin/src/page/orders/preparation/PreparationStockWaveDialog.jsx
new file mode 100644
index 0000000..6bd93c7
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/PreparationStockWaveDialog.jsx
@@ -0,0 +1,64 @@
+import { Box, Card, Grid, List, LinearProgress, Select, MenuItem, ListItemText, ListItemAvatar, Avatar, ListItemButton, Dialog, DialogTitle, ListItem, DialogContent, DialogActions, Button } from "@mui/material";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE, DEFAULT_TYPE } from '@/config/setting';
+import { SimpleForm, TextInput, ReferenceInput, useTranslate, AutocompleteInput } from "react-admin";
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { Delete, Edit, Add } from '@mui/icons-material';
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+
+const OutStockWaveDialog = (props) => {
+ const translate = useTranslate();
+ const { onClose, selectedValue, open, setOpen } = props;
+ const [siteNos, setSiteNos] = useState([]);
+ const [formData, setFormData] = useState({
+ id: DEFAULT_TYPE
+ });
+
+ const handleClose = () => {
+ onClose(null);
+ }
+
+ const handleSelect = () => {
+ onClose(formData);
+
+ }
+
+ const handleListItemClick = (value) => {
+ onClose(value);
+ }
+
+ const handleChange = (event) => {
+ console.log(event);
+ setFormData({ id: event })
+ };
+
+ return (
+ <Dialog
+ onClose={handleClose}
+ open={open}
+ aria-labelledby="alert-dialog-title"
+ aria-describedby="alert-dialog-description"
+ >
+ <DialogTitle id="alert-dialog-title">{translate("toolbar.selectWave")}</DialogTitle>
+ <DialogContent sx={{ width: 600 }}>
+ <SimpleForm toolbar={false} defaultValue={formData}>
+ <ReferenceInput source="id" reference="waveRule" >
+ <AutocompleteInput
+ label={'toolbar.selectWave'}
+ defaultValue={DEFAULT_TYPE}
+ onChange={handleChange}
+ />
+ </ReferenceInput>
+ </SimpleForm>
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={handleClose} variant="outlined">{translate('toolbar.cancel')}</Button>
+ <Button onClick={handleSelect} autoFocus startIcon={<SaveIcon />} variant="contained">
+ {translate('toolbar.confirm')}
+ </Button>
+ </DialogActions>
+ </Dialog>
+ );
+}
+
+export default OutStockWaveDialog;
\ No newline at end of file
diff --git a/rsf-admin/src/page/orders/preparation/index.jsx b/rsf-admin/src/page/orders/preparation/index.jsx
index 6214961..8ac1ccd 100644
--- a/rsf-admin/src/page/orders/preparation/index.jsx
+++ b/rsf-admin/src/page/orders/preparation/index.jsx
@@ -5,14 +5,14 @@
ShowGuesser,
} from "react-admin";
-import MatPreparationList from "./MatPreparationList";
-// import TaskEdit from "./TaskEdit";
+import PreparationOrderList from "./PreparationOrderList";
+import PreparationOrderEdit from "./PreparationOrderEdit";
export default {
- list: MatPreparationList,
- // edit: TaskEdit,
+ list: PreparationOrderList,
+ edit: PreparationOrderEdit,
show: ShowGuesser,
recordRepresentation: (record) => {
- return `${record.id}`
+ return `${record.name}`
}
};
diff --git a/rsf-admin/src/page/orders/preparation/preparation.css b/rsf-admin/src/page/orders/preparation/preparation.css
new file mode 100644
index 0000000..0df941e
--- /dev/null
+++ b/rsf-admin/src/page/orders/preparation/preparation.css
@@ -0,0 +1,5 @@
+
+.custom {
+ color: rgb(0, 195, 255) !important;
+ }
+
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatPreparationController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatPreparationController.java
index 09194cd..9e416e6 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatPreparationController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatPreparationController.java
@@ -1,96 +1,328 @@
package com.vincent.rsf.server.manager.controller;
import com.alibaba.fastjson.JSON;
+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.extension.plugins.pagination.Page;
+import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.framework.exception.CoolException;
+import com.vincent.rsf.server.common.annotation.OperationLog;
import com.vincent.rsf.server.common.domain.BaseParam;
+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.common.utils.FieldsUtils;
-import com.vincent.rsf.server.manager.entity.Task;
-import com.vincent.rsf.server.manager.entity.TaskItem;
-import com.vincent.rsf.server.manager.entity.WkOrder;
+import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams;
+import com.vincent.rsf.server.manager.controller.params.GenWaveParams;
+import com.vincent.rsf.server.manager.controller.params.OrderOutTaskParam;
+import com.vincent.rsf.server.manager.controller.params.OutStockToTaskParams;
+import com.vincent.rsf.server.manager.entity.*;
+import com.vincent.rsf.server.manager.entity.excel.AsnOrderTemplate;
+import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.OrderType;
+import com.vincent.rsf.server.manager.enums.OrderWorkType;
+import com.vincent.rsf.server.manager.service.OutStockItemService;
import com.vincent.rsf.server.manager.service.OutStockService;
import com.vincent.rsf.server.manager.service.TaskService;
+import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.controller.BaseController;
+import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
import java.util.*;
@RestController
@Api(tags = "澶囨枡鍗�")
public class MatPreparationController extends BaseController {
- Logger logger = LoggerFactory.getLogger(OutStockController.class);
+ @Autowired
+ private OutStockService outStockService;
+ @Autowired
+ private OutStockItemService outStockItemService;
- @Resource
- private TaskService taskService;
-
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
@PostMapping("/preparation/page")
public R page(@RequestBody Map<String, Object> map) {
-
-// JSONObject jsonObject = new JSONObject(map);
-// jsonObject.put("orderCode", "BL25090927787678");
-// jsonObject.put("orderStatus", 1);
-// jsonObject.put("orderTime", new Date());
-// jsonObject.put("anfme", 100);
-// List<JSONObject> list = new ArrayList<>();
-// list.add(jsonObject);
-//
-// return R.ok().add(list);
-
BaseParam baseParam = buildParam(map, BaseParam.class);
- PageParam<Task, BaseParam> pageParam = new PageParam<>(baseParam, Task.class);
- QueryWrapper<Task> queryWrapper = pageParam.buildWrapper(true);
- return R.ok().add(taskService.page(pageParam, queryWrapper));
+ PageParam<WkOrder, BaseParam> pageParam = new PageParam<>(baseParam, WkOrder.class);
+ QueryWrapper<WkOrder> queryWrapper = pageParam.buildWrapper(true);
+// List<String> list = Arrays.asList(OrderType.ORDER_OUT.type);
+// queryWrapper.in("type", list);
+ return R.ok().add(outStockService.page(pageParam, queryWrapper));
}
-// @PreAuthorize("hasAuthority('manager:outStock:list')")
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ @PostMapping("/preparation/dialog/page")
+ public R dialogPage(@RequestBody Map<String, Object> map) {
+ BaseParam baseParam = buildParam(map, BaseParam.class);
+ PageParam<WkOrder, BaseParam> pageParam = new PageParam<>(baseParam, WkOrder.class);
+ QueryWrapper<WkOrder> queryWrapper = pageParam.buildWrapper(true);
+ List<String> list = Arrays.asList(OrderType.ORDER_OUT.type);
+ queryWrapper.in("type", list);
+ return R.ok().add(outStockService.page(pageParam, queryWrapper));
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
@PostMapping("/preparation/list")
public R list(@RequestBody Map<String, Object> map) {
+ return R.ok().add(outStockService.list(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getType, OrderType.ORDER_OUT.type)));
+ }
- return R.ok().add(taskService.list());
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ @PostMapping({"/preparation/many/{ids}", "/asnOrders/many/{ids}"})
+ public R many(@PathVariable Long[] ids) {
+ return R.ok().add(outStockService.listByIds(Arrays.asList(ids)));
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ @OperationLog("琛ㄥ崟鏌ヨ")
+ @GetMapping("/preparation/{id}")
+ public R get(@PathVariable("id") Long id) {
+ return R.ok().add(outStockService.getById(id));
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:save')")
+ @OperationLog("Create 鍑哄簱鍗曟嵁")
+ @PostMapping("/preparation/save")
+ @ApiOperation("淇濆瓨")
+ public R save(@RequestBody WkOrder wkOrder) {
+ wkOrder.setCreateBy(getLoginUserId())
+ .setUpdateBy(getLoginUserId());
+ if (Objects.isNull(wkOrder.getCode())) {
+ String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, wkOrder);
+ if (Objects.isNull(ruleCode) || StringUtils.isBlank(ruleCode)) {
+ return R.error("缂栫爜瑙勫垯閿欒锛氱紪鐮併�孲YS_OUT_STOCK_CODE銆嶆槸鏈缃垚鍔燂紒锛�");
+ }
+ wkOrder.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val)
+ .setCode(ruleCode);
+ }
+ if (!outStockService.save(wkOrder)) {
+ return R.error("Save Fail");
+ }
+ return R.ok("Save Success").add(wkOrder);
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ @OperationLog("Update 锛涘嚭搴撳崟鎹�")
+ @PostMapping("/preparation/update")
+ @ApiOperation("鏇存柊")
+ public R update(@RequestBody WkOrder wkOrder) {
+ wkOrder.setType(OrderType.ORDER_OUT.type)
+ .setUpdateBy(getLoginUserId())
+ .setUpdateTime(new Date());
+ if (Objects.isNull(wkOrder.getCode())) {
+ String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, wkOrder);
+ wkOrder.setCode(ruleCode);
+ }
+ if (!outStockService.updateById(wkOrder)) {
+ return R.error("Update Fail");
+ }
+ return R.ok("Update Success").add(wkOrder);
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:remove')")
+ @OperationLog("Delete 鍑哄簱鍗曟嵁")
+ @PostMapping("/preparation/remove/{ids}")
+ public R remove(@PathVariable Long[] ids) {
+ if (!outStockService.removeByIds(Arrays.asList(ids))) {
+ return R.error("Delete Fail");
+ }
+ return R.ok("Delete Success").add(ids);
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ @PostMapping("/preparation/query")
+ @ApiOperation("鏌ヨ")
+ public R query(@RequestParam(required = false) String condition) {
+ List<KeyValVo> vos = new ArrayList<>();
+ LambdaQueryWrapper<WkOrder> wrapper = new LambdaQueryWrapper<>();
+ if (!Cools.isEmpty(condition)) {
+ wrapper.like(WkOrder::getCode, condition);
+ }
+ outStockService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
+ item -> vos.add(new KeyValVo(item.getId(), item.getCode()))
+ );
+ return R.ok().add(vos);
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ @ApiOperation("鍙栨秷鍑哄簱鍗曟嵁")
+ @GetMapping("/preparation/cancel/{id}")
+ public R cancel(@PathVariable String id) {
+ if (Objects.isNull(id)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ return outStockService.cancelOutOrder(id);
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ @ApiOperation("鍒犻櫎宸茬敓鎴愭槑缁�")
+ @GetMapping("/preparation/items/cancel/{ids}")
+ public R cancel(@PathVariable Long[] ids) {
+ List<Long> list = Arrays.asList(ids);
+ if (list.isEmpty()) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ List<WkOrderItem> orderItems = outStockItemService.list(new LambdaQueryWrapper<WkOrderItem>().in(WkOrderItem::getId, list));
+ if (orderItems.isEmpty()) {
+ throw new CoolException("鍗曟嵁鏄庣粏涓嶅瓨鍦紒锛�");
+ }
+ return outStockService.cancelOutOrderByItems(orderItems);
}
-// @PreAuthorize("hasAuthority('manager:taskItem:list')")
- @PostMapping("/preparationItem/page")
- public R itemPage(@RequestBody Map<String, Object> map) {
-// BaseParam baseParam = buildParam(map, BaseParam.class);
-// PageParam<TaskItem, BaseParam> pageParam = new PageParam<>(baseParam, TaskItem.class);
-// /**鎷兼帴鎵╁睍瀛楁*/
-// PageParam<TaskItem, BaseParam> page = taskItemService.page(pageParam, pageParam.buildWrapper(true));
-// List<TaskItem> records = page.getRecords();
-// for (TaskItem record : records) {
-// if (!Objects.isNull(record.getFieldsIndex())) {
-// Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex());
-// record.setExtendFields(fields);
-// }
-// }
-// page.setRecords(records);
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ @PostMapping("/preparation/export")
+ @ApiOperation("瀵煎嚭")
+ public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
+ List<WkOrder> orders = new ArrayList<>();
+ if (!Objects.isNull(map.get("ids"))) {
+ List<Long> ids = JSONArray.parseArray(JSONObject.toJSONString(map.get("ids")), Long.class);
+ if (!ids.isEmpty()) {
+ orders = outStockService.list(new LambdaQueryWrapper<WkOrder>().in(WkOrder::getId, ids));
+ } else {
+ orders = outStockService.list(new LambdaQueryWrapper<>());
+ }
+ } else {
+ orders = outStockService.list();
+ }
+ List<AsnOrderTemplate> orderTemplates = new ArrayList<>();
+ for (WkOrder order : orders) {
+ List<WkOrderItem> orderItems = outStockItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
+ for (WkOrderItem item : orderItems) {
+ if (Objects.isNull(item)) {
+ continue;
+ }
+ AsnOrderTemplate template = new AsnOrderTemplate();
+ template.setCode(order.getCode())
+ .setType(OrderType.getValType(order.getType()))
+ .setWkType(OrderWorkType.getWorkDesc(order.getWkType()))
+ .setAnfme(item.getAnfme() + "")
+ .setMaktx(item.getMaktx())
+ .setMemo(item.getMemo())
+ .setMatnrCode(item.getMatnrCode())
+ .setPoCode(item.getPoCode())
+ .setSplrName(item.getSplrName())
+ .setPlatItemId(item.getPlatItemId())
+ .setSplrBatch(item.getSplrBatch())
+ .setSplrCode(item.getSplrCode());
+ orderTemplates.add(template);
+ }
+ }
+ ExcelUtil.build(ExcelUtil.create(orderTemplates, AsnOrderTemplate.class), response);
+ }
- JSONObject jsonObject = new JSONObject(map);
- jsonObject.put("matnrCode", "BL25090927787678");
- jsonObject.put("maktx", "鎷夋潌");
- jsonObject.put("unit", "涓�");
- jsonObject.put("spec", "閾濆悎閲� 閾惰壊");
- jsonObject.put("model", "澶�");
- jsonObject.put("anfme", 100);
- jsonObject.put("workQty", 60);
- jsonObject.put("status", 11);
- List<JSONObject> list = new ArrayList<>();
- list.add(jsonObject);
- return R.ok().add(list);
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ @ApiOperation("閫氳繃DO鍗曠敓鎴愬嚭搴撳崟")
+ @PostMapping("/preparation/generate/orders")
+ public R genOutStock(@RequestBody Map<String, Object> params) {
+ if (Objects.isNull(params.get("ids"))) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ List<DeliveryItem> items = JSON.parseArray(JSONObject.toJSONString(params.get("ids")), DeliveryItem.class);
+ return outStockService.genOutStock(items, getLoginUserId());
+ }
+
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ @ApiOperation("鍑哄簱鍗曠敓鎴愭尝娆�")
+ @PostMapping("/preparation/generate/wave")
+ public R generateWave(@RequestBody GenWaveParams params) {
+ if (Objects.isNull(params)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ return outStockService.generateWaves(params);
+ }
+
+ @PostMapping("/preparation/items/save")
+ @ApiOperation("淇濆瓨涓诲崟鍙婃槑缁�")
+ @PreAuthorize("hasAuthority('manager:outStock:save')")
+ public R saveOutStock(@RequestBody AsnOrderAndItemsParams params) throws Exception {
+ if (Objects.isNull(params)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ return outStockService.saveOutStock(params, getLoginUserId());
+ }
+
+ @GetMapping("/preparation/complete/{id}")
+ @ApiOperation("瀹屾垚鍑哄簱鍗�")
+ @PreAuthorize("hasAuthority('manager:outStock:update')")
+ public R complete(@PathVariable Long id) {
+ if (Objects.isNull(id)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ return outStockService.completeOutOrderById(id);
+ }
+
+
+ @ApiOperation("鍗曟嵁淇℃伅淇敼")
+ @PostMapping("/preparation/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());
+ }
+
+ @PostMapping("/preparation/order/getOutTaskItems")
+ @ApiOperation("鍑哄簱鍗曞簱浣嶉瑙�")
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ public R getOrderOutTaskItem(@RequestBody OrderOutTaskParam param) {
+ if (Cools.isEmpty(param)) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖");
+ }
+
+ return outStockService.getOrderOutTaskItem(param);
+ }
+
+
+ /**
+ * 鍑哄簱鍗曠敓鎴愬嚭搴撲换鍔�
+ * @param params
+ * @return
+ */
+ @PostMapping("/preparation/generate/tasks")
+ @ApiOperation("鍑哄簱鍗曠敓鎴愬嚭搴撲换鍔�")
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ public R genOutStockTask( @RequestBody Map<String, Object> params) {
+ if (Cools.isEmpty()) {
+ return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ if (Objects.isNull(params.get("outId"))) {
+ return R.error("鍑哄簱鍙傛暟涓嶈兘涓虹┖锛侊紒");
+ }
+ List<OutStockToTaskParams> taskParams = JSONArray.parseArray(JSONArray.toJSONString(params.get("items")), OutStockToTaskParams.class);
+ List<OutStockToTaskParams> tasks = new ArrayList<>();
+ for (OutStockToTaskParams taskParam : taskParams) {
+ if (StringUtils.isNotBlank(taskParam.getLocCode())) {
+ tasks.add(taskParam);
+ }
+ }
+ return outStockService.genOutStockTask(tasks, getLoginUserId(), Long.parseLong(params.get("outId").toString()));
+ }
+
+ /**
+ * 鑾峰彇鍑哄簱绔欑偣
+ * @return
+ */
+ @GetMapping("/preparation/tasks/sites")
+ @ApiOperation("鑾峰彇鍑哄簱搴撳彛")
+ @PreAuthorize("hasAuthority('manager:outStock:list')")
+ public R getSiteNos() {
+ return outStockService.getSiteNos();
}
}
--
Gitblit v1.9.1