2799c6690aff9c1577ba4dc290dc56a28767a769..06d7fb698ce6d0efc7ff4224c6b68d2f50feb716
6 天以前 skyouc
DO单修改及优化
06d7fb 对比 | 目录
6 天以前 skyouc
新增DO单据
61e838 对比 | 目录
6 天以前 skyouc
#修改 1. 新增DO单,DO单明细
b9d414 对比 | 目录
6 天以前 zjj
#优化asn单编辑页面
4e5984 对比 | 目录
6 天以前 skyouc
no message
9bec56 对比 | 目录
27个文件已添加
19个文件已修改
3290 ■■■■■ 已修改文件
rsf-admin/.env 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/ResourceContent.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/loc/BindModal.jsx 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/MyExportButton.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/deliveryItem/DeliveryItemCreate.jsx 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/deliveryItem/DeliveryItemEdit.jsx 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/deliveryItem/DeliveryItemList.jsx 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/deliveryItem/DeliveryItemPanel.jsx 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/deliveryItem/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryCreate.jsx 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryEdit.jsx 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryItemCreate.jsx 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryItemEdit.jsx 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryItemList.jsx 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryList.jsx 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryPanel.jsx 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/serialRule/SerialRuleItemEdit.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/serialRule/SerialRuleItemList.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/TaskList.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/DeliveryController.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/DeliveryItemController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Delivery.java 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/DeliveryItem.java 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WaitPakinItem.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/DeliveryItemMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/DeliveryMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/DeliveryItemService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/DeliveryService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryItemServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/delivery.sql 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/deliveryItem.sql 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/DeliveryItemMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/DeliveryMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/.env
@@ -1,3 +1,3 @@
VITE_BASE_IP=127.0.0.1
VITE_BASE_IP=192.168.4.24
# VITE_BASE_IP=47.76.147.249
VITE_BASE_PORT=8080
rsf-admin/src/i18n/en.js
@@ -169,6 +169,7 @@
        statistics: 'Statistics',
        logs: 'Logs',
        permissions: 'Permissions',
        delivery: 'Delivery',
    },
    table: {
        field: {
@@ -595,6 +596,34 @@
                startTime: "startTime",
                endTime: "endTime",
            },
            delivery: {
                code: "code",
                platId: "platId",
                type: "type",
                wkType: "wkType",
                source: "source",
                anfme: "anfme",
                qty: "qty",
                workQty: "workQty",
                platCode: "platCode",
                startTime: "startTime",
                endTime: "endTime",
            },
            deliveryItem: {
                deliveryId: "deliveryId",
                platItemId: "platItemId",
                matnrCode: "matnrCode",
                matnrName: "matnrName",
                fieldsIndex: "fieldsIndex",
                unit: "unit",
                anfme: "anfme",
                qty: "qty",
                nromQty: "nromQty",
                printQty: "printQty",
                splrName: "splrName",
                splrCode: "splrCode",
                splrBatch: "splrBatch",
            },
            purchaseItem: {
                purchaseId: "purchaseId",
                platItemId: "erpItemId",
@@ -888,6 +917,7 @@
        cancel: "cancel",
        bulkExport: "Bulk Export",
        continue: 'Continue Receipt',
        confirmSelect: 'Confirm Select',
        selectSite: 'Select Site',
        top: "top",
        resort: "sort",
rsf-admin/src/i18n/zh.js
@@ -170,6 +170,7 @@
        statistics: '统计查询',
        logs: '日志',
        permissions: '权限管理',
        delivery: 'DO单',
    },
    table: {
@@ -605,6 +606,34 @@
                startTime: "开始时间",
                endTime: "结束时间",
            },
            delivery: {
                code: "DO编码",
                platId: "平台ID",
                type: "单据类型",
                wkType: "业务类型",
                source: "单据来源",
                anfme: "数量",
                qty: "完成数量",
                workQty: "执行数量",
                platCode: "平台编码",
                startTime: "开始时间",
                endTime: "结束时间",
            },
            deliveryItem: {
                deliveryId: "主单ID",
                platItemId: "行号",
                matnrCode: "物料编码",
                matnrName: "物料名称",
                fieldsIndex: "字段索引",
                unit: "单位",
                anfme: "数量",
                qty: "完成数量",
                nromQty: "nromQty",
                printQty: "打印数量",
                splrName: "供应商名称",
                splrCode: "供应商编码",
                splrBatch: "供应商批次",
            },
            purchaseItem: {
                purchaseId: "PO主单标识",
                platItemId: "erp明细标识",
@@ -900,6 +929,7 @@
        confirm: '确认',
        bulkExport: "批量导出",
        selectSite: '选择站点',
        confirmSelect: '确认选择',
        cancel: "取消",
        top: "置顶",
        resort: "排序",
rsf-admin/src/page/ResourceContent.js
@@ -41,6 +41,7 @@
import task from './task';
import taskLog from './histories/taskLog';
import stock from './orders/stock';
import delivery from './orders/delivery';
const ResourceContent = (node) => {
    switch (node.component) {
@@ -118,6 +119,8 @@
            return taskLog;
        case 'stock':
            return stock;
        case 'delivery':
            return delivery;
        default:
            return {
                list: ListGuesser,
rsf-admin/src/page/basicInfo/loc/BindModal.jsx
@@ -2,7 +2,6 @@
import {
    CreateBase,
    useTranslate,
    SearchInput,
    TextInput,
    NumberInput,
    BooleanInput,
@@ -25,9 +24,11 @@
    Form,
    useCreateController,
    useListContext,
    SearchInput,
    useRefresh,
    List,
    SelectArrayInput
    SelectArrayInput,
    useListController
} from 'react-admin';
import {
    Dialog,
@@ -56,10 +57,11 @@
import request from '@/utils/request';
import { Add, Edit, Delete } from '@mui/icons-material';
import _ from 'lodash';
import { DataGrid } from '@mui/x-data-grid';
import StatusSelectInput from "../../components/StatusSelectInput";
import TreeSelectInput from "@/page/components/TreeSelectInput";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
import ConfirmationNumber from '@mui/icons-material/ConfirmationNumber';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -73,7 +75,7 @@
}));
const filters = [
  <SearchInput source="condition" alwaysOn />
    <SearchInput source="condition" alwaysOn />,
]
const MatnrModal = ({ open, setOpen }) => {
@@ -134,12 +136,12 @@
            groupId: formData.groupId,
            matnrId: formData.matnrId,
        }
        // const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
        // if (res?.data?.code === 200) {
        //     handleClose()
        // } else {
        //     notify(res.data.msg);
        // }
        const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
        if (res?.data?.code === 200) {
            handleClose()
        } else {
            notify(res.data.msg);
        }
    }
    const [groupId, setGroupId] = useState();
@@ -147,16 +149,14 @@
        setGroupId(e.target.value)
    }
    return (
        <Dialog open={open} maxWidth="1" fullWidth>
        <Dialog open={open} maxWidth="md" fullWidth>
            <Form onSubmit={handleSubmit}>
                <DialogCloseButton onClose={handleClose} />
                <DialogTitle>{translate('toolbar.bindmatnr')}</DialogTitle>
                <DialogContent sx={{ mt: 2 }}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, height: 900 }}>
                        <Grid container spacing={2}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, height: 200 }}>
                        <Grid container spacing={3}>
                            <Grid item xs={3}>
                                <ReferenceInput
                                    source="areaMatId"
