From cebd9afa05ca5b17ca62b672010c29d115b89d60 Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 18 二月 2025 09:47:03 +0800
Subject: [PATCH] #新增 1. 添加批次规则信息 2. 物料添加控制属性

---
 rsf-server/src/main/resources/mapper/manager/BatchRegularMapper.xml                               |    5 
 rsf-admin/src/page/matnr/MatnrEdit.jsx                                                            |   88 +++
 rsf-admin/src/page/batchRegular/BatchRegularList.jsx                                              |  156 +++++++
 rsf-admin/src/page/batchRegular/BatchRegularEdit.jsx                                              |  104 ++++
 rsf-admin/src/page/matnr/MatnrList.jsx                                                            |   32 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BatchRegularServiceImpl.java |   12 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrController.java           |    6 
 rsf-admin/src/page/batchRegular/BatchRegularPanel.jsx                                             |   69 +++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BatchRegularMapper.java            |   12 
 rsf-admin/src/page/batchRegular/index.jsx                                                         |   18 
 rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java                           |    4 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BatchRegularController.java    |  110 +++++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java                         |  117 ++++-
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BatchRegularService.java          |    8 
 rsf-admin/src/page/matnr/MatnrCreate.jsx                                                          |   87 +++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BatchRegular.java                  |  194 ++++++++
 rsf-admin/src/page/matnr/MatnrPanel.jsx                                                           |   64 ++
 rsf-server/src/main/java/batchRegular.sql                                                         |   24 +
 rsf-server/src/main/java/matnr.sql                                                                |   20 
 rsf-admin/src/i18n/zh.js                                                                          |   19 
 rsf-admin/src/page/batchRegular/BatchRegularCreate.jsx                                            |  132 ++++++
 rsf-admin/src/i18n/en.js                                                                          |   13 
 22 files changed, 1,206 insertions(+), 88 deletions(-)

diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 8202d8b..0914029 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -234,24 +234,31 @@
                 name: "name",
             },
             matnr: {
-                uuid: "uuid",
-                shipperId: "shipperId",
                 name: "name",
                 code: "code",
+                shipperId: "shipperId",
                 groupId: "groupId",
+                batchRegularId: "batchRegularId",
                 erpCode: "erpCode",
                 spec: "spec",
                 model: "model",
                 weight: "weight",
                 color: "color",
                 size: "size",
-                desc: "desc",
+                describle: "describle",
                 nromNum: "nromNum",
                 unit: "unit",
                 purchaseUnit: "purchaseUnit",
                 stockUnit: "stockUnit",
                 stockLeval: "stockLeval",
                 isLabelMange: "isLabelMange",
+                safetyQty: "safetyQty",
+                minQty: "minQty",
+                maxQty: "maxQty",
+                stagnate: "stagnate",
+                validity: "validity",
+                validityWarr: "validityWarr",
+                flagCheck: "flagCheck",
             },
             matnrGroup: {
                 name: "name",
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index bc97763..8907d38 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -234,24 +234,31 @@
                 name: "鍚嶇О",
             },
             matnr: {
-                uuid: "缂栫爜",
-                shipperId: "璐т富ID",
-                name: "鍚嶇О",
+                name: "鐗╂枡鍚嶇О",
                 code: "鐗╂枡缂栫爜",
-                groupId: "鍒嗙被鏍囪瘑",
+                shipperId: "璐т富鏍囪瘑",
+                groupId: "鍒嗙粍鏍囪瘑",
+                batchRegularId: "鎵规瑙勫垯鏍囪瘑",
                 erpCode: "ERP缂栫爜",
                 spec: "瑙勬牸",
                 model: "鍨嬪彿",
                 weight: "閲嶉噺",
                 color: "棰滆壊",
                 size: "灏哄",
-                desc: "鎻忚堪",
+                describle: "鎻忚堪",
                 nromNum: "鏍囧寘鏁伴噺",
                 unit: "鍗曚綅",
                 purchaseUnit: "閲囪喘鍗曚綅",
                 stockUnit: "搴撳瓨鍗曚綅",
                 stockLeval: "ABC鍒嗙被",
-                isLabelMange: "鏄惁鏍囩绠$悊",
+                isLabelMange: "鏍囩绠$悊",
+                safetyQty: "瀹夊叏鍊�",
+                minQty: "鏈�灏忓��",
+                maxQty: "鏈�澶у��",
+                stagnate: "鍋滄粸棰勮鍊�",
+                validity: "淇濊川鏈�",
+                validityWarr: "鏁堟湡棰勮",
+                flagCheck: "鍏嶆",
             },
             matnrGroup: {
                 name: "鍚嶇О",
diff --git a/rsf-admin/src/page/batchRegular/BatchRegularCreate.jsx b/rsf-admin/src/page/batchRegular/BatchRegularCreate.jsx
new file mode 100644
index 0000000..74b73e1
--- /dev/null
+++ b/rsf-admin/src/page/batchRegular/BatchRegularCreate.jsx
@@ -0,0 +1,132 @@
+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 BatchRegularCreate = (props) => {
+    const { open, setOpen } = 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
+                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 container rowSpacing={2} columnSpacing={2}>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.batchRegular.name"
+                                        source="name"
+                                        parse={v => v}
+                                        autoFocus
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.batchRegular.code"
+                                        source="code"
+                                        parse={v => v}
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.batchRegular.property"
+                                        source="property"
+                                        parse={v => v}
+                                    />
+                                </Grid>
+
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <StatusSelectInput />
+                                </Grid>
+                                <Grid item xs={12} display="flex" gap={1}>
+                                    <Stack direction="column" spacing={1} width={'100%'}>
+                                        <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 BatchRegularCreate;
diff --git a/rsf-admin/src/page/batchRegular/BatchRegularEdit.jsx b/rsf-admin/src/page/batchRegular/BatchRegularEdit.jsx
new file mode 100644
index 0000000..36629d5
--- /dev/null
+++ b/rsf-admin/src/page/batchRegular/BatchRegularEdit.jsx
@@ -0,0 +1,104 @@
+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,
+    useRecordContext,
+    DeleteButton,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography } from '@mui/material';
+import * as Common from '@/utils/common';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+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: 'space-between' }}>
+            <SaveButton />
+            <DeleteButton mutationMode="optimistic" />
+        </Toolbar>
+    )
+}
+
+const BatchRegularEdit = () => {
+    const translate = useTranslate();
+
+    return (
+        <Edit
+            redirect="list"
+            mutationMode={EDIT_MODE}
+            actions={<CustomerTopToolBar />}
+            aside={<EditBaseAside />}
+        >
+            <SimpleForm
+                shouldUnregister
+                warnWhenUnsavedChanges
+                toolbar={<FormToolbar />}
+                mode="onTouched"
+                defaultValues={{}}
+            // validate={(values) => { }}
+            >
+                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
+                    <Grid item xs={12} md={8}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.main')}
+                        </Typography>
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.batchRegular.name"
+                                source="name"
+                                parse={v => v}
+                                autoFocus
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.batchRegular.code"
+                                source="code"
+                                parse={v => v}
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.batchRegular.property"
+                                source="property"
+                                parse={v => v}
+                            />
+                        </Stack>
+
+                    </Grid>
+                    <Grid item xs={12} md={4}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.common')}
+                        </Typography>
+                        <StatusSelectInput />
+                        <Box mt="2em" />
+                        <MemoInput />
+                    </Grid>
+                </Grid>
+            </SimpleForm>
+        </Edit >
+    )
+}
+
+export default BatchRegularEdit;
diff --git a/rsf-admin/src/page/batchRegular/BatchRegularList.jsx b/rsf-admin/src/page/batchRegular/BatchRegularList.jsx
new file mode 100644
index 0000000..5a19e66
--- /dev/null
+++ b/rsf-admin/src/page/batchRegular/BatchRegularList.jsx
@@ -0,0 +1,156 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useNavigate } 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,
+} from 'react-admin';
+import { Box, Typography, Card, Stack } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import BatchRegularCreate from "./BatchRegularCreate";
+import BatchRegularPanel from "./BatchRegularPanel";
+import EmptyData from "../components/EmptyData";
+import MyCreateButton from "../components/MyCreateButton";
+import MyExportButton from '../components/MyExportButton';
+import PageDrawer from "../components/PageDrawer";
+import MyField from "../components/MyField";
+import { 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
+    },
+}));
+
+const filters = [
+    <SearchInput source="condition" alwaysOn />,
+    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
+    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
+
+    <TextInput source="name" label="table.field.batchRegular.name" />,
+    <TextInput source="code" label="table.field.batchRegular.code" />,
+    <TextInput source="property" label="table.field.batchRegular.property" />,
+
+    <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 BatchRegularList = () => {
+    const translate = useTranslate();
+
+    const [createDialog, setCreateDialog] = useState(false);
+    const [drawerVal, setDrawerVal] = useState(false);
+
+    return (
+        <Box display="flex">
+            <List
+                sx={{
+                    flexGrow: 1,
+                    transition: (theme) =>
+                        theme.transitions.create(['all'], {
+                            duration: theme.transitions.duration.enteringScreen,
+                        }),
+                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                }}
+                title={"menu.batchRegular"}
+                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
+                filters={filters}
+                sort={{ field: "create_time", order: "desc" }}
+                actions={(
+                    <TopToolbar>
+                        <FilterButton />
+                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
+                        <SelectColumnsButton preferenceKey='batchRegular' />
+                        <MyExportButton />
+                    </TopToolbar>
+                )}
+                perPage={DEFAULT_PAGE_SIZE}
+            >
+                <StyledDatagrid
+                    preferenceKey='batchRegular'
+                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    rowClick={(id, resource, record) => false}
+                    expand={() => <BatchRegularPanel />}
+                    expandSingle={true}
+                    omit={['id', 'createTime', 'createBy', 'memo']}
+                >
+                    <NumberField source="id" />
+                    <TextField source="name" label="table.field.batchRegular.name" />
+                    <TextField source="code" label="table.field.batchRegular.code" />
+                    <TextField source="property" label="table.field.batchRegular.property" />
+
+                    <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} />
+                    <WrapperField cellClassName="opt" label="common.field.opt">
+                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
+                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
+                    </WrapperField>
+                </StyledDatagrid>
+            </List>
+            <BatchRegularCreate
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+            <PageDrawer
+                title='BatchRegular Detail'
+                drawerVal={drawerVal}
+                setDrawerVal={setDrawerVal}
+            >
+            </PageDrawer>
+        </Box>
+    )
+}
+
+export default BatchRegularList;
diff --git a/rsf-admin/src/page/batchRegular/BatchRegularPanel.jsx b/rsf-admin/src/page/batchRegular/BatchRegularPanel.jsx
new file mode 100644
index 0000000..d1c80be
--- /dev/null
+++ b/rsf-admin/src/page/batchRegular/BatchRegularPanel.jsx
@@ -0,0 +1,69 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
+import {
+    useTranslate,
+    useRecordContext,
+} from 'react-admin';
+import PanelTypography from "../components/PanelTypography";
+import * as Common from '@/utils/common'
+
+const BatchRegularPanel = () => {
+    const record = useRecordContext();
+    if (!record) return null;
+    const translate = useTranslate();
+    return (
+        <>
+            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
+                <CardContent>
+                    <Grid container spacing={2}>
+                        <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
+                            <Typography variant="h6" gutterBottom align="left" sx={{
+                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
+                                whiteSpace: 'nowrap',
+                                overflow: 'hidden',
+                                textOverflow: 'ellipsis',
+                            }}>
+                                {Common.camelToPascalWithSpaces(translate('table.field.batchRegular.name'))}: {record.name}
+                            </Typography>
+                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
+                            <Typography variant="h6" gutterBottom align="right" >
+                                ID: {record.id}
+                            </Typography>
+                        </Grid>
+                    </Grid>
+                    <Grid container spacing={2}>
+                        <Grid item xs={12} container alignContent="flex-end">
+                            <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
+                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
+                            </Typography>
+                        </Grid>
+                    </Grid>
+                    <Box height={20}>&nbsp;</Box>
+                    <Grid container spacing={2}>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.batchRegular.name" 
+                                property={record.name}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.batchRegular.code" 
+                                property={record.code}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.batchRegular.property" 
+                                property={record.property}
+                            />
+                        </Grid>
+
+                    </Grid>
+                </CardContent>
+            </Card >
+        </>
+    );
+};
+
+export default BatchRegularPanel;
diff --git a/rsf-admin/src/page/batchRegular/index.jsx b/rsf-admin/src/page/batchRegular/index.jsx
new file mode 100644
index 0000000..5752ce6
--- /dev/null
+++ b/rsf-admin/src/page/batchRegular/index.jsx
@@ -0,0 +1,18 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    ListGuesser,
+    EditGuesser,
+    ShowGuesser,
+} from "react-admin";
+
+import BatchRegularList from "./BatchRegularList";
+import BatchRegularEdit from "./BatchRegularEdit";
+
+export default {
+    list: BatchRegularList,
+    edit: BatchRegularEdit,
+    show: ShowGuesser,
+    recordRepresentation: (record) => {
+        return `${record.name}`
+    }
+};
diff --git a/rsf-admin/src/page/matnr/MatnrCreate.jsx b/rsf-admin/src/page/matnr/MatnrCreate.jsx
index ba9f72a..e2e0d9a 100644
--- a/rsf-admin/src/page/matnr/MatnrCreate.jsx
+++ b/rsf-admin/src/page/matnr/MatnrCreate.jsx
@@ -85,6 +85,21 @@
                         <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
                                 <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.matnr.name"
