skyouc
2025-08-02 60a665f3c576f8fe368ddfaabc9117a9c5dd47bf
Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop
4个文件已删除
73个文件已修改
5 文件已重命名
17个文件已添加
5240 ■■■■ 已修改文件
rsf-admin/src/config/setting.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/ResourceContent.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/loc/LocEdit.jsx 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/loc/LocList.jsx 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/DictSelect.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/DictionarySelect.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/WarehouseSelect.jsx 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/histories/asnOrderLog/AsnOrderItemLogList.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/histories/asnOrderLog/AsnOrderLogList.jsx 123 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locPreview/LocListAside.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locPreview/LocPreviewEdit.jsx 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locPreview/LocPreviewItems.jsx 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locPreview/LocPreviewList.jsx 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/locPreview/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnWareModal.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/check/MatnrInfoModal.jsx 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryEdit.jsx 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/purchase/PurchaseEdit.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/purchase/PurchaseItemList.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/stock/OrderEdit.jsx 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/stock/OrderList.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/CreateBySelectMats.jsx 281 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/ManualCreate.jsx 507 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferCreate.jsx 451 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferEdit.jsx 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferItemEdit.jsx 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferItemList.jsx 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferList.jsx 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferOrders.jsx 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/transfer/TransferPanel.jsx 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/dicts/dictType/DictDataCreate.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/dicts/dictType/DictDataEdit.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/system/dicts/dictType/DictDataList.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/TaskEdit.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/TaskItemList.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/utils/FieldsUtils.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocPreviewController.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TransferController.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TransferOrderController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/OrgLocParams.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/TransferItemParams.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderItemLog.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Loc.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItem.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Transfer.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/TransferItem.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/TransferOrder.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/MatnrsTemplate.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckExceStatus.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderSourceType.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TransferType.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/TransferMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/TransferOrderMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocPreviewService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocPreviewServiceImpl.java 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TransferItemService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TransferOrderService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TransferService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderLogServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryItemServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrServiceImpl.java 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TransferItemServiceImpl.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TransferOrderServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TransferServiceImpl.java 361 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/DictTypeCode.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/transferOrder.sql 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/TransferMapper.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/TransferOrderMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/config/setting.js
@@ -27,6 +27,8 @@
export const DEFAULT_PAGE_SIZE = 25;
export const DEFAULT_START_PAGE = 1;
export const DEFAULT_ITEM_PAGE_SIZE = 10;
export const PAGE_DRAWER_WIDTH = 400;
rsf-admin/src/i18n/en.js
@@ -189,7 +189,7 @@
        taskLog: 'TaskLog',
        orderItem: 'OrderItem',
        order: 'Order',
        locItem: 'LocItem',
        locPreview: 'LocItem',
        stock: 'Stock Manage',
        histories: 'Histories',
        wareWork: 'Warehouse Working',
@@ -689,6 +689,16 @@
                platOrderCode: "platOrderCode",
                platWorkCode: "platWorkCode",
                projectCode: "projectCode",
            },
            transferOrder: {
                code: 'Order No',
                poCode: 'transfer No',
                type: 'Type',
                wkType: 'Work Type',
                anfme: 'Anfme',
                workQty: 'Work Qty',
                qty: 'Qty',
            },
            checkDiffItem: {
@@ -1270,6 +1280,7 @@
        quality: "quality",
        complete: "complete",
        allComfirm: 'All Comfirm',
        createTransfer: 'Create Transfer Order',
        verifyComfirm: 'Verify Comfirm',
        close: "close",
        asnCreate: "Create By Order",
rsf-admin/src/i18n/zh.js
@@ -192,7 +192,7 @@
        taskItemLog: '任务明细历史档',
        stock: '入出库历史',
        stockItem: '单据明细',
        locItem: '库位明细',
        locPreview: '库位明细',
        histories: '历史档',
        wareWork: '仓库作业',
        statistics: '库存查询',
@@ -217,6 +217,7 @@
        checkOrder: '盘点单',
        checkDiff: '盘点差异单',
        transfer: '调拔单',
        transferItem: '调拔单明细'
    },
    table: {
        field: {
@@ -721,6 +722,15 @@
                projectCode: "项目单号",
            },
            transferOrder: {
                code: '单号',
                poCode: '调拔单',
                type: '单据类型',
                wkType: '调拔类型',
                anfme: '调拔数量',
                workQty: '执行数量',
                qty: '完成数',
            },
            checkDiffItem: {
                checkId: "盘点单ID",
@@ -1282,6 +1292,7 @@
        quality: "质检",
        complete: "完结",
        close: "关闭",
        createTransfer: '创建调拔单',
        asnCreate: "通过单据创建",
        poCreate: "通过PO单创建",
        orderPrint: '打印单据',
rsf-admin/src/page/ResourceContent.js
@@ -45,7 +45,7 @@
import outStock from "./orders/outStock";
import deviceBind from "./deviceBind";
import wave from "./orders/wave";
import locItem from "./locItem";
import locPreview from "./locPreview";
import basStation from "./basicInfo/basStation";
import warehouseStock from "./statistics/stockManage";
import basContainer from "./basicInfo/basContainer";
@@ -144,8 +144,8 @@
      return deviceBind;
    case "wave":
      return wave;
    case "locItem":
      return locItem;
    case "locPreview":
      return locPreview;
    case "basStation":
      return basStation;
    case "basContainer":
rsf-admin/src/page/basicInfo/loc/LocEdit.jsx
@@ -19,28 +19,31 @@
    NumberField,
    required,
    useRecordContext,
    useGetRecordId,
    useGetOne,
    DeleteButton,
    useNotify,
    useEditContext,
} 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 request from '@/utils/request';
import CustomerTopToolBar from "../../components/EditTopToolBar";
import DictionarySelect from "../../components/DictionarySelect";
import { Stack, Grid, Box, Typography } from '@mui/material';
import EditBaseAside from "../../components/EditBaseAside";
import { useWatch, useFormContext } from "react-hook-form";
import MemoInput from "../../components/MemoInput";
import * as Common from '@/utils/common';
import LocItemList from "./LocItemList";
import request from '@/utils/request';
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
        <Toolbar sx={{ justifyContent: 'flex-end' }}>
            {/* <DeleteButton mutationMode="optimistic" /> */}
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
@@ -49,10 +52,18 @@
    const translate = useTranslate();
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_type')) || [];
    const [warehouseId, setWrehouseId] = useState();
    const id = useGetRecordId();
    const { data, isLoading } = useGetOne('loc', { id });
    if (!isLoading) {
        data.typeIds = data?.type.split(',');
    } else {
        return
    }
    const warehouseChange = (val) => {
        setWrehouseId(val)
    }
    return (
        <>
@@ -64,15 +75,15 @@
                title={"menu.loc"}
            >
                <SimpleForm
                    record={data}
                    shouldUnregister
                    warnWhenUnsavedChanges
                    toolbar={<FormToolbar />}
                    mode="onTouched"
                    defaultValues={{}}
                // validate={(values) => { }}
                >
                    <Grid container width={{ xs: '100%', xl: '90%' }} rowSpacing={3} columnSpacing={3}>
                        <Grid item xs={12} md={10}>
                        <Grid item xs={12} md={12}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.main')}
                            </Typography>
@@ -159,14 +170,6 @@
                                </Grid>
                            </Grid>
                        </Grid>
                        <Grid item xs={12} md={2}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.common')}
                            </Typography>
                            <StatusSelectInput />
                            <Box mt="2em" />
                            <MemoInput />
                        </Grid>
                    </Grid>
                </SimpleForm>
            </Edit >
@@ -176,3 +179,4 @@
}
export default LocEdit;
rsf-admin/src/page/basicInfo/loc/LocList.jsx
@@ -35,26 +35,26 @@
    Button,
    useList,
} from 'react-admin';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import LocCreate from "./LocCreate";
import BindModal from "./BindModal";
import EmptyData from "../../components/EmptyData";
import DynamicField from "../../components/DynamicField";
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import DashboardIcon from '@mui/icons-material/Dashboard';
import DynamicField from "../../components/DynamicField";
import DiscountIcon from '@mui/icons-material/Discount';
import PageDrawer from "../../components/PageDrawer";
import EmptyData from "../../components/EmptyData";
import EditIcon from '@mui/icons-material/Edit';
import LinkIcon from '@mui/icons-material/Link';
import { styled } from '@mui/material/styles';
import SubzoneModal from './SubzoneModal';
import LocListAside from "./LocListAside";
import InitButton from './InitButton';
import BatchModal from './BatchModal';
import SubzoneModal from './SubzoneModal';
import PageDrawer from "../../components/PageDrawer";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import DashboardIcon from '@mui/icons-material/Dashboard';
import EditIcon from '@mui/icons-material/Edit';
import request from '@/utils/request';
import DiscountIcon from '@mui/icons-material/Discount';
import LinkIcon from '@mui/icons-material/Link';
import LocCreate from "./LocCreate";
import BindModal from "./BindModal";
import InitModal from "./InitModal";
import LocListAside from "./LocListAside";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -83,16 +83,14 @@
    },
}));
const LocList = () => {
    const translate = useTranslate();
    const notify = useNotify();
    const refresh = useRefresh();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const [initDialog, setInitDialog] = useState(false);
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_use_stas')) || [];
    const [createDialog, setCreateDialog] = useState(false);
    const [initDialog, setInitDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const translate = useTranslate();
    const refresh = useRefresh();
    const notify = useNotify();
    const filters = [
        <SearchInput source="condition" alwaysOn />,
@@ -223,12 +221,12 @@
                        </>
                    }
                    rowClick={() => false}
                    omit={['id', 'createTime', 'createBy', 'memo', 'updateTime', 'updateBy', 'length', 'width', 'height','statusBool','updateBy$','createBy$']}
                    omit={['id', 'createTime', 'createBy', 'memo', 'updateTime', 'updateBy', 'length', 'width', 'height', 'statusBool', 'updateBy$', 'createBy$']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.loc.code" />
                    <NumberField source="warehouseId$" label="table.field.loc.warehouseId" />
                    <NumberField source="areaId$" label="table.field.loc.areaId" />
                    <NumberField source="areaId$" label="table.field.loc.areaId" />
                    <TextField source="typeIds$" label="table.field.loc.type" cellClassName="type" />
                    {/* <TextField source="name" label="table.field.loc.name" /> */}
                    {/* <NumberField source="flagLogic" label="table.field.loc.flagLogic" />
rsf-admin/src/page/components/DictSelect.jsx
@@ -47,7 +47,6 @@
                variant="filled"
                onChange={handleChange}
                size='small'
            >
                {list.map((item) => (
                    <MenuItem key={item.value} value={item.value}>
rsf-admin/src/page/components/DictionarySelect.jsx
@@ -11,6 +11,7 @@
    const { 
        dictTypeCode, 
        name, 
        group,
        multiple = false, 
        perPage = 100,  // 默认每页显示100条数据
        page = 1,       // 默认第一页
@@ -30,6 +31,7 @@
        try {
            const res = await request.post('/dictData/page', { 
                dictTypeCode,
                group,
                current: page,
                pageSize: perPage
            });
rsf-admin/src/page/components/WarehouseSelect.jsx
New file
@@ -0,0 +1,64 @@
import { useState, useEffect } from 'react';
import {
    useTranslate, useNotify, required
} from 'react-admin';
import request from '@/utils/request';
import { Select, MenuItem, FormControl, InputLabel } from '@mui/material';
const WarehouseSelect = (props) => {
    const { dictTypeCode, label, value, onChange, ...params } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const [list, setList] = useState([]);
    useEffect(() => {
        http();
    }, [dictTypeCode]);
    const http = async () => {
        const res = await request.post('/warehouseAreas/page', { current: 1, pageSize: 100 });
        if (res?.data?.code === 200) {
            setList(res.data.data.records.map((item) => {
                return {
                    id: item.id,
                    name: item.name
                };
            }));
        } else {
            notify(res.data.msg);
        }
    };
    const handleChange = (event) => {
        const selectedValue = event.target.value;
        console.log(event);
        if (onChange) {
            onChange(event);
        }
    };
    const validValue = list.some(item => item.id === value) ? value : '';
    return (
        <FormControl required fullWidth>
            <InputLabel id="demo-select-small-label">{label}</InputLabel>
            <Select
                labelId="demo-select-small-label"
                value={validValue}
                variant="filled"
                onChange={handleChange}
                size='small'
            >
                {list.map((item) => (
                    <MenuItem
                        key={item.id}
                        value={item.id}>
                        {item.name}
                    </MenuItem>
                ))}
            </Select>
        </FormControl>
    );
};
export default WarehouseSelect;
rsf-admin/src/page/histories/asnOrderLog/AsnOrderItemLogList.jsx
@@ -144,8 +144,8 @@
                    omit={['id', 'orderId', 'poDetlId', 'poCode', 'qrcode', 'packName', 'createTime', 'memo', 'fieldsIndex', 'matnrId', 'splrCode', 'status', 'createBy$']}
                >
                    <NumberField source="id" />
                    <NumberField source="asnId" label="table.field.asnOrderItemLog.asnId" />
                    <TextField source="asnCode" label="table.field.asnOrderItemLog.asnCode" />
                    <NumberField source="asnId" label="table.field.asnOrderItemLog.orderId" />
                    <TextField source="asnCode" label="table.field.asnOrderItemLog.orderCode" />
                    <TextField source="platItemId" label="table.field.asnOrderItemLog.platItemId" />
                    <NumberField source="poDetlId" label="table.field.asnOrderItemLog.poDetlId" />
                    <TextField source="poCode" label="table.field.asnOrderItemLog.poCode" />
rsf-admin/src/page/histories/asnOrderLog/AsnOrderLogList.jsx
@@ -35,19 +35,22 @@
    useRecordSelection,
    useRefresh,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import AsnOrderLogCreate from "./AsnOrderLogCreate";
import AsnOrderLogPanel from "./AsnOrderLogPanel";
import EmptyData from "../../components/EmptyData";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import DictionarySelect from "../../components/DictionarySelect";
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import { Box, Typography, Card, Stack } from '@mui/material';
import ConfirmButton from '../../components/ConfirmButton';
import PageDrawer from "../../components/PageDrawer";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import AsnOrderLogCreate from "./AsnOrderLogCreate";
import CachedIcon from '@mui/icons-material/Cached';
import EmptyData from "../../components/EmptyData";
import AsnOrderLogPanel from "./AsnOrderLogPanel";
import { styled } from '@mui/material/styles';
import * as Common from '@/utils/common';
import request from '@/utils/request';
import ConfirmButton from '../../components/ConfirmButton';
import CachedIcon from '@mui/icons-material/Cached';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
@@ -61,53 +64,59 @@
        width: 150
    },
    '& .MuiTableCell-root': {
    whiteSpace: 'nowrap',
    overflow: 'visible',
    textOverflow: 'unset'
  }
        whiteSpace: 'nowrap',
        overflow: 'visible',
        textOverflow: 'unset'
    }
}));
const filters = [
    <SearchInput source="condition" alwaysOn />,
    <TextInput source="code" label="table.field.asnOrderLog.code" />,
    <TextInput source="poCode" label="table.field.asnOrderLog.poCode" />,
    <NumberInput source="poId" label="table.field.asnOrderLog.poId" />,
    <TextInput source="type" label="table.field.asnOrderLog.type" />,
    <TextInput source="wkType" label="table.field.asnOrderLog.wkType" />,
    <NumberInput source="anfme" label="table.field.asnOrderLog.anfme" />,
    <NumberInput source="qty" label="table.field.asnOrderLog.qty" />,
    <TextInput source="logisNo" label="table.field.asnOrderLog.logisNo" />,
    <DateInput source="arrTime" label="table.field.asnOrderLog.arrTime" />,
    <SelectInput source="rleStatus" label="table.field.asnOrderLog.rleStatus"
        choices={[
            { id: 0, name: ' 正常' },
            { id: 1, name: ' 已释放' },
        ]}
    />,
    <SelectInput source="ntyStatus" label="table.field.asnOrderLog.ntyStatus"
        choices={[
            { id: 0, name: ' 未上报' },
            { id: 1, name: ' 已上报' },
            { id: 2, name: ' 部分上报' },
        ]}
    />,
    <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 AsnOrderLogList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_order_type')) || [];
    const filters = [
        <SearchInput source="condition" alwaysOn />,
        <TextInput source="code" label="table.field.asnOrderLog.code" />,
        <TextInput source="poCode" label="table.field.asnOrderLog.poCode" />,
        <NumberInput source="poId" label="table.field.asnOrderLog.poId" />,
        // <TextInput source="type" label="table.field.asnOrderLog.type" />,
        // <TextInput source="wkType" label="table.field.asnOrderLog.wkType" />,
        <NumberInput source="anfme" label="table.field.asnOrderLog.anfme" />,
        <NumberInput source="qty" label="table.field.asnOrderLog.qty" />,
        <TextInput source="logisNo" label="table.field.asnOrderLog.logisNo" />,
        <DateInput source="arrTime" label="table.field.asnOrderLog.arrTime" />,
        // <SelectInput source="ntyStatus" label="table.field.asnOrderLog.ntyStatus"
        //     choices={[
        //         { id: 0, name: ' 未上报' },
        //         { id: 1, name: ' 已上报' },
        //         { id: 2, name: ' 部分上报' },
        //     ]}
        // />,
        <AutocompleteInput
            choices={dicts}
            optionText="label"
            label="table.field.asnOrder.type"
            source="type"
            // defaultValue="in"
            optionValue="value"
            parse={v => v}
            alwaysOn
        />,
        <ReferenceInput source="wkType" reference="dictData" filter={{ dictTypeCode: 'sys_business_type', group: "1" }} label="table.field.asnOrder.wkType" alwaysOn>
            <AutocompleteInput label="table.field.asnOrder.wkType" optionValue="value" />
        </ReferenceInput>,
        <DictionarySelect
            label='table.field.asnOrder.exceStatus'
            name="exceStatus"
            group="1"
            dictTypeCode="sys_asn_exce_status"
            alwaysOn
        />,
    ]
    return (
        <Box display="flex">
@@ -139,7 +148,7 @@
                    rowClick={'edit'}
                    expand={false}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo','logisNo', 'poId', 'rleStatus$','statusBool','createBy$']}
                    omit={['id', 'createTime', 'createBy', 'memo', 'logisNo', 'poId', 'rleStatus$', 'statusBool', 'createBy$']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.asnOrderLog.code" />
@@ -186,16 +195,16 @@
    const record = useRecordContext();
    const notify = useNotify();
    const continueReceipt = async () => {
      const { data: { code, data, msg } } = await request.post(`/asnOrderLog/continue/${record.id}`);
      if (code === 200) {
        notify(msg);
      } else {
        notify(msg);
      }
      refresh();
        const { data: { code, data, msg } } = await request.post(`/asnOrderLog/continue/${record.id}`);
        if (code === 200) {
            notify(msg);
        } else {
            notify(msg);
        }
        refresh();
    }
    return (
      <ConfirmButton label={"toolbar.continue"}  startIcon={<CachedIcon />} onConfirm={continueReceipt} />
        record.type == 'in' ? <ConfirmButton label={"toolbar.continue"} startIcon={<CachedIcon />} onConfirm={continueReceipt} /> : <></>
    )
  }
}
rsf-admin/src/page/locPreview/LocListAside.jsx
rsf-admin/src/page/locPreview/LocPreviewEdit.jsx
File was renamed from rsf-admin/src/page/locItem/LocItemEdit.jsx
@@ -22,28 +22,20 @@
    DeleteButton,
    useNotify,
} 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 request from '@/utils/request';
import DictionarySelect from "../components/DictionarySelect";
import LocQueryList from "./LocQueryList";
import CustomerTopToolBar from "../components/EditTopToolBar";
import { Stack, Grid, Box, Typography } from '@mui/material';
import { useWatch, useFormContext } from "react-hook-form";
import EditBaseAside from "../components/EditBaseAside";
import MemoInput from "../components/MemoInput";
import LocPreviewItems from "./LocPreviewItems";
import * as Common from '@/utils/common';
import request from '@/utils/request';
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'end' }}>
        </Toolbar>
    )
}
const LocItemEdit = () => {
const LocPreviewEdit = () => {
    const translate = useTranslate();
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_type')) || [];
    const [warehouseId, setWrehouseId] = useState();
@@ -55,7 +47,6 @@
    return (
        <>
            <Edit
                redirect="list"
                mutationMode={EDIT_MODE}
                actions={<CustomerTopToolBar />}
                aside={<EditBaseAside />}
@@ -66,26 +57,23 @@
                    warnWhenUnsavedChanges
                    toolbar={false}
                    mode="onTouched"
                    defaultValues={{}}
                    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',
                        }
                    }}
                // validate={(values) => { }}
                >
                    <Grid container width={{ xs: '100%', xl: '90%' }} 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={12} md={10}>
                    <Grid container width={{ xs: '100%', xl: '90%' }} rowSpacing={3} columnSpacing={3}>
                        <Grid item xs={12} md={12}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.main')}
                            </Typography>
@@ -98,10 +86,10 @@
                                        <AutocompleteInput
                                            label="table.field.loc.warehouseId"
                                            optionText="name"
                                            readOnly
                                            validate={[required()]}
                                            onChange={warehouseChange}
                                            filterToQuery={(val) => ({ name: val })}
                                            readOnly
                                        />
                                    </ReferenceInput>
                                    <ReferenceInput
@@ -112,94 +100,82 @@
                                        <AutocompleteInput
                                            label="table.field.loc.areaId"
                                            optionText="name"
                                            readOnly
                                            validate={[required()]}
                                            filterToQuery={(val) => ({ name: val })}
                                            readOnly
                                        />
                                    </ReferenceInput>
                                    <TextInput
                                        label="table.field.loc.code"
                                        source="code"
                                        parse={v => v}
                                        readOnly
                                        validate={required()}
                                        readOnly
                                    />
                                    <NumberInput
                                        label="table.field.loc.length"
                                        source="length"
                                        readOnly
                                        validate={required()}
                                    />
                                    <NumberInput
                                        label="table.field.loc.width"
                                        source="width"
                                        readOnly
                                        validate={required()}
                                    />
                                    <NumberInput
                                        label="table.field.loc.height"
                                        source="height"
                                        readOnly
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item display="flex" gap={1}>
                                    <ReferenceArrayInput source="typeIds" reference="locType" >
                                        <SelectArrayInput label="table.field.loc.type" readOnly validate={[required()]} />
                                        <SelectArrayInput label="table.field.loc.type"  readOnly/>
                                    </ReferenceArrayInput>
                                    <TextInput
                                        label="table.field.loc.unit"
                                        source="unit"
                                        readOnly
                                        parse={v => v}
                                        readOnly
                                    />
                                    <DictionarySelect
                                        label={translate("table.field.loc.useStatus")}
                                        name="useStatus"
                                        validate={[required()]}
                                        readOnly
                                        size="small"
                                        dictTypeCode="sys_loc_use_stas"
                                        readOnly
                                    />
                                    <NumberInput
                                        label="table.field.loc.row"
                                        source="row"
                                        readOnly
                                        validate={required()}
                                        readOnly
                                    />
                                    <NumberInput
                                        label="table.field.loc.col"
                                        source="col"
                                        readOnly
                                        validate={required()}
                                        readOnly
                                    />
                                    <NumberInput
                                        label="table.field.loc.lev"
                                        source="lev"
                                        readOnly
                                        validate={required()}
                                        readOnly
                                    />
                                </Grid>
                            </Grid>
                        </Grid>
                        {/* <Grid item xs={12} md={2}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.common')}
                            </Typography>
                            <StatusSelectInput readOnly />
                            <Box mt="2em" />
                            <MemoInput />
                        </Grid> */}
                    </Grid>
                </SimpleForm>
            </Edit >
            <LocQueryList />
            <LocPreviewItems />
        </>
    )
}
export default LocItemEdit;
export default LocPreviewEdit;
rsf-admin/src/page/locPreview/LocPreviewItems.jsx
File was renamed from rsf-admin/src/page/locItem/LocQueryList.jsx
@@ -1,5 +1,4 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
@@ -34,10 +33,11 @@
    DeleteButton,
    useGetRecordId,
} from 'react-admin';
import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material';
import { styled } from '@mui/material/styles';
import PageDrawer from "../components/PageDrawer";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material';
import PageDrawer from "../components/PageDrawer";
import { useNavigate } from 'react-router-dom';
import { styled } from '@mui/material/styles';
import request from '@/utils/request';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
@@ -53,10 +53,10 @@
        width: 100
    },
    '& .MuiTableCell-root': {
    whiteSpace: 'nowrap',
    overflow: 'visible',
    textOverflow: 'unset'
  }
        whiteSpace: 'nowrap',
        overflow: 'visible',
        textOverflow: 'unset'
    }
}));
const filters = [
@@ -94,12 +94,13 @@
    />,
]
const LocItemList = () => {
    const translate = useTranslate();
const LocPreviewItems = () => {
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const translate = useTranslate();
    const locId = useGetRecordId();
    console.log(locId);
    return (
        <Box display="flex">
            <List
@@ -111,15 +112,16 @@
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.locItem"}
                title={"menu.locPreview"}
                empty={false}
                filter={{locId: locId}}
                resource="locItem"
                filter={{ locId: locId }}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <SelectColumnsButton preferenceKey='locItem' />
                        <SelectColumnsButton preferenceKey='locPreview' />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
@@ -136,15 +138,16 @@
    )
}
export default LocItemList;
export default LocPreviewItems;
const DynamicFields = (props) => {
    const translate = useTranslate();
    const notify = useNotify();
    const [columns, setColumns] = useState([]);
    const { isLoading } = useListContext();
    const translate = useTranslate();
    const refresh = useRefresh();
    const notify = useNotify();
    useEffect(() => {
        getDynamicFields();
    }, []);
@@ -205,12 +208,12 @@
            )}
            {columns.length > 0 &&
                <StyledDatagrid
                    preferenceKey='locItem'
                    preferenceKey='locPreview'
                    bulkActionButtons={false}
                    rowClick={false}
                    expand={false}
                    expandSingle={true}
                    omit={['id', 'createTime','spec', 'model', 'locId', 'orderId', 'trackCode', 'orderItemId', 'matnrId', 'splrBatch','createBy$', 'memo', 'fieldsIndex','statusBool']}
                    omit={['id', 'createTime', 'spec', 'model', 'locId', 'orderId', 'trackCode', 'orderItemId', 'matnrId', 'splrBatch', 'createBy$', 'memo', 'fieldsIndex', 'statusBool']}
                >
                    {columns.map((column) => column)}
                </StyledDatagrid>}