@@ -181,19 +181,20 @@
                                    onChange={(e) => handleChange(e.target.value, 'groupId')}
                                />
                            </Grid>
                        </Grid>
                        <Grid item xs={4}>
                            <List
                            <Grid  item xs={3}>
                                {/* </Grid> */}
                                {/* <Grid item xs={4}> */}
                                {/* <List
                                resource="matnr"
                                filter={{ groupId: formData.groupId }}
                                queryOptions={{}}
                                // filters={filters}
                                storeKey="matnrSelectList"
                                filters={filters}
                                empty={false}
                                actions={<></>}
                            >
                                <StyledDatagrid
                                    preferenceKey='matnr'
                                    bulkActionButtons={<></>}
                                    bulkActionButtons={<> <SelectMatnrs></SelectMatnrs> </>}
                                    rowClick={false}
                                    omit={['id', 'createTime', 'createBy', 'memo', 'poDetlId', 'matnrId', 'asnId']}
                                >
@@ -216,14 +217,15 @@
                                    <BooleanField key="statusBool" source="statusBool" label="common.field.status" sortable={false} />,
                                    <TextField key="memo" source="memo" label="common.field.memo" sortable={false} />,
                                </StyledDatagrid>
                            </List>
                            {/* <ReferenceArrayInput source="matnrId" reference="matnr" filter={{ groupId: formData.groupId }}>
                                <SelectArrayInput
                                    label="table.field.locAreaMatRela.matnrId"
                                    value={formData.matnrId}
                                    onChange={(e) => handleChange(e.target.value, 'matnrId')}
                                />
                            </ReferenceArrayInput> */}
                            </List> */}
                                <ReferenceArrayInput source="matnrId" reference="matnr" filter={{ groupId: formData.groupId }}>
                                    <SelectArrayInput
                                        label="table.field.locAreaMatRela.matnrId"
                                        value={formData.matnrId}
                                        onChange={(e) => handleChange(e.target.value, 'matnrId')}
                                    />
                                </ReferenceArrayInput>
                            </Grid>
                        </Grid>
                    </Box>
                </DialogContent>
@@ -239,4 +241,18 @@
    );
}
export default MatnrModal;
export default MatnrModal;
const SelectMatnrs = () => {
    const { selectedIds, data, isPending, onUnselectItems } = useListContext();
    const clickMatnrs = () => {
        console.log(selectedIds);
        onUnselectItems()
    }
    return (
        <Button label={"toolbar.confirmSelect"} onClick={clickMatnrs}>
            <ConfirmationNumber />
        </Button>
    )
}
rsf-admin/src/page/components/MyExportButton.jsx
@@ -23,7 +23,6 @@
  const { filter, selectedIds, filterValues, resource, sort, total } = useListContext();
  const unSelect = useUnselectAll(resource);
  console.log(selectedIds);
  const dataProvider = useDataProvider();
  const notify = useNotify();
  const handleClick = 
rsf-admin/src/page/deliveryItem/DeliveryItemCreate.jsx
New file
@@ -0,0 +1,201 @@
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 DeliveryItemCreate = (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}>
                                    <NumberInput
                                        label="table.field.deliveryItem.deliveryId"
                                        source="deliveryId"
                                        autoFocus
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.platItemId"
                                        source="platItemId"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.matnrCode"
                                        source="matnrCode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.matnrName"
                                        source="matnrName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.fieldsIndex"
                                        source="fieldsIndex"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.unit"
                                        source="unit"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.anfme"
                                        source="anfme"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.qty"
                                        source="qty"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.nromQty"
                                        source="nromQty"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.printQty"
                                        source="printQty"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.splrName"
                                        source="splrName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.splrCode"
                                        source="splrCode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.splrBatch"
                                        source="splrBatch"
                                        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 DeliveryItemCreate;
rsf-admin/src/page/deliveryItem/DeliveryItemEdit.jsx
New file
@@ -0,0 +1,173 @@
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 DeliveryItemEdit = () => {
    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}>
                            <NumberInput
                                label="table.field.deliveryItem.deliveryId"
                                source="deliveryId"
                                autoFocus
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.platItemId"
                                source="platItemId"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.matnrCode"
                                source="matnrCode"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.matnrName"
                                source="matnrName"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.fieldsIndex"
                                source="fieldsIndex"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.unit"
                                source="unit"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.deliveryItem.anfme"
                                source="anfme"
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.deliveryItem.qty"
                                source="qty"
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.deliveryItem.nromQty"
                                source="nromQty"
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.deliveryItem.printQty"
                                source="printQty"
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.splrName"
                                source="splrName"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.splrCode"
                                source="splrCode"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.deliveryItem.splrBatch"
                                source="splrBatch"
                                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 DeliveryItemEdit;