+                                        source="name"
+                                        parse={v => v}
+                                        autoFocus
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.matnr.code"
+                                        source="code"
+                                        parse={v => v}
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
                                     <ReferenceInput
                                         source="shipperId"
                                         reference="shipper"
@@ -97,26 +112,24 @@
                                     </ReferenceInput>
                                 </Grid>
                                 <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.matnr.name"
-                                        source="name"
-                                        parse={v => v}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.matnr.code"
-                                        source="code"
-                                        parse={v => v}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
                                     <ReferenceInput
                                         source="groupId"
                                         reference="matnrGroup"
                                     >
                                         <AutocompleteInput
                                             label="table.field.matnr.groupId"
+                                            optionText="code"
+                                            filterToQuery={(val) => ({ code: val })}
+                                        />
+                                    </ReferenceInput>
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <ReferenceInput
+                                        source="batchRegularId"
+                                        reference="batchRegular"
+                                    >
+                                        <AutocompleteInput
+                                            label="table.field.matnr.batchRegularId"
                                             optionText="code"
                                             filterToQuery={(val) => ({ code: val })}
                                         />
@@ -165,8 +178,8 @@
                                 </Grid>
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <TextInput
-                                        label="table.field.matnr.desc"
-                                        source="desc"
+                                        label="table.field.matnr.describle"
+                                        source="describle"
                                         parse={v => v}
                                     />
                                 </Grid>
@@ -218,6 +231,48 @@
                                         ]}
                                     />
                                 </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.safetyQty"
+                                        source="safetyQty"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.minQty"
+                                        source="minQty"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.maxQty"
+                                        source="maxQty"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.stagnate"
+                                        source="stagnate"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.validity"
+                                        source="validity"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.validityWarr"
+                                        source="validityWarr"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.matnr.flagCheck"
+                                        source="flagCheck"
+                                    />
+                                </Grid>
 
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <StatusSelectInput />
diff --git a/rsf-admin/src/page/matnr/MatnrEdit.jsx b/rsf-admin/src/page/matnr/MatnrEdit.jsx
index 7c85bda..086aa72 100644
--- a/rsf-admin/src/page/matnr/MatnrEdit.jsx
+++ b/rsf-admin/src/page/matnr/MatnrEdit.jsx
@@ -64,6 +64,21 @@
                             {translate('common.edit.title.main')}
                         </Typography>
                         <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.matnr.name"
+                                source="name"
+                                parse={v => v}
+                                autoFocus
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.matnr.code"
+                                source="code"
+                                parse={v => v}
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
                             <ReferenceInput
                                 source="shipperId"
                                 reference="shipper"
@@ -77,20 +92,6 @@
                             </ReferenceInput>
                         </Stack>
                         <Stack direction='row' gap={2}>
-                            <TextInput
-                                label="table.field.matnr.name"
-                                source="name"
-                                parse={v => v}
-                            />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
-                            <TextInput
-                                label="table.field.matnr.code"
-                                source="code"
-                                parse={v => v}
-                            />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
                             <ReferenceInput
                                 source="groupId"
                                 reference="matnrGroup"
@@ -98,6 +99,19 @@
                             >
                                 <AutocompleteInput
                                     label="table.field.matnr.groupId"
+                                    optionText="code"
+                                    filterToQuery={(val) => ({ code: val })}
+                                />
+                            </ReferenceInput>
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <ReferenceInput
+                                source="batchRegularId"
+                                reference="batchRegular"
+                                perPage={REFERENCE_INPUT_PAGESIZE}
+                            >
+                                <AutocompleteInput
+                                    label="table.field.matnr.batchRegularId"
                                     optionText="code"
                                     filterToQuery={(val) => ({ code: val })}
                                 />
@@ -146,8 +160,8 @@
                         </Stack>
                         <Stack direction='row' gap={2}>
                             <TextInput
-                                label="table.field.matnr.desc"
-                                source="desc"
+                                label="table.field.matnr.describle"
+                                source="describle"
                                 parse={v => v}
                             />
                         </Stack>
@@ -201,6 +215,48 @@
                                 validate={required()}
                             />
                         </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.safetyQty"