rsf-admin/src/page/locPreview/LocPreviewList.jsx
File was renamed from rsf-admin/src/page/locItem/LocItemList.jsx
@@ -35,11 +35,11 @@
    Button,
    useList,
} from 'react-admin';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { styled } from '@mui/material/styles';
import LocListAside from "./LocListAside";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
@@ -62,24 +62,21 @@
        width: 'auto',
    },
    '& .MuiTableCell-root': {
    whiteSpace: 'nowrap',
    overflow: 'visible',
    textOverflow: 'unset'
  }
        whiteSpace: 'nowrap',
        overflow: 'visible',
        textOverflow: 'unset'
    }
}));
const LocItemList = () => {
    const translate = useTranslate();
    const notify = useNotify();
    const refresh = useRefresh();
const LocPreviewList = () => {
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_use_stas')) || [];
    const locType = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_type')) || [];
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const [initDialog, setInitDialog] = useState(false);
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_use_stas')) || [];
    const locType = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_loc_type')) || [];
    const translate = useTranslate();
    const refresh = useRefresh();
    const notify = useNotify();
    const filters = [
        <SearchInput source="condition" alwaysOn />,
@@ -112,7 +109,7 @@
            source="useStatus"
            optionValue="value"
            parse={v => v}
            alwaysOn
        />,
        <TextInput source="code" label="table.field.loc.code" />,
        <AutocompleteInput
@@ -122,10 +119,11 @@
            source="type"
            optionValue="value"
            parse={v => v}
        />, <TextInput source="name" label="table.field.loc.name" />,
        />,
        <TextInput source="name" label="table.field.loc.name" />,
        <NumberInput source="flagLogic" label="table.field.loc.flagLogic" />,
        <TextInput source="fucAtrrs" label="table.field.loc.fucAtrrs" />,
        <TextInput source="barcode" label="table.field.loc.barcode" />,
        <TextInput source="barcode" label="table.field.loc.barcode" alwaysOn/>,
        <TextInput source="unit" label="table.field.loc.unit" />,
        <TextInput source="size" label="table.field.loc.size" />,
        <NumberInput source="row" label="table.field.loc.row" />,
@@ -148,8 +146,6 @@
        />,
    ]
    return (
        <Box display="flex">
            <List
@@ -161,28 +157,27 @@
                        }),
                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                storeKey="locItem"
                resource="loc"
                title={"menu.locItem"}
                storeKey="locPreview"
                resource="locPreview"
                title={"menu.locPreview"}
                empty={false}
                filters={filters}
                filter={{ useStatus: 'F' }}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        {/* <SelectColumnsButton preferenceKey='loc' /> */}
                        <SelectColumnsButton preferenceKey='locPreview' />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
                aside={<LocListAside />}
            >
                <StyledDatagrid
                    preferenceKey='locItem'
                    preferenceKey='locPreview'
                    align="left"
                    bulkActionButtons={false}
                    rowClick={() => false}
                    omit={['id', 'createTime', 'createBy$', 'memo', 'updateTime', 'updateBy','statusBool','length','width','height']}
                    omit={['id', 'createTime', 'createBy$', 'memo', 'updateTime', 'updateBy', 'statusBool', 'length', 'width', 'height']}
                >
                    <NumberField source="id" />
                    <NumberField source="warehouseId$" label="table.field.loc.warehouseId" />
@@ -205,7 +200,7 @@
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} align="left" />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} resource="locItem" label="toolbar.detail" />
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }}  label="toolbar.detail" />
                    </WrapperField>
                </StyledDatagrid>
            </List>
@@ -213,4 +208,4 @@
    )
}
export default LocItemList;
export default LocPreviewList;
rsf-admin/src/page/locPreview/index.jsx
File was renamed from rsf-admin/src/page/locItem/index.jsx
@@ -5,12 +5,12 @@
    ShowGuesser,
} from "react-admin";
import LocItemList from "./LocItemList";
import LocItemEdit from "./LocItemEdit";
import LocPreviewList from "./LocPreviewList";
import LocPreviewEdit from "./LocPreviewEdit";
export default {
    list: LocItemList,
    edit: LocItemEdit,
    list: LocPreviewList,
    edit: LocPreviewEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx
@@ -47,7 +47,7 @@
                <SimpleForm
                    shouldUnregister
                    warnWhenUnsavedChanges
                    toolbar={<FormToolbar />}
                    toolbar={false}
                    mode="onTouched"
                    defaultValues={{}}
                >
rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
@@ -1,5 +1,3 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useLocation, useNavigate } from 'react-router-dom';
import {
  List,
  DatagridConfigurable,
@@ -8,9 +6,6 @@
  SelectColumnsButton,
  EditButton,
  FilterButton,
  CreateButton,
  ExportButton,
  BulkDeleteButton,
  useDataProvider,
  WrapperField,
  useRecordContext,
@@ -18,7 +13,6 @@
  useNotify,
  useRefresh,
  useListContext,
  FunctionField,
  TextField,
  NumberField,
  DateField,
@@ -37,29 +31,31 @@
  useRedirect,
  useUnselectAll,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import AsnOrderModal from "./AsnOrderModal";
import AsnOrderPanel from "./AsnOrderPanel";
import EmptyData from "../../components/EmptyData";
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import BillStatusField from '../../components/BillStatusField';
import ConfirmButton from '../../components/ConfirmButton';
import PageDrawer from "../../components/PageDrawer";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import ConstructionIcon from "@mui/icons-material/Construction";
import EditIcon from '@mui/icons-material/Edit';
import TaskIcon from '@mui/icons-material/Task';
import CloseIcon from '@mui/icons-material/Close';
import request from '@/utils/request';
import CreateNewFolderOutlinedIcon from '@mui/icons-material/CreateNewFolderOutlined';
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined';
import DictionarySelect from "../../components/DictionarySelect";
import ConstructionIcon from "@mui/icons-material/Construction";
import BillStatusField from '../../components/BillStatusField';
import MyExportButton from '../../components/MyExportButton';
import { Box, Typography, Card, Stack } from '@mui/material';
import MyCreateButton from "../../components/MyCreateButton";
import { useLocation, useNavigate } from 'react-router-dom';
import ConfirmButton from '../../components/ConfirmButton';
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
import ImportButton from "../../components/ImportButton";
import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined';
import OrderPrintPreview from "./OrderPrintPreview";
import CreateNewFolderOutlinedIcon from '@mui/icons-material/CreateNewFolderOutlined';
import AsnCreateByPoModal from "./AsnCreateByPoModal";
import PageDrawer from "../../components/PageDrawer";
import OrderPrintPreview from "./OrderPrintPreview";
import CloseIcon from '@mui/icons-material/Close';
import EditIcon from '@mui/icons-material/Edit';
import TaskIcon from '@mui/icons-material/Task';
import { styled } from '@mui/material/styles';
import AsnOrderModal from "./AsnOrderModal";
import request from '@/utils/request';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
  '& .css-1vooibu-MuiSvgIcon-root': {
    height: '.9em'
@@ -69,7 +65,7 @@
  },
  '& .column-name': {
  },
  '& .wkType': {
    width: 110
  },
@@ -83,7 +79,6 @@
  },
  '& .opt': {
    width: 220,
  },
}));
@@ -93,28 +88,21 @@
  <TextInput source="poCode" label="table.field.asnOrder.poCode" />,
  <NumberInput source="poId" label="table.field.asnOrder.poId" />,
  <TextInput source="type" label="table.field.asnOrder.type" />,
  <ReferenceInput source="wkType" reference="dictData" filter={{ dictTypeCode: 'sys_business_type' }} label="table.field.asnOrder.wkType">
  <ReferenceInput source="wkType" reference="dictData" filter={{ dictTypeCode: 'sys_business_type', group: "1" }} label="table.field.asnOrder.wkType" alwaysOn>
    <AutocompleteInput label="table.field.asnOrder.wkType" optionValue="value" />
  </ReferenceInput>,
  <NumberInput source="anfme" label="table.field.asnOrder.anfme" />,
  <NumberInput source="qty" label="table.field.asnOrder.qty" />,
  <TextInput source="logisNo" label="table.field.asnOrder.logisNo" />,
  <DateInput source="arrTime" label="table.field.asnOrder.arrTime" />,
  <SelectInput source="rleStatus" label="table.field.asnOrder.rleStatus"
    choices={[
      { id: 0, name: ' 正常' },
      { id: 1, name: ' 已释放' },
    ]}
  />,
  <TextInput label="common.field.memo" source="memo" />,
  <DictionarySelect
    label='table.field.asnOrder.exceStatus'
    name="exceStatus"
    group="1"
    dictTypeCode="sys_asn_exce_status"
    alwaysOn
  />,
]
const AsnOrderList = (props) => {
@@ -170,7 +158,7 @@
            </>}
          rowClick={false}
          expandSingle={true}
          omit={['id', 'createTime', 'createBy', 'memo', 'logisNo', 'poId', 'rleStatus$','createBy$']}
          omit={['id', 'createTime', 'createBy', 'memo', 'logisNo', 'poId', 'rleStatus$', 'createBy$']}
        >
          <NumberField source="id" />
          <TextField source="code" label="table.field.asnOrder.code" />
@@ -351,15 +339,16 @@
const BtnBulkExport = () => {
  const { filter, selectedIds, filterValues, resource, sort, total } = useListContext();
  const refresh = useRefresh();
  const dataProvider = useDataProvider();
  const notify = useNotify();
  const unSelect = useUnselectAll(resource);
  const dataProvider = useDataProvider();
  const refresh = useRefresh();
  const notify = useNotify();
  const bulkExport = () => {
    getExport()
    unSelect();
  }
  const getExport = () => {
    dataProvider
      .export(resource, {
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
@@ -44,24 +44,24 @@
    MenuItem
} from '@mui/material';
import { DataGrid, useGridApiRef, GRID_DATE_COL_DEF,  GRID_DATETIME_COL_DEF,  getGridDateOperators, useGridApiContext } from '@mui/x-data-grid';
import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
import { LocalizationProvider, DatePicker, DateTimePicker } from '@mui/x-date-pickers';
import DialogCloseButton from "../../components/DialogCloseButton";
import StatusSelectInput from "../../components/StatusSelectInput";
import ConfirmButton from "../../components/ConfirmButton";
import AsnWareModal from "./AsnWareModal";
import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
import { Add, Edit, Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import { DataGrid, useGridApiRef, GRID_DATE_COL_DEF,  GRID_DATETIME_COL_DEF,  getGridDateOperators, useGridApiContext } from '@mui/x-data-grid';
import { LocalizationProvider, DatePicker, DateTimePicker } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import DictionarySelect from "../../components/DictionarySelect";
import DictSelect from "../../components/DictSelect";
import "./asnOrder.css";
import { 'zhCN' as locale } from 'date-fns/locale';
import { format, } from 'date-fns';
import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
import DictionarySelect from "../../components/DictionarySelect";
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import ConfirmButton from "../../components/ConfirmButton";
import { Add, Edit, Delete } from '@mui/icons-material';
import DictSelect from "../../components/DictSelect";
import SaveIcon from '@mui/icons-material/Save';
import AsnWareModal from "./AsnWareModal";
import request from '@/utils/request';
import _, { set } from 'lodash';
import "./asnOrder.css";
const AsnOrderModal = (props) => {
    const { open, setOpen, asnId, billReload } = props;
rsf-admin/src/page/orders/asnOrder/AsnWareModal.jsx
@@ -12,6 +12,7 @@
    Paper,
    styled
} from '@mui/material';
import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import DialogCloseButton from "../../components/DialogCloseButton";
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import request from '@/utils/request';
@@ -28,7 +29,9 @@
            setOpen(false);
        }
    };
    const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE });
    const [rowCount, setRowCount] = useState(0);
    const [isLoading, setIsLoading] = useState(false);
    const [formData, setFormData] = useState({});
    const [tableData, setTableData] = useState([]);
    const [dyFields, setDyFields] = useState([]);