rsf-admin/src/page/deliveryItem/DeliveryItemList.jsx
New file
@@ -0,0 +1,176 @@
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 DeliveryItemCreate from "./DeliveryItemCreate";
import DeliveryItemPanel from "./DeliveryItemPanel";
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 />,
    <NumberInput source="deliveryId" label="table.field.deliveryItem.deliveryId" />,
    <TextInput source="platItemId" label="table.field.deliveryItem.platItemId" />,
    <TextInput source="matnrCode" label="table.field.deliveryItem.matnrCode" />,
    <TextInput source="matnrName" label="table.field.deliveryItem.matnrName" />,
    <TextInput source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" />,
    <TextInput source="unit" label="table.field.deliveryItem.unit" />,
    <NumberInput source="anfme" label="table.field.deliveryItem.anfme" />,
    <NumberInput source="qty" label="table.field.deliveryItem.qty" />,
    <NumberInput source="nromQty" label="table.field.deliveryItem.nromQty" />,
    <NumberInput source="printQty" label="table.field.deliveryItem.printQty" />,
    <TextInput source="splrName" label="table.field.deliveryItem.splrName" />,
    <TextInput source="splrCode" label="table.field.deliveryItem.splrCode" />,
    <TextInput source="splrBatch" label="table.field.deliveryItem.splrBatch" />,
    <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 DeliveryItemList = () => {
    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.deliveryItem"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='deliveryItem' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='deliveryItem'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <DeliveryItemPanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <NumberField source="deliveryId" label="table.field.deliveryItem.deliveryId" />
                    <TextField source="platItemId" label="table.field.deliveryItem.platItemId" />
                    <TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" />
                    <TextField source="matnrName" label="table.field.deliveryItem.matnrName" />
                    <TextField source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" />
                    <TextField source="unit" label="table.field.deliveryItem.unit" />
                    <NumberField source="anfme" label="table.field.deliveryItem.anfme" />
                    <NumberField source="qty" label="table.field.deliveryItem.qty" />
                    <NumberField source="nromQty" label="table.field.deliveryItem.nromQty" />
                    <NumberField source="printQty" label="table.field.deliveryItem.printQty" />
                    <TextField source="splrName" label="table.field.deliveryItem.splrName" />
                    <TextField source="splrCode" label="table.field.deliveryItem.splrCode" />
                    <TextField source="splrBatch" label="table.field.deliveryItem.splrBatch" />
                    <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>
            <DeliveryItemCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='DeliveryItem Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default DeliveryItemList;
rsf-admin/src/page/deliveryItem/DeliveryItemPanel.jsx
New file
@@ -0,0 +1,129 @@
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 DeliveryItemPanel = () => {
    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.deliveryItem.id'))}: {record.id}
                            </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.deliveryItem.deliveryId"
                                property={record.deliveryId}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.platItemId"
                                property={record.platItemId}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.matnrCode"
                                property={record.matnrCode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.matnrName"
                                property={record.matnrName}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.fieldsIndex"
                                property={record.fieldsIndex}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.unit"
                                property={record.unit}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.anfme"
                                property={record.anfme}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.qty"
                                property={record.qty}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.nromQty"
                                property={record.nromQty}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.printQty"
                                property={record.printQty}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.splrName"
                                property={record.splrName}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.splrCode"
                                property={record.splrCode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.deliveryItem.splrBatch"
                                property={record.splrBatch}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default DeliveryItemPanel;
rsf-admin/src/page/deliveryItem/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import DeliveryItemList from "./DeliveryItemList";
import DeliveryItemEdit from "./DeliveryItemEdit";
export default {
    list: DeliveryItemList,
    edit: DeliveryItemEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx
@@ -24,8 +24,9 @@
    return (
        <Toolbar sx={{ justifyContent: 'end' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
            <></>
            {/* <SaveButton />
            <DeleteButton mutationMode="optimistic" /> */}
        </Toolbar>
    )
}
@@ -50,8 +51,23 @@
                    mode="onTouched"
                    defaultValues={{}}
                >
                    <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}>
                        <Grid item xs={24} md={12}>
                    <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>
@@ -65,6 +81,7 @@
                                <TextInput
                                    label="table.field.asnOrder.poCode"
                                    source="poCode"
                                    readOnly
                                    parse={v => v}
                                />
                                <AutocompleteInput
@@ -74,6 +91,7 @@
                                    source="type"
                                    optionValue="value"
                                    parse={v => v}
                                    readOnly
                                />
                                <AutocompleteInput
                                    choices={business}
@@ -82,30 +100,46 @@
                                    source="wkType"
                                    optionValue="value"
                                    parse={v => v}
                                    readOnly
                                />
                                </Stack>
                                <Stack direction='row' gap={2}>
                                    <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: ' 正常' },
                                            { id: 1, name: ' 已释放' },
                                        ]}
                                        validate={required()}
                                    />
                                </Stack>
                            </Stack>
                            <Stack direction='row' gap={2}>
                                <TextInput
                                    label="table.field.asnOrder.logisNo"
                                    source="logisNo"
                                    readOnly
                                    parse={v => v}
                                />
                                <TextInput
                                    label="table.field.asnOrder.anfme"
                                    source="anfme"
                                    readOnly
                                    parse={v => v}
                                />
                                <TextInput
                                    label="table.field.asnOrder.qty"
                                    source="qty"
                                    readOnly
                                    parse={v => v}
                                />
                                <DateInput
                                    label="table.field.asnOrder.arrTime"
                                    source="arrTime"
                                    readOnly
                                />
                                <SelectInput
                                    label="table.field.asnOrder.rleStatus"
                                    source="rleStatus"
                                    readOnly
                                    choices={[
                                        { id: 0, name: ' 正常' },
                                        { id: 1, name: ' 已释放' },
                                    ]}
                                    validate={required()}
                                />
                            </Stack>
                        </Grid>
                    </Grid>
                    </Grid>
                </SimpleForm>
            </Edit >
            <AsnOrderItemList />
rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
@@ -162,12 +162,6 @@
            <DateField source="createTime" label="common.field.createTime" showTime />
            <BooleanField source="status$" label="common.field.status" sortable={false} />
            <TextField source="memo" label="common.field.memo" sortable={false} />
            <WrapperField cellClassName="opt" label="common.field.opt">
              <Button label="ra.action.edit" onClick={(id, resource, record) => {
                 setEditDialog(true)
                 setSelect(record) }} />
              <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE}   />
            </WrapperField>
          </StyledDatagrid>
        </List>
        <AsnOrderItemCreate
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
@@ -104,6 +104,7 @@
            ...prevData,
            [name]: value
        }));
        console.log(formData);
    };
    const resetData = () => {
@@ -181,7 +182,7 @@
            setFormData(res.data.data)
        } else {
            notify(res.data.msg);
        }
        }
    }
    const requestGetBody = async () => {
@@ -203,7 +204,7 @@
    }
    return (
        <>
        <>
            <Dialog
                open={open}
                onClose={handleClose}
@@ -212,7 +213,7 @@
                fullWidth
                disableRestoreFocus
                maxWidth="lg"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
            >
            >
                <DialogTitle id="form-dialog-title" sx={{
                    position: 'sticky',
                    top: 0,
@@ -226,7 +227,7 @@
                </DialogTitle>
                <DialogContent sx={{ mt: 2 }}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                        <Form>
                        <Form defaultValues={formData}>
                            <Grid container spacing={2}>
                                <Grid item md={3}>
                                    <DictSelect
@@ -335,19 +336,33 @@
    return (
        <Select
        value={params.value}
        onChange={(e) =>
          params.api.setEditCellValue({
            id: params.id,
            field: params.field,
            value: e.target.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);
          // 如果找到对应的供应商记录,同时更新splrCode字段
          if (selectedSupplier) {
            params.api.setEditCellValue({
              id: params.id,
              field: 'splrCode',
              value: selectedSupplier.id,
            });
          }
        }
        }
        fullWidth
        autoFocus
      >        
          {formData.map(e => {
            return(
                <MenuItem value={e.name} children={e.name} />
                <MenuItem value={e.name} children={e.name} key={e.id} />
            );
              
          })}
@@ -379,19 +394,31 @@
    return (
        <Select
        value={params.value}
        onChange={(e) =>
          params.api.setEditCellValue({
            id: params.id,
            field: params.field,
            value: e.target.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);
              // 如果找到对应的供应商记录,同时更新splrCode字段
              if (selectedSupplier) {
                params.api.setEditCellValue({
                  id: params.id,
                  field: 'splrName',
                  value: selectedSupplier.name,
                });
              }
        }
        }
        fullWidth
        autoFocus
      >        
          {formData.map(e => {
            return(
                <MenuItem value={e.id} children={e.name} />
                <MenuItem value={e.id} children={e.name} key={e.id} />
            );
              
          })}
rsf-admin/src/page/orders/delivery/DeliveryCreate.jsx
New file
@@ -0,0 +1,175 @@
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 DeliveryCreate = (props) => {
    const { open, setOpen } = props;
    const translate = useTranslate();
    const notify = useNotify();
    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 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={16} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.delivery.platId"
                                        source="platId"
                                        parse={v => v}
                                    />
                                    <AutocompleteInput
                                        choices={dicts}
                                        optionText="label"
                                        label="table.field.asnOrder.type"
                                        source="type"
                                        optionValue="value"
                                        parse={v => v}
                                    />
                                    <AutocompleteInput
                                        choices={business}
                                        optionText="label"
                                        label="table.field.asnOrder.wkType"
                                        source="wkType"
                                        optionValue="value"
                                        parse={v => v}
                                    />
                                    <TextInput
                                        label="table.field.delivery.source"
                                        source="source"
                                        parse={v => v}
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={16} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.delivery.anfme"
                                        source="anfme"
                                        validate={required()}
                                    />
                                    <NumberInput
                                        label="table.field.delivery.qty"
                                        source="qty"
                                        validate={required()}
                                    />
                                    <NumberInput
                                        label="table.field.delivery.workQty"
                                        source="workQty"
                                        validate={required()}
                                    />
                                    <TextInput
                                        label="table.field.delivery.platCode"
                                        source="platCode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <DateInput
                                        label="table.field.delivery.startTime"
                                        source="startTime"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <DateInput
                                        label="table.field.delivery.endTime"
                                        source="endTime"
                                    />
                                </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 DeliveryCreate;
rsf-admin/src/page/orders/delivery/DeliveryEdit.jsx
New file
@@ -0,0 +1,157 @@
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";
import DeliveryItemList from "./DeliveryItemList";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'end' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const DeliveryEdit = () => {
    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={<FormToolbar />}
                    mode="onTouched"
                    defaultValues={{}}
                >
                    <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}>
                        <Grid item xs={16} md={10}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.main')}
                            </Typography>
                            <Stack direction='row' gap={2}>
                                <TextInput
                                    label="table.field.delivery.code"
                                    source="code"
                                    parse={v => v}
                                    autoFocus
                                />
                                <TextInput
                                    label="table.field.delivery.platId"
                                    source="platId"
                                    parse={v => v}
                                />
                                <AutocompleteInput
                                    choices={dicts}
                                    optionText="label"
                                    label="table.field.asnOrder.type"
                                    source="type"
                                    optionValue="value"
                                    parse={v => v}
                                    readOnly
                                />
                                <AutocompleteInput
                                    choices={business}
                                    optionText="label"
                                    label="table.field.asnOrder.wkType"
                                    source="wkType"
                                    optionValue="value"
                                    parse={v => v}
                                />
                            </Stack>
                            <Stack direction='row' gap={2}>
                                <TextInput
                                    label="table.field.delivery.source"
                                    source="source"
                                    parse={v => v}
                                    validate={required()}
                                />
                                <NumberInput
                                    label="table.field.delivery.anfme"
                                    source="anfme"
                                    validate={required()}
                                />
                                <NumberInput
                                    label="table.field.delivery.qty"
                                    source="qty"
                                    validate={required()}
                                />
                                <NumberInput
                                    label="table.field.delivery.workQty"
                                    source="workQty"
                                    validate={required()}
                                />
                                <TextInput
                                    label="table.field.delivery.platCode"
                                    source="platCode"
                                    parse={v => v}
                                />
                            </Stack>
                            <Stack direction='row' gap={2}>
                                <DateInput
                                    label="table.field.delivery.startTime"
                                    source="startTime"
                                />
                                <DateInput
                                    label="table.field.delivery.endTime"
                                    source="endTime"
                                />
                            </Stack>
                        </Grid>
                        <Grid item xs={8} md={2}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.common')}
                            </Typography>
                            <StatusSelectInput />
                            <Box mt="2em" />
                            <MemoInput />
                        </Grid>
                    </Grid>
                </SimpleForm>
            </Edit >
            <Grid>
                <Box mt="2em"></Box>
                <DeliveryItemList />
            </Grid>
        </>
    )
}
export default DeliveryEdit;
rsf-admin/src/page/orders/delivery/DeliveryItemCreate.jsx
New file
@@ -0,0 +1,202 @@
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 DeliveryItemCreate = (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
                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} sx={{display : "none"}}>
                                    <NumberInput
                                        label="table.field.deliveryItem.deliveryId"
                                        source="deliveryId"
                                        defaultValue={record?.id}
                                        readOnly
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.platItemId"
                                        source="platItemId"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.matnrCode"
                                        source="matnrCode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.matnrName"
                                        source="matnrName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.fieldsIndex"
                                        source="fieldsIndex"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.unit"
                                        source="unit"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.anfme"
                                        source="anfme"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.qty"
                                        source="qty"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.nromQty"
                                        source="nromQty"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.deliveryItem.printQty"
                                        source="printQty"
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.splrName"
                                        source="splrName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.splrCode"
                                        source="splrCode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.deliveryItem.splrBatch"
                                        source="splrBatch"
                                        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 DeliveryItemCreate;
rsf-admin/src/page/orders/delivery/DeliveryItemEdit.jsx
New file
@@ -0,0 +1,204 @@
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,
    Form,
    DeleteButton,
    useGetOne,
    EditBase,
} from 'react-admin';
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography, Dialog, DialogActions, DialogContent, DialogTitle } 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";
import DialogCloseButton from "../../components/DialogCloseButton";
import { Visibility } from "@mui/icons-material";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const DeliveryItemEdit = (props) => {
    const { open, setOpen, record } = props;
    const translate = useTranslate();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const { data, isPending, } = useGetOne('deliveryItem', { id: record?.id });
    if (data == null || data == undefined) { return }
    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('update.title')}
                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                        <DialogCloseButton onClose={handleClose} />
                    </Box>
                </DialogTitle>
                <DialogContent sx={{ mt: 2 }}>
                    <EditBase
                        resource={'deliveryItem'}
                        id={record?.id}
                        mutationMode={EDIT_MODE}
                        // actions={<CustomerTopToolBar />}
                        aside={<EditBaseAside />}
                    >
                        <Form
                            shouldUnregister
                            warnWhenUnsavedChanges
                            toolbar={<FormToolbar />}
                            mode="onTouched"
                            defaultValues={{}}
                        // validate={(values) => { }}
                        >
                            <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}>
                                <Grid item xs={16} md={10}>
                                    <Typography variant="h6" gutterBottom>
                                        {translate('common.edit.title.main')}
                                    </Typography>
                                    <Stack direction='row' gap={2}>
                                        <NumberInput
                                            label="table.field.deliveryItem.deliveryId"
                                            source="deliveryId"
                                            autoFocus
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.platItemId"
                                            source="platItemId"
                                            parse={v => v}
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.matnrCode"
                                            source="matnrCode"
                                            parse={v => v}
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.matnrName"
                                            source="matnrName"
                                            parse={v => v}
                                        />
                                    </Stack>
                                    <Stack direction='row' gap={2}>
                                        <TextInput
                                            label="table.field.deliveryItem.fieldsIndex"
                                            source="fieldsIndex"
                                            parse={v => v}
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.unit"
                                            source="unit"
                                            parse={v => v}
                                        />
                                        <NumberInput
                                            label="table.field.deliveryItem.anfme"
                                            source="anfme"
                                            validate={required()}
                                        />
                                        <NumberInput
                                            label="table.field.deliveryItem.qty"
                                            source="qty"
                                            validate={required()}
                                        />
                                        <NumberInput
                                            label="table.field.deliveryItem.nromQty"
                                            source="nromQty"
                                            validate={required()}
                                        />
                                    </Stack>
                                    <Stack direction='row' gap={2}>
                                        <NumberInput
                                            label="table.field.deliveryItem.printQty"
                                            source="printQty"
                                            validate={required()}
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.splrName"
                                            source="splrName"
                                            parse={v => v}
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.splrCode"
                                            source="splrCode"
                                            parse={v => v}
                                        />
                                        <TextInput
                                            label="table.field.deliveryItem.splrBatch"
                                            source="splrBatch"
                                            parse={v => v}
                                        />
                                    </Stack>
                                </Grid>
                                <Grid item xs={8} md={2}>
                                    <Typography variant="h6" gutterBottom>
                                        {translate('common.edit.title.common')}
                                    </Typography>
                                    <StatusSelectInput />
                                    <Box mt="2em" />
                                    <MemoInput />
                                </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 DeliveryItemEdit;
rsf-admin/src/page/orders/delivery/DeliveryItemList.jsx
New file
@@ -0,0 +1,185 @@
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,
    useGetOne,
    useGetRecordId,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import DeliveryItemCreate from "./DeliveryItemCreate";
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';
import DeliveryItemEdit from "./DeliveryItemEdit";
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 />,
    <NumberInput source="deliveryId" label="table.field.deliveryItem.deliveryId" />,
    <TextInput source="platItemId" label="table.field.deliveryItem.platItemId" />,
    <TextInput source="matnrCode" label="table.field.deliveryItem.matnrCode" />,
    <TextInput source="matnrName" label="table.field.deliveryItem.matnrName" />,
    <TextInput source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" />,
    <TextInput source="unit" label="table.field.deliveryItem.unit" />,
    <NumberInput source="anfme" label="table.field.deliveryItem.anfme" />,
    <NumberInput source="qty" label="table.field.deliveryItem.qty" />,
    <NumberInput source="nromQty" label="table.field.deliveryItem.nromQty" />,
    <NumberInput source="printQty" label="table.field.deliveryItem.printQty" />,
    <TextInput source="splrName" label="table.field.deliveryItem.splrName" />,
    <TextInput source="splrCode" label="table.field.deliveryItem.splrCode" />,
    <TextInput source="splrBatch" label="table.field.deliveryItem.splrBatch" />,
    <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 DeliveryItemList = () => {
    const translate = useTranslate();
    const doId = useGetRecordId();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const [editDialog, setEditDialog] = useState(false);
    const [select, setSelect] = useState({});
    const { data: dicts, isPending, error } = useGetOne('delivery', { id: doId });
    return (
        <Box display="flex">
            <List
                resource="deliveryItem"
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.deliveryItem"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                filter={{deliveryId: doId}}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='deliveryItem' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='deliveryItem'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => {
                        setSelect(record)
                        setEditDialog(true)
                    }}
                    expand={false}
                    expandSingle={true}
                    omit={['id', 'createTime','deliveryId','fieldsIndex','qty', 'printQty', 'nromQty', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <NumberField source="deliveryId" label="table.field.deliveryItem.deliveryId" />
                    <TextField source="platItemId" label="table.field.deliveryItem.platItemId" />
                    <TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" />
                    <TextField source="matnrName" label="table.field.deliveryItem.matnrName" />
                    <TextField source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" />
                    <TextField source="unit" label="table.field.deliveryItem.unit" />
                    <NumberField source="anfme" label="table.field.deliveryItem.anfme" />
                    <NumberField source="qty" label="table.field.deliveryItem.qty" />
                    <NumberField source="nromQty" label="table.field.deliveryItem.nromQty" />
                    <NumberField source="printQty" label="table.field.deliveryItem.printQty" />
                    <TextField source="splrName" label="table.field.deliveryItem.splrName" />
                    <TextField source="splrCode" label="table.field.deliveryItem.splrCode" />
                    <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} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <DeliveryItemEdit
                open={editDialog}
                setOpen={setEditDialog}
                record={select}
            />
            <DeliveryItemCreate
                open={createDialog}
                setOpen={setCreateDialog}
                record={dicts}
            />
            <PageDrawer
                title='DeliveryItem Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default DeliveryItemList;
rsf-admin/src/page/orders/delivery/DeliveryList.jsx
New file
@@ -0,0 +1,164 @@
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 DeliveryCreate from "./DeliveryCreate";
import DeliveryPanel from "./DeliveryPanel";
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"  />,
    <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" />,
    <NumberInput source="anfme" label="table.field.delivery.anfme" />,
    <NumberInput source="qty" label="table.field.delivery.qty" />,
    <NumberInput source="workQty" label="table.field.delivery.workQty" />,
    <TextInput source="platCode" label="table.field.delivery.platCode" />,
    <DateInput source="startTime" label="table.field.delivery.startTime" />,
    <DateInput source="endTime" label="table.field.delivery.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
    />,
]
const DeliveryList = () => {
    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.delivery"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='delivery' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='delivery'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={false}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo', 'workQty', 'startTime', 'endTime', 'updateBy','createTime']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.delivery.code" />
                    <TextField source="platId" label="table.field.delivery.platId" />
                    <TextField source="type$" label="table.field.delivery.type" />
                    <TextField source="wkType$" label="table.field.delivery.wkType" />
                    <TextField source="source" label="table.field.delivery.source" />
                    <NumberField source="anfme" label="table.field.delivery.anfme" />
                    <NumberField source="qty" label="table.field.delivery.qty" />
                    <NumberField source="workQty" label="table.field.delivery.workQty" />
                    <TextField source="platCode" label="table.field.delivery.platCode" />
                    <DateField source="startTime" label="table.field.delivery.startTime" showTime />
                    <DateField source="endTime" label="table.field.delivery.endTime" showTime />
                    <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} />
                    <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>
            <DeliveryCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='Delivery Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default DeliveryList;
rsf-admin/src/page/orders/delivery/DeliveryPanel.jsx
New file
@@ -0,0 +1,117 @@
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 DeliveryPanel = () => {
    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.delivery.id'))}: {record.id}
                            </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.delivery.code"
                                property={record.code}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.platId"
                                property={record.platId}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.type"
                                property={record.type}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.wkType"
                                property={record.wkType}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.source"
                                property={record.source}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.anfme"
                                property={record.anfme}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.qty"
                                property={record.qty}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.workQty"
                                property={record.workQty}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.platCode"
                                property={record.platCode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.startTime"
                                property={record.startTime$}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.delivery.endTime"
                                property={record.endTime$}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default DeliveryPanel;
rsf-admin/src/page/orders/delivery/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import DeliveryList from "./DeliveryList";
import DeliveryEdit from "./DeliveryEdit";
export default {
    list: DeliveryList,
    edit: DeliveryEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-admin/src/page/system/serialRule/SerialRuleItemEdit.jsx
@@ -110,7 +110,7 @@
                                        source="wkType"
                                        optionValue="value"
                                        parse={v => v}
                                     />
                                    />
                                </Stack>
                                <Stack direction='row' gap={2}>
                                    <TextInput
@@ -152,7 +152,13 @@
                        </Grid>
                    </DialogContent>
                    <DialogActions>
                        <Toolbar sx={{ width: '100%', justifyContent: 'end' }}  >
                            <SaveButton type="button" mutationOptions={{
                                onSuccess: () => {
                                    setOpen(false)
                                }
                            }} />
                        </Toolbar>
                    </DialogActions>
                </Form>
rsf-admin/src/page/system/serialRule/SerialRuleItemList.jsx
@@ -118,7 +118,7 @@
          empty={false}
          filters={filters}
          filter={{ ruleId: ruleId }}
          sort={{ field: "create_time", order: "desc" }}
          sort={{ field: "sort", order: "asc" }}
          actions={
            <TopToolbar>
              <FilterButton />
rsf-admin/src/page/task/TaskList.jsx
@@ -87,7 +87,7 @@
    />,
]
const TaskList = () => {
const TaskList = (props) => {
    const translate = useTranslate();
    const [drawerVal, setDrawerVal] = useState(false);
    return (
@@ -171,16 +171,17 @@
 * 完成操作
 * @returns 
 */
const DoneButton = () => {
const DoneButton = (props) => {
    const record = useRecordContext();
    const notify = useNotify(); 
    const refresh = useRefresh();
    const clickComplete = (event) => {
        event.stopPropagation();
        completeTask([record])
        completeTask(record)
    };
    //完成任务
    const completeTask = async (row) => {
        console.log(row.id);
        const { data: { code, data, msg } } = await request.post(`task/complete/` + row.id);
        if (code === 200) {
            notify(msg);
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -248,6 +248,7 @@
//            }
            AsnOrderItem orderItem = asnOrderItemMapper.selectOne(new LambdaQueryWrapper<AsnOrderItem>()
                    .eq(AsnOrderItem::getAsnCode, asnCode)
                            .eq(AsnOrderItem::getTrackCode, dto.getBarcode())
                    .eq(AsnOrderItem::getMatnrId, dto.getMatnrId()));
            if (Objects.isNull(orderItem)) {
                throw new CoolException("通知单明细不存在!!");
@@ -850,7 +851,11 @@
     */
    @Override
    public R getDeviceSites() {
        return R.ok(deviceSiteMapper.selectList(new LambdaQueryWrapper<DeviceSite>().eq(DeviceSite::getStatus, 1).groupBy(DeviceSite::getSite)));
        List<DeviceSite> sites = deviceSiteMapper.selectList(new LambdaQueryWrapper<DeviceSite>()
                        .select(DeviceSite::getId, DeviceSite::getSite, DeviceSite::getName)
                .eq(DeviceSite::getStatus, 1)
                .groupBy(DeviceSite::getSite, DeviceSite::getId, DeviceSite::getName));
        return R.ok(sites);
    }
    /**
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -22,7 +22,7 @@
//        generator.username="sa";
//        generator.password="Zoneyung@zy56$";
        generator.table="man_stock_item";
        generator.table="man_delivery_item";
        generator.tableDesc="综合单据明细";
        generator.packagePath="com.vincent.rsf.server.manager";
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/DeliveryController.java
New file
@@ -0,0 +1,120 @@
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.Delivery;
import com.vincent.rsf.server.manager.service.DeliveryService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.system.service.SerialRuleService;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
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 DeliveryController extends BaseController {
    @Autowired
    private DeliveryService deliveryService;
    @PreAuthorize("hasAuthority('manager:delivery:list')")
    @PostMapping("/delivery/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<Delivery, BaseParam> pageParam = new PageParam<>(baseParam, Delivery.class);
        return R.ok().add(deliveryService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:delivery:list')")
    @PostMapping("/delivery/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(deliveryService.list());
    }
    @PreAuthorize("hasAuthority('manager:delivery:list')")
    @PostMapping({"/delivery/many/{ids}", "/deliverys/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(deliveryService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:delivery:list')")
    @GetMapping("/delivery/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(deliveryService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:delivery:save')")
    @OperationLog("Create 综合单据明细")
    @PostMapping("/delivery/save")
    public R save(@RequestBody Delivery delivery) {
        delivery.setCreateBy(getLoginUserId());
        delivery.setUpdateBy(getLoginUserId());
        if (Objects.isNull(delivery.getCode())) {
            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_DELIVERY_RULE_CODE, delivery);
            if (Objects.isNull(ruleCode) || StringUtils.isBlank(ruleCode)) {
                return R.error("编码规则错误:编码「SYS_DELIVERY_RULE_CODE」是未设置成功!!");
            }
            delivery.setCode(ruleCode);
        }
        if (!deliveryService.save(delivery)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(delivery);
    }
    @PreAuthorize("hasAuthority('manager:delivery:update')")
    @OperationLog("Update 综合单据明细")
    @PostMapping("/delivery/update")
    public R update(@RequestBody Delivery delivery) {
        delivery.setUpdateBy(getLoginUserId());
        delivery.setUpdateTime(new Date());
        if (!deliveryService.updateById(delivery)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(delivery);
    }
    @PreAuthorize("hasAuthority('manager:delivery:remove')")
    @OperationLog("Delete 综合单据明细")
    @PostMapping("/delivery/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!deliveryService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:delivery:list')")
    @PostMapping("/delivery/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<Delivery> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(Delivery::getId, condition);
        }
        deliveryService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getId()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('manager:delivery:list')")
    @PostMapping("/delivery/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(deliveryService.list(), Delivery.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/DeliveryItemController.java
New file
@@ -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.DeliveryItem;
import com.vincent.rsf.server.manager.service.DeliveryItemService;
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 DeliveryItemController extends BaseController {
    @Autowired
    private DeliveryItemService deliveryItemService;
    @PreAuthorize("hasAuthority('manager:deliveryItem:list')")
    @PostMapping("/deliveryItem/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<DeliveryItem, BaseParam> pageParam = new PageParam<>(baseParam, DeliveryItem.class);
        return R.ok().add(deliveryItemService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:list')")
    @PostMapping("/deliveryItem/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(deliveryItemService.list());
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:list')")
    @PostMapping({"/deliveryItem/many/{ids}", "/deliveryItems/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(deliveryItemService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:list')")
    @GetMapping("/deliveryItem/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(deliveryItemService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:save')")
    @OperationLog("Create 综合单据明细")
    @PostMapping("/deliveryItem/save")
    public R save(@RequestBody DeliveryItem deliveryItem) {
        deliveryItem.setCreateBy(getLoginUserId());
        deliveryItem.setCreateTime(new Date());
        deliveryItem.setUpdateBy(getLoginUserId());
        deliveryItem.setUpdateTime(new Date());
        if (!deliveryItemService.save(deliveryItem)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(deliveryItem);
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:update')")
    @OperationLog("Update 综合单据明细")
    @PostMapping("/deliveryItem/update")
    public R update(@RequestBody DeliveryItem deliveryItem) {
        deliveryItem.setUpdateBy(getLoginUserId());
        deliveryItem.setUpdateTime(new Date());
        if (!deliveryItemService.updateById(deliveryItem)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(deliveryItem);
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:remove')")
    @OperationLog("Delete 综合单据明细")
    @PostMapping("/deliveryItem/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!deliveryItemService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:list')")
    @PostMapping("/deliveryItem/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<DeliveryItem> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(DeliveryItem::getId, condition);
        }
        deliveryItemService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getId()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('manager:deliveryItem:list')")
    @PostMapping("/deliveryItem/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(deliveryItemService.list(), DeliveryItem.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java
@@ -132,20 +132,16 @@
    @PreAuthorize("hasAuthority('manager:task:update')")
    @ApiOperation("完成任务")
    @PostMapping("/task/complete/{id}")
    public R completeTask(@PathVariable String id) {
    public R completeTask(@PathVariable String id) throws Exception {
        if (Objects.isNull(id)) {
            throw new CoolException("参数不能为空!!");
        }
        List<Long> longs = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getId, id).in(Task::getTaskStatus, longs));
        if (tasks.isEmpty()) {
            throw new CoolException("任务已处执行状态不可一键完成!!");
        }
        try {
            taskService.completeTask(tasks);
        } catch (Exception ex) {
            return R.error("任务异常,无法完成!!");
        }
//        if (tasks.isEmpty()) {
//            throw new CoolException("任务已处执行状态不可一键完成!!");
//        }
        taskService.completeTask(tasks);
        return R.ok();
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Delivery.java
New file
@@ -0,0 +1,310 @@
package com.vincent.rsf.server.manager.entity;
import java.text.SimpleDateFormat;
import java.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.server.system.constant.DictTypeCode;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.service.DictDataService;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.text.SimpleDateFormat;
import java.util.Date;
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_delivery")
public class Delivery 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 code;
    /**
     * erp主单标识
     */
    @ApiModelProperty(value= "erp主单标识")
    private String platId;
    /**
     * 单据类型
     */
    @ApiModelProperty(value= "单据类型")
    private String type;
    /**
     * 业务类型
     */
    @ApiModelProperty(value= "业务类型")
    private String wkType;
    /**
     * 单据来源
     */
    @ApiModelProperty(value= "单据来源")
    private String source;
    /**
     * 出库数量
     */
    @ApiModelProperty(value= "出库数量")
    private Double anfme;
    /**
     * 已出库数量
     */
    @ApiModelProperty(value= "已出库数量")
    private Double qty;
    /**
     * 执行中数量
     */
    @ApiModelProperty(value= "执行中数量")
    private Double workQty;
    /**
     * 平台单号
     */
    @ApiModelProperty(value= "平台单号")
    private String platCode;
    /**
     * 计划出库时间
     */
    @ApiModelProperty(value= "计划出库时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date startTime;
    /**
     * 计划出库结束时间
     */
    @ApiModelProperty(value= "计划出库结束时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date endTime;
    /**
     * 状态 1: 已完成  0: 待执行   2:  未完成
     */
    @ApiModelProperty(value= "状态 1: 已完成  0: 待执行   2:  未完成  ")
    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 Delivery() {}
    public Delivery(String code,String platId,String type,String wkType,String source,Double anfme,Double qty,Double workQty,String platCode,Date startTime,Date endTime,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.code = code;
        this.platId = platId;
        this.type = type;
        this.wkType = wkType;
        this.source = source;
        this.anfme = anfme;
        this.qty = qty;
        this.workQty = workQty;
        this.platCode = platCode;
        this.startTime = startTime;
        this.endTime = endTime;
        this.status = status;
        this.deleted = deleted;
        this.tenantId = tenantId;
        this.createBy = createBy;
        this.createTime = createTime;
        this.updateBy = updateBy;
        this.updateTime = updateTime;
        this.memo = memo;
    }
//    Delivery delivery = new Delivery(
//            null,    // 采购单号
//            null,    // erp主单标识
//            null,    // 单据类型
//            null,    // 业务类型
//            null,    // 单据来源[非空]
//            null,    // 出库数量[非空]
//            null,    // 已出库数量[非空]
//            null,    // 执行中数量[非空]
//            null,    // 平台单号
//            null,    // 计划出库时间
//            null,    // 计划出库结束时间
//            null,    // 状态[非空]
//            null,    // 是否删除[非空]
//            null,    // 租户
//            null,    // 添加人员
//            null,    // 添加时间[非空]
//            null,    // 修改人员
//            null,    // 修改时间[非空]
//            null    // 备注
//    );
    public String getType$(){
        if (Cools.isEmpty(this.type)){
            return "";
        }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictData = dictDataService.getOne(new LambdaQueryWrapper<DictData>().eq(DictData::getDictTypeCode, DictTypeCode.DICT_SYS_ORDER_TYPE).eq(DictData::getValue, this.type));
        if (Objects.isNull(dictData)) {
            return null;
        }
        return dictData.getLabel();
    }
    public String getWkType$(){
        if (Cools.isEmpty(this.wkType)){
            return "";
        }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictData = dictDataService.getOne(new LambdaQueryWrapper<DictData>().eq(DictData::getDictTypeCode, DictTypeCode.DICT_SYS_BUSINESS_TYPE).eq(DictData::getValue, this.wkType));
        if (Objects.isNull(dictData)) {
            return null;
        }
        return dictData.getLabel();
    }
    public String getStartTime$(){
        if (Cools.isEmpty(this.startTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.startTime);
    }
    public String getEndTime$(){
        if (Cools.isEmpty(this.endTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.endTime);
    }
    public String getStatus$(){
        if (null == this.status){ return null; }
        switch (this.status){
            case 1:
                return "已完成";
            case 0:
                return "待执行";
            case  2:
                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;
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/DeliveryItem.java
New file
@@ -0,0 +1,279 @@
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_delivery_item")
public class DeliveryItem implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * ID
     */
    @ApiModelProperty(value= "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 主单标识
     */
    @ApiModelProperty(value= "主单标识")
    private Long deliveryId;
    @ApiModelProperty("主单编码")
    private String deliveryCode;
    /**
     * erp明细标识
     */
    @ApiModelProperty(value= "erp明细标识")
    private String platItemId;
    /**
     * 物料编码
     */
    @ApiModelProperty(value= "物料编码")
    private String matnrCode;
    /**
     * 物料名称
     */
    @ApiModelProperty(value= "物料名称")
    private String matnrName;
    /**
     * 动态字段索引
     */
    @ApiModelProperty(value= "动态字段索引")
    private String fieldsIndex;
    /**
     * 单位
     */
    @ApiModelProperty(value= "单位")
    private String unit;
    /**
     * 数量
     */
    @ApiModelProperty(value= "数量")
    private Double anfme;
    /**
     * 已出数量
     */
    @ApiModelProperty(value= "已出数量")
    private Double qty;
    /**
     * 标准包装
     */
    @ApiModelProperty(value= "标准包装")
    private Double nromQty;
    /**
     * 条码打印数量
     */
    @ApiModelProperty(value= "条码打印数量")
    private Double printQty;
    /**
     * 供应商名称
     */
    @ApiModelProperty(value= "供应商名称")
    private String splrName;
    /**
     * 供应商编码
     */
    @ApiModelProperty(value= "供应商编码")
    private String splrCode;
    /**
     * 供应商批次
     */
    @ApiModelProperty(value= "供应商批次")
    private String splrBatch;
    /**
     * 状态 1: 正常  0: 冻结
     */
    @ApiModelProperty(value= "状态 1: 正常  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 DeliveryItem() {}
    public DeliveryItem(Long deliveryId,String platItemId,String matnrCode,String matnrName,String fieldsIndex,String unit,Double anfme,Double qty,Double nromQty,Double printQty,String splrName,String splrCode,String splrBatch,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.deliveryId = deliveryId;
        this.platItemId = platItemId;
        this.matnrCode = matnrCode;
        this.matnrName = matnrName;
        this.fieldsIndex = fieldsIndex;
        this.unit = unit;
        this.anfme = anfme;
        this.qty = qty;
        this.nromQty = nromQty;
        this.printQty = printQty;
        this.splrName = splrName;
        this.splrCode = splrCode;
        this.splrBatch = splrBatch;
        this.status = status;
        this.deleted = deleted;
        this.tenantId = tenantId;
        this.createBy = createBy;
        this.createTime = createTime;
        this.updateBy = updateBy;
        this.updateTime = updateTime;
        this.memo = memo;
    }
//    DeliveryItem deliveryItem = new DeliveryItem(
//            null,    // 主单标识
//            null,    // erp明细标识
//            null,    // 物料编码
//            null,    // 物料名称
//            null,    // 动态字段索引
//            null,    // 单位
//            null,    // 数量[非空]
//            null,    // 已出数量[非空]
//            null,    // 标准包装[非空]
//            null,    // 条码打印数量[非空]
//            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 "正常";
            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;
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WaitPakinItem.java
@@ -43,6 +43,12 @@
    @ApiModelProperty(value= "主单ID")
    private Long pakinId;
    @ApiModelProperty("订单类型")
    private String type;
    @ApiModelProperty("业务类型")
    private Short wkType;
    /**
     * 订单ID
     */
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/DeliveryItemMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.DeliveryItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface DeliveryItemMapper extends BaseMapper<DeliveryItem> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/DeliveryMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.Delivery;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface DeliveryMapper extends BaseMapper<Delivery> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/DeliveryItemService.java
New file
@@ -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.DeliveryItem;
public interface DeliveryItemService extends IService<DeliveryItem> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/DeliveryService.java
New file
@@ -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.Delivery;
public interface DeliveryService extends IService<Delivery> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryItemServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.DeliveryItemMapper;
import com.vincent.rsf.server.manager.entity.DeliveryItem;
import com.vincent.rsf.server.manager.service.DeliveryItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("deliveryItemService")
public class DeliveryItemServiceImpl extends ServiceImpl<DeliveryItemMapper, DeliveryItem> implements DeliveryItemService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.DeliveryMapper;
import com.vincent.rsf.server.manager.entity.Delivery;
import com.vincent.rsf.server.manager.service.DeliveryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("deliveryService")
public class DeliveryServiceImpl extends ServiceImpl<DeliveryMapper, Delivery> implements DeliveryService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -138,13 +138,12 @@
            waitPakinItems.forEach(item -> {
                TaskItem taskItem = new TaskItem();
                BeanUtils.copyProperties(item, taskItem);
                AsnOrder order = asnOrderService.getOne(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getId, item.getAsnId()));
                if (Objects.isNull(order)) {
                    throw new CoolException("数据错误: 单据不存在!!");
                }
//                AsnOrder order = asnOrderService.getOne(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getId, item.getAsnId()));
//                if (Objects.isNull(order)) {
//                    throw new CoolException("数据错误: 单据不存在!!");
//                }
                taskItem.setTaskId(task.getId())
                        .setOrderType(OrderType.ORDER_RECEIPT.type)
                        .setWkType(Short.parseShort(order.getWkType()))
                        .setSource(item.getId())
                        .setTrackCode(item.getTrackCode())
                        .setCreateBy(loginUserId)
@@ -180,7 +179,7 @@
            return;
        }
        List<Long> list = tasks.stream().map(Task::getId).collect(Collectors.toList());
        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, list));
        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().in(TaskItem::getTaskId, list));
        if (taskItems.isEmpty()) {
            throw new CoolException("任务明细不存在!!");
        }
@@ -198,15 +197,19 @@
        });
        /**对任务明细按订单进行分组*/
        Map<Long, List<TaskItem>> orderMap = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getOrderId));
        Map<Long, List<TaskItem>> orderMap = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getSource));
        orderMap.keySet().forEach(key -> {
            AsnOrder order = asnOrderService.getOne(new LambdaQueryWrapper<AsnOrder>()
                    .eq(AsnOrder::getId, key)
                    .select(AsnOrder::getId, AsnOrder::getPoCode, AsnOrder::getCode));
            WaitPakinItem pakinItem = waitPakinItemService.getById(key);
//            AsnOrder order = asnOrderService.getOne(new LambdaQueryWrapper<AsnOrder>()
//                    .eq(AsnOrder::getId, key)
//                    .select(AsnOrder::getId, AsnOrder::getPoCode, AsnOrder::getCode));
            if (null == pakinItem) {
                throw new CoolException("数据错误:组拖数据不存在,请联系管理员!!");
            }
            List<TaskItem> items = orderMap.get(key);
            //保存库存明细
            try {
                saveStockItems(items, order);
                saveStockItems(items, pakinItem);
            } catch (Exception e) {
                throw new CoolException("库存管理保存更新失败!!");
            }
@@ -228,14 +231,14 @@
     * @time 2025/4/15 15:28
     */
    @Transactional(rollbackFor = Exception.class)
    private void saveLocItem(List<TaskItem> items, Long taskId) throws Exception {
    void saveLocItem(List<TaskItem> items, Long taskId) throws Exception {
        Task task = this.getById(taskId);
        if (Objects.isNull(task)) {
            throw new CoolException("任务不存在!!");
        }
        List<LocItem> locItems = new ArrayList<>();
        items.forEach(taskItem -> {
            Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()));
            Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()), false);
            LocItem item = new LocItem();
            BeanUtils.copyProperties(taskItem, item);
            item.setLocId(loc.getId()).setType(taskItem.getOrderType());
@@ -252,7 +255,7 @@
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    private void saveStockItems(List<TaskItem> items, AsnOrder order) throws Exception {
    void saveStockItems(List<TaskItem> items, WaitPakinItem order) throws Exception {
        Stock stock = new Stock();
//        if (!Objects.isNull(order.getPoCode()) && StringUtils.isNotBlank(order.getPoCode())) {
//            Purchase purchase = purchaseService.getOne(new LambdaQueryWrapper<Purchase>().eq(Purchase::getCode, order.getPoCode()));
@@ -267,9 +270,9 @@
        double sum = items.stream().mapToDouble(TaskItem::getAnfme).sum();
        stock.setSourceId(order.getId())
                .setCode(ruleCode)
                .setSourceCode(order.getCode())
                .setSourceCode(order.getAsnCode())
                .setAnfme(sum)
                .setWkType(Short.parseShort(order.getWkType()))
                .setWkType(order.getWkType())
                .setType(order.getType());
        if (!stockService.save(stock)) {
            throw new CoolException("库存保存失败!!");
@@ -278,15 +281,15 @@
        List<StockItem> stockItems = new ArrayList<>();
        for (TaskItem item : items) {
            /**通过任务明细中的taskId查询,获取TASK的目标库位信息*/
            AsnOrderItem orderItem = asnOrderItemService.getOne(new LambdaQueryWrapper<AsnOrderItem>().eq(AsnOrderItem::getId, item.getOrderItemId()));
            if (Objects.isNull(orderItem)) {
                throw new CoolException("单据明细不存在!!");
            }
//            AsnOrderItem orderItem = asnOrderItemService.getOne(new LambdaQueryWrapper<AsnOrderItem>().eq(AsnOrderItem::getId, item.getOrderItemId()));
//            if (Objects.isNull(orderItem)) {
//                throw new CoolException("单据明细不存在!!");
//            }
            StockItem stockItem = new StockItem();
            BeanUtils.copyProperties(orderItem, stockItem);
            BeanUtils.copyProperties(item, stockItem);
            stockItem.setSourceItemId(item.getOrderItemId())
                    .setStockCode(stock.getCode())
                    .setSourceItemId(orderItem.getId())
                    .setSourceItemId(item.getOrderItemId())
                    .setId(null)
                    .setStockId(stock.getId());
            stockItems.add(stockItem);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java
@@ -129,6 +129,11 @@
                        .setUpdateBy(userId)
                        .setCreateBy(userId)
                        .setMatnrCode(item.getMatnrCode());
                AsnOrder order = asnOrderService.getById(item.getAsnId());
                if (!Objects.isNull(order)) {
                    pakinItem.setType(null == order.getType() ?  null :order.getType())
                            .setWkType(null == order.getWkType() ? null : Short.parseShort(order.getWkType()) );
                }
                for (PakinItem waitPakinItem : waitPakin.getItems()) {
                    if (waitPakinItem.getTrackCode().equals(item.getTrackCode())) {
                        if (waitPakinItem.getReceiptQty() > item.getAnfme() || waitPakinItem.getReceiptQty().compareTo(0.0) >= 0) {
@@ -165,6 +170,12 @@
                        .setUpdateBy(userId)
                        .setCreateBy(userId)
                        .setMatnrCode(item.getMatnrCode());
                AsnOrder order = asnOrderService.getById(item.getAsnId());
                if (!Objects.isNull(order)) {
                    pakinItem.setType(null == order.getType() ?  null :order.getType())
                            .setWkType(null == order.getWkType() ? null : Short.parseShort(order.getWkType()) );
                }
                for (PakinItem waitPakinItem : waitPakin.getItems()) {
                    if (waitPakinItem.getTrackCode().equals(item.getTrackCode())) {
                        if (waitPakinItem.getReceiptQty() > item.getAnfme() || waitPakinItem.getReceiptQty().compareTo(0.0) <= 0) {
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java
@@ -58,4 +58,9 @@
     * 综合订单编码规则
     */
    public final static String SYS_MANAGE_ORDER_CODE = "sys_manage_order_code";
    /**
     * DO单据编码规则
     */
    public final static String SYS_DELIVERY_RULE_CODE = "sys_delivery_rule_code";
}
rsf-server/src/main/java/delivery.sql
New file
@@ -0,0 +1,32 @@
-- save delivery record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.delivery', '0', '/manager/delivery', 'delivery', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 综合单据明细', '', '1', 'manager:delivery:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 综合单据明细', '', '1', 'manager:delivery:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 综合单据明细', '', '1', 'manager:delivery:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 综合单据明细', '', '1', 'manager:delivery:remove', '3', '1', '1');
-- locale menu name
delivery: 'Delivery',
-- locale field
delivery: {
    code: "code",
    platId: "platId",
    type: "type",
    wkType: "wkType",
    source: "source",
    anfme: "anfme",
    qty: "qty",
    workQty: "workQty",
    platCode: "platCode",
    startTime: "startTime",
    endTime: "endTime",
},
-- ResourceContent
import delivery from './delivery';
case 'delivery':
    return delivery;
rsf-server/src/main/java/deliveryItem.sql
New file
@@ -0,0 +1,34 @@
-- save deliveryItem record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.deliveryItem', '0', '/manager/deliveryItem', 'deliveryItem', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 综合单据明细', '', '1', 'manager:deliveryItem:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 综合单据明细', '', '1', 'manager:deliveryItem:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 综合单据明细', '', '1', 'manager:deliveryItem:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 综合单据明细', '', '1', 'manager:deliveryItem:remove', '3', '1', '1');
-- locale menu name
deliveryItem: 'DeliveryItem',
-- locale field
deliveryItem: {
    deliveryId: "deliveryId",
    platItemId: "platItemId",
    matnrCode: "matnrCode",
    matnrName: "matnrName",
    fieldsIndex: "fieldsIndex",
    unit: "unit",
    anfme: "anfme",
    qty: "qty",
    nromQty: "nromQty",
    printQty: "printQty",
    splrName: "splrName",
    splrCode: "splrCode",
    splrBatch: "splrBatch",
},
-- ResourceContent
import deliveryItem from './deliveryItem';
case 'deliveryItem':
    return deliveryItem;
rsf-server/src/main/resources/mapper/manager/DeliveryItemMapper.xml
New file
@@ -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.DeliveryItemMapper">
</mapper>
rsf-server/src/main/resources/mapper/manager/DeliveryMapper.xml
New file
@@ -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.DeliveryMapper">
</mapper>