+                                source="safetyQty"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.minQty"
+                                source="minQty"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.maxQty"
+                                source="maxQty"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.stagnate"
+                                source="stagnate"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.validity"
+                                source="validity"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.validityWarr"
+                                source="validityWarr"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.matnr.flagCheck"
+                                source="flagCheck"
+                            />
+                        </Stack>
 
                     </Grid>
                     <Grid item xs={12} md={4}>
diff --git a/rsf-admin/src/page/matnr/MatnrList.jsx b/rsf-admin/src/page/matnr/MatnrList.jsx
index a2abf5a..f823136 100644
--- a/rsf-admin/src/page/matnr/MatnrList.jsx
+++ b/rsf-admin/src/page/matnr/MatnrList.jsx
@@ -63,13 +63,16 @@
     <DateInput label='common.time.after' source="timeStart" alwaysOn />,
     <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
 
+    <TextInput source="name" label="table.field.matnr.name" />,
+    <TextInput source="code" label="table.field.matnr.code" />,
     <ReferenceInput source="shipperId" label="table.field.matnr.shipperId" reference="shipper">
         <AutocompleteInput label="table.field.matnr.shipperId" optionText="name" filterToQuery={(val) => ({ name: val })} />
     </ReferenceInput>,
-    <TextInput source="name" label="table.field.matnr.name" />,
-    <TextInput source="code" label="table.field.matnr.code" />,
     <ReferenceInput source="groupId" label="table.field.matnr.groupId" reference="matnrGroup">
         <AutocompleteInput label="table.field.matnr.groupId" optionText="code" filterToQuery={(val) => ({ code: val })} />
+    </ReferenceInput>,
+    <ReferenceInput source="batchRegularId" label="table.field.matnr.batchRegularId" reference="batchRegular">
+        <AutocompleteInput label="table.field.matnr.batchRegularId" optionText="code" filterToQuery={(val) => ({ code: val })} />
     </ReferenceInput>,
     <TextInput source="erpCode" label="table.field.matnr.erpCode" />,
     <TextInput source="spec" label="table.field.matnr.spec" />,
@@ -77,7 +80,7 @@
     <NumberInput source="weight" label="table.field.matnr.weight" />,
     <TextInput source="color" label="table.field.matnr.color" />,
     <TextInput source="size" label="table.field.matnr.size" />,
-    <TextInput source="desc" label="table.field.matnr.desc" />,
+    <TextInput source="describle" label="table.field.matnr.describle" />,
     <NumberInput source="nromNum" label="table.field.matnr.nromNum" />,
     <TextInput source="unit" label="table.field.matnr.unit" />,
     <TextInput source="purchaseUnit" label="table.field.matnr.purchaseUnit" />,
@@ -95,6 +98,13 @@
             { id:  1, name: ' 鏄�' },
         ]}
     />,
+    <NumberInput source="safetyQty" label="table.field.matnr.safetyQty" />,
+    <NumberInput source="minQty" label="table.field.matnr.minQty" />,
+    <NumberInput source="maxQty" label="table.field.matnr.maxQty" />,
+    <NumberInput source="stagnate" label="table.field.matnr.stagnate" />,
+    <NumberInput source="validity" label="table.field.matnr.validity" />,
+    <NumberInput source="validityWarr" label="table.field.matnr.validityWarr" />,
+    <NumberInput source="flagCheck" label="table.field.matnr.flagCheck" />,
 
     <TextInput label="common.field.memo" source="memo" />,
     <SelectInput
@@ -148,12 +158,15 @@
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
+                    <TextField source="name" label="table.field.matnr.name" />
+                    <TextField source="code" label="table.field.matnr.code" />
                     <ReferenceField source="shipperId" label="table.field.matnr.shipperId" reference="shipper" link={false} sortable={false}>
                         <TextField source="name" />
                     </ReferenceField>
-                    <TextField source="name" label="table.field.matnr.name" />
-                    <TextField source="code" label="table.field.matnr.code" />
                     <ReferenceField source="groupId" label="table.field.matnr.groupId" reference="matnrGroup" link={false} sortable={false}>
+                        <TextField source="code" />
+                    </ReferenceField>
+                    <ReferenceField source="batchRegularId" label="table.field.matnr.batchRegularId" reference="batchRegular" link={false} sortable={false}>
                         <TextField source="code" />
                     </ReferenceField>
                     <TextField source="erpCode" label="table.field.matnr.erpCode" />
@@ -162,13 +175,20 @@
                     <NumberField source="weight" label="table.field.matnr.weight" />
                     <TextField source="color" label="table.field.matnr.color" />
                     <TextField source="size" label="table.field.matnr.size" />
-                    <TextField source="desc" label="table.field.matnr.desc" />
+                    <TextField source="describle" label="table.field.matnr.describle" />
                     <NumberField source="nromNum" label="table.field.matnr.nromNum" />
                     <TextField source="unit" label="table.field.matnr.unit" />
                     <TextField source="purchaseUnit" label="table.field.matnr.purchaseUnit" />
                     <TextField source="stockUnit" label="table.field.matnr.stockUnit" />
                     <TextField source="stockLeval$" label="table.field.matnr.stockLeval" sortable={false} />
                     <TextField source="isLabelMange$" label="table.field.matnr.isLabelMange" sortable={false} />
+                    <NumberField source="safetyQty" label="table.field.matnr.safetyQty" />
+                    <NumberField source="minQty" label="table.field.matnr.minQty" />
+                    <NumberField source="maxQty" label="table.field.matnr.maxQty" />
+                    <NumberField source="stagnate" label="table.field.matnr.stagnate" />
+                    <NumberField source="validity" label="table.field.matnr.validity" />
+                    <NumberField source="validityWarr" label="table.field.matnr.validityWarr" />
+                    <NumberField source="flagCheck" label="table.field.matnr.flagCheck" />
 
                     <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                         <TextField source="nickname" />