@@ -73,22 +76,26 @@
    };
    const getData = async () => {
        setIsLoading(true)
        const res = await request.post(`/matnr/page`, {
            ...formData,
            current: 1,
            pageSize: 100,
            current: page?.page,
            pageSize: page?.pageSize,
            orderBy: "create_time desc"
        });
        if (res?.data?.code === 200) {
            setTableData(res.data.data.records);
            console.log(res.data);
            setRowCount(res.data?.data.total)
        } else {
            notify(res.data.msg);
        }
        setIsLoading(false)
    };
    useEffect(() => {
        getData();
    }, [open]);
    }, [open, page]);
    const handleSearch = () => {
        getData()
@@ -156,6 +163,10 @@
                    <AsnWareModalTable
                        tableData={tableData}
                        setTableData={setTableData}
                        page={page}
                        rowCount={rowCount}
                        setPage={setPage}
                        isLoading={isLoading}
                        dyFields={dyFields}
                        setDyFields={setDyFields}
                        selectedRows={selectedRows}
@@ -175,7 +186,7 @@
};
export default AsnWareModal;
const AsnWareModalTable = ({ tableData, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
const AsnWareModalTable = ({ tableData, isLoading, page, setPage, rowCount, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
    const translate = useTranslate();
    const notify = useNotify();
    const [columns, setColumns] = useState([
@@ -236,6 +247,17 @@
                disableColumnMenu={true}
                disableColumnSorting
                disableMultipleColumnsSorting
                rowCount={rowCount}
                paginationMode="server"
                paginationModel={page}
                onPaginationModelChange={setPage}
                loading={isLoading}
                slotProps={{
                    loadingOverlay: {
                        variant: 'linear-progress',
                        noRowsVariant: 'linear-progress',
                    },
                }}
            />
        </div>
    );
rsf-admin/src/page/orders/check/MatnrInfoModal.jsx
@@ -12,6 +12,7 @@
    Paper,
    styled
} from '@mui/material';
import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import DialogCloseButton from "../../components/DialogCloseButton";
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import request from '@/utils/request';
@@ -35,7 +36,9 @@
    const [tableData, setTableData] = useState([]);
    const [dyFields, setDyFields] = useState([]);
    const [selectedRows, setSelectedRows] = useState([]);
    const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE });
    const [rowCount, setRowCount] = useState(0);
    const [isLoading, setIsLoading] = useState(false);
    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData(() => ({
@@ -74,22 +77,26 @@
    };
    const getData = async () => {
        setIsLoading(true)
        const res = await request.post(`/matnr/page`, {
            ...formData,
            current: 1,
            pageSize: 100,
            current: page?.page,
            pageSize: page?.pageSize,
            orderBy: "create_time desc"
        });
        if (res?.data?.code === 200) {
            setTableData(res.data.data.records);
            setRowCount(res.data?.data?.total);
        } else {
            notify(res.data.msg);
        }
        setIsLoading(false)
    };
    useEffect(() => {
        getData();
    }, [open]);
    }, [open, page]);
    const handleSearch = () => {
        getData()
@@ -159,6 +166,10 @@
                        setTableData={setTableData}
                        dyFields={dyFields}
                        setDyFields={setDyFields}
                        page={page}
                        rowCount={rowCount}
                        setPage={setPage}
                        isLoading={isLoading}
                        selectedRows={selectedRows}
                        setSelectedRows={setSelectedRows}
                    />
@@ -177,7 +188,7 @@
export default MatnrInfoModal;
const AsnWareModalTable = ({ tableData, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
const AsnWareModalTable = ({ tableData, page, isLoading, pageSize, setPage, rowCount, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
    const translate = useTranslate();
    const notify = useNotify();
@@ -241,7 +252,17 @@
                disableColumnMenu={true}
                disableColumnSorting
                disableMultipleColumnsSorting
            />
                rowCount={rowCount}
                paginationMode="server"
                paginationModel={page}
                onPaginationModelChange={setPage}
                loading={isLoading}
                slotProps={{
                    loadingOverlay: {
                        variant: 'linear-progress',
                        noRowsVariant: 'linear-progress',
                    },
                }} />
        </div>
    );
};
rsf-admin/src/page/orders/delivery/DeliveryEdit.jsx
@@ -57,8 +57,22 @@
                <SimpleForm
                    shouldUnregister
                    warnWhenUnsavedChanges
                    toolbar={<FormToolbar />}
                    toolbar={false}
                    mode="onTouched"
                    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',
                        }
                    }}
                    defaultValues={{}}
                >
                    <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}>
@@ -71,7 +85,8 @@
                                    label="table.field.delivery.code"
                                    source="code"
                                    parse={v => v}
                                    autoFocus
                                    readOnly
                                />
                                <AutocompleteInput
                                    choices={dicts}
@@ -89,12 +104,15 @@
                                    source="wkType"
                                    optionValue="value"
                                    parse={v => v}
                                    readOnly
                                />
                                <TextInput
                                    label="table.field.delivery.source"
                                    source="source"
                                    parse={v => v}
                                    validate={required()}
                                    readOnly
                                />
                            </Stack>
                            <Stack direction='row' gap={2}>
@@ -102,45 +120,44 @@
                                    label="table.field.delivery.anfme"
                                    source="anfme"
                                    validate={required()}
                                    readOnly
                                />
                                <NumberInput
                                    label="table.field.delivery.qty"
                                    source="qty"
                                    readOnly
                                />
                                <NumberInput
                                    label="table.field.delivery.workQty"
                                    source="workQty"
                                    readOnly
                                />
                                <TextInput
                                    label="table.field.delivery.platId"
                                    source="platId"
                                    parse={v => v}
                                    readOnly
                                />
                                <TextInput
                                    label="table.field.delivery.platCode"
                                    source="platCode"
                                    parse={v => v}
                                    readOnly
                                />
                            </Stack>
                            <Stack direction='row' gap={2}>
                                <DateInput
                                    label="table.field.delivery.startTime"
                                    source="startTime"
                                    readOnly
                                />
                                <DateInput
                                    label="table.field.delivery.endTime"
                                    source="endTime"
                                    readOnly
                                />
                            </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 >
rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx
@@ -13,6 +13,7 @@
    styled
} from '@mui/material';
import DialogCloseButton from "../../components/DialogCloseButton";
import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import request from '@/utils/request';
import { DataGrid } from '@mui/x-data-grid';
@@ -35,7 +36,9 @@
    const [tableData, setTableData] = useState([]);
    const [dyFields, setDyFields] = useState([]);
    const [selectedRows, setSelectedRows] = useState([]);
    const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE });
    const [rowCount, setRowCount] = useState(0);
    const [isLoading, setIsLoading] = useState(false);
    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData(() => ({
@@ -74,22 +77,27 @@
    };
    const getData = async () => {
        setIsLoading(true)
        const res = await request.post(`/matnr/page`, {
            ...formData,
            current: 1,
            pageSize: 100,
            current: page?.page,
            pageSize: page?.pageSize,
            orderBy: "create_time desc"
        });
        if (res?.data?.code === 200) {
            setTableData(res.data.data.records);
            setRowCount(res.data?.data?.total);
        } else {
            notify(res.data.msg);
        }
        setIsLoading(false)
    };
    useEffect(() => {
        getData();
    }, [open]);
    }, [open, page]);
    const handleSearch = () => {
        getData()
@@ -158,6 +166,10 @@
                        tableData={tableData}
                        setTableData={setTableData}
                        dyFields={dyFields}
                        page={page}
                        rowCount={rowCount}
                        setPage={setPage}
                        isLoading={isLoading}
                        setDyFields={setDyFields}
                        selectedRows={selectedRows}
                        setSelectedRows={setSelectedRows}
@@ -177,7 +189,7 @@
export default MatnrInfoModal;
const AsnWareModalTable = ({ tableData, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
const AsnWareModalTable = ({ tableData, setTableData, page, isLoading, pageSize, setPage, rowCount, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
    const translate = useTranslate();
    const notify = useNotify();
@@ -200,7 +212,6 @@
    const handleSelectionChange = (ids) => {
        setSelectedRows(ids)
    };
    useEffect(() => {
@@ -241,6 +252,17 @@
                disableColumnMenu={true}
                disableColumnSorting
                disableMultipleColumnsSorting
                rowCount={rowCount}
                paginationMode="server"
                paginationModel={page}
                onPaginationModelChange={setPage}
                loading={isLoading}
                slotProps={{
                    loadingOverlay: {
                        variant: 'linear-progress',
                        noRowsVariant: 'linear-progress',
                    },
                }}
            />
        </div>
    );
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
@@ -92,9 +92,7 @@
    const ComfirmButton = () => {
        const { data } = useListContext();
        const [selectedIds, selectionModifiers] = useRecordSelection();
        const { selectedIds, data } = useListContext();
        const handleRowClick = () => {
            console.log(selectedIds);
            
rsf-admin/src/page/orders/purchase/PurchaseEdit.jsx
@@ -55,9 +55,23 @@
                <SimpleForm
                    shouldUnregister
                    warnWhenUnsavedChanges
                    toolbar={<FormToolbar />}
                    toolbar={false}
                    mode="onTouched"
                    defaultValues={{}}
                    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',
                        }
                    }}
                // validate={(values) => { }}
                >
                    <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}>
@@ -81,6 +95,7 @@
                                    source="type"
                                    optionValue="value"
                                    parse={v => v}
                                    readOnly
                                />
                                <AutocompleteInput
                                    choices={business}
@@ -89,16 +104,19 @@
                                    source="wkType"
                                    optionValue="value"
                                    parse={v => v}
                                    readOnly
                                />
                                <TextInput
                                    label="table.field.purchase.source"
                                    source="source"
                                    parse={v => v}
                                    readOnly
                                    validate={required()}
                                />
                                <NumberInput
                                    label="table.field.purchase.anfme"
                                    source="anfme"
                                    readOnly
                                    validate={required()}
                                />
                            </Stack>
@@ -106,25 +124,30 @@
                                <TextInput
                                    label="table.field.purchase.project"
                                    source="project"
                                    readOnly
                                    parse={v => v}
                                />
                                <TextInput
                                    label="table.field.purchase.channel"
                                    source="channel"
                                    parse={v => v}
                                    readOnly
                                />
                                <TextInput
                                    label="table.field.purchase.platCode"
                                    source="platCode"
                                    parse={v => v}
                                    readOnly
                                />
                                <DateInput
                                    label="table.field.purchase.startTime"
                                    source="startTime"
                                    readOnly
                                />
                                <DateInput
                                    label="table.field.purchase.endTime"
                                    source="endTime"
                                    readOnly
                                />
                            </Stack>
                        </Grid>
rsf-admin/src/page/orders/purchase/PurchaseItemList.jsx
@@ -108,7 +108,7 @@
          actions={(
            <TopToolbar>
              <FilterButton />
              <MyCreateButton onClick={() => { setCreateDialog(true) }} />
              {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */}
              <SelectColumnsButton preferenceKey='purchaseItem' />
              {/* <MyExportButton /> */}
            </TopToolbar>
rsf-admin/src/page/orders/stock/OrderEdit.jsx
@@ -17,25 +17,16 @@
    required,
    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 CustomerTopToolBar from "../../components/EditTopToolBar";
import { Stack, Grid, Box, Typography } from '@mui/material';
import { useWatch, useFormContext } from "react-hook-form";
import EditBaseAside from "../../components/EditBaseAside";
import MemoInput from "../../components/MemoInput";
import OrderItemList from "./OrderItemList";
const FormToolbar = () => {
    const { getValues } = useFormContext();
import * as Common from '@/utils/common';
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const OrderEdit = () => {
    const translate = useTranslate();
@@ -53,12 +44,27 @@
                <SimpleForm
                    shouldUnregister
                    warnWhenUnsavedChanges
                    toolbar={<FormToolbar />}
                    toolbar={false}
                    mode="onTouched"
                    defaultValues={{}}
                    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 container width={{ xs: '100%', xl: '90%' }} rowSpacing={3} columnSpacing={3}>
                        <Grid item xs={16} md={10}>
                        <Grid item xs={24} md={12}>
                            <Typography variant="h6" gutterBottom>
                                {translate('common.edit.title.main')}
                            </Typography>
@@ -69,7 +75,6 @@
                                    parse={v => v}
                                    autoFocus
                                />
                                <TextInput
                                    label="table.field.stock.sourceCode"
                                    source="sourceCode"
@@ -103,14 +108,6 @@
                                    validate={required()}
                                />
                            </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>
rsf-admin/src/page/orders/stock/OrderList.jsx
@@ -32,17 +32,19 @@
    AutocompleteInput,
    DeleteButton,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import OrderCreate from "./OrderCreate";
import OrderPanel from "./OrderPanel";
import EmptyData from "../../components/EmptyData";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import { Box, Typography, Card, Stack } from '@mui/material';
import PageDrawer from "../../components/PageDrawer";
import EmptyData from "../../components/EmptyData";
import MyField from "../../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { styled } from '@mui/material/styles';
import * as Common from '@/utils/common';
import OrderCreate from "./OrderCreate";
import OrderPanel from "./OrderPanel";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -62,14 +64,12 @@
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
    <TextInput source="code" label="table.field.stock.code" />,
    <TextInput source="sourceCode" label="table.field.stock.sourceCode" />,
    <NumberInput source="sourceId" label="table.field.stock.sourceId" />,
    <TextInput source="type" label="table.field.stock.type" />,
    <TextInput source="wkType" label="table.field.stock.wkType" />,
    <NumberInput source="anfme" label="table.field.stock.anfme" />,
    <TextInput label="common.field.memo" source="memo" />,
    <SelectInput
        label="common.field.status"
@@ -83,9 +83,9 @@
]
const OrderList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const translate = useTranslate();
    return (
        <Box display="flex">
@@ -116,7 +116,7 @@
                    bulkActionButtons={false}
                    rowClick='edit'
                    expandSingle={false}
                    omit={['id', 'createTime', 'sourceId', 'createBy$', 'memo','statusBool','opt']}
                    omit={['id', 'sourceId', 'memo','statusBool','opt']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.stock.code" />
@@ -131,12 +131,7 @@
                    <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>
            <OrderCreate
rsf-admin/src/page/orders/transfer/CreateBySelectMats.jsx
New file
@@ -0,0 +1,281 @@
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,
    useNotify,
    useRefresh,
    required,
    useRecordContext,
    DeleteButton,
} from 'react-admin';
import { Stack, Grid, Box, Typography, Dialog, DialogTitle, DialogContent, TextField, Button, DialogActions } from '@mui/material';
import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import DialogCloseButton from "../../components/DialogCloseButton.jsx";
import StatusSelectInput from "../../components/StatusSelectInput";
import CustomerTopToolBar from "../../components/EditTopToolBar";
import TreeSelectInput from "@/page/components/TreeSelectInput";
import EditBaseAside from "../../components/EditBaseAside";
import MemoInput from "../../components/MemoInput";
import SaveIcon from '@mui/icons-material/Save';
import { DataGrid } from '@mui/x-data-grid';
import * as Common from '@/utils/common';
import request from '@/utils/request';
const CreateBySelectMats = (props) => {
    const { open, setOpen, data, setData, queryForm } = props;
    const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE });
    const [rowCount, setRowCount] = useState(0);
    const [isLoading, setIsLoading] = useState(false);
    const [formData, setFormData] = useState({});
    const [tableData, setTableData] = useState([]);
    const [dyFields, setDyFields] = useState([]);
    const [pageSize, setPageSize] = useState(25);
    const [selectedRows, setSelectedRows] = useState([]);
    const translate = useTranslate();
    const notify = useNotify();
    const refresh = useRefresh();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData(() => ({
            [name]: value
        }));
    };
    const reset = () => {
        setFormData({
            maktx: '',
            matnrCode: '',
        })
    }
    const handleSubmit = () => {
        const hasarr = data.map(el => +el.matnrId)
        const selectedData = selectedRows.filter(item => !hasarr.includes(item)).map(id => (tableData.find(row => row.id === id)));
        const value = selectedData.map((el => {
            const dynamicFields = dyFields.reduce((acc, item) => {
                acc[item.fields] = el['extendFields']?.[item.fields] || '';
                return acc;
            }, {});
            return {
                id: el.id,
                matnrId: el.matnrId,
                maktx: el.maktx,
                matnrCode: el.matnrCode,
                anfme: el.anfme,
                batch: el.batch,
                spec: el.spec,
                model: el.model,
                fieldsIndex: el.fieldsIndex,
                stockUnit: el.unit || '',
                ...dynamicFields
            }
        }));
        setData([...data, ...value]);
        setOpen(false);
        reset();
    };
    const getData = async () => {
        let params = {
            ...formData,
            orgAreaId: queryForm?.orgAreaId,
            current: page?.page,
            pageSize: page?.pageSize,
            orderBy: "create_time desc"
        };
        setIsLoading(true)
        const res = await request.post(`/transfer/locs/items`, params);
        if (res?.data?.code === 200) {
            const { data } = res.data;
            setTableData(data?.records);
            setRowCount(data?.total);
        } else {
            notify(res.data.msg);
        }
        setIsLoading(false)
    };
    useEffect(() => {
        getData();
    }, [open, page]);
    const handleSearch = () => {
        getData()
    };
    return (
        <Dialog
            open={open}
            onClose={handleClose}
            aria-labelledby="form-dialog-title"
            fullWidth
            disableRestoreFocus
            maxWidth="xl"
        >
            <DialogTitle id="form-dialog-title" sx={{
                position: 'sticky',
                top: 0,
                backgroundColor: 'background.paper',
                zIndex: 1000
            }}>
                {translate("common.action.newAddMats")}
                <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                    <DialogCloseButton onClose={handleClose} />
                </Box>
            </DialogTitle>
            <DialogContent sx={{ mt: 2 }}>
                <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                    <Grid container spacing={2}>
                        <Grid item md={3}>
                            <TextField
                                label={translate('table.field.matnr.name')}
                                name="maktx"
                                value={formData.maktx}
                                onChange={handleChange}
                                size="small"
                            />
                        </Grid>
                        <Grid item md={3}>
                            <TextField
                                label={translate('table.field.matnr.code')}
                                name="matnrCode"
                                value={formData.matnrCode}
                                onChange={handleChange}
                                size="small"
                            />
                        </Grid>
                        <Grid item md={2} sx={{ margin: 'auto' }}>
                            <Button variant="contained" onClick={handleSearch}>{translate('toolbar.query')}</Button>
                        </Grid>
                    </Grid>
                </Box>
                <Box sx={{ mt: 2, height: 600, width: '100%' }}>
                    <SelectMatsTableView
                        tableData={tableData}
                        setTableData={setTableData}
                        page={page}
                        rowCount={rowCount}
                        pageSize={pageSize}
                        setPage={setPage}
                        isLoading={isLoading}
                        setPageSize={setPageSize}
                        dyFields={dyFields}
                        setDyFields={setDyFields}
                        selectedRows={selectedRows}
                        setSelectedRows={setSelectedRows}
                    />
                </Box>
            </DialogContent>
            <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                <Box sx={{ width: '100%', display: 'flex', justifyContent: 'flex-end' }}>
                    <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
                        {translate('toolbar.confirm')}
                    </Button>
                </Box>
            </DialogActions>
        </Dialog>
    );
}
export default CreateBySelectMats;
const SelectMatsTableView = ({ tableData, page, isLoading, pageSize, setPage, setPageSize, rowCount, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
    const translate = useTranslate();
    const notify = useNotify();
    const [extendColumns, setExtendColumns] = useState([]);
    const [columns, setColumns] = useState([
        { field: 'maktx', headerName: translate('table.field.matnr.name'), width: 300 },
        { field: 'matnrCode', headerName: translate('table.field.matnr.code'), width: 200 },
        { field: 'locCode', headerName: translate('table.field.locItem.locCode'), width: 100 },
        { field: 'spec', headerName: translate('table.field.matnr.spec'), width: 100 },
        { field: 'batch', headerName: translate('table.field.locItem.batch'), width: 100 },
        { field: 'model', headerName: translate('table.field.matnr.model'), width: 100 },
        { field: 'anfme', headerName: translate('table.field.locItem.anfme'), width: 100 },
        { field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 },
        { field: 'wareArea', headerName: translate('table.field.locItem.wareArea'), width: 100, sortable: false },
    ])
    const handleSelectionChange = (ids) => {
        setSelectedRows(ids)
    };
    useEffect(() => {
        if (extendColumns == undefined || extendColumns.length < 1) {
            getDynamicFields();
        }
    }, []);
    const getDynamicFields = async () => {
        const {
            data: { code, data, msg },
        } = await request.get("/fields/enable/list");
        if (code === 200) {
            const cols = data.map(el => ({
                field: el.fields,
                headerName: el.fieldsAlise,
                minWidth: 100,
                flex: 1,
                editable: el.unique,
                valueGetter: (value, row) => {
                    return row.extendFields?.[el.fields] || '';
                },
            }))
            setExtendColumns(cols);
            setDyFields(data)
            setColumns([...columns, ...cols])
        } else {
            notify(msg);
        }
    }
    return (
        <div style={{ height: 590, width: '100%' }}>
            <DataGrid
                rows={tableData}
                rowCount={rowCount}
                columns={columns}
                paginationMode="server"
                paginationModel={page}
                checkboxSelection
                onPaginationModelChange={setPage}
                onRowSelectionModelChange={handleSelectionChange}
                selectionModel={selectedRows}
                disableColumnMenu={true}
                disableColumnSorting
                disableMultipleColumnsSorting
                loading={isLoading}
                slotProps={{
                    loadingOverlay: {
                        variant: 'linear-progress',
                        noRowsVariant: 'linear-progress',
                    },
                }}
            />
        </div>
    );
};
rsf-admin/src/page/orders/transfer/ManualCreate.jsx
New file
@@ -0,0 +1,507 @@
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,
    SimpleForm,
    useRefresh,
} from 'react-admin';
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    TextField,
    IconButton,
    MenuItem,
    Tooltip,
    Select,
    Button,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import ConfirmationNumberIcon from '@mui/icons-material/ConfirmationNumber';
import DialogCloseButton from "../../components/DialogCloseButton.jsx";
import WarehouseSelect from "../../components/WarehouseSelect.jsx";
import { useFormContext, useWatch } from "react-hook-form";
import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
import ConfirmButton from "../../components/ConfirmButton";
import CreateBySelectMats from "./CreateBySelectMats.jsx";
import { Add, Edit, Delete } from '@mui/icons-material';
import DictSelect from "../../components/DictSelect";
import { minHeight, padding } from "@mui/system";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
import _, { set } from 'lodash';
const ManualCreate = (props) => {
    const { open, setOpen, orderId } = props;
    const tableRef = useRef();
    const notify = useNotify();
    const refresh = useRefresh();
    const translate = useTranslate();
    const [tabelData, setTableData] = useState([]);
    const [disabled, setDisabled] = useState(false);
    const [selectedRows, setSelectedRows] = useState([]);
    const [createDialog, setCreateDialog] = useState(false);
    const [formData, setFormData] = useState({ type: '1', orgAreaId: null, tarAreaId: null });
    const [list, setList] = useState([]);
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const setFinally = () => {
        const rows = tableRef.current.state.editRows;
        for (const key in rows) {
            const find = tabelData.find(item => item.matnrId === +key);
            find.anfme = rows[key].anfme.value;
        }
        setTableData([...tabelData]);
    }
    const handleSubmit = async () => {
        setFinally()
        setDisabled(true)
        if (orderId == null || orderId == undefined) {
            const parmas = {
                "transfer": formData,
                "items": tabelData,
            }
            const res = await request.post(`/transfer/items/save`, parmas);
            if (res?.data?.code === 200) {
                setOpen(false);
            } else {
                notify(res.data.msg);
            }
        } else {
            const parmas = {
                "transfer": formData,
                "items": tabelData,
            }
            const res = await request.post(`/transfer/items/update`, parmas);
            if (res?.data?.code === 200) {
                setOpen(false);
            } else {
                notify(res.data.msg);
            }
        }
        setDisabled(false)
        refresh();
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        notify('common.response.success');
    };
    const handleDeleteItem = () => {
        const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
        setTableData(newTableData);
    }
    const handleError = async (error) => {
        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
    };
    const getWarehouse = async () => {
        const res = await request.post('/warehouseAreas/page');
        if (res?.data?.code === 200) {
            setList(res.data.data.records.map((item) => {
                return {
                    id: item.id,
                    name: item.name
                };
            }));
        } else {
            notify(res.data.msg);
        }
    }
    const newAddClick = () => {
        if (formData.orgAreaId == null || formData.orgAreaId == undefined) {
            notify("原库区不能为空!!", { type: 'error' })
            return
        }
        if (formData.tarAreaId == null || formData.tarAreaId == undefined) {
            notify("目标库区不能为空!!", { type: 'error' })
            return
        }
        console.log(formData);
        setCreateDialog(true)
    }
    const handleChange = (value, name) => {
        setFormData((prevData) => ({
            ...prevData,
            [name]: value
        }));
    };
    return (
        <>
            <Box sx={{ padding: 1 }}>
                <SimpleForm toolbar={false}>
                    <Grid container spacing={2}>
                        <Grid item md={2}>
                            <DictSelect
                                label={translate("table.field.transfer.type")}
                                value={formData.type}
                                variant="filled"
                                onChange={(e) => handleChange(e.target.value, 'type')}
                                dictTypeCode="sys_transfer_type"
                            />
                        </Grid>
                        <Grid item md={2}>
                            <WarehouseSelect
                                value={formData.orgAreaId}
                                variant="filled"
                                dictTypeCode="warehouse"
                                onChange={(e) => handleChange(e.target.value, 'orgAreaId')}
                                label={translate("table.field.transfer.orgAreaName")} />
                        </Grid>
                        <Grid item md={2}>
                            <WarehouseSelect
                                label={translate("table.field.transfer.tarAreaName")}
                                value={formData.tarAreaId}
                                dictTypeCode="warehouse"
                                variant="filled"
                                onChange={(e) => handleChange(e.target.value, 'tarAreaId')}
                            />
                        </Grid>
                    </Grid>
                </SimpleForm>
                <Box sx={{ mt: 2 }}>
                    <Stack direction="row" spacing={2} sx={{ justifyContent: "flex-end" }}>
                        <Button variant="contained" onClick={newAddClick} >
                            {translate('common.action.newAddMats')}
                        </Button>
                        <ConfirmButton label={"toolbar.delete"} variant="outlined" color="error" onConfirm={handleDeleteItem} />
                    </Stack>
                </Box>
                <Box sx={{ mt: 2 }}>
                    <TransferTableView
                        tabelData={tabelData}
                        setTableData={setTableData}
                        orderId={orderId}
                        selectedRows={selectedRows}
                        setSelectedRows={setSelectedRows}
                        tableRef={tableRef}>
                    </TransferTableView>
                </Box>
                <Toolbar sx={{ width: '100%', justifyContent: 'flex-end', bgcolor: 'white' }}  >
                    <Button disabled={disabled} onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
                        {translate('toolbar.confirm')}
                    </Button>
                </Toolbar>
                <CreateBySelectMats
                    data={tabelData}
                    queryForm={formData}
                    open={createDialog}
                    setOpen={setCreateDialog}
                    selectedRows={selectedRows}
                    setSelectedRows={setSelectedRows}
                    setData={setTableData}
                />
            </Box>
        </>
    )
}
const SelectInputSplrNameEditCell = (params) => {
    const [formData, setFormData] = useState([{}])
    useEffect(() => {
        getOptions();
    }, []);
    const getOptions = async () => {
        const parmas = {
            "type": "supplier"
        }
        const {
            data: { code, data, msg },
        } = await request.post("companys/page", parmas);
        if (code === 200) {
            setFormData(data.records)
        } else {
            notify(msg);
        }
    }
    return (
        <Select
            value={params.value}
            onChange={(e) => {
                params.api.setEditCellValue({
                    id: params.id,
                    field: params.field,
                    value: e.target.value,
                })
                // 找到选中的供应商记录
                const selectedSupplier = formData.find(supplier => supplier.name === e.target.value);
                // 如果找到对应的供应商记录,同时更新splrCode字段
                if (selectedSupplier) {
                    params.api.setEditCellValue({
                        id: params.id,
                        field: 'splrCode',
                        value: selectedSupplier.id,
                    });
                }
            }}
            fullWidth
        >
            {formData.map(e => {
                return (
                    <MenuItem value={e.name} children={e.name} key={e.id} />
                );
            })}
        </Select>
    );
};
const SelectInputSplrCodeEditCell = (params) => {
    const [formData, setFormData] = useState([{}])
    useEffect(() => {
        getOptions();
    }, []);
    const getOptions = async () => {
        const parmas = {
            "type": "supplier"
        }
        const {
            data: { code, data, msg },
        } = await request.post("companys/page", parmas);
        if (code === 200) {
            setFormData(data.records)
        } else {
            notify(msg);
        }
    }
    return (
        <Select
            value={params.value}
            onChange={(e) => {
                params.api.setEditCellValue({
                    id: params.id,
                    field: params.field,
                    value: e.target.value,
                })
                const selectedSupplier = formData.find(supplier => supplier.id === e.target.value);
                // 如果找到对应的供应商记录,同时更新splrCode字段
                if (selectedSupplier) {
                    params.api.setEditCellValue({
                        id: params.id,
                        field: 'splrName',
                        value: selectedSupplier.name,
                    });
                }
            }}
            fullWidth
        >
            {formData.map(e => {
                return (
                    <MenuItem value={e.id} children={e.name} key={e.id} />
                );
            })}
        </Select>
    );
};
const TransferTableView = ({ tabelData, setTableData, orderId, selectedRows, setSelectedRows, tableRef }) => {
    const translate = useTranslate();
    const notify = useNotify();
    const [extendColumns, setExtendColumns] = useState([]);
    const [columns, setColumns] = useState([
        {
            field: 'maktx',
            headerName: translate('table.field.outStockItem.maktx'),
            width: 250,
            editable: false,
        },
        {
            field: 'matnrCode',
            headerName: translate('table.field.outStockItem.matnrCode'),
            width: 130,
            editable: false,
        },
        {
            field: 'anfme',
            headerName: translate('table.field.outStockItem.anfme'),
            type: 'number',
            minWidth: 100,
            flex: 1,
            editable: true,
            valueFormatter: (val) => val < 0 ? 0 : val,
        },
        {
            field: 'splrCode',
            headerName: translate('table.field.outStockItem.splrCode'),
            minWidth: 100,
            flex: 1,
            editable: true,
            renderEditCell: (params) => (
                <SelectInputSplrCodeEditCell {...params} />
            ),
        },
        {
            field: 'splrName',
            headerName: translate('table.field.outStockItem.splrName') + "*",
            minWidth: 100,
            flex: 1,
            editable: true,
            renderEditCell: (params) => (
                <SelectInputSplrNameEditCell {...params} />
            ),
        },
        {
            field: 'batch',
            headerName: translate('table.field.outStockItem.splrBatch'),
            minWidth: 100,
            flex: 1,
            editable: true,
        },
        {
            field: 'stockUnit',
            headerName: translate('table.field.outStockItem.stockUnit'),
            minWidth: 100,
            flex: 1,
            editable: true,
        },
    ])
    const action = {
        field: 'action',
        headerName: '操作',
        width: 70,
        lockPosition: 'left',
        renderCell: (params) => (
            <Tooltip title="Delete">
                <IconButton onClick={() => handleDelete(params.row)}>
                    <Delete />
                </IconButton>
            </Tooltip>
        ),
    }
    let cdata = useRef([]);
    useEffect(() => {
        if (extendColumns == undefined || extendColumns.length < 1) {
            getDynamicFields();
        }
    }, []);
    useEffect(() => {
        cdata.current = tabelData
    }, [tabelData]);
    const getDynamicFields = async () => {
        const {
            data: { code, data, msg },
        } = await request.get("/fields/enable/list");
        if (code === 200) {
            const cols = data.map(el => ({
                field: el.fields,
                headerName: el.fieldsAlise,
                minWidth: 100,
                flex: 1,
                editable: false
            }))
            setColumns([...columns, ...cols, action])
            setExtendColumns(cols);
        } else {
            notify(msg);
        }
    }
    const handleDelete = (row) => {
        const newData = _.filter(cdata.current, (item) => item.matnrId !== row.matnrId);
        setTableData(newData);
    };
    const processRowUpdate = (newRow, oldRow) => {
        const rows = tabelData.map((r) =>
            r.matnrId === newRow.matnrId ? { ...newRow } : r
        )
        setTableData(rows)
        return newRow;
    };
    const handleSelectionChange = (ids) => {
        setSelectedRows(ids)
    };
    tableRef.current = useGridApiRef();
    const tableIds = tabelData.map(map => map.id);
    // setSelectedRows(tableIds);
    // // console.log(selectedRows);
    return (
        <Box>
            <DataGrid
                apiRef={tableRef}
                rows={tabelData}
                columns={columns}
                disableRowSelectionOnClick
                initialState={{
                    pagination: {
                        paginationModel: {
                            pageSize: 25,
                        },
                    },
                }}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                rowSelectionModel={tableIds}
                onRowSelectionModelChange={handleSelectionChange}
                sx={{
                    height: 580,
                    '& .MuiDataGrid-cell input': {
                        border: '1px solid #ccc'
                    },
                }}
            />
        </Box>
    );
};
export default ManualCreate;
rsf-admin/src/page/orders/transfer/TransferCreate.jsx
@@ -23,19 +23,30 @@
    DialogActions,
    DialogContent,
    DialogTitle,
    TextField,
    Button,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../../components/DialogCloseButton.jsx";
import StatusSelectInput from "../../components/StatusSelectInput.jsx";
import MemoInput from "../../components/MemoInput.jsx";
import CreateBySelectMats from "./CreateBySelectMats.jsx";
import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
import ConfirmButton from "../../components/ConfirmButton";
import DictSelect from "../../components/DictSelect";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
const TransferCreate = (props) => {
    const { open, setOpen } = props;
    const translate = useTranslate();
    const { open, setOpen, orderId } = props;
    const tableRef = useRef();
    const notify = useNotify();
    const translate = useTranslate();
    const [tabelData, setTableData] = useState([]);
    const [disabled, setDisabled] = useState(false)
    const [selectedRows, setSelectedRows] = useState([]);
    const [createDialog, setCreateDialog] = useState(false);
    const [formData, setFormData] = useState({});
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
@@ -43,10 +54,50 @@
        }
    };
    const handleSubmit = async () => {
        setFinally()
        setDisabled(true)
        if (asnId === 0) {
            const parmas = {
                "orders": formData,
                "items": tabelData,
            }
            const res = await request.post(`/outStock/items/save`, parmas);
            if (res?.data?.code === 200) {
                setOpen(false);
                refresh();
                resetData()
            } else {
                notify(res.data.msg);
            }
        } else {
            const parmas = {
                "orders": formData,
                "items": tabelData,
            }
            const res = await request.post(`/outStock/items/update`, parmas);
            if (res?.data?.code === 200) {
                setOpen(false);
                refresh();
                resetData()
            } else {
                notify(res.data.msg);
            }
        }
        setDisabled(false)
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        notify('common.response.success');
    };
    const handleDeleteItem = () => {
        const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
        setTableData(newTableData);
    }
    const handleError = async (error) => {
        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
@@ -54,146 +105,280 @@
    return (
        <>
            <CreateBase
                record={{}}
                transform={(data) => {
                    return data;
                }}
                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
            <Dialog
                open={open}
                onClose={handleClose}
                aria-labelledby="form-dialog-title"
                aria-hidden
                fullWidth
                disableRestoreFocus
                maxWidth="xl"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
            >
                <Dialog
                    open={open}
                    onClose={handleClose}
                    aria-labelledby="form-dialog-title"
                    fullWidth
                    disableRestoreFocus
                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
                >
                    <Form>
                        <DialogTitle id="form-dialog-title" sx={{
                            position: 'sticky',
                            top: 0,
                            backgroundColor: 'background.paper',
                            zIndex: 1000
                        }}
                        >
                            {translate('create.title')}
                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                                <DialogCloseButton onClose={handleClose} />
                            </Box>
                        </DialogTitle>
                        <DialogContent sx={{ mt: 2 }}>
                            <Grid container rowSpacing={2} columnSpacing={2}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.transfer.code"
                                        source="code"
                                        parse={v => v}
                                        autoFocus
                <DialogTitle id="form-dialog-title" sx={{
                    position: 'sticky',
                    top: 0,
                    backgroundColor: 'background.paper',
                    zIndex: 1000
                }}>
                    {translate('create.title')}
                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                        <DialogCloseButton onClose={handleClose} />
                    </Box>
                </DialogTitle>
                <DialogContent sx={{ mt: 2 }}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                        <Form defaultValues={formData}>
                            <Grid container spacing={2}>
                                <Grid item md={2}>
                                    <DictSelect
                                        label={translate("table.field.outStock.wkType")}
                                        value={formData.wkType}
                                        variant="filled"
                                        group='2'
                                        onChange={(e) => handleChange(e.target.value, 'wkType')}
                                        dictTypeCode="sys_business_type"
                                        required
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.transfer.type"
                                        source="type"
                                <Grid item md={2}>
                                    <TextField
                                        label={translate("table.field.outStock.poCode")}
                                        value={formData.poCode}
                                        variant="filled"
                                        size='small'
                                        onChange={(e) => handleChange(e.target.value, 'poCode')}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <SelectInput
                                        label="table.field.transfer.source"
                                        source="source"
                                        choices={[
                                            { id: 1, name: 'ERP系统' },
                                            { id:  2, name: 'WMS系统生成' },
                                            { id:  3, name: 'EXCEL导入 ' },
                                            { id:  4, name: 'QMS系统' },
                                        ]}
                                <Grid item md={2}>
                                    <TextField
                                        label={translate("table.field.outStock.logisNo")}
                                        value={formData.logisNo}
                                        variant="filled"
                                        size='small'
                                        onChange={(e) => handleChange(e.target.value, 'logisNo')}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <SelectInput
                                        label="table.field.transfer.exceStatus"
                                        source="exceStatus"
                                        choices={[
                                            { id: 0, name: '未执行' },
                                            { id:  1, name: '执行中' },
                                            { id:  2, name: '执行完成' },
                                        ]}
                                <Grid item md={2}>
                                    <DateInput
                                        source="arrTime"
                                        label="table.field.outStock.arrTime"
                                        size='small'
                                        variant="filled"
                                        value={formData.arrTime}
                                        onChange={(e) => handleChange(e.target.value, 'arrTime')}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.transfer.orgWareId"
                                        source="orgWareId"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.transfer.orgWareName"
                                        source="orgWareName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.transfer.tarWareId"
                                        source="tarWareId"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.transfer.tarWareName"
                                        source="tarWareName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.transfer.orgAreaId"
                                        source="orgAreaId"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.transfer.orgAreaName"
                                        source="orgAreaName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.transfer.tarAreaId"
                                        source="tarAreaId"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.transfer.tarAreaName"
                                        source="tarAreaName"
                                        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>
                        </Form>
                    </Box>
                    <Box sx={{ mt: 2 }}>
                        <Stack direction="row" spacing={2}>
                            <Button variant="contained" onClick={() => setCreateDialog(true)} >
                                {translate('common.action.newAddMats')}
                            </Button>
                            <ConfirmButton label={"toolbar.delete"} variant="outlined" color="error" onConfirm={handleDeleteItem} />
                        </Stack>
                    </Box>
                    <Box sx={{ mt: 2 }}>
                        <TransferTableView
                            tabelData={tabelData}
                            setTableData={setTableData}
                            asnId={orderId}
                            selectedRows={selectedRows}
                            setSelectedRows={setSelectedRows}
                            tableRef={tableRef}>
                        </TransferTableView>
                    </Box>
                </DialogContent>
                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                    <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
                        <Button disabled={disabled} onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
                            {translate('toolbar.confirm')}
                        </Button>
                    </Toolbar>
                </DialogActions>
            </Dialog>
            <CreateBySelectMats
                open={createDialog}
                setOpen={setCreateDialog}
                data={tabelData}
                setData={setTableData}
            />
        </>
    )
}
const TransferTableView = ({ tabelData, setTableData, orderId, selectedRows, setSelectedRows, tableRef }) => {
    const translate = useTranslate();
    const notify = useNotify();
    const [columns, setColumns] = useState([
        {
            field: 'maktx',
            headerName: translate('table.field.outStockItem.maktx'),
            width: 250,
            editable: false,
        },
        {
            field: 'matnrCode',
            headerName: translate('table.field.outStockItem.matnrCode'),
            width: 130,
            editable: false,
        },
        {
            field: 'anfme',
            headerName: translate('table.field.outStockItem.anfme') + "*",
            type: 'number',
            minWidth: 100,
            flex: 1,
            editable: true,
            valueFormatter: (val) => val < 0 ? 0 : val,
            headerClassName: "custom",
        },
        {
            field: 'splrCode',
            headerName: translate('table.field.outStockItem.splrCode') + "*",
            minWidth: 100,
            flex: 1,
            editable: true,
            renderEditCell: (params) => (
                <SelectInputSplrCodeEditCell {...params} />
            ),
            headerClassName: "custom",
        },
        {
            field: 'splrName',
            headerName: translate('table.field.outStockItem.splrName') + "*",
            minWidth: 100,
            flex: 1,
            editable: true,
            renderEditCell: (params) => (
                <SelectInputSplrNameEditCell {...params} />
            ),
            headerClassName: "custom",
        },
        {
            field: 'splrBatch',
            headerName: translate('table.field.outStockItem.splrBatch'),
            minWidth: 100,
            flex: 1,
            editable: true,
        },
        {
            field: 'poCode',
            headerName: translate('table.field.outStockItem.poDetlCode'),
            minWidth: 100,
            flex: 1,
            editable: true,
        },
        {
            field: 'stockUnit',
            headerName: translate('table.field.outStockItem.stockUnit'),
            minWidth: 100,
            flex: 1,
            editable: true,
        },
    ])
    const action = {
        field: 'action',
        headerName: '操作',
        width: 70,
        lockPosition: 'left',
        renderCell: (params) => (
            <Tooltip title="Delete">
                <IconButton onClick={() => handleDelete(params.row)}>
                    <Delete />
                </IconButton>
            </Tooltip>
        ),
    }
    let cdata = useRef([]);
    useEffect(() => {
        getDynamicFields();
    }, []);
    useEffect(() => {
        cdata.current = tabelData
    }, [tabelData]);
    const getDynamicFields = async () => {
        const {
            data: { code, data, msg },
        } = await request.get("/fields/enable/list");
        if (code === 200) {
            const cols = data.map(el => ({
                field: el.fields,
                headerName: el.fieldsAlise,
                minWidth: 100,
                flex: 1,
                editable: false
            }))
            setColumns([...columns, ...cols, action])
        } else {
            notify(msg);
        }
    }
    const handleDelete = (row) => {
        const newData = _.filter(cdata.current, (item) => item.matnrId !== row.matnrId);
        setTableData(newData);
    };
    const processRowUpdate = (newRow, oldRow) => {
        const rows = tabelData.map((r) =>
            r.matnrId === newRow.matnrId ? { ...newRow } : r
        )
        setTableData(rows)
        return newRow;
    };
    const handleSelectionChange = (ids) => {
        setSelectedRows(ids)
    };
    tableRef.current = useGridApiRef();
    return (
        <div style={{ height: 400, width: '100%' }}>
            <DataGrid
                apiRef={tableRef}
                rows={tabelData}
                columns={columns}
                disableRowSelectionOnClick
                getRowId={(row) => row.matnrId ? row.matnrId : row.id}
                disableColumnFilter
                disableColumnSelector
                disableColumnSorting
                disableMultipleColumnsSorting
                processRowUpdate={processRowUpdate}
                initialState={{
                    pagination: {
                        paginationModel: {
                            pageSize: 25,
                        },
                    },
                }}
                pageSizeOptions={[15, 25, 50, 100]}
                editMode="row"
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
                selectionModel={selectedRows}
                sx={{
                    '& .MuiDataGrid-cell input': {
                        border: '1px solid #ccc'
                    },
                }}
            />
        </div>
    );
};
export default TransferCreate;
rsf-admin/src/page/orders/transfer/TransferEdit.jsx
@@ -20,21 +20,22 @@
  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.js";
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from "@/config/setting.js";
import EditBaseAside from "../../components/EditBaseAside.jsx";
import CustomerTopToolBar from "../../components/EditTopToolBar.jsx";
import MemoInput from "../../components/MemoInput.jsx";
import StatusSelectInput from "../../components/StatusSelectInput.jsx";
import CustomerTopToolBar from "../../components/EditTopToolBar.jsx";
import EditBaseAside from "../../components/EditBaseAside.jsx";
import { Stack, Grid, Box, Typography } from "@mui/material";
import { useWatch, useFormContext } from "react-hook-form";
import MemoInput from "../../components/MemoInput.jsx";
import TransferItemList from "./TransferItemList.jsx";
import * as Common from "@/utils/common.js";
const FormToolbar = () => {
  const { getValues } = useFormContext();
  return (
    <Toolbar sx={{ justifyContent: "space-between" }}>
    <Toolbar sx={{ justifyContent: "flex-end" }}>
      <SaveButton />
      <DeleteButton mutationMode="optimistic" />
    </Toolbar>
@@ -53,20 +54,34 @@
        aside={<EditBaseAside />}
      >
        <SimpleForm
          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',
            }
          }}
          shouldUnregister
          warnWhenUnsavedChanges
          toolbar={<FormToolbar />}
          toolbar={false}
          mode="onTouched"
          defaultValues={{}}
          // validate={(values) => { }}
        >
          <Grid
            container
            width={{ xs: "100%", xl: "80%" }}
            width={{ xs: "100%", xl: "90%", }}
            rowSpacing={3}
            columnSpacing={3}
          >
            <Grid item xs={12} md={8}>
            <Grid item xs={24} md={16}>
              <Typography variant="h6" gutterBottom>
                {translate("common.edit.title.main")}
              </Typography>
@@ -76,13 +91,13 @@
                  source="code"
                  parse={(v) => v}
                  autoFocus
                  readOnly
                />
              </Stack>
              <Stack direction="row" gap={2}>
                <NumberInput label="table.field.transfer.type" source="type" />
                <TextInput label="table.field.transfer.type" source="type$" readOnly/>
                <SelectInput
                  label="table.field.transfer.source"
                  source="source"
                  readOnly
                  choices={[
                    { id: 1, name: "ERP系统" },
                    { id: 2, name: "WMS系统生成" },
@@ -92,7 +107,8 @@
                />
                <SelectInput
                  label="table.field.transfer.exceStatus"
                  source="exceStatus"
                  source="exceStatus$"
                  readOnly
                  choices={[
                    { id: 0, name: "未执行" },
                    { id: 1, name: "执行中" },
@@ -104,19 +120,23 @@
                <NumberInput
                  label="table.field.transfer.orgWareId"
                  source="orgWareId"
                  readOnly
                />
                <TextInput
                  label="table.field.transfer.orgWareName"
                  source="orgWareName"
                  readOnly
                  parse={(v) => v}
                />
                <NumberInput
                  label="table.field.transfer.tarWareId"
                  source="tarWareId"
                  readOnly
                />
                <TextInput
                  label="table.field.transfer.tarWareName"
                  source="tarWareName"
                  readOnly
                  parse={(v) => v}
                />
              </Stack>
@@ -124,19 +144,23 @@
                <NumberInput
                  label="table.field.transfer.orgAreaId"
                  source="orgAreaId"
                  readOnly
                />
                <TextInput
                  label="table.field.transfer.orgAreaName"
                  source="orgAreaName"
                  readOnly
                  parse={(v) => v}
                />
                <NumberInput
                  label="table.field.transfer.tarAreaId"
                  source="tarAreaId"
                  readOnly
                />
                <TextInput
                  label="table.field.transfer.tarAreaName"
                  source="tarAreaName"
                  readOnly
                  parse={(v) => v}
                />
              </Stack>
rsf-admin/src/page/orders/transfer/TransferItemEdit.jsx
File was deleted
rsf-admin/src/page/orders/transfer/TransferItemList.jsx
@@ -31,6 +31,7 @@
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
    useGetRecordId,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
@@ -91,77 +92,67 @@
const TransferItemList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const orderId = useGetRecordId();
    const [drawerVal, setDrawerVal] = useState(false);
    const [createDialog, setCreateDialog] = useState(false);
    return (
        <Box display="flex">
            <List
                resource="transferItem"
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.transferItem"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                title={false}
                empty={false}
                filters={filters}
                filter={{transferId: orderId}}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='transferItem' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='transferItem'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    bulkActionButtons={false}
                    rowClick={(id, resource, record) => false}
                    expand={false}
                    expandSingle={false}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                    omit={['id', 'transferId', 'matnrId', 'createTime', 'createBy', 'workQty', 'qty', 'memo', 'platItemId', 'splrId', 'fieldsIndex', 'platOrderCode', 'platWorkCode', 'projectCode']}
                >
                    <NumberField source="id" />
                    <NumberField source="transferId" label="table.field.transferItem.transferId" />
                    <TextField source="transferCode" label="table.field.transferItem.transferCode" />
                    <NumberField source="matnrId" label="table.field.transferItem.matnrId" />
                    <TextField source="maktx" label="table.field.transferItem.maktx" />
                    <TextField source="matnrCode" label="table.field.transferItem.matnrCode" />
                    <TextField source="unit" label="table.field.transferItem.unit" />
                    <NumberField source="anfme" label="table.field.transferItem.anfme" />
                    <NumberField source="qty" label="table.field.transferItem.qty" />
                    <NumberField source="workQty" label="table.field.transferItem.workQty" />
                    <TextField source="batch" label="table.field.transferItem.batch" />
                    <NumberField source="splrId" label="table.field.transferItem.splrId" />
                    <TextField source="maktx" label="table.field.transferItem.maktx" />
                    <TextField source="spec" label="table.field.transferItem.spec" />
                    <TextField source="model" label="table.field.transferItem.model" />
                    <TextField source="batch" label="table.field.transferItem.batch" />
                    <TextField source="unit" label="table.field.transferItem.unit" />
                    <NumberField source="anfme" label="table.field.transferItem.anfme" />
                    <NumberField source="workQty" label="table.field.transferItem.workQty" />
                    <NumberField source="qty" label="table.field.transferItem.qty" />
                    <NumberField source="splrId" label="table.field.transferItem.splrId" />
                    <TextField source="fieldsIndex" label="table.field.transferItem.fieldsIndex" />
                    <TextField source="platItemId" label="table.field.transferItem.platItemId" />
                    <TextField source="platOrderCode" label="table.field.transferItem.platOrderCode" />
                    <TextField source="platWorkCode" label="table.field.transferItem.platWorkCode" />
                    <TextField source="projectCode" label="table.field.transferItem.projectCode" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <TextField source="updateBy$" label="common.field.updateBy" />
                    <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>
                    <TextField source="createBy$" label="common.field.createBy" />
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    {/* <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>
            <PageDrawer
rsf-admin/src/page/orders/transfer/TransferList.jsx
@@ -20,9 +20,11 @@
    TextField,
    NumberField,
    DateField,
    useRefresh,
    BooleanField,
    ReferenceField,
    TextInput,
    Button,
    DateTimeInput,
    DateInput,
    SelectInput,
@@ -31,18 +33,22 @@
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
    useRedirect,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import TransferCreate from "./TransferCreate.jsx";
import TransferPanel from "./TransferPanel.jsx";
import EmptyData from "../../components/EmptyData.jsx";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting.js';
import MyCreateButton from "../../components/MyCreateButton.jsx";
import MyExportButton from '../../components/MyExportButton.jsx';
import PageDrawer from "../../components/PageDrawer.jsx";
import MyField from "../../components/MyField.jsx";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting.js';
import BillStatusField from '../../components/BillStatusField';
import { Box, Typography, Card, Stack, } from '@mui/material';
import PageEditDrawer from "../../components/PageEditDrawer";
import ConfirmButton from '../../components/ConfirmButton';
import AddTaskIcon from '@mui/icons-material/AddTask';
import TransferOrders from "./TransferOrders.jsx";
import ManualCreate from "./ManualCreate.jsx";
import { styled } from '@mui/material/styles';
import * as Common from '@/utils/common.js';
import request from '@/utils/request';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -62,22 +68,21 @@
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
    <TextInput source="code" label="table.field.transfer.code" />,
    <NumberInput source="type" label="table.field.transfer.type" />,
    <SelectInput source="source" label="table.field.transfer.source"
        choices={[
            { id: 1, name: 'ERP系统' },
            { id:  2, name: 'WMS系统生成' },
            { id:  3, name: 'EXCEL导入 ' },
            { id:  4, name: 'QMS系统' },
            { id: 2, name: 'WMS系统生成' },
            { id: 3, name: 'EXCEL导入 ' },
            { id: 4, name: 'QMS系统' },
        ]}
    />,
    <SelectInput source="exceStatus" label="table.field.transfer.exceStatus"
        choices={[
            { id: 0, name: '未执行' },
            { id:  1, name: '执行中' },
            { id:  2, name: '执行完成' },
            { id: 1, name: '执行中' },
            { id: 2, name: '执行完成' },
        ]}
    />,
    <NumberInput source="orgWareId" label="table.field.transfer.orgWareId" />,
@@ -88,7 +93,6 @@
    <TextInput source="orgAreaName" label="table.field.transfer.orgAreaName" />,
    <NumberInput source="tarAreaId" label="table.field.transfer.tarAreaId" />,
    <TextInput source="tarAreaName" label="table.field.transfer.tarAreaName" />,
    <TextInput label="common.field.memo" source="memo" />,
    <SelectInput
        label="common.field.status"
@@ -103,9 +107,9 @@
const TransferList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const [select, setSelect] = useState({});
    return (
        <Box display="flex">
@@ -134,17 +138,16 @@
            >
                <StyledDatagrid
                    preferenceKey='transfer'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    bulkActionButtons={false}
                    rowClick={(id, resource, record) => false}
                    expand={() => <TransferPanel />}
                    expand={() => <TransferOrders />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                    omit={['id', 'createTime', 'createBy$', 'memo', 'orgWareId', 'tarWareId', 'orgAreaId', 'tarAreaId']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.transfer.code" />
                    <NumberField source="type" label="table.field.transfer.type" />
                    <NumberField source="type$" label="table.field.transfer.type" />
                    <TextField source="source$" label="table.field.transfer.source" sortable={false} />
                    <TextField source="exceStatus$" label="table.field.transfer.exceStatus" sortable={false} />
                    <NumberField source="orgWareId" label="table.field.transfer.orgWareId" />
                    <TextField source="orgWareName" label="table.field.transfer.orgWareName" />
                    <NumberField source="tarWareId" label="table.field.transfer.tarWareId" />
@@ -153,35 +156,50 @@
                    <TextField source="orgAreaName" label="table.field.transfer.orgAreaName" />
                    <NumberField source="tarAreaId" label="table.field.transfer.tarAreaId" />
                    <TextField source="tarAreaName" label="table.field.transfer.tarAreaName" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <BillStatusField source="exceStatus$" cellClassName="status" label="table.field.transfer.exceStatus" sortable={false} />
                    <TextField source="updateBy$" label="common.field.updateBy" />
                    <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>
                    <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' }} />
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} label="toolbar.detail"/>
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                        <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <TransferCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='Transfer Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            <PageEditDrawer
                title={"toolbar.createTransfer"}
                drawerVal={createDialog}
                setDrawerVal={setCreateDialog}
            >
            </PageDrawer>
                <ManualCreate setOpen={setCreateDialog} />
            </PageEditDrawer>
        </Box>
    )
}
export default TransferList;
//下发执行
const PublicButton = ({ setDrawerVal, setSelect }) => {
    const record = useRecordContext();
    const refresh = useRefresh();
    const redirct = useRedirect();
    const taskEvent = async () => {
        const { data: { code, data, msg } } = await request.post(`/transfer/pub/outStock`, record);
        if (code === 200) {
            notify(msg);
            redirct("/outStock");
            refresh()
        } else {
            notify(msg);
        }
        refresh();
    }
    return (
        record?.exceStatus == 0 ? <ConfirmButton label={"toolbar.publicWorking"} startIcon={<AddTaskIcon />} onConfirm={taskEvent} size={"small"} /> : <></>
    )
}
rsf-admin/src/page/orders/transfer/TransferOrders.jsx
New file
@@ -0,0 +1,104 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
import {
    List,
    DateField,
    TextField,
    TopToolbar,
    FilterButton,
    NumberField,
    useTranslate,
    WrapperField,
    useRecordContext,
    DatagridConfigurable,
    useRedirect,
} from 'react-admin';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting.js';
import BillStatusField from '../../components/BillStatusField';
import { styled } from '@mui/material/styles';
import * as Common from '@/utils/common.js';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 220
    },
    '& .wkType': {
        width: 110
    },
    '& .status': {
        width: 90
    },
}));
const TransferOrders = () => {
    const redirct = useRedirect();
    const record = useRecordContext();
    if (!record) return null;
    const translate = useTranslate();
    return (
        <>
            <Card sx={{ margin: 'auto' }}>
                <List
                    resource="transfer/orders"
                    sx={{
                        flexGrow: 1,
                        transition: (theme) =>
                            theme.transitions.create(['all'], {
                                duration: theme.transitions.duration.enteringScreen,
                            }),
                    }}
                    title={false}
                    empty={false}
                    pagination={false}
                    filters={false}
                    filter={{ id: record?.id }}
                    sort={{ field: "create_time", order: "desc" }}
                    actions={false}
                    perPage={DEFAULT_PAGE_SIZE}
                >
                    <StyledDatagrid
                        sx={{ margin: 'auto', width: '100%' }}
                        preferenceKey='outStock'
                        bulkActionButtons={false}
                        rowClick={(id, resource, record) => {
                            if (record.type == 'out') {
                                redirct("/outStock")
                            } else if (record.type == 'in') {
                                redirct("/asnOrder")
                            }
                        }}
                        expandSingle={true}
                        omit={['id', 'memo']}
                    >
                        <NumberField source="id" />
                        <TextField source="code" label="table.field.transferOrder.code"/>
                        <TextField source="poCode" label="table.field.transferOrder.poCode" />
                        <TextField source="type$" label="table.field.transferOrder.type" />
                        <TextField cellClassName="wkType" source="wkType$" label="table.field.transferOrder.wkType" />
                        <NumberField source="anfme" label="table.field.transferOrder.anfme" />
                        <NumberField source="workQty" label="table.field.transferOrder.workQty" />
                        <NumberField source="qty" label="table.field.transferOrder.qty" />
                        <TextField source="createBy$" label="common.field.createBy" />
                        <TextField source="updateBy$" label="common.field.updateBy" />
                        <DateField source="createTime" label="common.field.createTime" showTime />
                        <DateField source="updateTime" label="common.field.updateTime" showTime />
                        <BillStatusField cellClassName="status" source="exceStatus" label="table.field.outStock.exceStatus" />
                        <TextField source="memo" label="common.field.memo" sortable={false} />
                    </StyledDatagrid>
                </List>
            </Card >
        </>
    );
};
export default TransferOrders;
rsf-admin/src/page/orders/transfer/TransferPanel.jsx
File was deleted
rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx
File was deleted
rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx
File was deleted
rsf-admin/src/page/system/dicts/dictType/DictDataCreate.jsx
@@ -122,6 +122,15 @@
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.dictData.group"
                                        validate={required()}
                                        autoFocus
                                        source="group"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.dictData.sort"
                                        source="sort"
rsf-admin/src/page/system/dicts/dictType/DictDataEdit.jsx
@@ -58,8 +58,8 @@
            setOpen(false);
        }
    };
    const {data, isPending, } = useGetOne('dictData', {id: record?.id});
    if (data == null || data == undefined) {return}
    const { data, isPending, } = useGetOne('dictData', { id: record?.id });
    if (data == null || data == undefined) { return }
    return (
        <>
            <Edit
@@ -131,6 +131,14 @@
                                        />
                                    </Stack>
                                    <Stack direction='row' gap={2}>
                                        <TextInput
                                            label="table.field.dictData.group"
                                            source="group"
                                            validate={required()}
                                            parse={v => v}
                                        />
                                    </Stack>
                                    <Stack direction='row' gap={2}>
                                        <NumberInput
                                            label="table.field.dictData.sort"
                                            source="sort"
rsf-admin/src/page/system/dicts/dictType/DictDataList.jsx
@@ -125,13 +125,14 @@
                            setSelect(record)
                            setEditDialog(true)
                        }}
                        omit={['id', 'createTime', 'createBy$', 'memo','statusBool']}
                        omit={['id', 'createTime', 'createBy$', 'memo', 'statusBool']}
                    >
                        <NumberField source="id" />
                        <TextField source="dictTypeId" label="table.field.dictData.dictTypeId" />
                        <TextField source="dictTypeCode" label="table.field.dictData.dictTypeCode" />
                        <TextField source="value" label="table.field.dictData.value" />
                        <TextField source="label" label="table.field.dictData.label" />
                        <TextField source="group" label="table.field.dictData.group" />
                        <NumberField source="sort" label="table.field.dictData.sort" />
                        <TextField source="updateBy$" label="common.field.updateBy" />
                        <DateField source="updateTime" label="common.field.updateTime" showTime />
rsf-admin/src/page/task/TaskEdit.jsx
@@ -40,7 +40,7 @@
                <SimpleForm
                    shouldUnregister
                    warnWhenUnsavedChanges
                    toolbar={<FormToolbar />}
                    toolbar={false}
                    mode="onTouched"
                    defaultValues={{}}
                    sx={{
@@ -113,6 +113,7 @@
                                <NumberInput
                                    label="table.field.task.sort"
                                    source="sort"
                                    readOnly
                                />
                            </Stack>
                        </Grid>
rsf-admin/src/page/task/TaskItemList.jsx
@@ -22,11 +22,11 @@
    NumberInput,
    useGetRecordId,
} from 'react-admin';
import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material';
import { styled } from '@mui/material/styles';
import PageDrawer from "../components/PageDrawer";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material';
import MyCreateButton from "../components/MyCreateButton";
import PageDrawer from "../components/PageDrawer";
import { styled } from '@mui/material/styles';
import TaskItemCreate from "./TaskItemCreate";
import request from '@/utils/request';
@@ -103,7 +103,7 @@
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */}
                        <SelectColumnsButton preferenceKey='taskItem' />
                        {/* <MyExportButton /> */}
                    </TopToolbar>
rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx
@@ -236,7 +236,7 @@
    }
    return (
        <Box sx={{ position: 'relative', minHeight: "60vh", }}>
        <Box sx={{ position: 'relative', minHeight: "82vh", }}>
            {isLoading && (
                <LinearProgress
                    sx={{
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -91,13 +91,10 @@
    private FieldsMapper fieldsMapper;
    @Autowired
    private IsptHistoriesMapper isptHistoriesMapper;
    @Autowired
    private AsnOrderLogService asnOrderLogService;
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private WaitPakinItemService waitPakinItemService;
    @Autowired
@@ -128,6 +125,8 @@
    private ConfigService configService;
    @Autowired
    private CompanysService companysService;
    @Autowired
    private OutStockService outStockService;
    /**
     * @return
@@ -233,19 +232,31 @@
        WkOrder wkOrder = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>()
                .eq(WkOrder::getCode, asnCode));
        //判断调拔单出库是否完成
        if (wkOrder.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) {
            WkOrder one = outStockService.getOne(new LambdaQueryWrapper<WkOrder>()
                    .eq(WkOrder::getPoId, wkOrder.getPoId())
                    .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)
                    .eq(WkOrder::getType, OrderType.ORDER_OUT.type));
            if (Objects.isNull(one)) {
                throw new CoolException("数据错误!!");
            }
            if (!one.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val)) {
                throw new CoolException("调拔出库单未完成,不可执行收货操作!!");
            }
        }
        if (Objects.isNull(wkOrder)) {
            throw new CoolException("数据错误:主单不存在!!");
        }
        //TODO /**收货数量累加,1. 会出超收情况 2. 会有收货不足情况*/
        Double rcptedQty = Math.round((wkOrder.getQty() + receiptQty) * 10000) / 10000.0;
        wkOrder.setQty(rcptedQty).setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val);
        if (!asnOrderMapper.updateById(wkOrder)) {
            throw new CoolException("已收货数量修改失败!!");
        }
        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.ALLOW_OVER_CHANGE));
        List<Map<String, Object>> receipts1 = (List<Map<String, Object>>) params.get("receipts");
        for (Map<String, Object> rcpt : receipts1) {
@@ -352,7 +363,7 @@
        Companys companys = new Companys();
        if (StringUtils.isNoneBlank(orderItem.getSplrCode())) {
             companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode()));
            companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode()));
        }
        WarehouseAreasItem item = new WarehouseAreasItem();
@@ -711,13 +722,13 @@
        }
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, params.getBarcode())
                .eq(WaitPakin::getIoStatus,PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
                .eq(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
        );
        if (Cools.isEmpty(waitPakin)){
        if (Cools.isEmpty(waitPakin)) {
            throw new CoolException("未找到组托数据,请检查状态");
        }
        List<WaitPakinItem> waitPakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
        if (Cools.isEmpty(waitPakinItems)){
        if (Cools.isEmpty(waitPakinItems)) {
            throw new CoolException("数据错误,未找到组托明细");
        }
@@ -745,7 +756,7 @@
        /**获取平库订单*/
        WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>()
                .eq(WkOrder::getId, OrderId)
                        .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type)
                .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type)
                .eq(WkOrder::getType, OrderType.ORDER_IN.type));
        if (Objects.isNull(order)) {
            throw new CoolException("非平库单据不可执行人工上架!!");
@@ -937,15 +948,15 @@
     */
    @Override
    public R getUnItemByContainer(Map<String, Object> params) {
        if (Cools.isEmpty(params.get("barcode")) && Cools.isEmpty(params.get("code"))){
        if (Cools.isEmpty(params.get("barcode")) && Cools.isEmpty(params.get("code"))) {
            throw new CoolException("容器号与组托档编码不能全为空");
        }
        //获取组拖未生成任务的组拖档
//        List<Short> asList = Arrays.asList(Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_DONE.val), Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_DONE.val));
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(!Cools.isEmpty(params.get("barcode")),WaitPakin::getBarcode, params.get("barcode"))
                .eq(!Cools.isEmpty(params.get("code")),WaitPakin::getCode, params.get("code"))
                .eq(!Cools.isEmpty(params.get("barcode")), WaitPakin::getBarcode, params.get("barcode"))
                .eq(!Cools.isEmpty(params.get("code")), WaitPakin::getCode, params.get("code"))
                .eq(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val));
        if (Objects.isNull(waitPakin)) {
            return R.error("未找到该容器码的组托明细,请检查组托状态");
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -22,8 +22,8 @@
//        generator.username="sa";
//        generator.password="Zoneyung@zy56$";
        generator.table = "man_transfer_item";
        generator.tableDesc = "调拔单明细";
        generator.table = "man_transfer_order";
        generator.tableDesc = "调拔单订单关联表";
        generator.packagePath = "com.vincent.rsf.server.manager";
        generator.build();
rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java
@@ -51,6 +51,7 @@
                        "man_loc_type_rela",
                        "man_qly_inspect_result",
                        "view_stock_manage",
                        "man_transfer_order",
                        "man_wave_order_rela"
                ).contains(tableName);
            }
rsf-server/src/main/java/com/vincent/rsf/server/common/utils/FieldsUtils.java
@@ -104,7 +104,7 @@
     * @time 2025/3/18 15:00
     */
    @Transactional(rollbackFor = Exception.class)
    public static boolean saveFields(Map<String, ?> template, String uuid) throws Exception {
    public static boolean saveFields(Map<String, ?> template, String uuid) {
        List<Fields> fields = getFieldsSta();
        FieldsItemService fieldsItemService = SpringUtils.getBean(FieldsItemService.class);
        List<FieldsItem> fieldsItems = new ArrayList<>();
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java
@@ -160,7 +160,7 @@
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @GetMapping("/locItem/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(locService.getById(id));
        return R.ok().add(locItemService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:locItem:save')")
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocPreviewController.java
New file
@@ -0,0 +1,178 @@
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.framework.exception.CoolException;
import com.vincent.rsf.server.common.annotation.OperationLog;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.manager.controller.params.LocModifyParams;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.server.system.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;
@Api(tags = "库位信息")
@RestController
public class LocPreviewController extends BaseController {
    @Autowired
    private LocService locService;
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @PostMapping("/locPreview/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<Loc, BaseParam> pageParam = new PageParam<>(baseParam, Loc.class);
        List<String> list = new ArrayList<>();
        list.add("row");
        list.add("col");
        list.add("lev");
        return R.ok().add(locService.page(pageParam, pageParam.buildWrapper(true,list)));
    }
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @PostMapping("/locPreview/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(locService.list());
    }
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @PostMapping("/locPreview/areaNoUse/list")
    public R areaNoUselist(@RequestBody Map<String, Object> map) {
        String locCode = map.get("locCode").toString();
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locCode),false);
        List<Loc> list = locService.list(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getAreaId, loc.getAreaId())
                .eq(Loc::getChannel,loc.getChannel())
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
        );
        List<String> list1 = list.stream().map(obj -> obj.getCode()).collect(Collectors.toList());
        return R.ok(list1);
    }
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @PostMapping({"/locPreview/many/{ids}", "/locPreview/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(locService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @GetMapping("/locPreview/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(locService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:locPreview:save')")
    @OperationLog("Create 库位信息表")
    @PostMapping("/locPreview/save")
    public R save(@RequestBody Loc loc) {
        if (Objects.isNull(loc.getWarehouseId())) {
            throw new CoolException("仓库ID不能为空!!");
        }
        if (Objects.isNull(loc.getAreaId())) {
            throw new CoolException("仓库ID不能为空!!");
        }
        if (Objects.isNull(loc.getTypeIds())) {
            throw new CoolException("库位类型不能为空!!");
        }
        String join = StringUtils.join(loc.getTypeIds(), ",");
        loc.setType(join);
        loc.setCreateBy(getLoginUserId());
        loc.setUpdateBy(getLoginUserId());
        if (!locService.save(loc)) {
            return R.error("Save Fail");
        }
        if (!locService.saveType(loc)) {
            throw new CoolException("库位类型关联关系保存失败!!");
        }
        return R.ok("Save Success").add(loc);
    }
    @PreAuthorize("hasAuthority('manager:locPreview:update')")
    @OperationLog("Update 库位信息表")
    @PostMapping("/locPreview/update")
    @Transactional(rollbackFor = Exception.class)
    public R update(@RequestBody Loc loc) {
        loc.setUpdateBy(getLoginUserId());
        String join = StringUtils.join(loc.getTypeIds(), ",");
        loc.setType(join);
        if (Objects.isNull(loc.getTypeIds())) {
            throw new CoolException("库位类型不能为空!!");
        }
        if (!locService.updateById(loc)) {
            return R.error("Update Fail");
        }
        if (!locService.updateLoc(loc)) {
            throw new CoolException("库位类型关联关系修改失败!!");
        }
        return R.ok("Update Success").add(loc);
    }
    @PreAuthorize("hasAuthority('manager:locPreview:remove')")
    @OperationLog("Delete 库位信息表")
    @PostMapping("/locPreview/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!locService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @PostMapping("/locPreview/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<Loc> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(Loc::getCode, condition);
        }
        locService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getCode()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('manager:locPreview:list')")
    @ApiOperation("库位导出")
    @PostMapping("/locPreview/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        List<Loc> locs = new ArrayList<>();
        if (Objects.isNull(map.get("ids"))) {
            locs = locService.list();
        } else {
            locs = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getStatus, 1));
        }
        ExcelUtil.build(ExcelUtil.create(locs, Loc.class), response);
    }
    @PreAuthorize("hasAuthority('manager:locPreview:update')")
    @ApiOperation("库位批量修改")
    @PostMapping("/locPreview/modify")
    public R batchUpdate(@RequestBody LocModifyParams locs) {
        if (Objects.isNull(locs)) {
            throw new CoolException("参为不能为空!!");
        }
        return locService.modifyLocs(locs);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java
@@ -58,8 +58,8 @@
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<WkOrder, BaseParam> pageParam = new PageParam<>(baseParam, WkOrder.class);
        QueryWrapper<WkOrder> queryWrapper = pageParam.buildWrapper(true);
        List<String> list = Arrays.asList(OrderType.ORDER_OUT.type);
        queryWrapper.in("type", list);
//        List<String> list = Arrays.asList(OrderType.ORDER_OUT.type);
//        queryWrapper.in("type", list);
        return R.ok().add(outStockService.page(pageParam, queryWrapper));
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TaskController.java
@@ -37,15 +37,6 @@
    @Autowired
    private TaskService taskService;
    @Autowired
    private TaskItemService taskItemService;
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private LocService locService;
    @Autowired
    private ConfigServiceImpl configService;
    @PreAuthorize("hasAuthority('manager:task:list')")
    @PostMapping("/task/page")
@@ -139,7 +130,6 @@
        }
        return R.ok("完成任务成功").add(taskService.operateComplete(id, getLoginUserId()));
    }
    /**
     * 拣料出库(用于测试拣料出库)
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TransferController.java
@@ -4,15 +4,22 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.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.controller.params.AsnOrderAndItemsParams;
import com.vincent.rsf.server.manager.controller.params.OrgLocParams;
import com.vincent.rsf.server.manager.controller.params.TransferItemParams;
import com.vincent.rsf.server.manager.entity.Transfer;
import com.vincent.rsf.server.manager.entity.excel.CheckOrderTemplate;
import com.vincent.rsf.server.manager.service.OutStockService;
import com.vincent.rsf.server.manager.service.TransferService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,6 +35,8 @@
    @Autowired
    private TransferService transferService;
    @Autowired
    private OutStockService outStockService;
    @PreAuthorize("hasAuthority('manager:transfer:list')")
    @PostMapping("/transfer/page")
@@ -35,6 +44,25 @@
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<Transfer, BaseParam> pageParam = new PageParam<>(baseParam, Transfer.class);
        return R.ok().add(transferService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @ApiOperation("获取调拔单关联订单")
    @PreAuthorize("hasAuthority('manager:transfer:list')")
    @PostMapping("/transfer/orders/page")
    public R getTransferInfo(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<Transfer, BaseParam> pageParam = new PageParam<>(baseParam, Transfer.class);
        return R.ok().add(transferService.transfersPage(pageParam, pageParam.buildWrapper(true)));
    }
    @ApiOperation("调拔单生成出库单")
    @PreAuthorize("hasAuthority('manager:transfer:list')")
    @PostMapping("/transfer/pub/outStock")
    public R genOutstock(@RequestBody Transfer transfer) {
        if (Objects.isNull(transfer)) {
            throw new CoolException("参数不能为空!!");
        }
        return R.ok(transferService.genOutStock(transfer, getLoginUserId()));
    }
    @PreAuthorize("hasAuthority('manager:transfer:list')")
@@ -63,6 +91,12 @@
        transfer.setCreateTime(new Date());
        transfer.setUpdateBy(getLoginUserId());
        transfer.setUpdateTime(new Date());
        if (Objects.isNull(transfer.getCode())) {
            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TRANSFER_ORDER_CODE, transfer);
            transfer.setCode(ruleCode);
        }
        if (!transferService.save(transfer)) {
            return R.error("Save Fail");
        }
@@ -85,8 +119,12 @@
    @OperationLog("Delete 调拔单")
    @PostMapping("/transfer/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!transferService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        List<Long> list = Arrays.asList(ids);
        if (list.isEmpty()) {
            return R.error("参数不能为空!!");
        }
        if (!transferService.removeTransfer(list)) {
            throw new CoolException("调拔单移除失败!!");
        }
        return R.ok("Delete Success").add(ids);
    }
@@ -105,6 +143,37 @@
        return R.ok().add(vos);
    }
    @PostMapping("/transfer/items/save")
    @ApiOperation("保存主单及明细")
    @PreAuthorize("hasAuthority('manager:transfer:save')")
    public R saveOutStock(@RequestBody TransferItemParams params) throws Exception {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return transferService.saveTransfer(params, getLoginUserId());
    }
    @ApiOperation("单据信息修改")
    @PostMapping("/transfer/items/update")
    @PreAuthorize("hasAuthority('manager:transfer:update')")
    public R orderAndrItemUpdate(@RequestBody TransferItemParams params) {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return transferService.updateTransfer(params, getLoginUserId());
    }
    @ApiOperation("获取原库区物料信息")
    @PostMapping("/transfer/locs/items")
    @PreAuthorize("hasAuthority('manager:transfer:list')")
    public R locsPage(@RequestBody OrgLocParams params) {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return R.ok().add(transferService.getLocsItems(params, getLoginUserId()));
    }
    /**
     * @author Ryan
     * @description 下载模板
@@ -115,7 +184,7 @@
    @PostMapping("/transfer/template/download")
    @ApiOperation("下载盘点单模板")
    @PreAuthorize("hasAuthority('manager:transfer:update')")
    public void downloadTemplate(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
    public void downloadTemplate(@RequestBody Map<String, Object> map, HttpServletResponse response) {
        CheckOrderTemplate template = ExcelUtil.mockData(CheckOrderTemplate.class);
        List<CheckOrderTemplate> list = Arrays.asList(template);
        ExcelUtil.build(ExcelUtil.create(list, CheckOrderTemplate.class, true), response);
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/TransferOrderController.java
New file
@@ -0,0 +1,104 @@
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.TransferOrder;
import com.vincent.rsf.server.manager.service.TransferOrderService;
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 TransferOrderController extends BaseController {
    @Autowired
    private TransferOrderService transferOrderService;
    @PreAuthorize("hasAuthority('manager:transferOrder:list')")
    @PostMapping("/transferOrder/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<TransferOrder, BaseParam> pageParam = new PageParam<>(baseParam, TransferOrder.class);
        return R.ok().add(transferOrderService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:list')")
    @PostMapping("/transferOrder/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(transferOrderService.list());
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:list')")
    @PostMapping({"/transferOrder/many/{ids}", "/transferOrders/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(transferOrderService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:list')")
    @GetMapping("/transferOrder/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(transferOrderService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:save')")
    @OperationLog("Create 调拔单订单关联表")
    @PostMapping("/transferOrder/save")
    public R save(@RequestBody TransferOrder transferOrder) {
        if (!transferOrderService.save(transferOrder)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(transferOrder);
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:update')")
    @OperationLog("Update 调拔单订单关联表")
    @PostMapping("/transferOrder/update")
    public R update(@RequestBody TransferOrder transferOrder) {
        if (!transferOrderService.updateById(transferOrder)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(transferOrder);
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:remove')")
    @OperationLog("Delete 调拔单订单关联表")
    @PostMapping("/transferOrder/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!transferOrderService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:transferOrder:list')")
    @PostMapping("/transferOrder/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<TransferOrder> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(TransferOrder::getId, condition);
        }
        transferOrderService.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:transferOrder:list')")
    @PostMapping("/transferOrder/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(transferOrderService.list(), TransferOrder.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/OrgLocParams.java
New file
@@ -0,0 +1,30 @@
package com.vincent.rsf.server.manager.controller.params;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
@ApiModel(value = "OrgLocParams", description = "原库区物料")
public class OrgLocParams implements Serializable {
    @ApiModelProperty("原库区ID")
    private Long orgAreaId;
    @ApiModelProperty("当前页")
    private Integer current;
    @ApiModelProperty("物料编码")
    private String matnrCode;
    @ApiModelProperty("物料名称")
    private String maktx;
    @ApiModelProperty("当前页数")
    private Integer pageSize;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/TransferItemParams.java
New file
@@ -0,0 +1,24 @@
package com.vincent.rsf.server.manager.controller.params;
import com.vincent.rsf.server.manager.entity.Transfer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@Data
@Accessors(chain = true)
@ApiModel(value = "TransferItemParams", description = "调拔单参数")
public class TransferItemParams implements Serializable {
    @ApiModelProperty("调拔单")
    private Transfer transfer;
    @ApiModelProperty("调拔单明细")
    private List<Map<String, Object>>  items;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderItemLog.java
@@ -83,7 +83,7 @@
     * 物料标识
     */
    @ApiModelProperty(value= "物料标识")
    private String matnrId;
    private Long matnrId;
    /**
     * 物料助记码
@@ -230,7 +230,7 @@
    public AsnOrderItemLog() {}
    public AsnOrderItemLog(Long asnId,String asnCode,String platItemId,Long poDetlId,String poCode,String fieldsIndex,String matnrId,String matnrCode,String maktx,Double anfme,String stockUnit,Double purQty,String purUnit,Double qty,String splrCode,String splrBatch,String splrName,String qrcode,String trackCode,String barcode,String packName,Short ntyStatus,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
    public AsnOrderItemLog(Long asnId,String asnCode,String platItemId,Long poDetlId,String poCode,String fieldsIndex,Long matnrId,String matnrCode,String maktx,Double anfme,String stockUnit,Double purQty,String purUnit,Double qty,String splrCode,String splrBatch,String splrName,String qrcode,String trackCode,String barcode,String packName,Short ntyStatus,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.asnId = asnId;
        this.asnCode = asnCode;
        this.platItemId = platItemId;
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Loc.java
@@ -304,6 +304,7 @@
        return StringUtils.join(strings, ",");
    }
    public String getUseStatus$(){
        if (null == this.useStatus){ return null; }
        switch (this.useStatus){
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItem.java
@@ -219,6 +219,9 @@
    @ApiModelProperty(value= "修改人员")
    private Long updateBy;
    @ApiModelProperty("供应商ID")
    private Long splrId;
    /**
     * 修改时间
     */
@@ -238,7 +241,7 @@
    @ApiModelProperty("出站口")
    @TableField(exist = false)
    private String siteNo;
    private String site;
    /**
@@ -382,8 +385,6 @@
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
    }
    public Boolean getStatusBool(){
        if (null == this.status){ return null; }
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Transfer.java
@@ -3,6 +3,13 @@
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.server.manager.enums.OrderType;
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 lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -20,8 +27,10 @@
import com.vincent.rsf.server.system.entity.User;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
@Data
@Accessors(chain = true)
@TableName("man_transfer")
public class Transfer implements Serializable {
@@ -47,16 +56,16 @@
    private Integer type;
    /**
     * 来源: 1: ERP系统   2: WMS系统生成   3: EXCEL导入    4: QMS系统
     * 来源: 1: ERP系统   2: WMS系统生成   3: EXCEL导入    4: QMS系统
     */
    @ApiModelProperty(value= "来源: 1: ERP系统   2: WMS系统生成   3: EXCEL导入    4: QMS系统  ")
    private Integer source;
    /**
     * 执行状态: 0: 未执行   1: 执行中   2: 执行完成
     * 执行状态: 0: 未执行   1: 执行中   2: 执行完成
     */
    @ApiModelProperty(value= "执行状态: 0: 未执行   1: 执行中   2: 执行完成  ")
    private Integer exceStatus;
    private Short exceStatus;
    /**
     * 源仓库ID
@@ -107,13 +116,13 @@
    private String tarAreaName;
    /**
     * 状态 1: 正常  0: 冻结
     * 状态 1: 正常  0: 冻结
     */
    @ApiModelProperty(value= "状态 1: 正常  0: 冻结  ")
    private Integer status;
    /**
     * 是否删除 1: 是  0: 否
     * 是否删除 1: 是  0: 否
     */
    @ApiModelProperty(value= "是否删除 1: 是  0: 否  ")
    @TableLogic
@@ -159,7 +168,7 @@
    public Transfer() {}
    public Transfer(String code,Integer type,Integer source,Integer exceStatus,Long orgWareId,String orgWareName,Long tarWareId,String tarWareName,Long orgAreaId,String orgAreaName,Long tarAreaId,String tarAreaName,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
    public Transfer(String code,Integer type,Integer source,Short exceStatus,Long orgWareId,String orgWareName,Long tarWareId,String tarWareName,Long orgAreaId,String orgAreaName,Long tarAreaId,String tarAreaName,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.code = code;
        this.type = type;
        this.source = source;
@@ -221,20 +230,33 @@
        }
    }
    public String getExceStatus$(){
        if (null == this.exceStatus){ return null; }
        switch (this.exceStatus){
            case 0:
                return "未执行";
            case  1:
                return "执行中";
            case  2:
                return "执行完成";
            default:
                return String.valueOf(this.exceStatus);
    public String getType$() {
        if (null == this.type){ return null; }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictData = dictDataService.getOne(new LambdaQueryWrapper<DictData>()
                .eq(DictData::getDictTypeCode, DictTypeCode.SYS_TRANSFER_TYPE)
                .eq(DictData::getValue, this.type));
        if (Objects.isNull(dictData)) {
            return null;
        }
        return dictData.getLabel();
    }
    public String getExceStatus$() {
        if (Cools.isEmpty(this.exceStatus)){
            return null;
        }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictData = dictDataService.getOne(new LambdaQueryWrapper<DictData>()
                .eq(DictData::getDictTypeCode, DictTypeCode.DICT_ASN_EXCE_STATUS)
                .eq(DictData::getValue, this.exceStatus));
        if (Objects.isNull(dictData)) {
            return null;
        }
        return dictData.getLabel();
    }
    public String getStatus$(){
        if (null == this.status){ return null; }
        switch (this.status){
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/TransferItem.java
@@ -1,16 +1,18 @@
package com.vincent.rsf.server.manager.entity;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.vincent.rsf.server.manager.service.CompanysService;
import lombok.experimental.Accessors;
import org.checkerframework.checker.units.qual.A;
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;
@@ -20,8 +22,10 @@
import com.vincent.rsf.server.system.entity.User;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
@Data
@Accessors(chain = true)
@TableName("man_transfer_item")
public class TransferItem implements Serializable {
@@ -99,6 +103,15 @@
     */
    @ApiModelProperty(value= "供应商ID")
    private Long splrId;
    @TableField(exist = false)
    @ApiModelProperty("供应商编码")
    private String splrCode;
    @TableField(exist = false)
    @ApiModelProperty("供应商名称")
    private String splrName;
    /**
     * 规格
@@ -253,6 +266,28 @@
//            null    // 备注
//    );
    public String getSplrName() {
        if (null == this.splrId) { return null; }
        CompanysService companysService = SpringUtils.getBean(CompanysService.class);
        Companys companys = companysService.getById(this.splrId);
        if (Objects.isNull(companys)) {
            return null;
        } else {
            return companys.getName();
        }
    }
    public String getSplrCode() {
        if (null == this.splrId) { return null; }
        CompanysService companysService = SpringUtils.getBean(CompanysService.class);
        Companys companys = companysService.getById(this.splrId);
        if (Objects.isNull(companys)) {
            return null;
        } else {
            return companys.getCode();
        }
    }
    public String getStatus$(){
        if (null == this.status){ return null; }
        switch (this.status){
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/TransferOrder.java
New file
@@ -0,0 +1,31 @@
package com.vincent.rsf.server.manager.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
@TableName("man_transfer_order")
public class TransferOrder implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty("单据类型:in: 入库, out:出库")
    private String type;
    @ApiModelProperty("调拔单ID")
    private Long transferId;
    @ApiModelProperty("订单ID")
    private Long orderId;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.enums.OrderWorkType;
import com.vincent.rsf.server.system.constant.DictTypeCode;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.service.DictDataService;
@@ -25,6 +26,7 @@
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;
@Data
@@ -37,38 +39,38 @@
    /**
     * ID
     */
    @ApiModelProperty(value= "ID")
    @ApiModelProperty(value = "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 编号
     */
    @ApiModelProperty(value= "编号")
    @ApiModelProperty(value = "编号")
    private String code;
    /**
     * PO单号
     */
    @ApiModelProperty(value= "PO单号")
    @ApiModelProperty(value = "PO单号")
    private String poCode;
    /**
     * PO单据标识
     */
    @ApiModelProperty(value= "PO单据标识")
    @ApiModelProperty(value = "PO单据标识")
    private Long poId;
    /**
     * 单据类型
     */
    @ApiModelProperty(value= "单据类型")
    @ApiModelProperty(value = "单据类型")
    private String type;
    /**
     * 业务类型
     */
    @ApiModelProperty(value= "业务类型")
    @ApiModelProperty(value = "业务类型")
    private String wkType;
    @ApiModelProperty("盘点类型")
@@ -77,7 +79,7 @@
    /**
     * 送货数量
     */
    @ApiModelProperty(value= "送货数量")
    @ApiModelProperty(value = "送货数量")
    private Double anfme;
    @ApiModelProperty("执行数量")
@@ -86,13 +88,13 @@
    /**
     * 已收数量
     */
    @ApiModelProperty(value= "已收数量")
    @ApiModelProperty(value = "已收数量")
    private Double qty;
    /**
     * 物流单号
     */
    @ApiModelProperty(value= "物流单号")
    @ApiModelProperty(value = "物流单号")
    private String logisNo;
    @ApiModelProperty("波次ID")
@@ -101,8 +103,8 @@
    /**
     * 预计到达时间
     */
    @ApiModelProperty(value= "预计到达时间")
    @DateTimeFormat(pattern="yyyy-MM-dd")
    @ApiModelProperty(value = "预计到达时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date arrTime;
    /**
@@ -112,9 +114,9 @@
    private Integer ntyStatus;
    /**
     * 释放状态 0:  正常   1:  已释放
     * 释放状态 0:  正常   1:  已释放
     */
    @ApiModelProperty(value= "释放状态 0:  正常   1:  已释放  ")
    @ApiModelProperty(value = "释放状态 0:  正常   1:  已释放  ")
    private Short rleStatus;
@@ -122,59 +124,60 @@
    private Short exceStatus;
    /**
     * 状态 1: 正常  0: 冻结
     * 状态 1: 正常  0: 冻结
     */
    @ApiModelProperty(value= "状态 1: 正常  0: 冻结  ")
    @ApiModelProperty(value = "状态 1: 正常  0: 冻结  ")
    private Integer status;
    /**
     * 是否删除 1: 是  0: 否
     * 是否删除 1: 是  0: 否
     */
    @ApiModelProperty(value= "是否删除 1: 是  0: 否  ")
    @ApiModelProperty(value = "是否删除 1: 是  0: 否  ")
    @TableLogic
    private Integer deleted;
    /**
     * 租户
     */
    @ApiModelProperty(value= "租户")
    @ApiModelProperty(value = "租户")
    private Integer tenantId;
    /**
     * 添加人员
     */
    @ApiModelProperty(value= "添加人员")
    @ApiModelProperty(value = "添加人员")
    private Long createBy;
    /**
     * 添加时间
     */
    @ApiModelProperty(value= "添加时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    @ApiModelProperty(value = "添加时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    /**
     * 修改人员
     */
    @ApiModelProperty(value= "修改人员")
    @ApiModelProperty(value = "修改人员")
    private Long updateBy;
    /**
     * 修改时间
     */
    @ApiModelProperty(value= "修改时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    @ApiModelProperty(value = "修改时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    @ApiModelProperty(value = "备注")
    private String memo;
    public WkOrder() {}
    public WkOrder() {
    }
    public WkOrder(String code, String poCode, Long poId, String type, String wkType, Double anfme, Double qty, String logisNo, Date arrTime, Short rleStatus, Integer status, Integer deleted, Integer tenantId, Long createBy, Date createTime, Long updateBy, Date updateTime, String memo) {
        this.code = code;
@@ -198,7 +201,7 @@
    }
    public String getExceStatus$() {
        if (Cools.isEmpty(this.exceStatus)){
        if (Cools.isEmpty(this.exceStatus)) {
            return "";
        }
        String exceType = DictTypeCode.DICT_ASN_EXCE_STATUS;
@@ -216,42 +219,57 @@
    }
    public String getType$(){
        if (Cools.isEmpty(this.type)){
    public String getType$() {
        return OrderType.getValType(this.type);
//        if (this.type.equals(OrderType.ORDER_TRANSFER.type)) {
//            return OrderType.getValType(this.type);
//        } else {
//            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 (this.type.equals(OrderType.ORDER_TRANSFER.type)) {
            return OrderWorkType.getWorkDesc(this.wkType);
//        } else {
//            String typeCode = DictTypeCode.DICT_SYS_BUSINESS_TYPE;
//            if (type.equals(OrderType.ORDER_CHECK.type)) {
//                typeCode = DictTypeCode.SYS_CHECK_ORDER_TYPE;
//            }
//            if (Cools.isEmpty(this.wkType)) {
//                return "";
//            }
//            DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
//            DictData dictData = dictDataService
//                    .getOne(new LambdaQueryWrapper<DictData>()
//                    .eq(DictData::getDictTypeCode, typeCode)
//                            .eq(DictData::getValue, this.wkType));
//            if (Objects.isNull(dictData)) {
//                return null;
//            }
//            return dictData.getLabel();
//        }
    }
    public String getCheckType$() {
        if (Cools.isEmpty(this.checkType)) {
            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$(){
        String typeCode = DictTypeCode.DICT_SYS_BUSINESS_TYPE;
        if (type.equals(OrderType.ORDER_CHECK.type)) {
            typeCode = DictTypeCode.SYS_CHECK_ORDER_TYPE;
        }
        if (Cools.isEmpty(this.wkType)){
            return "";
        }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictData = dictDataService.getOne(new LambdaQueryWrapper<DictData>().eq(DictData::getDictTypeCode, typeCode).eq(DictData::getValue, this.wkType));
        if (Objects.isNull(dictData)) {
            return null;
        }
        return dictData.getLabel();
    }
    public String getCheckType$(){
        if (Cools.isEmpty(this.checkType)){
            return "";
        }
        DictDataService dictDataService = SpringUtils.getBean(DictDataService.class);
        DictData dictData = dictDataService.getOne(new LambdaQueryWrapper<DictData>().eq(DictData::getDictTypeCode, DictTypeCode.SYS_CHECK_TYPE).eq(DictData::getValue, this.checkType));
                .eq(DictData::getDictTypeCode, DictTypeCode.SYS_CHECK_TYPE)
                .eq(DictData::getValue, this.checkType));
        if (Objects.isNull(dictData)) {
            return null;
        }
@@ -259,28 +277,32 @@
    }
    public String getArrTime$(){
        if (Cools.isEmpty(this.arrTime)){
    public String getArrTime$() {
        if (Cools.isEmpty(this.arrTime)) {
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.arrTime);
    }
    public String getRleStatus$(){
        if (null == this.rleStatus){ return null; }
        switch (this.rleStatus){
    public String getRleStatus$() {
        if (null == this.rleStatus) {
            return null;
        }
        switch (this.rleStatus) {
            case 0:
                return " 正常";
            case  1:
            case 1:
                return " 已释放";
            default:
                return String.valueOf(this.rleStatus);
        }
    }
    public String getStatus$(){
        if (null == this.status){ return null; }
        switch (this.status){
    public String getStatus$() {
        if (null == this.status) {
            return null;
        }
        switch (this.status) {
            case 1:
                return "正常";
            case 0:
@@ -290,43 +312,44 @@
        }
    }
    public String getCreateBy$(){
    public String getCreateBy$() {
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.getById(this.createBy);
        if (!Cools.isEmpty(user)){
        if (!Cools.isEmpty(user)) {
            return String.valueOf(user.getNickname());
        }
        return null;
    }
    public String getCreateTime$(){
        if (Cools.isEmpty(this.createTime)){
    public String getCreateTime$() {
        if (Cools.isEmpty(this.createTime)) {
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
    }
    public String getUpdateBy$(){
    public String getUpdateBy$() {
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.getById(this.updateBy);
        if (!Cools.isEmpty(user)){
        if (!Cools.isEmpty(user)) {
            return String.valueOf(user.getNickname());
        }
        return null;
    }
    public String getUpdateTime$(){
        if (Cools.isEmpty(this.updateTime)){
    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){
    public Boolean getStatusBool() {
        if (null == this.status) {
            return null;
        }
        switch (this.status) {
            case 1:
                return true;
            case 0:
@@ -335,9 +358,12 @@
                return null;
        }
    }
    public String getNtyStatus$(){
        if (null == this.ntyStatus){ return "error"; }
        switch (this.ntyStatus){
    public String getNtyStatus$() {
        if (null == this.ntyStatus) {
            return "error";
        }
        switch (this.ntyStatus) {
            case 0:
                return "未上报";
            case 1:
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/MatnrsTemplate.java
@@ -19,6 +19,8 @@
 * @create 2025/3/3 08:40
 */
@Data
@ExcelAutoColumnSize
@Accessors(chain = true)
public class MatnrsTemplate {
    @NotNull
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
@@ -13,9 +13,10 @@
    ASN_EXCE_STATUS_UN_EXCE("0", "未执行"),
    ASN_EXCE_STATUS_EXCE_ING("1", "执行中"),
    ASN_EXCE_STATUS_RECEIPT_DONE("2", "收货完成"),
    ASN_EXCE_STATUS_TASK_DONE("3", "已完成"),
    ASN_EXCE_STATUS_TASK_CANCEL("4", "取消"),
    ASN_EXCE_STATUS_TASK_CLOSE("5", "已关闭"),
    ASN_EXCE_STATUS_TASK_EXCE("3", "任务执行中"),
    ASN_EXCE_STATUS_TASK_DONE("4", "已完成"),
    ASN_EXCE_STATUS_TASK_CANCEL("8", "取消"),
    ASN_EXCE_STATUS_TASK_CLOSE("9", "已关闭"),
    //PO单执行状态
//    PO_EXCE_STATUS_UN_EXCE("0", "未执行"),
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckExceStatus.java
@@ -2,7 +2,7 @@
public enum CheckExceStatus {
    //盘点单执行状态
    //盘点单执行状态 /调拔单执行状态
    CHECK_ORDER_STATUS_UN_EXCE("0", "未执行"),
    CHECK_ORDER_STATUS_INIT("1", "初始化"),
    CHECK_ORDER_STATUS_EXCE_ING("2", "执行中"),
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderSourceType.java
@@ -16,10 +16,37 @@
    ;
    OrderSourceType(String val, String desc) {
        this.val = Short.parseShort(val);
        this.val = Integer.parseInt(val);
        this.desc = desc;
    }
    public Short val;
    public Integer val;
    public String desc;
    public static Integer getSourceVal(String desc) {
        if (desc.equals(OrderSourceType.ORDER_SOURCE_TYPE_ERP.desc)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_ERP.val;
        } else if (desc.equals(OrderSourceType.ORDER_SOURCE_TYPE_SYSTEM.desc)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_SYSTEM.val;
        } else if (desc.equals(OrderSourceType.ORDER_SOURCE_TYPE_EXCEL.desc)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_EXCEL.val;
        } else if (desc.equals(OrderSourceType.ORDER_SOURCE_TYPE_QMS.desc)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_QMS.val;
        }
        return null;
    }
    public static String getSourceDesc(Integer val) {
        if (val.equals(OrderSourceType.ORDER_SOURCE_TYPE_ERP.val)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_ERP.desc;
        } else if (val.equals(OrderSourceType.ORDER_SOURCE_TYPE_SYSTEM.val)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_SYSTEM.desc;
        } else if (val.equals(OrderSourceType.ORDER_SOURCE_TYPE_EXCEL.val)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_EXCEL.desc;
        } else if (val.equals(OrderSourceType.ORDER_SOURCE_TYPE_QMS.val)) {
            return OrderSourceType.ORDER_SOURCE_TYPE_QMS.desc;
        }
        return null;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java
@@ -11,8 +11,9 @@
    //订单类型
    ORDER_OUT("out", "出库单"),
    ORDER_IN("in", "入库单"),
    ORDER_TRANSFER("transfer", "调拔单"),
    ORDER_CHECK("check", "盘点单");
    ;
    OrderType(String type, String desc) {
        this.type = type;
@@ -29,6 +30,8 @@
            return OrderType.ORDER_OUT.type;
        } else if (desc.equals(OrderType.ORDER_CHECK.desc)) {
            return OrderType.ORDER_CHECK.type;
        } else if (desc.equals(OrderType.ORDER_TRANSFER.desc)) {
            return OrderType.ORDER_TRANSFER.type;
        }
        return null;
    }
@@ -40,6 +43,8 @@
            return OrderType.ORDER_OUT.desc;
        } else if (type.equals(OrderType.ORDER_CHECK.type)) {
            return OrderType.ORDER_CHECK.desc;
        } else if (type.equals(OrderType.ORDER_TRANSFER.type)) {
            return OrderType.ORDER_TRANSFER.desc;
        }
        return null;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java
@@ -14,12 +14,13 @@
    ORDER_WORK_TYPE_PURCHASE("3", "领料退回入库单"),
    ORDER_WORK_TYPE_SALE("4", "销售退回入库单"),
    ORDER_WORK_TYPE_OTHER_IN("5", "其它入库单"),
    ORDER_WORK_TYPE_OTHER_TERANSFER("6", "调拔入库单"),
    ORDER_WORK_TYPE_SUPPLIER("11", "销售出库单"),
    ORDER_WORK_TYPE_RETURN_ORDER("12", "领料出库单"),
    ORDER_WORK_TYPE_PURCHASE_RETURN("13", "采购退回出库单"),
    ORDER_WORK_TYPE_STOCK_OUT("15", "库存出库"),
    ORDER_WORK_TYPE_STOCK_CHECK("16", "盘点出库"),
    ORDER_WORK_TYPE_STOCK_TERANSFER("17", "调拔出库单"),
    ORDER_WORK_TYPE_OTHER("14", "其它出库单");
@@ -54,6 +55,10 @@
            return OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type;
        }
        return null;
    }
@@ -81,6 +86,10 @@
            return OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.desc;
        }
        return null;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TransferType.java
New file
@@ -0,0 +1,48 @@
package com.vincent.rsf.server.manager.enums;
/**
 * @author Ryan
 * @date 2025/7/25
 * @description: 调拔类型
 * @version 1.0
 */
public enum TransferType {
    //调拔类型
    TRANSFER_TYPE_WAREHOUSE("1" ,"跨仓调拔"),
    TRANSFER_TYPE_AREAS("2", "跨区调拔"),
    TRANSFER_TYPE_LOCAL("0", "本地调拔");
    private Integer val;
    private String desc;
    TransferType(String val, String desc) {
        this.val = Integer.parseInt(val);
        this.desc = desc;
    }
    public static String getValType(Integer type) {
        if (type.equals(TransferType.TRANSFER_TYPE_WAREHOUSE.val)) {
            return TransferType.TRANSFER_TYPE_WAREHOUSE.desc;
        } else if (type.equals(TransferType.TRANSFER_TYPE_AREAS.val)) {
            return TransferType.TRANSFER_TYPE_AREAS.desc;
        } else if (type.equals(TransferType.TRANSFER_TYPE_LOCAL.val)) {
            return TransferType.TRANSFER_TYPE_LOCAL.desc;
        }
        return null;
    }
    public static Integer getTypeVal(String desc) {
        if (desc.equals(TransferType.TRANSFER_TYPE_WAREHOUSE.desc)) {
            return TransferType.TRANSFER_TYPE_WAREHOUSE.val;
        } else if (desc.equals(TransferType.TRANSFER_TYPE_AREAS.desc)) {
            return TransferType.TRANSFER_TYPE_AREAS.val;
        } else if (desc.equals(TransferType.TRANSFER_TYPE_LOCAL.desc)) {
            return TransferType.TRANSFER_TYPE_LOCAL.val;
        }
        return null;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/TransferMapper.java
@@ -1,12 +1,20 @@
package com.vincent.rsf.server.manager.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.Transfer;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.vincent.rsf.server.manager.entity.WkOrder;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface TransferMapper extends BaseMapper<Transfer> {
    IPage<WkOrder> transfersPage(PageParam<Transfer, BaseParam> pageParam, @Param("transferId") Long transferId);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/TransferOrderMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.TransferOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface TransferOrderMapper extends BaseMapper<TransferOrder> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderLogSchedule.java
@@ -1,17 +1,15 @@
package com.vincent.rsf.server.manager.schedules;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.WkOrder;
import com.vincent.rsf.server.manager.entity.WkOrderItem;
import com.vincent.rsf.server.manager.entity.AsnOrderItemLog;
import com.vincent.rsf.server.manager.entity.AsnOrderLog;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.service.AsnOrderItemLogService;
import com.vincent.rsf.server.manager.service.AsnOrderItemService;
import com.vincent.rsf.server.manager.service.AsnOrderLogService;
import com.vincent.rsf.server.manager.service.AsnOrderService;
import com.vincent.rsf.server.manager.enums.OrderWorkType;
import com.vincent.rsf.server.manager.enums.POExceStatus;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.TransferOrderServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@@ -20,6 +18,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -34,55 +33,71 @@
public class AsnOrderLogSchedule {
    @Autowired
    private PurchaseService purchaseService;
    @Autowired
    private DeliveryService deliveryService;
    @Autowired
    private AsnOrderService asnOrderService;
    @Autowired
    private AsnOrderItemService asnOrderItemService;
    @Autowired
    private AsnOrderLogService asnOrderLogService;
    @Autowired
    private AsnOrderItemLogService asnOrderItemLogService;
    @Autowired
    private TransferOrderService transferOrderService;
    @Autowired
    private TransferService transferService;
    /**
     * @author Ryan
     * @description 删除已完成订单加入Log表
     * @param
     * @return
     * @author Ryan
     * @description 删除已完成订单加入Log表
     * @time 2025/3/19 19:09
     */
    @Scheduled(cron = "0 0/05 * * * ?  ")
    @Scheduled(cron = "0/35 * * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void moveOrderToLog() {
    public void InStockToLog() {
        List<WkOrder> wkOrders = asnOrderService.list(new LambdaQueryWrapper<WkOrder>()
                        .eq(WkOrder::getType, OrderType.ORDER_IN.type)
                .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val));
                .eq(WkOrder::getType, OrderType.ORDER_IN.type)
                .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_TASK_EXCE.val));
        if (wkOrders.isEmpty()) {
            return;
        }
        moveOrderToLog(wkOrders, OrderType.ORDER_IN.type);
        try {
            moveOrderToLog(wkOrders, OrderType.ORDER_IN.type);
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
    }
    /**
    * @author Ryan
    * @description 出库单完成后,状态修改
    * @param
    * @return
    * @time 2025/6/16 08:35
    */
//    @Scheduled(cron = "0/30 * * * * ?  ")
     * @param
     * @return
     * @author Ryan
     * @description 出库单完成后,状态修改
     * @time 2025/6/16 08:35
     */
    @Scheduled(cron = "0/30 * * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void outStockComplete() {
        List<WkOrder> wkOrders = asnOrderService.list(new LambdaQueryWrapper<WkOrder>()
                        .eq(WkOrder::getType, OrderType.ORDER_OUT.type)
                .apply("anfme = work_qty")
                .eq(WkOrder::getType, OrderType.ORDER_OUT.type)
                .eq(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)
                .apply("anfme = qty")
        );
        if (wkOrders.isEmpty()) {
            return;
        }
        moveOrderToLog(wkOrders, OrderType.ORDER_OUT.type);
        try {
            moveOrderToLog(wkOrders, OrderType.ORDER_OUT.type);
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
    }
    /**
     * @param
@@ -92,48 +107,106 @@
     * @description 添加历史单据
     * @time 2025/6/16 08:56
     */
    private void moveOrderToLog(List<WkOrder> wkOrders, String type) {
    @Transactional(rollbackFor = Exception.class)
    public void moveOrderToLog(List<WkOrder> wkOrders, String type) {
        Set<Long> longSet = wkOrders.stream().map(WkOrder::getId).collect(Collectors.toSet());
        List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().in(WkOrderItem::getOrderId, longSet));
        List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
                .in(WkOrderItem::getOrderId, longSet));
        if (orderItems.isEmpty()) {
            throw new CoolException("收货明细为空!!");
        }
        for (WkOrder order : wkOrders) {
            AsnOrderLog orderLog = new AsnOrderLog();
            if (type.equals(OrderType.ORDER_OUT.type)) {
                order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val);
                order.setQty(order.getWorkQty());
            }
            BeanUtils.copyProperties(order, orderLog);
            orderLog.setId(null);
            orderLog.setAsnId(order.getId());
            AsnOrderLog one = asnOrderLogService.getOne(new LambdaQueryWrapper<AsnOrderLog>().eq(AsnOrderLog::getCode, order.getCode()), false);
            if (Objects.isNull(one)) {
                AsnOrderLog orderLog = new AsnOrderLog();
                if (type.equals(OrderType.ORDER_OUT.type)) {
                    order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val);
                    order.setQty(order.getWorkQty());
                }
                BeanUtils.copyProperties(order, orderLog);
                orderLog.setId(null);
                orderLog.setAsnId(order.getId());
            if (!asnOrderLogService.save(orderLog)) {
                throw new CoolException("主单历史档添加失败!!");
                if (!asnOrderLogService.save(orderLog)) {
                    throw new CoolException("主单历史档添加失败!!");
                }
                List<AsnOrderItemLog> logs = new ArrayList<>();
                List<WkOrderItem> items = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
                        .eq(WkOrderItem::getOrderId, order.getId()));
                items.forEach(item -> {
                    AsnOrderItemLog itemLog = new AsnOrderItemLog();
                    BeanUtils.copyProperties(item, itemLog);
                    itemLog.setAsnItemId(itemLog.getId())
                            .setId(null)
                            .setMatnrId(item.getMatnrId())
                            .setLogId(orderLog.getId())
                            .setAsnId(item.getOrderId());
                    logs.add(itemLog);
                });
                if (!asnOrderItemLogService.saveBatch(logs)) {
                    throw new CoolException("单据明细历史档保存失败!!");
                }
                //更新PO/DO单执行状态
                if (type.equals(OrderType.ORDER_IN.type)) {
                    if (order.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) {
                        order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val);
                        if (!asnOrderService.updateById(order)) {
                            throw new CoolException("单据状态更新失败!!");
                        }
//                        List<TransferOrder> orders = transferOrderService.list(new LambdaQueryWrapper<TransferOrder>().eq(TransferOrder::getTransferId, order.getPoId()));
//                        if (orders.isEmpty()) {
//                            throw new CoolException("数据错误:关联表信息不存在!!");
//                        }
//                        Set<Long> orderIds = orders.stream().map(TransferOrder::getOrderId).collect(Collectors.toSet());
//                        if (!asnOrderItemService.remove(new LambdaQueryWrapper<WkOrderItem>()
//                                .in(WkOrderItem::getOrderId, orderIds))) {
//                            throw new CoolException("原单据明细删除失败!!");
//                        }
//                        if (!this.asnOrderService.removeByIds(orderIds)) {
//                            throw new CoolException("原单据删除失败!!");
//                        }
                          if (!transferService.update(new LambdaUpdateWrapper<Transfer>()
                                  .eq(Transfer::getId, order.getPoId())
                                  .set(Transfer::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val))) {
                              throw new CoolException("调拔单状态修改失败!!");
                          }
                        return;
                    } else {
                        if (!Objects.isNull(order.getPoId())) {
                            purchaseService.update(new LambdaUpdateWrapper<Purchase>()
                                    .set(Purchase::getExceStatus, POExceStatus.PO_EXCE_STATUS_ALL_DONE.val)
                                    .eq(Purchase::getId, order.getPoId()));
                        }
                    }
                } else {
                    if (order.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)) {
                        order.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val);
                        if (!asnOrderService.updateById(order)) {
                            throw new CoolException("单据状态更新失败!!");
                        }
                        //如果为调拔单据保留
                        return;
                    } else {
                        if (!Objects.isNull(order.getPoId())) {
                            deliveryService.update(new LambdaUpdateWrapper<Delivery>()
                                    .eq(Delivery::getId, order.getPoId())
                                    .set(Delivery::getExceStatus, POExceStatus.PO_EXCE_STATUS_ALL_DONE.val));
                        }
                    }
                }
            }
            List<AsnOrderItemLog> logs = new ArrayList<>();
            List<WkOrderItem> items = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
            items.forEach(item -> {
                AsnOrderItemLog itemLog = new AsnOrderItemLog();
                BeanUtils.copyProperties(item, itemLog);
                itemLog.setAsnItemId(itemLog.getId())
                        .setLogId(orderLog.getId())
                        .setAsnId(item.getOrderId());
                logs.add(itemLog);
            });
            if (!asnOrderItemLogService.saveBatch(logs)) {
                throw new CoolException("单据明细历史档保存失败!!");
            if (!asnOrderItemService.remove(new LambdaQueryWrapper<WkOrderItem>()
                    .eq(WkOrderItem::getOrderId, order.getId()))) {
                throw new CoolException("原单据明细删除失败!!");
            }
        }
        if (!asnOrderItemService.remove(new LambdaQueryWrapper<WkOrderItem>().in(WkOrderItem::getOrderId, longSet))) {
            throw new CoolException("原单据明细删除失败!!");
        }
        if (!this.asnOrderService.removeByIds(longSet)) {
            throw new CoolException("原单据删除失败!!");
            if (!this.asnOrderService.removeById(order.getId())) {
                throw new CoolException("原单据删除失败!!");
            }
        }
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
@@ -7,10 +7,7 @@
import com.vincent.rsf.server.common.config.SysStockProperties;
import com.vincent.rsf.server.common.utils.DateUtils;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.enums.POExceStatus;
import com.vincent.rsf.server.manager.enums.WarehouseAreasType;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.WarehouseAreasItemServiceImpl;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
@@ -61,6 +58,10 @@
    private WarehouseAreasItemServiceImpl warehouseAreasItemService;
    @Autowired
    private CompanysService companysService;
    @Autowired
    private TransferService transferService;
    @Autowired
    private OutStockService outStockService;
    /**
     * @author Ryan
@@ -68,7 +69,6 @@
     * @description: 直接组托开关为true,将收货单直接加入临时库存
     * @version 1.0
     */
//    @Scheduled(cron = "0 0/05 * * * ?  ")
    @Scheduled(cron = "0/25 * * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public synchronized void IgnoreReceipt() {
@@ -85,6 +85,18 @@
                .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val));
        if (!orders.isEmpty()) {
            for (WkOrder order : orders) {
                if (order.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) {
                    WkOrder one = outStockService.getOne(new LambdaQueryWrapper<WkOrder>()
                            .eq(WkOrder::getPoId, order.getPoId())
                            .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type));
                    if (Objects.isNull(one)) {
                        throw new CoolException("数据错误");
                    }
                    if (!one.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val)) {
                        continue;
                    }
                }
                List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
                if (orderItems.isEmpty()) {
                    return;
@@ -109,7 +121,11 @@
                        throw new CoolException("物料不存在!!");
                    }
                    //更新收货区库存
                    extracted(one, item, order, matnr);
                    try {
                        updateReceipt(one, item, order, matnr);
                    } catch (Exception e) {
                        throw new CoolException(e.getMessage());
                    }
                    if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>().set(WkOrderItem::getQty, item.getAnfme()).eq(WkOrderItem::getId, item.getId()))) {
                        throw new CoolException("收货单明细完成数量修改失败!!");
@@ -136,7 +152,8 @@
     * @description: 收货区库存更新
     * @version 1.0
     */
    private void extracted(WarehouseAreas areasItem, WkOrderItem orderItem, WkOrder wkOrder, Matnr matnr) {
    @Transactional(rollbackFor = Exception.class)
    public void updateReceipt(WarehouseAreas areasItem, WkOrderItem orderItem, WkOrder wkOrder, Matnr matnr) throws Exception {
        Companys companys = new Companys();
        if (StringUtils.isNoneBlank(orderItem.getSplrCode())) {
            companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode()));
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -2,18 +2,21 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.service.WcsService;
import com.vincent.rsf.server.api.utils.LocUtils;
import com.vincent.rsf.server.common.constant.Constants;
import com.vincent.rsf.server.manager.controller.params.LocToTaskParams;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.TaskStsType;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.TaskType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
import com.vincent.rsf.server.manager.service.impl.TransferOrderServiceImpl;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.entity.Config;
import com.vincent.rsf.server.system.service.ConfigService;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import com.vincent.rsf.server.system.utils.SystemAuthUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -53,6 +56,18 @@
    private List<Integer> rows;
    @Autowired
    private LocItemService locItemService;
    @Autowired
    private OutStockService outStockService;
    @Autowired
    private OutStockItemService outStockItemService;
    @Autowired
    private AsnOrderItemService asnOrderItemService;
    @Autowired
    private AsnOrderService asnOrderService;
    @Autowired
    private TransferOrderService transferOrderService;
    @Autowired
    private TransferService transferService;
    /**
     * @param
@@ -79,6 +94,7 @@
     * @version 1.0
     */
    @Scheduled(cron = "0/5 * * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void complateOutStock() throws Exception {
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
                .eq(Task::getTaskStatus, TaskStsType.COMPLETE_OUT.id)
@@ -89,6 +105,110 @@
        List<Long> longSet = tasks.stream().map(Task::getId).collect(Collectors.toList());
        List<Task> vaildTasks = taskService.list(new LambdaQueryWrapper<Task>().in(Task::getId, longSet));
        taskService.completeTask(vaildTasks);
//        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>()
//                .eq(TaskItem::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)
//                .in(TaskItem::getTaskId, longSet));
//        if (!taskItems.isEmpty()) {
//            genInStock(taskItems);
//        }
    }
    /**
     * @author Ryan
     * @date 2025/7/29
     * @description: 生成入库单
     * @version 1.0
     */
    @Transactional(rollbackFor = Exception.class)
    public void genInStock(List<TaskItem> taskItems) throws Exception {
        Set<Long> orderIds = taskItems.stream().map(TaskItem::getSourceId).collect(Collectors.toSet());
        List<WkOrder> wkOrders = outStockService.list(new LambdaQueryWrapper<WkOrder>().in(WkOrder::getId, orderIds));
        wkOrders.forEach(wkOrder -> {
            List<WkOrderItem> orderItems = outStockItemService.list(new LambdaQueryWrapper<WkOrderItem>()
                    .eq(WkOrderItem::getOrderId, wkOrder.getId()));
            if (!orderItems.isEmpty()) {
                WkOrder order = new WkOrder();
                BeanUtils.copyProperties(wkOrder, order);
                String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, order);
                if (StringUtils.isBlank(ruleCode)) {
                    throw new CoolException("入库单号生成失败!!");
                }
                order.setWkType(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)
                        .setId(null)
                        .setCode(ruleCode)
                        .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)
                        .setType(OrderType.ORDER_IN.type);
//                Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
//                if (!Boolean.parseBoolean(config.getVal())) {
//                    order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val);
//                } else {
//                    order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val);
//                }
                if (!asnOrderService.save(order)) {
                    throw new CoolException("入库单生成失败!!");
                }
                orderItems.forEach(orderItem -> {
                   orderItem.setOrderId(order.getId()).setOrderCode(order.getCode()).setId(null);
                   if (!asnOrderItemService.save(orderItem)) {
                       throw new CoolException("入库单明细保存失败!!");
                   }
                });
                Transfer transfer = transferService.getById(order.getPoId());
                TransferOrder transferOrder = new TransferOrder();
                transferOrder.setOrderId(order.getId())
                        .setType(OrderType.ORDER_IN.type)
                        .setTransferId(transfer.getId());
                if (!transferOrderService.save(transferOrder)) {
                    throw new CoolException("关联单保存失败!!");
                }
            }
        });
//        Set<Long> taskIds = taskItems.stream().map(TaskItem::getTaskId).collect(Collectors.toSet());
//        List<Task> tasks = taskService.listByIds(taskIds);
//        if (!tasks.isEmpty()) {
//            tasks.forEach(task -> {
//                TaskItem one = taskItemService.getOne(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId()), false);
//                if (Objects.isNull(one)) {
//                    throw new CoolException("数据错误:任务明细丢失!!");
//                }
//                TransferOrder order = transferOrderService.getOne(new LambdaQueryWrapper<TransferOrder>().eq(TransferOrder::getOrderId, one.getOrderId()));
//                if (Objects.isNull(order)) {
//                    throw new CoolException("数据错误!!");
//                }
//                Transfer transfer = transferService.getById(order.getTransferId());
//                Task task1 = new Task();
//                BeanUtils.copyProperties(task, task1);
//                String targetLoc = LocManageUtil.getTargetLoc(transfer.getTarAreaId());
//                if (Objects.isNull(targetLoc)) {
//                    throw new CoolException("未能找到有效库位");
//                }
//                task.setTaskType(TaskType.TASK_TYPE_IN.type)
//                        .setTargLoc(targetLoc)
//                        .setTargSite(null)
//                        .setId(null)
//                        .setTaskStatus(TaskStsType.GENERATE_IN.id);
//                if (!taskService.save(task1)) {
//                    throw new CoolException("任务生成失败!!");
//                }
//                List<TaskItem> items = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId()));
//                if (items.isEmpty()) {
//                    throw new CoolException("数据错误!!");
//                }
//                items.forEach(taskItem -> {
//                    TaskItem item = new TaskItem();
//                    BeanUtils.copyProperties(taskItem, item);
//                    item.setTaskId(task1.getId()).setId(null);
//                    if (!taskItemService.save(item)) {
//                        throw new CoolException("入库任务明细保存失败!!");
//                    }
//                });
//            });
//        }
    }
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocPreviewService.java
New file
@@ -0,0 +1,20 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.manager.controller.params.LocMastInitParam;
import com.vincent.rsf.server.manager.controller.params.LocModifyParams;
import com.vincent.rsf.server.manager.entity.Loc;
public interface LocPreviewService extends IService<Loc> {
    R modifyLocs(LocModifyParams locs);
    R initLocs(LocMastInitParam param, Long loginUserId);
    boolean saveType(Loc typeIds);
    boolean updateLoc(Loc loc);
    R batchBindLocs(LocModifyParams locs);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocPreviewServiceImpl.java
New file
@@ -0,0 +1,218 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.controller.params.LocMastInitParam;
import com.vincent.rsf.server.manager.controller.params.LocModifyParams;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.mapper.LocMapper;
import com.vincent.rsf.server.manager.mapper.LocTypeRelaMapper;
import com.vincent.rsf.server.manager.utils.Shelves;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Service("locPreviewService")
public class LocPreviewServiceImpl extends ServiceImpl<LocMapper, Loc> implements LocPreviewService {
    @Autowired
    private WarehouseAreasService warehouseAreasService;
    @Autowired
    private LocTypeRelaService locTypeRelaService;
    @Autowired
    private LocAreaRelaService locAreaRelaService;
    @Autowired
    private LocAreaService locAreaService;
    @Autowired
    private LocTypeRelaMapper locTypeRelaMapper;
    @Override
    public R modifyLocs(LocModifyParams locs) {
        if (locs.getId().isEmpty()) {
            throw new CoolException("库位ID不能为空!!");
        }
        Loc loc = locs.getLoc();
        if (Objects.isNull(loc)) {
            throw new CoolException("修改库位信息不能为空!!");
        }
        String join = loc.getType();
        if (!Objects.isNull(loc.getTypeIds()) && !loc.getTypeIds().isEmpty()) {
             join = StringUtils.join(loc.getTypeIds(), ",");
        }
        boolean update = this.update(new LambdaUpdateWrapper<Loc>()
                .in(Loc::getId, locs.getId())
                .eq(Loc::getStatus, 1)
                .set(!Objects.isNull(loc.getAreaId()), Loc::getAreaId, loc.getAreaId())
                .set(!Objects.isNull(loc.getWarehouseId()), Loc::getWarehouseId, loc.getWarehouseId())
                .set(!Objects.isNull(loc.getUseStatus()), Loc::getUseStatus, loc.getUseStatus())
                .set(!Objects.isNull(loc.getTypeIds()) && !loc.getTypeIds().isEmpty(), Loc::getType, join)
                .set(!Objects.isNull(loc.getLength()), Loc::getLength, loc.getLength())
                .set(!Objects.isNull(loc.getWidth()), Loc::getWidth, loc.getWidth())
                .set(!Objects.isNull(loc.getHeight()), Loc::getHeight, loc.getHeight())
                .set(!Objects.isNull(loc.getChannel()), Loc::getChannel, loc.getChannel())
                .set(!Objects.isNull(loc.getFlagLabelMange()), Loc::getFlagLabelMange, loc.getFlagLabelMange())
                .set(!Objects.isNull(loc.getStatus()), Loc::getStatus, loc.getStatus()));
        if (!update) {
            throw new CoolException("库位信息修改失败!!");
        }
        return R.ok(loc);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R initLocs(LocMastInitParam param, Long loginUserId) {
        //清空表
//        this.baseMapper.deleteAll();
        //清空当前库区库位
        List<Loc> locs = this.list(new LambdaQueryWrapper<Loc>().eq(Loc::getWarehouseId, param.getWarehouseId()).eq(Loc::getAreaId, param.getAreaId()));
        if (!locs.isEmpty()) {
            if (!this.remove(new LambdaQueryWrapper<Loc>().eq(Loc::getWarehouseId, param.getWarehouseId()).eq(Loc::getAreaId, param.getAreaId()))) {
                throw new CoolException("初始化失败:数据删除失败!!");
            }
        }
        WarehouseAreas warehouseAreas = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>()
                .eq(WarehouseAreas::getWarehouseId, param.getWarehouseId())
                .eq(WarehouseAreas::getId, param.getAreaId()));
        if (Objects.isNull(warehouseAreas)) {
            throw new CoolException("库区不存在!!");
        }
        String join = StringUtils.join(param.getTypeIds(), ",");
        String[] split = warehouseAreas.getCode().split("\\.");
        if (split.length == 0){
            throw new CoolException("库区编码错误!!");
        }
        StringBuilder locStar = new StringBuilder();
        for (int i = 0; i < split.length; i++) {
            locStar.append(split[i]).append("-");
        }
        List<Loc> list = new ArrayList<>();
        Integer chanl = 0; //默认第一巷道
        for (int r = param.getStartRow(); r <= param.getEndRow(); r++) {
            try{
                Shelves shelves = new Shelves(param.getEndRow() - param.getStartRow() + 1, param.getChannel(),param.getStartRow());
                for (List<Integer> node : shelves.nodes){
                    if (node.contains(r)) {
                        if (!Cools.isEmpty(param.getStartChannel()) && param.getStartChannel() > 0){
                            chanl = shelves.nodes.indexOf(node) + param.getStartChannel();
                        }else {
                            chanl = shelves.nodes.indexOf(node) + 1;
                        }
                        break;
                    }
                }
            }catch (Exception e){
                throw new CoolException("解析巷道号失败");
            }
            for (int b = param.getStartBay(); b <= param.getEndBay(); b++) {
                for (int l = param.getStartLev(); l <= param.getEndLev(); l++) {
                    // 获取库位号
                    String locNo = locStar +  String.format("%d", r) + String.format("-%d", b) + String.format("-%d", l);
                    Loc loc = new Loc();
                    loc.setCode(locNo)
                            .setUseStatus("O")
                            .setRow(r)
                            .setCol(b)
                            .setLev(l)
                            .setChannel(chanl)
                            .setType(join)
                            .setAreaId(param.getAreaId())
                            .setUpdateBy(loginUserId)
                            .setCreateBy(loginUserId)
                            .setWarehouseId(warehouseAreas.getWarehouseId());
                    list.add(loc);
                }
            }
        }
        if (!this.saveBatch(list)) {
            throw new CoolException("库位初始化失败!!");
        }
        List<LocTypeRela> locTypeRelas = new ArrayList<>();
        for (Long typeId : param.getTypeIds()) {
            for (Loc loc : list) {
                LocTypeRela typeRela = new LocTypeRela();
                typeRela.setLocId(loc.getId()).setTypeId(typeId);
                locTypeRelas.add(typeRela);
            }
        }
        if (!locTypeRelaService.saveBatch(locTypeRelas)) {
            throw new CoolException("库位类型关联失败!!");
        }
        return R.ok("初始化成功!!");
    }
    @Override
    public boolean saveType(Loc loc) {
        List<LocTypeRela> relas =  new ArrayList<>();
        loc.getTypeIds().forEach(id -> {
            LocTypeRela typeRela = new LocTypeRela();
            typeRela.setTypeId(id)
                    .setLocId(loc.getId());
            relas.add(typeRela);
        });
        if (!locTypeRelaService.saveOrUpdateBatch(relas)) {
            throw new CoolException("库位关联关系保存失败!!");
        }
        return true;
    }
    @Override
    public boolean updateLoc(Loc loc) {
        locTypeRelaMapper.delete(new LambdaQueryWrapper<LocTypeRela>().eq(LocTypeRela::getLocId, loc.getId()));
        List<LocTypeRela> relas =  new ArrayList<>();
        loc.getTypeIds().forEach(id -> {
            LocTypeRela typeRela = new LocTypeRela();
            typeRela.setTypeId(id)
                    .setLocId(loc.getId());
            relas.add(typeRela);
        });
        if (!locTypeRelaService.saveOrUpdateBatch(relas)) {
            throw new CoolException("库位关联关系保存失败!!");
        }
        return true;
    }
    @Override
    public R batchBindLocs(LocModifyParams locs) {
        if (locs.getId().isEmpty()) {
            throw new CoolException("库位ID不能为空!!");
        }
        if (Objects.isNull(locs.getLocAreaId())) {
            throw new CoolException("修改库位信息不能为空!!");
        }
        List<LocArea> locAreas = locAreaService.list(new LambdaQueryWrapper<LocArea>().eq(LocArea::getId, locs.getLocAreaId()));
        if (locAreas.isEmpty()) {
            throw new CoolException("库位分区不存在!!");
        }
        List<LocAreaRela> relas = new ArrayList<>();
        locs.getId().forEach(id -> {
            LocAreaRela locAreaRela = new LocAreaRela();
            locAreaRela.setLocId(id)
                    .setLocAreaId(locs.getLocAreaId());
            relas.add(locAreaRela);
        });
        if (!locAreaRelaService.saveBatch(relas)) {
            throw new CoolException("库位分区失败!!");
        }
        return R.ok();
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -16,7 +16,6 @@
    R generateAGVTasks(WaitPakin waitPakins, String locCode, String orgSta, Long loginUserId);
    //    R completeTask(String id);
    void completeTask(List<Task> task) throws Exception;
    R removeTask(Long[] ids, Long loginUserId);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TransferItemService.java
@@ -3,6 +3,9 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.server.manager.entity.TransferItem;
import java.util.Map;
public interface TransferItemService extends IService<TransferItem> {
    boolean fieldsSave(Map<String, Object> item, Long loginUserId);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TransferOrderService.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.TransferOrder;
public interface TransferOrderService extends IService<TransferOrder> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TransferService.java
@@ -1,8 +1,31 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.params.OrgLocParams;
import com.vincent.rsf.server.manager.controller.params.TransferItemParams;
import com.vincent.rsf.server.manager.entity.LocItem;
import com.vincent.rsf.server.manager.entity.Transfer;
import com.vincent.rsf.server.manager.entity.WkOrder;
import java.util.List;
public interface TransferService extends IService<Transfer> {
    R saveTransfer(TransferItemParams params, Long loginUserId);
    R updateTransfer(TransferItemParams params, Long loginUserId);
    IPage<WkOrder> transfersPage(PageParam<Transfer, BaseParam> pageParam, QueryWrapper<Transfer> transferQueryWrapper);
    Transfer genOutStock(Transfer transfer, Long loginUserId);
    boolean removeTransfer(List<Long> list);
    IPage<LocItem> getLocsItems(OrgLocParams params, Long loginUserId);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderLogServiceImpl.java
@@ -53,7 +53,7 @@
                .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val);
        WkOrder wkOrder = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, orderLog.getCode()));
        if (Objects.isNull(wkOrder)) {
        if (!Objects.isNull(wkOrder)) {
            throw new CoolException("收货单据已添加,刷新后再操作!!");
        }
@@ -70,7 +70,7 @@
                BeanUtils.copyProperties(itemLog, item);
                item.setId(itemLog.getAsnItemId())
                        .setOrderId(order.getId())
                        .setMatnrId(Long.parseLong(itemLog.getMatnrId()))
                        .setMatnrId(itemLog.getMatnrId())
                        .setDeleted(0);
                orderItems.add(item);
            }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java
@@ -251,7 +251,7 @@
                throw new CoolException("库口不为空!!");
            }
            locItems.forEach(locItem -> {
                locItem.setSiteNo(deviceSite.getSite());
                locItem.setSite(deviceSite.getSite());
            });
        }
        return R.ok().add(locItems);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryItemServiceImpl.java
@@ -22,6 +22,7 @@
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@@ -50,6 +51,7 @@
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R excelImport(MultipartFile file, Map<String, Object> hashMap, Long loginUserId) throws Exception {
        ExcelImportResult result = ExcelImportUtil.importExcelMore(file.getInputStream(), DeliveryTemplate.class, ExcelUtil.getDefaultImportParams());
        if (result.getList().isEmpty()) {
@@ -116,6 +118,9 @@
                    sbFaild.append(orderTemplate.getMatnrCode()).append("物料不存在");
                    throw new CoolException(sbFaild.toString());
                }
                if (!matnr.getName().equals(orderTemplate.getMaktx())) {
                    throw new CoolException("导入物料名称与库内名称不一致!!");
                }
                orderItem.setDeliveryId(order.getId())
                        .setDeliveryCode(order.getCode())
                        .setSplrBatch(orderTemplate.getSplrBatch())
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeliveryServiceImpl.java
@@ -23,7 +23,7 @@
    @Override
    public Delivery removeDo(List<Long> list) {
        List<Delivery> deliveries = this.list(new LambdaQueryWrapper<Delivery>().eq(Delivery::getId, list));
        List<Delivery> deliveries = this.list(new LambdaQueryWrapper<Delivery>().in(Delivery::getId, list));
        if (deliveries.isEmpty()) {
            throw new BusinessException("数据错误:单据信息不存在!!");
        }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrServiceImpl.java
@@ -57,39 +57,43 @@
            throw new CoolException("物料导入失败!!");
        }
        List<Matnr> matnrs = new ArrayList<>();
        List<Map<String, String>> list = result.getList();
        List<MatnrsTemplate> list = result.getList();
        list.forEach(template -> {
            Matnr matnr = new Matnr();
            matnr.setBarcode(template.get("barcode"))
                    .setCode(template.get("code"))
                    .setDescrible(template.get("describle"))
                    .setColor(template.get("color"))
                    .setFlagCheck(!Objects.isNull(template.get("flagCheck")) ? Short.parseShort(template.get("flagCheck")) : 0)
                    .setWeight(!Objects.isNull(template.get("weight")) ? Double.parseDouble(template.get("weight")) : 0.0)
                    .setValidWarn(!Objects.isNull(template.get("validWarn")) ? Integer.parseInt(template.get("validWarn")): 0)
                    .setValid(!Objects.isNull(template.get("valid")) ? Integer.parseInt( template.get("valid")) : 0)
                    .setUnit(template.get("unit"))
                    .setStockUnit(template.get("purUnit"))
                    .setSpec(template.get("spec"))
                    .setStagn(!Objects.isNull(template.get("stagn")) ? Integer.parseInt(template.get("stagn")) : 0)
                    .setModel(template.get("model"))
                    .setGroupCode(template.get("groupCode"))
                    .setPurUnit(template.get("purUnit"))
                    .setStockLevel(!Objects.isNull(template.get("stockLevel")) ? Short.parseShort(template.get("stockLevel")) : 0)
                    .setSafeQty(!Objects.isNull(template.get("safeQty")) ? Double.parseDouble(template.get("safeQty")) : 0)
                    .setMinQty(!Objects.isNull(template.get("safeQty")) ? Double.parseDouble(template.get("minQty")) : 0);
            if (Objects.isNull(template.get("groupCode")) && Objects.isNull(template.get("groupName"))) {
            matnr.setBarcode(template.getBarcode())
                    .setCode(template.getCode())
                    .setName(template.getName())
                    .setDescrible(template.getDescrible())
                    .setColor(template.getColor())
                    .setFlagCheck(!Objects.isNull(template.getFlagCheck()) ? Short.parseShort(template.getFlagCheck()) : 0)
                    .setWeight(!Objects.isNull(template.getWeight()) ? Double.parseDouble(template.getWeight()) : 0.0)
                    .setValidWarn(!Objects.isNull(template.getValidWarn()) ? Integer.parseInt(template.getValidWarn()): 0)
                    .setValid(!Objects.isNull(template.getValid()) ? Integer.parseInt( template.getValid()) : 0)
                    .setUnit(template.getUnit())
                    .setStockUnit(template.getPurUnit())
                    .setShipperId(template.getShipperId())
                    .setSize(template.getSize())
                    .setSpec(template.getSpec())
                    .setStagn(!Objects.isNull(template.getStagn()) ? Integer.parseInt(template.getStagn()) : 0)
                    .setModel(template.getModel())
                    .setGroupCode(template.getGroupCode())
                    .setPurUnit(template.getPurUnit())
                    .setStockLevel(!Objects.isNull(template.getStockLevel()) ? Short.parseShort(template.getStockLevel()) : 0)
                    .setSafeQty(!Objects.isNull(template.getSafeQty()) ? Double.parseDouble(template.getSafeQty()) : 0)
                    .setMinQty(!Objects.isNull(template.getMinQty()) ? Double.parseDouble(template.getMinQty()) : 0);
            if (Objects.isNull(template.getGroupCode()) && Objects.isNull(template.getGroupName())) {
                MatnrGroup matnrGroups = matnrGroupService.getOne(new LambdaQueryWrapper<MatnrGroup>()
                        .eq(!Objects.isNull(template.get("groupCode")), MatnrGroup::getCode, template.get("groupCode"))
                        .eq(!Objects.isNull(template.get("groupName")),MatnrGroup::getName, template.get("groupName")));
                        .eq(!Objects.isNull(template.getGroupCode()), MatnrGroup::getCode, template.getGroupCode())
                        .eq(!Objects.isNull(template.getGroupName()),MatnrGroup::getName, template.getGroupName()));
                matnr.setGroupId(matnrGroups.getId());
            }
            //获取动态字段,并保存明细内容
            if (!FieldsUtils.getFieldsSta().isEmpty()) {
                //保存物料扩展属性值
                try {
                    Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(template), Map.class);
                    String uuid = CommonUtil.randomUUID16();
                    boolean b = FieldsUtils.saveFields(template, uuid);
                    boolean b = FieldsUtils.saveFields(map, uuid);
                    if (b) {
                        matnr.setFieldsIndex(uuid);
                    }
@@ -115,15 +119,15 @@
            if (null != group){
                pageParam.getWhere().getMap().remove("groupId");
                if(!group.getCode().equals("01")){
                    List<MatnrGroup> matnrGroups = matnrGroupService.list(new LambdaQueryWrapper<MatnrGroup>().eq(MatnrGroup::getParentId, Long.parseLong(groupId.toString())).select(MatnrGroup::getId));
                    List<MatnrGroup> matnrGroups = matnrGroupService.list(new LambdaQueryWrapper<MatnrGroup>()
                            .eq(MatnrGroup::getParentId, Long.parseLong(groupId.toString()))
                            .select(MatnrGroup::getId));
                    if (!matnrGroups.isEmpty()) {
                        longs = matnrGroups.stream().map(MatnrGroup::getId).collect(Collectors.toList());
                    }
                    longs.add(group.getId());
                }
            }
        }
        QueryWrapper<Matnr> queryWrapper = pageParam.buildWrapper(true);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -155,9 +155,7 @@
        if (!this.remove(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getId, id))) {
            throw new CoolException("主单删除失败!!");
        }
        if (!outStockItemService.remove(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, id))) {
            throw new CoolException("单据明细删除失败!!");
        }
        outStockItemService.remove(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, id));
        return R.ok("操作成功");
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -422,6 +422,7 @@
                //移库
                moveInStock(task, loginUserId);
            }
        }
    }
@@ -636,19 +637,14 @@
    @Synchronized
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeTask(List<Task> tasks) throws Exception {
    public void completeTask(List<Task> tasks) {
        Long loginUserId = SystemAuthUtils.getLoginUserId();
        for (Task task : tasks) {
            //出库任务
            if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) {
                //全托出库
            try {
                complateOutStock(task, loginUserId);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)) {
                //拣料出库
                complateOutStock(task, loginUserId);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_OUT.type)) {
                //盘点出库
                complateOutStock(task, loginUserId);
            } catch (Exception e) {
                throw new CoolException(e.getMessage());
            }
        }
    }
@@ -1148,14 +1144,9 @@
                    } catch (Exception e) {
                        throw new CoolException(e.getMessage());
                    }
                } else if (task.getResource().equals(TaskResouceType.TASK_RESOUCE_ORDER_TYPE.val) || task.getResource().equals(TaskResouceType.TASK_RESOUCE_CHECK_TYPE.val)) {
                    WkOrderItem orderItem = new WkOrderItem();
                    if (task.getResource().equals(TaskResouceType.TASK_RESOUCE_CHECK_TYPE.val)) {
                        CheckDiffItem diffItem = checkDiffItemService.getById(key);
                    } else {
                        orderItem = asnOrderItemService.getById(key);
                    }
                } else if (task.getResource().equals(TaskResouceType.TASK_RESOUCE_ORDER_TYPE.val)
                        || task.getResource().equals(TaskResouceType.TASK_RESOUCE_CHECK_TYPE.val)) {
                    WkOrderItem orderItem = asnOrderItemService.getById(key);
                    if (Objects.isNull(orderItem)) {
                        throw new CoolException("单据明细不存在!!");
                    }
@@ -1243,20 +1234,26 @@
                .setUpdateBy(loginUserId)
                .setUpdateTime(new Date())
                .setAnfme(sum);
        if (Objects.isNull(waveItem)) {
            stock.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type))
                    .setMemo("库存出库,无单据信息!!")
                    .setType(OrderType.ORDER_OUT.type);
        if (!Objects.isNull(waveItem)) {
            //TODO 生成波次时需要将波次号写入单据,通过物料,批次,动态字段等唯一值反查单据信息
            stock.setSourceId(waveItem.getId()).setType(OrderType.ORDER_OUT.type);
        } else if (!Objects.isNull(orderItem) && StringUtils.isNotBlank(orderItem.getId() + "")) {
            WkOrder wkOrder = asnOrderService.getById(orderItem.getOrderId());
            Double qty = Math.round((wkOrder.getQty() + sum) * 10000) / 10000.0;
            wkOrder.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)
                    .setQty(qty);
            if (!asnOrderService.updateById(wkOrder)) {
                throw new CoolException("出库单更新失败!!");
            }
            stock.setWkType(Short.parseShort(wkOrder.getWkType()))
                    .setType(OrderType.ORDER_OUT.type);
        } else if (!Objects.isNull(diffItem)) {
            stock.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.type))
                    .setType(OrderType.ORDER_CHECK.type);
        } else {
            //TODO 生成波次时需要将波次号写入单据,通过物料,批次,动态字段等唯一值反查单据信息
            stock.setSourceId(waveItem.getId()).setType(OrderType.ORDER_OUT.type);
            stock.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type))
                    .setMemo("库存出库,无单据信息!!")
                    .setType(OrderType.ORDER_OUT.type);
        }
        if (!stockService.save(stock)) {
            throw new CoolException("库存保存失败!!");
@@ -1277,7 +1274,6 @@
        if (!stockItemService.saveBatch(stockItems)) {
            throw new CoolException("库存修改架失败!!");
        }
    }
    /**
@@ -1445,8 +1441,7 @@
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveStockItems(List<TaskItem> items, Task task, Long id, String code, Short wkType, String type, Long loginUserId) throws
            Exception {
    public void saveStockItems(List<TaskItem> items, Task task, Long id, String code, Short wkType, String type, Long loginUserId) {
        Stock stock = new Stock();
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_STOCK_CODE, null);
        if (StringUtils.isBlank(ruleCode)) {
@@ -1491,5 +1486,14 @@
        if (!stockItemService.saveBatch(stockItems)) {
            throw new CoolException("库存修改架失败!!");
        }
        WkOrder order = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, code));
        if (!Objects.isNull(order)) {
//            Double qty = Math.round((order.getQty() + sum) * 10000) / 10000.0;
            order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_TASK_EXCE.val);
            if (!asnOrderService.updateById(order)) {
                throw new CoolException("入库单状态修改失败!!");
            }
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TransferItemServiceImpl.java
@@ -1,12 +1,72 @@
package com.vincent.rsf.server.manager.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.entity.Companys;
import com.vincent.rsf.server.manager.enums.CompanysType;
import com.vincent.rsf.server.manager.mapper.TransferItemMapper;
import com.vincent.rsf.server.manager.entity.TransferItem;
import com.vincent.rsf.server.manager.service.CompanysService;
import com.vincent.rsf.server.manager.service.TransferItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
import java.util.Objects;
@Service("transferItemService")
public class TransferItemServiceImpl extends ServiceImpl<TransferItemMapper, TransferItem> implements TransferItemService {
    @Autowired
    private CompanysService companysService;
    /**
     * @author Ryan
     * @date 2025/7/28
     * @description: 调拔单扩展字段保存
     * @version 1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean fieldsSave(Map<String, Object> params, Long loginUserId) {
        TransferItem wkOrderItem = JSONObject.parseObject(JSONObject.toJSONString(params), TransferItem.class);
        if (StringUtils.isNoneBlank(wkOrderItem.getSplrCode())) {
            Companys companys = companysService.getOne(new LambdaQueryWrapper<Companys>()
                    .eq(Companys::getId, wkOrderItem.getSplrCode())
                    .eq(Companys::getType, CompanysType.COMPANYS_TYPE_SUPPLIER.val));
            if (!Objects.isNull(companys)) {
                wkOrderItem.setSplrId(companys.getId());
            }
        }
        if (Objects.isNull(wkOrderItem.getAnfme()) || Double.compare(wkOrderItem.getAnfme(), 0.0) <= 0) {
            throw new CoolException("计划数不能为空!!");
        }
//        //保存扩展字段
        try {
            StringBuffer sb = new StringBuffer();
            if (Objects.isNull(wkOrderItem.getFieldsIndex()) || StringUtils.isBlank(wkOrderItem.getFieldsIndex())) {
                sb.append(wkOrderItem.getMatnrId() + wkOrderItem.getBatch());
                //获取16位uuid
                String uuid16 = Cools.md5Chinese(sb.toString());
                wkOrderItem.setFieldsIndex(uuid16);
                params.put("index", uuid16);
            }
            //保存或更新动态字段值
            FieldsUtils.updateFieldsValue(params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        wkOrderItem.setUpdateBy(loginUserId).setCreateBy(loginUserId);
        if (!this.saveOrUpdate(wkOrderItem)) {
            throw new CoolException("收货通知单明细保存失败!!");
        }
        return true;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TransferOrderServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.TransferOrderMapper;
import com.vincent.rsf.server.manager.entity.TransferOrder;
import com.vincent.rsf.server.manager.service.TransferOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("transferOrderService")
public class TransferOrderServiceImpl extends ServiceImpl<TransferOrderMapper, TransferOrder> implements TransferOrderService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TransferServiceImpl.java
@@ -1,12 +1,369 @@
package com.vincent.rsf.server.manager.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.domain.PageResult;
import com.vincent.rsf.server.manager.controller.params.OrgLocParams;
import com.vincent.rsf.server.manager.controller.params.TransferItemParams;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.mapper.TransferMapper;
import com.vincent.rsf.server.manager.entity.Transfer;
import com.vincent.rsf.server.manager.service.TransferService;
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
@Service("transferService")
public class TransferServiceImpl extends ServiceImpl<TransferMapper, Transfer> implements TransferService {
    @Autowired
    private TransferItemService transferItemService;
    @Autowired
    private WarehouseAreasService warehouseAreasService;
    @Autowired
    private OutStockService outStockService;
    @Autowired
    private OutStockItemService outStockItemService;
    @Autowired
    private TransferOrderService transferOrderService;
    @Autowired
    private TransferService transferService;
    @Autowired
    private AsnOrderService asnOrderService;
    @Autowired
    private AsnOrderItemService asnOrderItemService;
    @Autowired
    private LocItemService locItemService;
    @Autowired
    private LocService locService;
    /**
     * @author Ryan
     * @date 2025/7/25
     * @description: 保存调拔单及明细
     * @version 1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveTransfer(TransferItemParams params, Long loginUserId) {
        if (Objects.isNull(params.getTransfer())) {
            throw new CoolException("主单信息不能为空");
        }
        Transfer transfer = params.getTransfer();
        if (StringUtils.isBlank(transfer.getType() + "")) {
            throw new CoolException("业务类型不能为空!!");
        }
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TRANSFER_ORDER_CODE, transfer);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("编码规则错误:请检查「SYS_TRANSFER_ORDER_CODE」是否设置正确!!");
        }
        WarehouseAreas orgWarehosue = warehouseAreasService.getById(transfer.getOrgAreaId());
        if (Objects.isNull(orgWarehosue)) {
            throw new CoolException("所选原库区不存在!!");
        }
        WarehouseAreas tarWarehouse = warehouseAreasService.getById(transfer.getTarAreaId());
        if (Objects.isNull(tarWarehouse)) {
            throw new CoolException("所选目标库区不存在!!");
        }
        transfer.setCode(ruleCode)
                .setExceStatus(CheckExceStatus.CHECK_ORDER_STATUS_UN_EXCE.val)
                .setSource(OrderSourceType.ORDER_SOURCE_TYPE_SYSTEM.val)
                .setOrgAreaId(orgWarehosue.getId())
                .setOrgAreaName(orgWarehosue.getName())
                .setOrgWareId(orgWarehosue.getWarehouseId())
                .setOrgWareName(orgWarehosue.getWarehouseId$())
                .setTarAreaId(tarWarehouse.getId())
                .setTarWareId(tarWarehouse.getWarehouseId())
                .setTarAreaName(tarWarehouse.getName())
                .setTarWareName(tarWarehouse.getWarehouseId$())
                .setUpdateTime(new Date())
                .setCreateTime(new Date())
                .setUpdateBy(loginUserId)
                .setCreateBy(loginUserId);
        if (!this.save(transfer)) {
            throw new CoolException("主单保存失败!!");
        }
        if (params.getItems().isEmpty()) {
            throw new CoolException("收货通知单明细不能为空!!");
        }
        params.setTransfer(transfer);
        try {
            svaeOrUpdateOrderItem(params, loginUserId);
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
        /***保存成功,自动生成出库单*/
        genOutStock(transfer, loginUserId);
        return R.ok();
    }
    /**
     * @author Ryan
     * @date 2025/7/28
     * @description: 调拔单据修改
     * @version 1.0
     */
    private void svaeOrUpdateOrderItem(TransferItemParams params, Long loginUserId) {
        Transfer orders = params.getTransfer();
        params.getItems().forEach(item -> {
            item.put("transferId", orders.getId());
            item.put("transferCode", orders.getCode());
            item.put("createBy", loginUserId);
            item.put("updateBy", loginUserId);
            if (!transferItemService.fieldsSave(item, loginUserId)) {
                throw new CoolException("明细保存失败!!");
            }
        });
//        List<TransferItem> orderItems = transferItemService.list(new LambdaQueryWrapper<TransferItem>()
//                .eq(TransferItem::getTransferId, params.getTransfer().getId()));
//        Double sum = orderItems.stream().mapToDouble(TransferItem::getAnfme).sum();
        if (!this.updateById(orders)) {
            throw new CoolException("计划收货数量修改失败!!");
        }
    }
    /**
     * @author Ryan
     * @date 2025/7/25
     * @description: 调拔单及明细修改
     * @version 1.0
     */
    @Override
    public R updateTransfer(TransferItemParams params, Long loginUserId) {
        Transfer orders = params.getTransfer();
        if (Objects.isNull(orders)) {
            throw new CoolException("主单信息不能为空!!");
        }
        if (Objects.isNull(orders.getId())) {
            throw new CoolException("数据错误:单据ID不能为空!!");
        }
        if (!this.updateById(orders)) {
            throw new CoolException("主单修改失败!!");
        }
        if (Objects.isNull(params.getItems()) || params.getItems().isEmpty()) {
            return R.ok("明细参数不能为空!!");
        }
        svaeOrUpdateOrderItem(params, loginUserId);
        return R.ok("修改完成!!");
    }
    /**
     * @author Ryan
     * @date 2025/7/28
     * @description: 获取调拔单关联订单
     * @version 1.0
     */
    @Override
    public IPage<WkOrder> transfersPage(PageParam<Transfer, BaseParam> pageParam, QueryWrapper<Transfer> transferQueryWrapper) {
        Transfer one = this.getOne(transferQueryWrapper);
        if (Objects.isNull(one)) {
            throw new CoolException("单据不存在!!");
        }
        return this.baseMapper.transfersPage(pageParam, one.getId());
    }
    /**
     * @author Ryan
     * @date 2025/7/28
     * @description: 调拔单生成出库单
     * @version 1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Transfer genOutStock(Transfer param, Long loginUserId) {
        Transfer transfer = this.getById(param.getId());
        if (Objects.isNull(transfer)) {
            throw new CoolException("数据错误:单据不存在!!");
        }
        List<TransferItem> items = transferItemService.list(new LambdaQueryWrapper<TransferItem>().eq(TransferItem::getTransferId, transfer.getId()));
        if (items.isEmpty()) {
            throw new CoolException("数据错误:调拔单明细不存在!!");
        }
        WkOrder wkOrder = new WkOrder();
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, transfer);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("出库单生成失败!!");
        }
        Double anfmes = items.stream().mapToDouble(TransferItem::getAnfme).sum();
        wkOrder.setCode(ruleCode)
                .setAnfme(anfmes)
                .setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val)
                .setType(OrderType.ORDER_OUT.type)
                .setWkType(OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)
                .setCreateBy(loginUserId)
                .setUpdateBy(loginUserId)
                .setCreateTime(new Date())
                .setUpdateTime(new Date())
                .setPoCode(transfer.getCode())
                .setPoId(transfer.getId());
        if (!outStockService.saveOrUpdate(wkOrder)) {
            throw new CoolException("出库单保存失败!!");
        }
        List<WkOrderItem> orderItems = new ArrayList<>();
        items.forEach(item -> {
            WkOrderItem orderItem = new WkOrderItem();
            BeanUtils.copyProperties(item, orderItem);
            orderItem.setOrderCode(wkOrder.getCode())
                    .setSplrBatch(item.getBatch())
                    .setSplrCode(item.getSplrCode())
                    .setSplrName(item.getSplrName())
                    .setOrderId(wkOrder.getId());
            orderItems.add(orderItem);
        });
        if (!outStockItemService.saveBatch(orderItems)) {
            throw new CoolException("出库单明细保存失败!!");
        }
        transfer.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val);
        if (!this.updateById(transfer)) {
            throw new CoolException("调拔单更新失败!!");
        }
        TransferOrder transferOrder = new TransferOrder();
        transferOrder.setTransferId(transfer.getId())
                .setOrderId(wkOrder.getId())
                .setType(OrderType.ORDER_OUT.type);
        if (!transferOrderService.save(transferOrder)) {
            throw new CoolException("单据关联失败!!");
        }
        try {
            /**生成入库单据信息*/
            genInStock(wkOrder, orderItems);
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
        return transfer;
    }
    /**
     * @author Ryan
     * @date 2025/7/29
     * @description: TODO
     * @version 1.0
     */
    @Transactional(rollbackFor = Exception.class)
    public void genInStock(WkOrder wkOrder, List<WkOrderItem> orderItems) throws Exception {
        WkOrder order = new WkOrder();
        BeanUtils.copyProperties(wkOrder, order);
        order.setType(OrderType.ORDER_IN.type)
                .setWkType(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)
                .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)
                .setId(null);
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, order);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("入库单号生成失败!!");
        }
        order.setCode(ruleCode);
        if (!asnOrderService.save(order)) {
            throw new CoolException("单据保存失败!!");
        }
        orderItems.forEach(item -> {
            item.setOrderId(order.getId())
                    .setOrderCode(order.getCode())
                    .setId(null);
            if (!asnOrderItemService.save(item)) {
                throw new CoolException("入库单明细保存失败!!");
            }
        });
        TransferOrder transferOrder = new TransferOrder();
        transferOrder.setTransferId(wkOrder.getPoId())
                .setOrderId(order.getId())
                .setType(OrderType.ORDER_IN.type);
        if (!transferOrderService.save(transferOrder)) {
            throw new CoolException("单据关联失败!!");
        }
    }
    /**
     * @author Ryan
     * @date 2025/7/29
     * @description: 删除调拔单
     * @version 1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeTransfer(List<Long> list) {
        List<WkOrder> wkOrders = outStockService.list(new LambdaQueryWrapper<WkOrder>().in(WkOrder::getPoId, list));
        if (!wkOrders.isEmpty()) {
            Set<Long> longs = wkOrders.stream().map(WkOrder::getId).collect(Collectors.toSet());
            if (!outStockService.remove(new LambdaQueryWrapper<WkOrder>()
                    .in(WkOrder::getId, longs)
                    .eq(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val))) {
                throw new CoolException("当前出库单已执行,不支持删除!!");
            }
            outStockItemService.remove(new LambdaQueryWrapper<WkOrderItem>().in(WkOrderItem::getOrderId, longs));
            transferOrderService.remove(new LambdaQueryWrapper<TransferOrder>().in(TransferOrder::getTransferId, list));
        }
        transferService.removeByIds(list);
        transferItemService.remove(new LambdaQueryWrapper<TransferItem>().in(TransferItem::getTransferId, list));
        return true;
    }
    /**
     * @author Ryan
     * @date 2025/7/29
     * @description: 获取原库区物料信息
     * @version 1.0
     */
    @Override
    public IPage<LocItem> getLocsItems(OrgLocParams params, Long loginUserId) {
        List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type)
                .eq(!Objects.isNull(params.getOrgAreaId()), Loc::getAreaId, params.getOrgAreaId()));
        if (!locs.isEmpty()) {
            Page<LocItem> page = new Page<>(params.getCurrent(), params.getPageSize());
            QueryWrapper<LocItem> wrapper = new QueryWrapper<>();
            wrapper.select("id, matnr_id, maktx, matnr_code, SUM(anfme) anfme, SUM(work_qty) work_qty, SUM(qty) qty, batch, unit, fields_index, model, spec, loc_id, loc_code ")
                    .lambda()
                    .eq(StringUtils.isNotBlank(params.getMatnrCode()), LocItem::getMatnrCode, params.getMatnrCode())
                    .like(StringUtils.isNotBlank(params.getMaktx()), LocItem::getMaktx, params.getMaktx());
            Set<Long> locIds = locs.stream().map(Loc::getId).collect(Collectors.toSet());
            wrapper.lambda().in(LocItem::getLocId, locIds)
                    .groupBy(LocItem::getBatch, LocItem::getMatnrId);
            return locItemService.page(page, wrapper);
        } else {
            IPage<LocItem> page = new Page<>(params.getCurrent(), params.getPageSize());
            return page;
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java
@@ -142,7 +142,6 @@
                }
            }
            items.add(pakinItem);
        }
        Double sum1 = items.stream().mapToDouble(WaitPakinItem::getAnfme).sum();
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java
@@ -11,6 +11,7 @@
import com.vincent.rsf.server.manager.enums.WaveRuleType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.enums.LocStsType;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import java.math.BigDecimal;
@@ -29,7 +30,6 @@
    public static String getTargetLoc(Long areaId) {
        //TODO 库位策略后续排期
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getAreaId, areaId)
                .orderByAsc(Loc::getLev)
@@ -66,7 +66,7 @@
    public static List<LocItem> getEfficiencyFirstItemList(String matnrCode, String splrBatch, Double anfme) {
        LambdaQueryWrapper<LocItem> locItemQueryWrapper = new LambdaQueryWrapper<>();
        locItemQueryWrapper.eq(LocItem::getMatnrCode, matnrCode);
        locItemQueryWrapper.eq(LocItem::getBatch, splrBatch);
        locItemQueryWrapper.eq(StringUtils.isNotBlank(splrBatch), LocItem::getBatch, splrBatch);
        String applySql = String.format(
                "EXISTS (SELECT 1 FROM man_loc ml " +
                        "WHERE ml.use_status = '%s'" +
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/DictTypeCode.java
@@ -91,4 +91,9 @@
    public final static String SYS_CHECK_DIFF_REASON =  "sys_check_diff_reason";
    /**盘点类型*/
    public final static String SYS_CHECK_TYPE = "sys_check_type";
    /**单据来源*/
    public final static String SYS_ORDER_SOURCE = "sys_order_source";
    public final static String SYS_TRANSFER_TYPE = "sys_transfer_type";
}
rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java
@@ -88,5 +88,8 @@
    /**盘点单号*/
    public final static String SYS_CHECK_RULE_CODE = "sys_check_rule_code";
    /**调拔单编码规则*/
    public final static String SYS_TRANSFER_ORDER_CODE = "sys_transfer_order_code";
}
rsf-server/src/main/java/transferOrder.sql
New file
@@ -0,0 +1,24 @@
-- save transferOrder record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.transferOrder', '0', '/manager/transferOrder', 'transferOrder', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 调拔单订单关联表', '', '1', 'manager:transferOrder:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 调拔单订单关联表', '', '1', 'manager:transferOrder:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 调拔单订单关联表', '', '1', 'manager:transferOrder:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 调拔单订单关联表', '', '1', 'manager:transferOrder:remove', '3', '1', '1');
-- locale menu name
transferOrder: 'TransferOrder',
-- locale field
transferOrder: {
    transferId: "transferId",
    orderId: "orderId",
    exceStatus: "exceStatus",
},
-- ResourceContent
import transferOrder from './transferOrder';
case 'transferOrder':
    return transferOrder;
rsf-server/src/main/resources/mapper/manager/TransferMapper.xml
@@ -2,4 +2,36 @@
<!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.TransferMapper">
    <select id="transfersPage" resultType="com.vincent.rsf.server.manager.entity.WkOrder">
        SELECT
            id,
            `code`,
            `po_code`,
            `po_id`,
            `type`,
            `wk_type`,
            `anfme`,
            `qty`,
            `work_qty`,
            `warehouse_id`,
            `ware_area_id`,
            `wave_id`,
            `exce_status`,
            `update_time`,
            `create_time`,
            `update_by`,
            `create_by`,
            `update_by`
        FROM
            man_asn_order
        WHERE
            id IN (
                SELECT
                    order_id
                FROM
                    man_transfer_order
                WHERE
                    transfer_id = #{transferId}
            )
    </select>
</mapper>
rsf-server/src/main/resources/mapper/manager/TransferOrderMapper.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.TransferOrderMapper">
</mapper>