diff --git a/rsf-admin/src/page/matnr/MatnrPanel.jsx b/rsf-admin/src/page/matnr/MatnrPanel.jsx
index 434ce30..fe8ad1f 100644
--- a/rsf-admin/src/page/matnr/MatnrPanel.jsx
+++ b/rsf-admin/src/page/matnr/MatnrPanel.jsx
@@ -42,12 +42,6 @@
                     <Grid container spacing={2}>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.matnr.shipperId" 
-                                property={record.shipperId$}
-                            />
-                        </Grid>
-                        <Grid item xs={6}>
-                            <PanelTypography
                                 title="table.field.matnr.name" 
                                 property={record.name}
                             />
@@ -60,8 +54,20 @@
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
+                                title="table.field.matnr.shipperId" 
+                                property={record.shipperId$}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
                                 title="table.field.matnr.groupId" 
                                 property={record.groupId$}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.batchRegularId" 
+                                property={record.batchRegularId$}
                             />
                         </Grid>
                         <Grid item xs={6}>
@@ -102,8 +108,8 @@
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.matnr.desc" 
-                                property={record.desc}
+                                title="table.field.matnr.describle" 
+                                property={record.describle}
                             />
                         </Grid>
                         <Grid item xs={6}>
@@ -142,6 +148,48 @@
                                 property={record.isLabelMange$}
                             />
                         </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.safetyQty" 
+                                property={record.safetyQty}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.minQty" 
+                                property={record.minQty}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.maxQty" 
+                                property={record.maxQty}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.stagnate" 
+                                property={record.stagnate}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.validity" 
+                                property={record.validity}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.validityWarr" 
+                                property={record.validityWarr}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.matnr.flagCheck" 
+                                property={record.flagCheck}
+                            />
+                        </Grid>
 
                     </Grid>
                 </CardContent>
diff --git a/rsf-server/src/main/java/batchRegular.sql b/rsf-server/src/main/java/batchRegular.sql
new file mode 100644
index 0000000..25e481d
--- /dev/null
+++ b/rsf-server/src/main/java/batchRegular.sql
@@ -0,0 +1,24 @@
+-- save batchRegular record
+-- mysql
+insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.batchRegular', '0', '/manager/batchRegular', 'batchRegular', '0' , '0', '1' , '1');
+
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 鎵规灞炴�ц鍒�', '', '1', 'manager:batchRegular:list', '0', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 鎵规灞炴�ц鍒�', '', '1', 'manager:batchRegular:save', '1', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 鎵规灞炴�ц鍒�', '', '1', 'manager:batchRegular:update', '2', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 鎵规灞炴�ц鍒�', '', '1', 'manager:batchRegular:remove', '3', '1', '1');
+
+-- locale menu name
+batchRegular: 'BatchRegular',
+
+-- locale field
+batchRegular: {
+    name: "name",
+    code: "code",
+    property: "property",
+},
+
+-- ResourceContent
+import batchRegular from './batchRegular';
+
+case 'batchRegular':
+    return batchRegular;
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
index 78fd8e2..b0983bb 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -22,8 +22,8 @@
 //        generator.username="sa";
 //        generator.password="Zoneyung@zy56$";
 
-        generator.table="man_matnr_group";
-        generator.tableDesc="鐗╂枡鍒嗙被琛�";
+        generator.table="man_matnr";
+        generator.tableDesc="鐗╂枡淇℃伅琛�";
         generator.packagePath="com.vincent.rsf.server.manager";
 
         generator.build();
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BatchRegularController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BatchRegularController.java
new file mode 100644
index 0000000..b08f2df
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BatchRegularController.java
@@ -0,0 +1,110 @@
+package com.vincent.rsf.server.manager.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.server.common.utils.ExcelUtil;
+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.manager.entity.BatchRegular;
+import com.vincent.rsf.server.manager.service.BatchRegularService;
+import com.vincent.rsf.server.system.controller.BaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+@RestController
+public class BatchRegularController extends BaseController {
+
+    @Autowired
+    private BatchRegularService batchRegularService;
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:list')")
+    @PostMapping("/batchRegular/page")
+    public R page(@RequestBody Map<String, Object> map) {
+        BaseParam baseParam = buildParam(map, BaseParam.class);
+        PageParam<BatchRegular, BaseParam> pageParam = new PageParam<>(baseParam, BatchRegular.class);
+        return R.ok().add(batchRegularService.page(pageParam, pageParam.buildWrapper(true)));
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:list')")
+    @PostMapping("/batchRegular/list")
+    public R list(@RequestBody Map<String, Object> map) {
+        return R.ok().add(batchRegularService.list());
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:list')")
+    @PostMapping({"/batchRegular/many/{ids}", "/batchRegulars/many/{ids}"})
+    public R many(@PathVariable Long[] ids) {
+        return R.ok().add(batchRegularService.listByIds(Arrays.asList(ids)));
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:list')")
+    @GetMapping("/batchRegular/{id}")
+    public R get(@PathVariable("id") Long id) {
+        return R.ok().add(batchRegularService.getById(id));
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:save')")
+    @OperationLog("Create 鎵规灞炴�ц鍒�")
+    @PostMapping("/batchRegular/save")
+    public R save(@RequestBody BatchRegular batchRegular) {
+        batchRegular.setCreateBy(getLoginUserId());
+        batchRegular.setCreateTime(new Date());
+        batchRegular.setUpdateBy(getLoginUserId());
+        batchRegular.setUpdateTime(new Date());
+        if (!batchRegularService.save(batchRegular)) {
+            return R.error("Save Fail");
+        }
+        return R.ok("Save Success").add(batchRegular);
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:update')")
+    @OperationLog("Update 鎵规灞炴�ц鍒�")
+    @PostMapping("/batchRegular/update")
+    public R update(@RequestBody BatchRegular batchRegular) {
+        batchRegular.setUpdateBy(getLoginUserId());
+        batchRegular.setUpdateTime(new Date());
+        if (!batchRegularService.updateById(batchRegular)) {
+            return R.error("Update Fail");
+        }
+        return R.ok("Update Success").add(batchRegular);
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:remove')")
+    @OperationLog("Delete 鎵规灞炴�ц鍒�")
+    @PostMapping("/batchRegular/remove/{ids}")
+    public R remove(@PathVariable Long[] ids) {
+        if (!batchRegularService.removeByIds(Arrays.asList(ids))) {
+            return R.error("Delete Fail");
+        }
+        return R.ok("Delete Success").add(ids);
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:list')")
+    @PostMapping("/batchRegular/query")
+    public R query(@RequestParam(required = false) String condition) {
+        List<KeyValVo> vos = new ArrayList<>();
+        LambdaQueryWrapper<BatchRegular> wrapper = new LambdaQueryWrapper<>();
+        if (!Cools.isEmpty(condition)) {
+            wrapper.like(BatchRegular::getName, condition);
+        }
+        batchRegularService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
+                item -> vos.add(new KeyValVo(item.getId(), item.getName()))
+        );
+        return R.ok().add(vos);
+    }
+
+    @PreAuthorize("hasAuthority('manager:batchRegular:list')")
+    @PostMapping("/batchRegular/export")
+    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
+        ExcelUtil.build(ExcelUtil.create(batchRegularService.list(), BatchRegular.class), response);
+    }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrController.java
index 24e5621..32b9061 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrController.java
@@ -52,7 +52,7 @@
     }
 
     @PreAuthorize("hasAuthority('manager:matnr:save')")
-    @OperationLog("Create 鐗╂枡琛�")
+    @OperationLog("Create 鐗╂枡淇℃伅琛�")
     @PostMapping("/matnr/save")
     public R save(@RequestBody Matnr matnr) {
         matnr.setCreateBy(getLoginUserId());
@@ -66,7 +66,7 @@
     }
 
     @PreAuthorize("hasAuthority('manager:matnr:update')")
-    @OperationLog("Update 鐗╂枡琛�")
+    @OperationLog("Update 鐗╂枡淇℃伅琛�")
     @PostMapping("/matnr/update")
     public R update(@RequestBody Matnr matnr) {
         matnr.setUpdateBy(getLoginUserId());
@@ -78,7 +78,7 @@
     }
 
     @PreAuthorize("hasAuthority('manager:matnr:remove')")
-    @OperationLog("Delete 鐗╂枡琛�")
+    @OperationLog("Delete 鐗╂枡淇℃伅琛�")
     @PostMapping("/matnr/remove/{ids}")
     public R remove(@PathVariable Long[] ids) {
         if (!matnrService.removeByIds(Arrays.asList(ids))) {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BatchRegular.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BatchRegular.java
new file mode 100644
index 0000000..399c785
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BatchRegular.java
@@ -0,0 +1,194 @@
+package com.vincent.rsf.server.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.SpringUtils;
+import com.vincent.rsf.server.system.service.UserService;
+import com.vincent.rsf.server.system.entity.User;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("man_batch_regular")
+public class BatchRegular implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value= "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鍚嶇О
+     */
+    @ApiModelProperty(value= "鍚嶇О")
+    private String name;
+
+    /**
+     * 缂栫爜
+     */
+    @ApiModelProperty(value= "缂栫爜")
+    private String code;
+
+    /**
+     * 灞炴�ф牸寮�
+     */
+    @ApiModelProperty(value= "灞炴�ф牸寮�")
+    private String property;
+
+    /**
+     * 鐘舵�� 1: 姝e父  0: 鍐荤粨  
+     */
+    @ApiModelProperty(value= "鐘舵�� 1: 姝e父  0: 鍐荤粨  ")
+    private Integer status;
+
+    /**
+     * 鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  
+     */
+    @ApiModelProperty(value= "鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  ")
+    @TableLogic
+    private Integer deleted;
+
+    /**
+     * 绉熸埛
+     */
+    @ApiModelProperty(value= "绉熸埛")
+    private Integer tenantId;
+
+    /**
+     * 娣诲姞浜哄憳
+     */
+    @ApiModelProperty(value= "娣诲姞浜哄憳")
+    private Long createBy;
+
+    /**
+     * 娣诲姞鏃堕棿
+     */
+    @ApiModelProperty(value= "娣诲姞鏃堕棿")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 淇敼浜哄憳
+     */
+    @ApiModelProperty(value= "淇敼浜哄憳")
+    private Long updateBy;
+
+    /**
+     * 淇敼鏃堕棿
+     */
+    @ApiModelProperty(value= "淇敼鏃堕棿")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+     * 澶囨敞
+     */
+    @ApiModelProperty(value= "澶囨敞")
+    private String memo;
+
+    public BatchRegular() {}
+
+    public BatchRegular(String name,String code,String property,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
+        this.name = name;
+        this.code = code;
+        this.property = property;
+        this.status = status;
+        this.deleted = deleted;
+        this.tenantId = tenantId;
+        this.createBy = createBy;
+        this.createTime = createTime;
+        this.updateBy = updateBy;
+        this.updateTime = updateTime;
+        this.memo = memo;
+    }
+
+//    BatchRegular batchRegular = new BatchRegular(
+//            null,    // 鍚嶇О
+//            null,    // 缂栫爜
+//            null,    // 灞炴�ф牸寮�
+//            null,    // 鐘舵�乕闈炵┖]
+//            null,    // 鏄惁鍒犻櫎[闈炵┖]
+//            null,    // 绉熸埛
+//            null,    // 娣诲姞浜哄憳
+//            null,    // 娣诲姞鏃堕棿[闈炵┖]
+//            null,    // 淇敼浜哄憳
+//            null,    // 淇敼鏃堕棿
+//            null    // 澶囨敞
+//    );
+
+    public String getStatus$(){
+        if (null == this.status){ return null; }
+        switch (this.status){
+            case 1:
+                return "姝e父";
+            case 0:
+                return "鍐荤粨";
+            default:
+                return String.valueOf(this.status);
+        }
+    }
+
+    public String getCreateBy$(){
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.getById(this.createBy);
+        if (!Cools.isEmpty(user)){
+            return String.valueOf(user.getNickname());
+        }
+        return null;
+    }
+
+    public String getCreateTime$(){
+        if (Cools.isEmpty(this.createTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
+    }
+
+    public String getUpdateBy$(){
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.getById(this.updateBy);
+        if (!Cools.isEmpty(user)){
+            return String.valueOf(user.getNickname());
+        }
+        return null;
+    }
+
+    public String getUpdateTime$(){
+        if (Cools.isEmpty(this.updateTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
+    }
+
+
+
+    public Boolean getStatusBool(){
+        if (null == this.status){ return null; }
+        switch (this.status){
+            case 1:
+                return true;
+            case 0:
+                return false;
+            default:
+                return null;
+        }
+    }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java
index 14b9743..20e800b 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java
@@ -4,6 +4,8 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+import com.vincent.rsf.server.manager.service.BatchRegularService;
+import com.vincent.rsf.server.manager.service.MatnrGroupService;
 import com.vincent.rsf.server.manager.service.ShipperService;
 import org.springframework.format.annotation.DateTimeFormat;
 import java.text.SimpleDateFormat;
@@ -36,13 +38,6 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-
-    /**
-     * 璐т富ID
-     */
-    @ApiModelProperty(value= "璐т富ID")
-    private Long shipperId;
-
     /**
      * 鍚嶇О
      */
@@ -56,10 +51,22 @@
     private String code;
 
     /**
-     * 鍒嗙粍ID
+     * 璐т富ID
      */
-    @ApiModelProperty(value= "鍒嗙粍ID")
+    @ApiModelProperty(value= "璐т富ID")
+    private Long shipperId;
+
+    /**
+     * 鍒嗙粍ID(*)
+     */
+    @ApiModelProperty(value= "鍒嗙粍ID(*)")
     private Long groupId;
+
+    /**
+     * 瑙勫垯浠g爜
+     */
+    @ApiModelProperty(value= "瑙勫垯浠g爜")
+    private Long batchRegularId;
 
     /**
      * ERP缂栫爜
@@ -140,6 +147,48 @@
     private Short isLabelMange;
 
     /**
+     * 瀹夊叏搴撳瓨
+     */
+    @ApiModelProperty(value= "瀹夊叏搴撳瓨")
+    private Double safetyQty;
+
+    /**
+     * 鏈�灏忓簱瀛橀璀﹀��
+     */
+    @ApiModelProperty(value= "鏈�灏忓簱瀛橀璀﹀��")
+    private Double minQty;
+
+    /**
+     * 鏈�澶у簱瀛橀璀﹀��
+     */
+    @ApiModelProperty(value= "鏈�澶у簱瀛橀璀﹀��")
+    private Double maxQty;
+
+    /**
+     * 鍋滄粸澶╂暟
+     */
+    @ApiModelProperty(value= "鍋滄粸澶╂暟")
+    private Integer stagnate;
+
+    /**
+     * 淇濊川鏈熷ぉ鏁�
+     */
+    @ApiModelProperty(value= "淇濊川鏈熷ぉ鏁�")
+    private Integer validity;
+
+    /**
+     * 鏁堟湡棰勮闃堝��
+     */
+    @ApiModelProperty(value= "鏁堟湡棰勮闃堝��")
+    private Integer validityWarr;
+
+    /**
+     * 鏄惁鍏嶆
+     */
+    @ApiModelProperty(value= "鏄惁鍏嶆")
+    private Short flagCheck;
+
+    /**
      * 鐘舵�� 1: 姝e父  0: 鍐荤粨  
      */
     @ApiModelProperty(value= "鐘舵�� 1: 姝e父  0: 鍐荤粨  ")
@@ -192,11 +241,12 @@
 
     public Matnr() {}
 
-    public Matnr(Long shipperId,String name,String code,Long groupId,String erpCode,String spec,String model,Double weight,String color,String size,String describle,Integer nromNum,String unit,String purchaseUnit,String stockUnit,Short stockLeval,Short isLabelMange,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
-        this.shipperId = shipperId;
+    public Matnr(String name,String code,Long shipperId,Long groupId,Long batchRegularId,String erpCode,String spec,String model,Double weight,String color,String size,String describle,Integer nromNum,String unit,String purchaseUnit,String stockUnit,Short stockLeval,Short isLabelMange,Double safetyQty,Double minQty,Double maxQty,Integer stagnate,Integer validity,Integer validityWarr,Short flagCheck,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
         this.name = name;
         this.code = code;
+        this.shipperId = shipperId;
         this.groupId = groupId;
+        this.batchRegularId = batchRegularId;
         this.erpCode = erpCode;
         this.spec = spec;
         this.model = model;
@@ -210,6 +260,13 @@
         this.stockUnit = stockUnit;
         this.stockLeval = stockLeval;
         this.isLabelMange = isLabelMange;
+        this.safetyQty = safetyQty;
+        this.minQty = minQty;
+        this.maxQty = maxQty;
+        this.stagnate = stagnate;
+        this.validity = validity;
+        this.validityWarr = validityWarr;
+        this.flagCheck = flagCheck;
         this.status = status;
         this.deleted = deleted;
         this.tenantId = tenantId;
@@ -221,11 +278,11 @@
     }
 
 //    Matnr matnr = new Matnr(
-//            null,    // 鏍囪瘑
-//            null,    // 璐т富ID
 //            null,    // 鍚嶇О
 //            null,    // 缂栫爜
-//            null,    // 鍒嗙粍ID
+//            null,    // 璐т富ID
+//            null,    // 鍒嗙粍ID(*)
+//            null,    // 瑙勫垯浠g爜
 //            null,    // ERP缂栫爜
 //            null,    // 瑙勬牸
 //            null,    // 鍨嬪彿
@@ -239,6 +296,13 @@
 //            null,    // 搴撲綅鍗曚綅
 //            null,    // 鍑哄叆搴撲紭鍏堢骇鍒玔闈炵┖]
 //            null,    // 鏄惁鏍囩绠$悊(*)[闈炵┖]
+//            null,    // 瀹夊叏搴撳瓨
+//            null,    // 鏈�灏忓簱瀛橀璀﹀��
+//            null,    // 鏈�澶у簱瀛橀璀﹀��
+//            null,    // 鍋滄粸澶╂暟
+//            null,    // 淇濊川鏈熷ぉ鏁�
+//            null,    // 鏁堟湡棰勮闃堝��
+//            null,    // 鏄惁鍏嶆
 //            null,    // 鐘舵�乕闈炵┖]
 //            null,    // 鏄惁鍒犻櫎[闈炵┖]
 //            null,    // 绉熸埛
@@ -258,14 +322,23 @@
         return null;
     }
 
-//    public String getGroupId$(){
-//        MatnrGroupService service = SpringUtils.getBean(MatnrGroupService.class);
-//        MatnrGroup matnrGroup = service.getById(this.groupId);
-//        if (!Cools.isEmpty(matnrGroup)){
-//            return String.valueOf(matnrGroup.getCode());
-//        }
-//        return null;
-//    }
+    public String getGroupId$(){
+        MatnrGroupService service = SpringUtils.getBean(MatnrGroupService.class);
+        MatnrGroup matnrGroup = service.getById(this.groupId);
+        if (!Cools.isEmpty(matnrGroup)){
+            return String.valueOf(matnrGroup.getCode());
+        }
+        return null;
+    }
+
+    public String getBatchRegularId$(){
+        BatchRegularService service = SpringUtils.getBean(BatchRegularService.class);
+        BatchRegular batchRegular = service.getById(this.batchRegularId);
+        if (!Cools.isEmpty(batchRegular)){
+            return String.valueOf(batchRegular.getCode());
+        }
+        return null;
+    }
 
     public String getStockLeval$(){
         if (null == this.stockLeval){ return null; }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BatchRegularMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BatchRegularMapper.java
new file mode 100644
index 0000000..1e159b3
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BatchRegularMapper.java
@@ -0,0 +1,12 @@
+package com.vincent.rsf.server.manager.mapper;
+
+import com.vincent.rsf.server.manager.entity.BatchRegular;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface BatchRegularMapper extends BaseMapper<BatchRegular> {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BatchRegularService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BatchRegularService.java
new file mode 100644
index 0000000..f42d36f
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BatchRegularService.java
@@ -0,0 +1,8 @@
+package com.vincent.rsf.server.manager.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.vincent.rsf.server.manager.entity.BatchRegular;
+
+public interface BatchRegularService extends IService<BatchRegular> {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BatchRegularServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BatchRegularServiceImpl.java
new file mode 100644
index 0000000..9986808
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BatchRegularServiceImpl.java
@@ -0,0 +1,12 @@
+package com.vincent.rsf.server.manager.service.impl;
+
+import com.vincent.rsf.server.manager.mapper.BatchRegularMapper;
+import com.vincent.rsf.server.manager.entity.BatchRegular;
+import com.vincent.rsf.server.manager.service.BatchRegularService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service("batchRegularService")
+public class BatchRegularServiceImpl extends ServiceImpl<BatchRegularMapper, BatchRegular> implements BatchRegularService {
+
+}
diff --git a/rsf-server/src/main/java/matnr.sql b/rsf-server/src/main/java/matnr.sql
index 281034f..b5ffa42 100644
--- a/rsf-server/src/main/java/matnr.sql
+++ b/rsf-server/src/main/java/matnr.sql
@@ -2,33 +2,41 @@
 -- mysql
 insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.matnr', '0', '/manager/matnr', 'matnr', '0' , '0', '1' , '1');
 
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 鐗╂枡琛�', '57', '1', 'manager:matnr:list', '0', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 鐗╂枡琛�', '57', '1', 'manager:matnr:save', '1', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 鐗╂枡琛�', '57', '1', 'manager:matnr:update', '2', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 鐗╂枡琛�', '57', '1', 'manager:matnr:remove', '3', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 鐗╂枡淇℃伅琛�', '', '1', 'manager:matnr:list', '0', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 鐗╂枡淇℃伅琛�', '', '1', 'manager:matnr:save', '1', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 鐗╂枡淇℃伅琛�', '', '1', 'manager:matnr:update', '2', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 鐗╂枡淇℃伅琛�', '', '1', 'manager:matnr:remove', '3', '1', '1');
 
 -- locale menu name
 matnr: 'Matnr',
 
 -- locale field
 matnr: {
-    shipperId: "shipperId",
     name: "name",
     code: "code",
+    shipperId: "shipperId",
     groupId: "groupId",
+    batchRegularId: "batchRegularId",
     erpCode: "erpCode",
     spec: "spec",
     model: "model",
     weight: "weight",
     color: "color",
     size: "size",
-    desc: "desc",
+    describle: "describle",
     nromNum: "nromNum",
     unit: "unit",
     purchaseUnit: "purchaseUnit",
     stockUnit: "stockUnit",
     stockLeval: "stockLeval",
     isLabelMange: "isLabelMange",
+    safetyQty: "safetyQty",
+    minQty: "minQty",
+    maxQty: "maxQty",
+    stagnate: "stagnate",
+    validity: "validity",
+    validityWarr: "validityWarr",
+    flagCheck: "flagCheck",
 },
 
 -- ResourceContent
diff --git a/rsf-server/src/main/resources/mapper/manager/BatchRegularMapper.xml b/rsf-server/src/main/resources/mapper/manager/BatchRegularMapper.xml
new file mode 100644
index 0000000..b8cb70f
--- /dev/null
+++ b/rsf-server/src/main/resources/mapper/manager/BatchRegularMapper.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.vincent.rsf.server.manager.mapper.BatchRegularMapper">
+
+</mapper>

--
Gitblit v1.9.1