1
11 小时以前 e711c834aec2293c53b07efe53e81e3573c289b6
lsh#
25个文件已添加
27个文件已修改
3098 ■■■■ 已修改文件
rsf-admin/src/page/basStationType/BasStationTypeCreate.jsx 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basStationType/BasStationTypeEdit.jsx 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basStationType/BasStationTypeList.jsx 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basStationType/BasStationTypePanel.jsx 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basStationType/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehouseCreate.jsx 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehouseEdit.jsx 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehouseList.jsx 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehousePanel.jsx 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/matnrRestrictionWarehouse/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/basStationType.sql 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsStockTools.java 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/TaskInParam.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/mcp/McpController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/WcsService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/InBoundServiceImpl.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/utils/LocUtils.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationTypeController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrRestrictionWarehouseController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/GenerateTaskParams.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasContainer.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStation.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStationType.java 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MatnrRestrictionWarehouse.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BasStationTypeMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/MatnrRestrictionWarehouseMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AutoRunSchedules.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskMissionSchedules.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BasStationTypeService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrRestrictionWarehouseService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BasStationTypeServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeviceSiteServiceImpl.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java 111 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrRestrictionWarehouseServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/WarehouseLocationRetrievalUtil.java 534 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskPathTemplateMerge.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/matnrRestrictionWarehouse.sql 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/BasStationTypeMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/MatnrRestrictionWarehouseMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basStationType/BasStationTypeCreate.jsx
New file
@@ -0,0 +1,173 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    CreateBase,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SaveButton,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    Toolbar,
    required,
    useDataProvider,
    useNotify,
    Form,
    useCreateController,
} from 'react-admin';
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
const BasStationTypeCreate = (props) => {
    const { open, setOpen } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        notify('common.response.success');
    };
    const handleError = async (error) => {
        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
    };
    return (
        <>
            <CreateBase
                record={{}}
                transform={(data) => {
                    return data;
                }}
                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
            >
                <Dialog
                    open={open}
                    onClose={handleClose}
                    aria-labelledby="form-dialog-title"
                    fullWidth
                    disableRestoreFocus
                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
                >
                    <Form>
                        <DialogTitle id="form-dialog-title" sx={{
                            position: 'sticky',
                            top: 0,
                            backgroundColor: 'background.paper',
                            zIndex: 1000
                        }}
                        >
                            {translate('create.title')}
                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                                <DialogCloseButton onClose={handleClose} />
                            </Box>
                        </DialogTitle>
                        <DialogContent sx={{ mt: 2 }}>
                            <Grid container rowSpacing={2} columnSpacing={2}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basStationType.stationTypeCode"
                                        source="stationTypeCode"
                                        parse={v => v}
                                        autoFocus
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basStationType.stationTypeName"
                                        source="stationTypeName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowFullPalletOut"
                                        source="allowFullPalletOut"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowEmptyPalletOut"
                                        source="allowEmptyPalletOut"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowPick"
                                        source="allowPick"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowFullPalletIn"
                                        source="allowFullPalletIn"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowEmptyPalletIn"
                                        source="allowEmptyPalletIn"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.conveyorLine"
                                        source="conveyorLine"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowGroundStation"
                                        source="allowGroundStation"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStationType.allowGroundBarcodeStation"
                                        source="allowGroundBarcodeStation"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <StatusSelectInput />
                                </Grid>
                                <Grid item xs={12} display="flex" gap={1}>
                                    <Stack direction="column" spacing={1} width={'100%'}>
                                        <MemoInput />
                                    </Stack>
                                </Grid>
                            </Grid>
                        </DialogContent>
                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
                                <SaveButton />
                            </Toolbar>
                        </DialogActions>
                    </Form>
                </Dialog>
            </CreateBase>
        </>
    )
}
export default BasStationTypeCreate;
rsf-admin/src/page/basStationType/BasStationTypeEdit.jsx
New file
@@ -0,0 +1,145 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    Edit,
    SimpleForm,
    FormDataConsumer,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    SaveButton,
    Toolbar,
    Labeled,
    NumberField,
    required,
    useRecordContext,
    DeleteButton,
} from 'react-admin';
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const BasStationTypeEdit = () => {
    const translate = useTranslate();
    return (
        <Edit
            redirect="list"
            mutationMode={EDIT_MODE}
            actions={<CustomerTopToolBar />}
            aside={<EditBaseAside />}
        >
            <SimpleForm
                shouldUnregister
                warnWhenUnsavedChanges
                toolbar={<FormToolbar />}
                mode="onTouched"
                defaultValues={{}}
            // validate={(values) => { }}
            >
                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
                    <Grid item xs={12} md={8}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.main')}
                        </Typography>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.basStationType.stationTypeCode"
                                source="stationTypeCode"
                                parse={v => v}
                                autoFocus
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.basStationType.stationTypeName"
                                source="stationTypeName"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowFullPalletOut"
                                source="allowFullPalletOut"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowEmptyPalletOut"
                                source="allowEmptyPalletOut"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowPick"
                                source="allowPick"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowFullPalletIn"
                                source="allowFullPalletIn"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowEmptyPalletIn"
                                source="allowEmptyPalletIn"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.conveyorLine"
                                source="conveyorLine"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowGroundStation"
                                source="allowGroundStation"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basStationType.allowGroundBarcodeStation"
                                source="allowGroundBarcodeStation"
                            />
                        </Stack>
                    </Grid>
                    <Grid item xs={12} md={4}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.common')}
                        </Typography>
                        <StatusSelectInput />
                        <Box mt="2em" />
                        <MemoInput />
                    </Grid>
                </Grid>
            </SimpleForm>
        </Edit >
    )
}
export default BasStationTypeEdit;
rsf-admin/src/page/basStationType/BasStationTypeList.jsx
New file
@@ -0,0 +1,170 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import BasStationTypeCreate from "./BasStationTypeCreate";
import BasStationTypePanel from "./BasStationTypePanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
}));
const filters = [
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
    <TextInput source="stationTypeCode" label="table.field.basStationType.stationTypeCode" />,
    <TextInput source="stationTypeName" label="table.field.basStationType.stationTypeName" />,
    <NumberInput source="allowFullPalletOut" label="table.field.basStationType.allowFullPalletOut" />,
    <NumberInput source="allowEmptyPalletOut" label="table.field.basStationType.allowEmptyPalletOut" />,
    <NumberInput source="allowPick" label="table.field.basStationType.allowPick" />,
    <NumberInput source="allowFullPalletIn" label="table.field.basStationType.allowFullPalletIn" />,
    <NumberInput source="allowEmptyPalletIn" label="table.field.basStationType.allowEmptyPalletIn" />,
    <NumberInput source="conveyorLine" label="table.field.basStationType.conveyorLine" />,
    <NumberInput source="allowGroundStation" label="table.field.basStationType.allowGroundStation" />,
    <NumberInput source="allowGroundBarcodeStation" label="table.field.basStationType.allowGroundBarcodeStation" />,
    <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 BasStationTypeList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    return (
        <Box display="flex">
            <List
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.basStationType"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='basStationType' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='basStationType'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <BasStationTypePanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="stationTypeCode" label="table.field.basStationType.stationTypeCode" />
                    <TextField source="stationTypeName" label="table.field.basStationType.stationTypeName" />
                    <NumberField source="allowFullPalletOut" label="table.field.basStationType.allowFullPalletOut" />
                    <NumberField source="allowEmptyPalletOut" label="table.field.basStationType.allowEmptyPalletOut" />
                    <NumberField source="allowPick" label="table.field.basStationType.allowPick" />
                    <NumberField source="allowFullPalletIn" label="table.field.basStationType.allowFullPalletIn" />
                    <NumberField source="allowEmptyPalletIn" label="table.field.basStationType.allowEmptyPalletIn" />
                    <NumberField source="conveyorLine" label="table.field.basStationType.conveyorLine" />
                    <NumberField source="allowGroundStation" label="table.field.basStationType.allowGroundStation" />
                    <NumberField source="allowGroundBarcodeStation" label="table.field.basStationType.allowGroundBarcodeStation" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <BasStationTypeCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='BasStationType Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default BasStationTypeList;
rsf-admin/src/page/basStationType/BasStationTypePanel.jsx
New file
@@ -0,0 +1,111 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
import {
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import * as Common from '@/utils/common'
const BasStationTypePanel = () => {
    const record = useRecordContext();
    if (!record) return null;
    const translate = useTranslate();
    return (
        <>
            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
                <CardContent>
                    <Grid container spacing={2}>
                        <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
                            <Typography variant="h6" gutterBottom align="left" sx={{
                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
                                whiteSpace: 'nowrap',
                                overflow: 'hidden',
                                textOverflow: 'ellipsis',
                            }}>
                                {Common.camelToPascalWithSpaces(translate('table.field.basStationType.id'))}: {record.id}
                            </Typography>
                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
                            <Typography variant="h6" gutterBottom align="right" >
                                ID: {record.id}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid container spacing={2}>
                        <Grid item xs={12} container alignContent="flex-end">
                            <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Box height={20}>&nbsp;</Box>
                    <Grid container spacing={2}>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.stationTypeCode"
                                property={record.stationTypeCode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.stationTypeName"
                                property={record.stationTypeName}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowFullPalletOut"
                                property={record.allowFullPalletOut}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowEmptyPalletOut"
                                property={record.allowEmptyPalletOut}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowPick"
                                property={record.allowPick}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowFullPalletIn"
                                property={record.allowFullPalletIn}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowEmptyPalletIn"
                                property={record.allowEmptyPalletIn}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.conveyorLine"
                                property={record.conveyorLine}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowGroundStation"
                                property={record.allowGroundStation}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStationType.allowGroundBarcodeStation"
                                property={record.allowGroundBarcodeStation}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default BasStationTypePanel;
rsf-admin/src/page/basStationType/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import BasStationTypeList from "./BasStationTypeList";
import BasStationTypeEdit from "./BasStationTypeEdit";
export default {
    list: BasStationTypeList,
    edit: BasStationTypeEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehouseCreate.jsx
New file
@@ -0,0 +1,132 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    CreateBase,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SaveButton,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    Toolbar,
    required,
    useDataProvider,
    useNotify,
    Form,
    useCreateController,
} from 'react-admin';
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
const MatnrRestrictionWarehouseCreate = (props) => {
    const { open, setOpen } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        notify('common.response.success');
    };
    const handleError = async (error) => {
        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
    };
    return (
        <>
            <CreateBase
                record={{}}
                transform={(data) => {
                    return data;
                }}
                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
            >
                <Dialog
                    open={open}
                    onClose={handleClose}
                    aria-labelledby="form-dialog-title"
                    fullWidth
                    disableRestoreFocus
                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
                >
                    <Form>
                        <DialogTitle id="form-dialog-title" sx={{
                            position: 'sticky',
                            top: 0,
                            backgroundColor: 'background.paper',
                            zIndex: 1000
                        }}
                        >
                            {translate('create.title')}
                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                                <DialogCloseButton onClose={handleClose} />
                            </Box>
                        </DialogTitle>
                        <DialogContent sx={{ mt: 2 }}>
                            <Grid container rowSpacing={2} columnSpacing={2}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.matnrRestrictionWarehouse.productionLineCode"
                                        source="productionLineCode"
                                        parse={v => v}
                                        autoFocus
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.matnrRestrictionWarehouse.productionLineName"
                                        source="productionLineName"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.matnrRestrictionWarehouse.matnrRestrictionCode"
                                        source="matnrRestrictionCode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <StatusSelectInput />
                                </Grid>
                                <Grid item xs={12} display="flex" gap={1}>
                                    <Stack direction="column" spacing={1} width={'100%'}>
                                        <MemoInput />
                                    </Stack>
                                </Grid>
                            </Grid>
                        </DialogContent>
                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
                                <SaveButton />
                            </Toolbar>
                        </DialogActions>
                    </Form>
                </Dialog>
            </CreateBase>
        </>
    )
}
export default MatnrRestrictionWarehouseCreate;
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehouseEdit.jsx
New file
@@ -0,0 +1,104 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    Edit,
    SimpleForm,
    FormDataConsumer,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    SaveButton,
    Toolbar,
    Labeled,
    NumberField,
    required,
    useRecordContext,
    DeleteButton,
} from 'react-admin';
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const MatnrRestrictionWarehouseEdit = () => {
    const translate = useTranslate();
    return (
        <Edit
            redirect="list"
            mutationMode={EDIT_MODE}
            actions={<CustomerTopToolBar />}
            aside={<EditBaseAside />}
        >
            <SimpleForm
                shouldUnregister
                warnWhenUnsavedChanges
                toolbar={<FormToolbar />}
                mode="onTouched"
                defaultValues={{}}
            // validate={(values) => { }}
            >
                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
                    <Grid item xs={12} md={8}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.main')}
                        </Typography>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.matnrRestrictionWarehouse.productionLineCode"
                                source="productionLineCode"
                                parse={v => v}
                                autoFocus
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.matnrRestrictionWarehouse.productionLineName"
                                source="productionLineName"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.matnrRestrictionWarehouse.matnrRestrictionCode"
                                source="matnrRestrictionCode"
                                parse={v => v}
                            />
                        </Stack>
                    </Grid>
                    <Grid item xs={12} md={4}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.common')}
                        </Typography>
                        <StatusSelectInput />
                        <Box mt="2em" />
                        <MemoInput />
                    </Grid>
                </Grid>
            </SimpleForm>
        </Edit >
    )
}
export default MatnrRestrictionWarehouseEdit;
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehouseList.jsx
New file
@@ -0,0 +1,156 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import MatnrRestrictionWarehouseCreate from "./MatnrRestrictionWarehouseCreate";
import MatnrRestrictionWarehousePanel from "./MatnrRestrictionWarehousePanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
}));
const filters = [
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
    <TextInput source="productionLineCode" label="table.field.matnrRestrictionWarehouse.productionLineCode" />,
    <TextInput source="productionLineName" label="table.field.matnrRestrictionWarehouse.productionLineName" />,
    <TextInput source="matnrRestrictionCode" label="table.field.matnrRestrictionWarehouse.matnrRestrictionCode" />,
    <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 MatnrRestrictionWarehouseList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    return (
        <Box display="flex">
            <List
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.matnrRestrictionWarehouse"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='matnrRestrictionWarehouse' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='matnrRestrictionWarehouse'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <MatnrRestrictionWarehousePanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="productionLineCode" label="table.field.matnrRestrictionWarehouse.productionLineCode" />
                    <TextField source="productionLineName" label="table.field.matnrRestrictionWarehouse.productionLineName" />
                    <TextField source="matnrRestrictionCode" label="table.field.matnrRestrictionWarehouse.matnrRestrictionCode" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <MatnrRestrictionWarehouseCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='MatnrRestrictionWarehouse Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default MatnrRestrictionWarehouseList;
rsf-admin/src/page/matnrRestrictionWarehouse/MatnrRestrictionWarehousePanel.jsx
New file
@@ -0,0 +1,69 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
import {
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import * as Common from '@/utils/common'
const MatnrRestrictionWarehousePanel = () => {
    const record = useRecordContext();
    if (!record) return null;
    const translate = useTranslate();
    return (
        <>
            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
                <CardContent>
                    <Grid container spacing={2}>
                        <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
                            <Typography variant="h6" gutterBottom align="left" sx={{
                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
                                whiteSpace: 'nowrap',
                                overflow: 'hidden',
                                textOverflow: 'ellipsis',
                            }}>
                                {Common.camelToPascalWithSpaces(translate('table.field.matnrRestrictionWarehouse.id'))}: {record.id}
                            </Typography>
                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
                            <Typography variant="h6" gutterBottom align="right" >
                                ID: {record.id}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid container spacing={2}>
                        <Grid item xs={12} container alignContent="flex-end">
                            <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Box height={20}>&nbsp;</Box>
                    <Grid container spacing={2}>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.matnrRestrictionWarehouse.productionLineCode"
                                property={record.productionLineCode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.matnrRestrictionWarehouse.productionLineName"
                                property={record.productionLineName}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.matnrRestrictionWarehouse.matnrRestrictionCode"
                                property={record.matnrRestrictionCode}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default MatnrRestrictionWarehousePanel;
rsf-admin/src/page/matnrRestrictionWarehouse/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import MatnrRestrictionWarehouseList from "./MatnrRestrictionWarehouseList";
import MatnrRestrictionWarehouseEdit from "./MatnrRestrictionWarehouseEdit";
export default {
    list: MatnrRestrictionWarehouseList,
    edit: MatnrRestrictionWarehouseEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-server/src/main/java/basStationType.sql
New file
@@ -0,0 +1,31 @@
-- save basStationType record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.basStationType', '0', '/manager/basStationType', 'basStationType', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 作业站类型', '', '1', 'manager:basStationType:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 作业站类型', '', '1', 'manager:basStationType:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 作业站类型', '', '1', 'manager:basStationType:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 作业站类型', '', '1', 'manager:basStationType:remove', '3', '1', '1');
-- locale menu name
basStationType: 'BasStationType',
-- locale field
basStationType: {
    stationTypeCode: "stationTypeCode",
    stationTypeName: "stationTypeName",
    allowFullPalletOut: "allowFullPalletOut",
    allowEmptyPalletOut: "allowEmptyPalletOut",
    allowPick: "allowPick",
    allowFullPalletIn: "allowFullPalletIn",
    allowEmptyPalletIn: "allowEmptyPalletIn",
    conveyorLine: "conveyorLine",
    allowGroundStation: "allowGroundStation",
    allowGroundBarcodeStation: "allowGroundBarcodeStation",
},
-- ResourceContent
import basStationType from './basStationType';
case 'basStationType':
    return basStationType;
rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsStockTools.java
@@ -85,28 +85,28 @@
            @ToolParam(required = true, description = "作业类型列表") List<String> types,
            @ToolParam(description = "返回条数,默认 20,最大 50") Integer limit) {
        List<String> normalizedTypes = BuiltinToolGovernanceSupport.sanitizeStringList(types, "站点类型列表", 10, 32);
        int finalLimit = BuiltinToolGovernanceSupport.normalizeLimit(limit, 20, 50);
        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                .in(DeviceSite::getType, normalizedTypes)
                .orderByAsc(DeviceSite::getType)
                .orderByAsc(DeviceSite::getSite)
                .last("LIMIT " + finalLimit));
//        int finalLimit = BuiltinToolGovernanceSupport.normalizeLimit(limit, 20, 50);
//        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
//                .in(DeviceSite::getType, normalizedTypes)
//                .orderByAsc(DeviceSite::getType)
//                .orderByAsc(DeviceSite::getSite)
//                .last("LIMIT " + finalLimit));
        List<Map<String, Object>> result = new ArrayList<>();
        for (DeviceSite site : sites) {
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("id", site.getId());
            item.put("type", site.getType());
            item.put("site", site.getSite());
            item.put("name", site.getName());
            item.put("target", site.getTarget());
            item.put("label", site.getLabel());
            item.put("device", site.getDevice());
            item.put("deviceCode", site.getDeviceCode());
            item.put("deviceSite", site.getDeviceSite());
            item.put("channel", site.getChannel());
            item.put("status", site.getStatus());
            result.add(item);
        }
//        for (DeviceSite site : sites) {
//            Map<String, Object> item = new LinkedHashMap<>();
//            item.put("id", site.getId());
//            item.put("type", site.getType());
//            item.put("site", site.getSite());
//            item.put("name", site.getName());
//            item.put("target", site.getTarget());
//            item.put("label", site.getLabel());
//            item.put("device", site.getDevice());
//            item.put("deviceCode", site.getDeviceCode());
//            item.put("deviceSite", site.getDeviceSite());
//            item.put("channel", site.getChannel());
//            item.put("status", site.getStatus());
//            result.add(item);
//        }
        return result;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/TaskInParam.java
@@ -25,6 +25,9 @@
    @ApiModelProperty("任务编码")
    private String taskCode;
    @ApiModelProperty("库区ID")
    private Long areaId;
//    @ApiModelProperty("库位类型")
//    private String locType;
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/mcp/McpController.java
@@ -75,7 +75,8 @@
            longs = JSONArray.parseArray(map.get("type").toString(), String.class);
            map.entrySet().removeIf(next -> next.getKey().equals("type"));
        }
        List<DeviceSite> list = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, longs));
//        List<DeviceSite> list = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, longs));
        List<DeviceSite> list = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>());
        return R.ok().add(list);
    }
rsf-server/src/main/java/com/vincent/rsf/server/api/service/WcsService.java
@@ -11,6 +11,7 @@
    void agvTaskPickUpComplete(TaskInParam param);
    InTaskMsgDto getLocNo(TaskInParam param) throws Exception;
    InTaskMsgDto getLocNoArea(TaskInParam param) throws Exception;
    void syncLocsToWms();
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java
@@ -19,6 +19,7 @@
import com.vincent.rsf.server.manager.service.impl.DeviceSiteServiceImpl;
import com.vincent.rsf.server.manager.service.impl.MatnrServiceImpl;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -279,12 +280,12 @@
        if (Cools.isEmpty(area)) {
            throw new CoolException("目标库区不能为空");
        }
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getSite, sta)
                .eq(DeviceSite::getAreaIdEnd, Long.parseLong(area))
                .eq(DeviceSite::getType, TaskType.TASK_TYPE_IN.type).last("limit 1"));
        if (Cools.isEmpty(deviceSite)) {
        boolean isItAvailable = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableInArea(sta, area, waitPakinPda.getBarcode(), "in");
//        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                .eq(DeviceSite::getSite, sta)
//                .eq(DeviceSite::getAreaIdEnd, Long.parseLong(area))
//                .eq(DeviceSite::getType, TaskType.TASK_TYPE_IN.type).last("limit 1"));
        if (!isItAvailable) {
            throw new CoolException("无可用路径!!");
        }
@@ -307,7 +308,7 @@
        }
        String targetLoc = LocManageUtil.getTargetLoc(Long.parseLong(area));
        taskService.generateAGVTasks(waitPakin, targetLoc, sta, deviceSite.getDeviceCode(),loginUserId);
        taskService.generateAGVTasks(waitPakin, targetLoc, sta,loginUserId,area);
        if (!basStation.getType().equals(0)){
            basStation.setUseStatus(LocStsType.LOC_STS_TYPE_R.type);
        }
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/InBoundServiceImpl.java
@@ -15,6 +15,7 @@
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.extern.slf4j.Slf4j;
@@ -214,14 +215,20 @@
//                throw new CoolException("未找到所属库区信息");
            }
            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                    .eq(DeviceSite::getSite, station.getStationName())
                    .eq(DeviceSite::getAreaIdEnd, warehouseArea.getId())
                    .eq(DeviceSite::getType, TaskType.TASK_TYPE_EMPTY_IN.type).last("limit 1"));
            if (Cools.isEmpty(deviceSite)) {
            boolean isItAvailable = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableInArea(station.getStationName(),  warehouseArea.getId(), param.getContainerNo(), TaskType.TASK_TYPE_EMPTY_IN.type);
//            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                    .eq(DeviceSite::getSite, )
//                    .eq(DeviceSite::getAreaIdEnd,)
//                    .eq(DeviceSite::getType, TaskType.TASK_TYPE_EMPTY_IN.type).last("limit 1"));
//            if (Cools.isEmpty(deviceSite)) {
//                errorBuilder.append("无可用路径");
//                continue;
//                throw new CoolException("无可用路径!!");
//            }
            if (!isItAvailable){
                errorBuilder.append("无可用路径");
                continue;
//                throw new CoolException("无可用路径!!");
            }
//        BasContainer container = basContainerService.getOne(new LambdaUpdateWrapper<BasContainer>()
@@ -244,16 +251,7 @@
            if (StringUtils.isBlank(ruleCode)) {
                throw new CoolException("编码错误:请确认编码「SYS_TASK_CODE」是否已生成!!");
            }
            String stationName = null;
            if (Cools.isEmpty(deviceSite.getDeviceCode())) {
                stationName = station.getStationName();
            } else {
                BasStation stationCode = basStationService.getById(deviceSite.getDeviceCode());
                stationName = stationCode.getStationName();
                if (Cools.isEmpty(stationCode)) {
                    stationName = station.getStationName();
                }
            }
            String stationName = station.getStationName();
            Task task = new Task();
            task.setTaskCode(ruleCode)
                    .setTaskStatus(TaskStsType.MISSION_INITIAL.id)
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -21,6 +21,7 @@
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.mapper.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.BasStationServiceImpl;
import com.vincent.rsf.server.system.constant.CodeRes;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
@@ -131,6 +132,7 @@
    private BasContainerService basContainerService;
    @Resource
    private UserRoleService userRoleService;
    private BasStationServiceImpl basStationService;
    /**
     * @return
@@ -1180,11 +1182,12 @@
     */
    @Override
    public R getDeviceSites() {
        List<DeviceSite> sites = deviceSiteMapper.selectList(new LambdaQueryWrapper<DeviceSite>()
                .select(DeviceSite::getId, DeviceSite::getSite, DeviceSite::getName)
                .eq(DeviceSite::getStatus, 1)
                .groupBy(DeviceSite::getSite, DeviceSite::getId, DeviceSite::getName));
        return R.ok(sites);
//        List<DeviceSite> sites = deviceSiteMapper.selectList(new LambdaQueryWrapper<DeviceSite>()
//                .select(DeviceSite::getId, DeviceSite::getSite, DeviceSite::getName)
//                .eq(DeviceSite::getStatus, 1)
//                .groupBy(DeviceSite::getSite, DeviceSite::getId, DeviceSite::getName));
        List<BasStation> basStationList = basStationService.list(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStatus, 1));
        return R.ok(basStationList);
    }
    /**
@@ -1214,7 +1217,7 @@
        }
        GenerateTaskParams taskParams = new GenerateTaskParams();
        taskParams.setWaitPakins(waitPakins)
                .setSiteId(Long.parseLong(map.get("site").toString()))
                .setSiteNo(map.get("siteNo").toString())
                .setLocCode(map.get("locCode").toString());
        return R.ok(taskService.generateTasks(taskParams, loginUserId));
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -30,6 +30,7 @@
import com.vincent.rsf.server.manager.mapper.LocItemMapper;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.system.entity.*;
@@ -130,7 +131,7 @@
    public InTaskMsgDto createInTask(TaskInParam param) {
        // 验证设备站点
        DeviceSite deviceSite = validateDeviceSite(param);
//        DeviceSite deviceSite = validateDeviceSite(param);
        // 验证组拖状态
        WaitPakin waitPakin = validateWaitPakin(param.getBarcode());
@@ -148,7 +149,7 @@
        // 创建并保存任务
        Task task = createTask(ruleCode, locNo.getLocNo(), waitPakin.getBarcode(),
                deviceSite.getDeviceSite(), param.getSourceStaNo().toString(), param.getUser());
                null, param.getSourceStaNo().toString(), param.getUser());
        // 更新库位状态
        updateLocStatus(task.getTargLoc(), waitPakin.getBarcode());
@@ -171,16 +172,16 @@
    /**
     * 验证设备站点
     */
    private DeviceSite validateDeviceSite(TaskInParam param) {
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getSite, param.getSourceStaNo())
                .eq(DeviceSite::getType, param.getIoType()));
        if (Objects.isNull(deviceSite)) {
            throw new CoolException("站点不存在!!");
        }
        return deviceSite;
    }
//    private DeviceSite validateDeviceSite(TaskInParam param) {
//        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                .eq(DeviceSite::getSite, param.getSourceStaNo())
//                .eq(DeviceSite::getType, param.getIoType()));
//
//        if (Objects.isNull(deviceSite)) {
//            throw new CoolException("站点不存在!!");
//        }
//        return deviceSite;
//    }
    /**
     * 验证组拖状态
@@ -393,6 +394,42 @@
//        return locNo;
//    }
    @Override
    public InTaskMsgDto getLocNoArea(TaskInParam param) throws Exception {
        String matnr = null;
        String batch = null;
        List<WaitPakin> waitPakins = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>().eq(WaitPakin::getBarcode, param.getBarcode()));
        if (Cools.isEmpty(waitPakins) && param.getIoType().equals(TaskType.TASK_TYPE_IN.type)) {
            throw new CoolException("未找到组托信息,请组托");
        } else if (!Cools.isEmpty(waitPakins)) {
            matnr = waitPakins.get(0).getCode();
            batch = waitPakins.get(0).getCode();
        }
        DeviceBind deviceBind = deviceBindService.getById(LocUtils.getAreaType(param.getSourceStaNo()));
        if (Cools.isEmpty(deviceBind)) {
            throw new CoolException("数据异常,请联系管理员===>库位规则未知");
        }
        WarehouseAreas warehouseArea = warehouseAreasService.getById(deviceBind.getTypeId());
        if (Cools.isEmpty(warehouseArea)) {
            throw new CoolException("未找到所属库区信息");
        }
        LocTypeDto locTypeDto = new LocTypeDto(param);
        InTaskMsgDto dto = null;
        //根据立库类型获取获取库位
        if (warehouseArea.getType().equals(WarehType.WAREHOUSE_TYPE_CRN.val)) {
            //堆垛机
            dto = getLocNoCrn(param.getOrgLoc(), deviceBind, warehouseArea.getId(), param.getSourceStaNo(), matnr, batch, locTypeDto, 0, param.getIoType());
        } else if (warehouseArea.getType().equals(WarehType.WAREHOUSE_TYPE_FOUR_DIRECTIONS.val)) {
            //四向库
        } else {
            //CTU 库以及其它
            dto = getLocNoCtu(deviceBind, warehouseArea.getId(), param.getSourceStaNo(), matnr, batch, locTypeDto, 0, param.getIoType());
        }
        return dto;
    }
    @Override
    public InTaskMsgDto getLocNo(TaskInParam param) throws Exception {
        String matnr = null;
        String batch = null;
@@ -403,13 +440,13 @@
            matnr = waitPakins.get(0).getCode();
            batch = waitPakins.get(0).getCode();
        }
        List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getSite, param.getSourceStaNo())
                .eq(DeviceSite::getType, param.getIoType())
        );
        if (Cools.isEmpty(deviceSites)) {
            throw new CoolException("未找到站点路径信息");
        }
//        List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
//                .eq(DeviceSite::getSite, param.getSourceStaNo())
//                .eq(DeviceSite::getType, param.getIoType())
//        );
//        if (Cools.isEmpty(deviceSites)) {
//            throw new CoolException("未找到站点路径信息");
//        }
        DeviceBind deviceBind = deviceBindService.getById(LocUtils.getAreaType(param.getSourceStaNo()));
        if (Cools.isEmpty(deviceBind)) {
            throw new CoolException("数据异常,请联系管理员===>库位规则未知");
@@ -730,40 +767,22 @@
            }
        }
//        // 靠近摆放规则 --- 空托 //互通版
//        if (ioType == 10 && deviceBind.getEmptySimilar().equals("1")) {
//            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
//                    .eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow).eq("whs_type", rowLastnoType.getType().longValue()));
//            if (!locMasts.isEmpty()) {
//                for (LocMast loc : locMasts) {
//                    if (Utils.isShallowLoc(slaveProperties, loc.getLocNo())) {
//                        continue;
//                    }
//                    String shallowLocNo = Utils.getShallowLoc(slaveProperties, loc.getLocNo());
//                    // 检测目标库位是否为空库位
//                    LocMast shallowLoc = locMastService.selectById(shallowLocNo);
//                    if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) {
//                        if (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
//                            if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
//                                locMast = shallowLoc;
//                                crnNo = locMast.getCrnNo();
//                                break;
//                            }
//                        }
//                    }
//                }
//            }
//        }
        if (loc != null) {
        //查找路径
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getType, ioType)
                .eq(DeviceSite::getSite, sourceStaNo)
                .eq(DeviceSite::getChannel, channel).last("limit 1")
        );
        if (Cools.isEmpty(deviceSite)) {
            boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableInArea(sourceStaNo, loc.getAreaId().toString() ,loc.getBarcode(),"in");
//            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                    .eq(DeviceSite::getType, ioType)
//                    .eq(DeviceSite::getSite, sourceStaNo)
//                    .eq(DeviceSite::getChannel, channel).last("limit 1")
//            );
            if (!available) {
            channel = 0;
                loc = null;
        } else {
            inTaskMsgDto.setStaNo(deviceSite.getDeviceSite());
                inTaskMsgDto.setStaNo(sourceStaNo);
            }
        }
        //更新当前排
@@ -891,6 +910,23 @@
                }
            }
        }
        if (loc != null) {
            //查找路径
            boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableInArea(sourceStaNo, loc.getAreaId().toString() ,loc.getBarcode(),"in");
//            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                    .eq(DeviceSite::getType, ioType)
//                    .eq(DeviceSite::getSite, sourceStaNo)
//                    .eq(DeviceSite::getChannel, channel).last("limit 1")
//            );
            if (!available) {
                channel = 0;
                loc = null;
            } else {
                inTaskMsgDto.setStaNo(sourceStaNo);
            }
        }
        //查询当前库位类型空库位 小于5个则locmast = null
        List<Loc> locTypeLocMasts = locService.list(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
@@ -954,18 +990,34 @@
            loc = loc2;
            break;
        }
        //查找路径
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getType, ioType)
                .eq(DeviceSite::getSite, sourceStaNo)
                .eq(!Objects.isNull(loc.getDeviceNo()), DeviceSite::getDeviceCode, loc.getDeviceNo())
        );
        if (Cools.isEmpty(deviceSite)) {
        if (loc != null) {
            //查找路径
            boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableInArea(sourceStaNo, loc.getAreaId().toString() ,loc.getBarcode(),"in");
//            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                    .eq(DeviceSite::getType, ioType)
//                    .eq(DeviceSite::getSite, sourceStaNo)
//                    .eq(DeviceSite::getChannel, channel).last("limit 1")
//            );
            if (!available) {
            deviceNo = 0;
            loc = null;
        } else {
            inTaskMsgDto.setStaNo(deviceSite.getDeviceSite());
                inTaskMsgDto.setStaNo(sourceStaNo);
        }
        }
//        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                .eq(DeviceSite::getType, ioType)
//                .eq(DeviceSite::getSite, sourceStaNo)
//                .eq(!Objects.isNull(loc.getDeviceNo()), DeviceSite::getDeviceCode, loc.getDeviceNo())
//        );
//        if (Cools.isEmpty(deviceSite)) {
//            deviceNo = 0;
//            loc = null;
//        } else {
//            inTaskMsgDto.setStaNo(deviceSite.getDeviceSite());
//        }
        // 递归查询
        if (Cools.isEmpty(loc) || !loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
rsf-server/src/main/java/com/vincent/rsf/server/api/utils/LocUtils.java
@@ -346,17 +346,6 @@
//                }
//            }
//        }
        //查找路径
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getType, ioType)
                .eq(DeviceSite::getSite, sourceStaNo)
                .eq(DeviceSite::getChannel, channel)
        );
        if (Cools.isEmpty(deviceSite)) {
            channel = 0;
        } else {
            inTaskMsgDto.setStaNo(deviceSite.getDeviceSite());
        }
        //更新当前排
        deviceBind.setCurrentRow(curRow);
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_bas_station_area";
        generator.tableDesc = "物料权限";
        generator.table = "man_matnr_restriction_warehouse";
        generator.tableDesc = "物料限制";
        generator.packagePath = "com.vincent.rsf.server.manager";
        generator.build();
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationTypeController.java
New file
@@ -0,0 +1,110 @@
package com.vincent.rsf.server.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.common.annotation.OperationLog;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.BasStationType;
import com.vincent.rsf.server.manager.service.BasStationTypeService;
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 jakarta.servlet.http.HttpServletResponse;
import java.util.*;
@RestController
public class BasStationTypeController extends BaseController {
    @Autowired
    private BasStationTypeService basStationTypeService;
    @PreAuthorize("hasAuthority('manager:basStationType:list')")
    @PostMapping("/basStationType/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<BasStationType, BaseParam> pageParam = new PageParam<>(baseParam, BasStationType.class);
        return R.ok().add(basStationTypeService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:basStationType:list')")
    @PostMapping("/basStationType/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(basStationTypeService.list());
    }
    @PreAuthorize("hasAuthority('manager:basStationType:list')")
    @PostMapping({"/basStationType/many/{ids}", "/basStationTypes/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(basStationTypeService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:basStationType:list')")
    @GetMapping("/basStationType/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(basStationTypeService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:basStationType:save')")
    @OperationLog("Create 作业站类型")
    @PostMapping("/basStationType/save")
    public R save(@RequestBody BasStationType basStationType) {
//        basStationType.setCreateBy(getLoginUserId());
//        basStationType.setCreateTime(new Date());
//        basStationType.setUpdateBy(getLoginUserId());
//        basStationType.setUpdateTime(new Date());
//        if (!basStationTypeService.save(basStationType)) {
//            return R.error("Save Fail");
//        }
        return R.ok("Save Success").add(basStationType);
    }
    @PreAuthorize("hasAuthority('manager:basStationType:update')")
    @OperationLog("Update 作业站类型")
    @PostMapping("/basStationType/update")
    public R update(@RequestBody BasStationType basStationType) {
//        basStationType.setUpdateBy(getLoginUserId());
//        basStationType.setUpdateTime(new Date());
//        if (!basStationTypeService.updateById(basStationType)) {
//            return R.error("Update Fail");
//        }
        return R.ok("Update Success").add(basStationType);
    }
    @PreAuthorize("hasAuthority('manager:basStationType:remove')")
    @OperationLog("Delete 作业站类型")
    @PostMapping("/basStationType/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!basStationTypeService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:basStationType:list')")
    @PostMapping("/basStationType/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<BasStationType> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(BasStationType::getId, condition);
        }
        basStationTypeService.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:basStationType:list')")
    @PostMapping("/basStationType/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(basStationTypeService.list(), BasStationType.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrRestrictionWarehouseController.java
New file
@@ -0,0 +1,110 @@
package com.vincent.rsf.server.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.common.annotation.OperationLog;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.MatnrRestrictionWarehouse;
import com.vincent.rsf.server.manager.service.MatnrRestrictionWarehouseService;
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 jakarta.servlet.http.HttpServletResponse;
import java.util.*;
@RestController
public class MatnrRestrictionWarehouseController extends BaseController {
    @Autowired
    private MatnrRestrictionWarehouseService matnrRestrictionWarehouseService;
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:list')")
    @PostMapping("/matnrRestrictionWarehouse/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<MatnrRestrictionWarehouse, BaseParam> pageParam = new PageParam<>(baseParam, MatnrRestrictionWarehouse.class);
        return R.ok().add(matnrRestrictionWarehouseService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:list')")
    @PostMapping("/matnrRestrictionWarehouse/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(matnrRestrictionWarehouseService.list());
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:list')")
    @PostMapping({"/matnrRestrictionWarehouse/many/{ids}", "/matnrRestrictionWarehouses/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(matnrRestrictionWarehouseService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:list')")
    @GetMapping("/matnrRestrictionWarehouse/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(matnrRestrictionWarehouseService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:save')")
    @OperationLog("Create 物料限制")
    @PostMapping("/matnrRestrictionWarehouse/save")
    public R save(@RequestBody MatnrRestrictionWarehouse matnrRestrictionWarehouse) {
        matnrRestrictionWarehouse.setCreateBy(getLoginUserId());
        matnrRestrictionWarehouse.setCreateTime(new Date());
        matnrRestrictionWarehouse.setUpdateBy(getLoginUserId());
        matnrRestrictionWarehouse.setUpdateTime(new Date());
        if (!matnrRestrictionWarehouseService.save(matnrRestrictionWarehouse)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(matnrRestrictionWarehouse);
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:update')")
    @OperationLog("Update 物料限制")
    @PostMapping("/matnrRestrictionWarehouse/update")
    public R update(@RequestBody MatnrRestrictionWarehouse matnrRestrictionWarehouse) {
        matnrRestrictionWarehouse.setUpdateBy(getLoginUserId());
        matnrRestrictionWarehouse.setUpdateTime(new Date());
        if (!matnrRestrictionWarehouseService.updateById(matnrRestrictionWarehouse)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(matnrRestrictionWarehouse);
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:remove')")
    @OperationLog("Delete 物料限制")
    @PostMapping("/matnrRestrictionWarehouse/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!matnrRestrictionWarehouseService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:matnrRestrictionWarehouse:list')")
    @PostMapping("/matnrRestrictionWarehouse/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<MatnrRestrictionWarehouse> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(MatnrRestrictionWarehouse::getId, condition);
        }
        matnrRestrictionWarehouseService.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:matnrRestrictionWarehouse:list')")
    @PostMapping("/matnrRestrictionWarehouse/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(matnrRestrictionWarehouseService.list(), MatnrRestrictionWarehouse.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/GenerateTaskParams.java
@@ -27,6 +27,10 @@
    @ApiModelProperty("站点ID")
    public Long siteId;
    @ApiModelProperty("站点名称")
    public String siteNo;
    @ApiModelProperty("库位编码")
    public String locCode;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java
@@ -13,7 +13,7 @@
@ApiModel(value = "WaitPakinParam", description = "组拖参数")
public class WaitPakinParam implements Serializable {
    @ApiModelProperty("拖盘码")
    @ApiModelProperty("托盘码")
    private String barcode;
    @ApiModelProperty("跟踪码")
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasContainer.java
@@ -52,9 +52,9 @@
    private Long containerType;
    /**
     * 容器条码类型
     * 容器条码规则
     */
    @ApiModelProperty(value = "容器条码类型")
    @ApiModelProperty(value = "容器条码规则")
    private String codeType;
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStation.java
@@ -193,6 +193,12 @@
    @ApiModelProperty(value = "仓库名称")
    private String productionLineName;
    /**
     * 仓库名称
     */
    @ApiModelProperty(value = "仓库名称")
    private String stationTypeCode;
    public BasStation() {
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStationType.java
New file
@@ -0,0 +1,188 @@
package com.vincent.rsf.server.manager.entity;
import com.baomidou.mybatisplus.annotation.TableLogic;
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 com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.entity.User;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Data
@TableName("man_bas_station_type")
public class BasStationType implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @ApiModelProperty(value= "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 编码
     */
    @ApiModelProperty(value= "编码")
    private String stationTypeCode;
    /**
     * 名称
     */
    @ApiModelProperty(value= "名称")
    private String stationTypeName;
    /**
     * 状态
     */
    @ApiModelProperty(value= "状态")
    private Integer status;
    /**
     * 全板出库
     */
    @ApiModelProperty(value= "全板出库")
    private Integer allowFullPalletOut;
    /**
     * 空板出库
     */
    @ApiModelProperty(value= "空板出库")
    private Integer allowEmptyPalletOut;
    /**
     * 拣选
     */
    @ApiModelProperty(value= "拣选")
    private Integer allowPick;
    /**
     * 入库
     */
    @ApiModelProperty(value= "入库")
    private Integer allowFullPalletIn;
    /**
     * 空板入库
     */
    @ApiModelProperty(value= "空板入库")
    private Integer allowEmptyPalletIn;
    /**
     * 输送线
     */
    @ApiModelProperty(value= "输送线")
    private Integer conveyorLine;
    /**
     * 地面站
     */
    @ApiModelProperty(value= "地面站")
    private Integer allowGroundStation;
    /**
     * 地面条码站
     */
    @ApiModelProperty(value= "地面条码站")
    private Integer allowGroundBarcodeStation;
    @ApiModelProperty(value= "")
    @TableLogic
    private Integer deleted;
    @ApiModelProperty(value= "")
    private Long tenantId;
    @ApiModelProperty(value= "类型集合")
    private List<String> taskType;
    /**
     * 添加人员
     */
    @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")
    private Date createTime;
    /**
     * 修改人员
     */
    @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")
    private Date updateTime;
    public BasStationType() {}
    public BasStationType(String stationTypeCode,String stationTypeName,Integer status,Integer allowFullPalletOut,Integer allowEmptyPalletOut,Integer allowPick,Integer allowFullPalletIn,Integer allowEmptyPalletIn,Integer conveyorLine,Integer allowGroundStation,Integer allowGroundBarcodeStation,Integer deleted,Long tenantId) {
        this.stationTypeCode = stationTypeCode;
        this.stationTypeName = stationTypeName;
        this.status = status;
        this.allowFullPalletOut = allowFullPalletOut;
        this.allowEmptyPalletOut = allowEmptyPalletOut;
        this.allowPick = allowPick;
        this.allowFullPalletIn = allowFullPalletIn;
        this.allowEmptyPalletIn = allowEmptyPalletIn;
        this.conveyorLine = conveyorLine;
        this.allowGroundStation = allowGroundStation;
        this.allowGroundBarcodeStation = allowGroundBarcodeStation;
        this.deleted = deleted;
        this.tenantId = tenantId;
    }
//    BasStationType basStationType = new BasStationType(
//            null,    // 编码
//            null,    // 名称
//            null,    // 状态
//            null,    // 全板出库
//            null,    // 空板出库
//            null,    // 拣选
//            null,    // 入库
//            null,    // 空板入库
//            null,    // 输送线
//            null,    // 地面站
//            null,    // 地面条码站
//            null,    //
//            null    //
//    );
    public Boolean getStatusBool(){
        if (null == this.status){ return null; }
        switch (this.status){
            case 1:
                return true;
            case 0:
                return false;
            default:
                return null;
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Matnr.java
@@ -5,6 +5,7 @@
import java.text.SimpleDateFormat;
import java.util.*;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.vincent.rsf.server.manager.service.BatchRegularService;
import com.vincent.rsf.server.manager.service.CompanysService;
@@ -29,7 +30,7 @@
import java.util.Date;
@Data
@TableName("man_matnr")
@TableName(value = "man_matnr", autoResultMap = true)
@Accessors(chain = true)
@ApiModel(value = "Matnr", description = "物料所有基础属性")
public class Matnr implements Serializable {
@@ -277,6 +278,19 @@
    private String erpClsId;
    /**
     * 仓库限制名称
     */
    @ApiModelProperty(value= "仓库限制编码")
    private String warehouseRestrictionCode;
    /**
     * 容器类型
     */
    @ApiModelProperty(value= "容器类型集合")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<Integer> containerTypes;
    /**
     * 备注
     */
    @ApiModelProperty(value= "分类列表")
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MatnrRestrictionWarehouse.java
New file
@@ -0,0 +1,106 @@
package com.vincent.rsf.server.manager.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.entity.User;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Data
@TableName(value = "man_matnr_restriction_warehouse", autoResultMap = true)
public class MatnrRestrictionWarehouse implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @ApiModelProperty(value= "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 仓库编码
     */
    @ApiModelProperty(value= "仓库编码")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<Integer> productionLineCode;
    /**
     * 仓库
     */
    @ApiModelProperty(value= "仓库")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<String> productionLineName;
    /**
     * 限制编码
     */
    @ApiModelProperty(value= "限制编码")
    private String matnrRestrictionCode;
    @ApiModelProperty(value= "")
    private Integer status;
    @ApiModelProperty(value= "")
    private Long tenantId;
    @ApiModelProperty(value= "")
    @TableLogic
    private Integer deleted;
    /**
     * 添加人员
     */
    @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")
    private Date createTime;
    /**
     * 修改人员
     */
    @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")
    private Date updateTime;
    public MatnrRestrictionWarehouse() {}
    public Boolean getStatusBool(){
        if (null == this.status){ return null; }
        switch (this.status){
            case 1:
                return true;
            case 0:
                return false;
            default:
                return null;
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java
@@ -40,6 +40,8 @@
            return TaskType.TASK_TYPE_IN.desc;
        } else if (TaskType.TASK_TYPE_EMPTY_IN.type.equals(type)) {
            return TaskType.TASK_TYPE_EMPTY_IN.desc;
        } else if (TaskType.TASK_TYPE_LOC_MOVE.type.equals(type)) {
            return TaskType.TASK_TYPE_LOC_MOVE.desc;
        } else if (TaskType.TASK_TYPE_OUT.type.equals(type)) {
            return TaskType.TASK_TYPE_OUT.desc;
        } else if (TaskType.TASK_TYPE_PICK_IN.type.equals(type)) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BasStationTypeMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.BasStationType;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BasStationTypeMapper extends BaseMapper<BasStationType> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/MatnrRestrictionWarehouseMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.MatnrRestrictionWarehouse;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface MatnrRestrictionWarehouseMapper extends BaseMapper<MatnrRestrictionWarehouse> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AutoRunSchedules.java
@@ -14,6 +14,7 @@
import com.vincent.rsf.server.manager.enums.TaskStsType;
import com.vincent.rsf.server.manager.enums.TaskType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.entity.Config;
import com.vincent.rsf.server.system.service.ConfigService;
@@ -221,25 +222,25 @@
                });
                List<BasStation> stations = stationService.list(new LambdaQueryWrapper<BasStation>()
                        .eq(BasStation::getStatus, 1)
                        .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type));
                );
//                        .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                List<String> stationNames = stations.stream().map(BasStation::getStationName).collect(Collectors.toList());
                if (Cools.isEmpty(stations)) {
                    throw new CoolException("无可用站点!!");
                }
                DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                        .in(DeviceSite::getSite, stationNames)
                        .eq(DeviceSite::getType, TaskType.TASK_TYPE_CHECK_OUT.type).last("limit 1"));
                if (Cools.isEmpty(deviceSite)) {
                    throw new CoolException("无可用路径!!");
                for (String stationName : stationNames) {
                    boolean isItAvailable = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId(), stationName, loc.getBarcode(), TaskType.TASK_TYPE_CHECK_OUT.type);
                    if (!isItAvailable) {
                        continue;
                }
                //生成盘点任务参数
                LocToTaskParams locToTaskParams = new LocToTaskParams();
                locToTaskParams.setType(Constants.TASK_TYPE_OUT_CHECK)
                        .setItems(locItems)
                        .setSiteNo(deviceSite.getSite())
                            .setSiteNo(stationName)
                        .setOrgLoc(loc.getCode());
                List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTargSite, deviceSite.getSite()));
                    List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTargSite, stationName));
                if (!tasks.isEmpty()) {
                    continue;
                }
@@ -250,6 +251,7 @@
                }
            }
        }
        }
        // 入库 应该根据工作档回去
//        this.runStaToLoc(locGroupList, staGroupList, staTaskMemo);
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskMissionSchedules.java
@@ -13,6 +13,7 @@
import com.vincent.rsf.server.manager.service.impl.BasStationAreaServiceImpl;
import com.vincent.rsf.server.manager.service.impl.BasStationServiceImpl;
import com.vincent.rsf.server.manager.service.impl.DeviceSiteServiceImpl;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.entity.*;
import com.vincent.rsf.server.system.service.ConfigService;
@@ -132,9 +133,21 @@
                Loc loc2 = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getOrgLoc()));
                sou = loc2.getAreaId().toString();
            }
            List<TaskPathTemplateMerge> taskPathTemplateMergeList = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>().eq(TaskPathTemplateMerge::getSourceType, sou).eq(TaskPathTemplateMerge::getTargetType, end));
            BasContainer containerByBarcode = new WarehouseLocationRetrievalUtil().getContainerByBarcode(task.getBarcode());
            List<TaskPathTemplateMerge> taskPathTemplateMergeList = taskPathTemplateMergeService.list(
                    new LambdaQueryWrapper<TaskPathTemplateMerge>()
                            .eq(TaskPathTemplateMerge::getSourceType, sou)
                            .eq(TaskPathTemplateMerge::getTargetType, end)
                            .apply("container_type != '[]'")  // 不是空数组
                            .apply("JSON_CONTAINS(container_type, {0}) = 1", containerByBarcode.getContainerType().toString())
            );
            if (Objects.isNull(taskPathTemplateMergeList) || taskPathTemplateMergeList.isEmpty() || !endSign) {
                List<TaskPathTemplateMerge> list = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>().eq(TaskPathTemplateMerge::getStepSize,1));
                List<TaskPathTemplateMerge> list = taskPathTemplateMergeService.list(
                        new LambdaQueryWrapper<TaskPathTemplateMerge>()
                                .eq(TaskPathTemplateMerge::getStepSize,1)
                                .apply("container_type != '[]'")  // 不是空数组
                                .apply("JSON_CONTAINS(container_type, {0}) = 1", containerByBarcode.getContainerType().toString())
                );
                if (!Cools.isEmpty(list)) {
                    List<String[]> stationList = new ArrayList<>();
                    list.forEach(taskPathTemplate -> {
@@ -196,11 +209,8 @@
                                    if (!siteListRoute.isEmpty()) {
                                        for (String[] siteArray : siteListRoute) {
                                            //出库路径排查
                                            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                                                    .eq(DeviceSite::getSite, siteArray[1])
                                                    .eq(!Objects.isNull(loc.getChannel()),DeviceSite::getChannel, loc.getChannel())
                                                    .eq(DeviceSite::getType, task.getTaskType()).last("limit 1"),false);
                                            if (!Objects.isNull(deviceSite)) {
                                            boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), siteArray[1], loc.getBarcode(),"out");
                                            if (available) {
                                                BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                                        .eq(BasStation::getStationName, siteArray[1])
                                                        .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
@@ -218,7 +228,6 @@
                                }
                            }
                        }
                    }
//                    System.out.println("任务:"+task.getTaskCode()+"查询步序为:"+longs);
                }
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -26,6 +26,7 @@
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.entity.*;
@@ -179,43 +180,11 @@
                    MissionTaskIssueParam missionTaskIssueParam = new MissionTaskIssueParam(flowStepInstance,subsystemFlowTemplate,flowStepTemplate);
                    missionTaskIssueParam.setType(RcsTaskType.getTypeDesc(task.getTaskType()));
                    boolean souSign = taskInstance.getSourceCode().matches("\\d+");
                    boolean souSign = new WarehouseLocationRetrievalUtil().retrieveMissionmMergeReservoirAreaIsItAvailable(taskInstance.getSourceCode());
                    if (souSign){
                        WarehouseAreas warehouseAreas = warehouseAreasService.getById(Long.parseLong(taskInstance.getSourceCode()));
                        if (Cools.isEmpty(warehouseAreas)){
                            BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, taskInstance.getSourceCode()).last("limit 1"));
                            if (Cools.isEmpty(basStation)){
                                basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                        .apply("station_alias != '[]'")  // 不是空数组
                                        .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", taskInstance.getSourceCode())
                                        .eq(BasStation::getDeleted, 0)  // 通常需要加上未删除条件
                                        .last("LIMIT 1"));
                            }
                            if (Cools.isEmpty(basStation)){
                                flowStepInstance.setRetryTimes(flowStepInstance.getRetryTimes() + 1);
                                if (flowStepInstance.getRetryTimes()>5){
                                    flowStepInstance.setStatus((short)4);
                                    flowStepInstanceService.updateById(flowStepInstance);
                                    log.error("任务下发失败,源点未查询到,重试次数大于等于五次,标记为失败!!!");
                                } else {
                                    flowStepInstanceService.updateById(flowStepInstance);
                                    log.error("任务下发失败,源点未查询到目标点未查询到,等待重试....");
                                }
                                continue;
                            } else {
                                missionTaskIssueParam.setSourceCode(basStation.getStationName());
                            }
                        } else {
                            missionTaskIssueParam.setSourceCode(taskInstance.getSourceCode());
                        }
                    } else {
                        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, taskInstance.getSourceCode()).last("limit 1"));
                        if (Cools.isEmpty(basStation)){
                            basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                    .apply("station_alias != '[]'")  // 不是空数组
                                    .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", taskInstance.getSourceCode())
                                    .eq(BasStation::getDeleted, 0)  // 通常需要加上未删除条件
                                    .last("LIMIT 1"));                            }
                        BasStation basStation = new WarehouseLocationRetrievalUtil().retrieveMissionmMergeSizeIsItAvailable(taskInstance.getSourceCode());
                        if (Cools.isEmpty(basStation)){
                            flowStepInstance.setRetryTimes(flowStepInstance.getRetryTimes() + 1);
                            if (flowStepInstance.getRetryTimes()>5){
@@ -231,52 +200,20 @@
                            missionTaskIssueParam.setSourceCode(basStation.getStationName());
                        }
                    }
                    boolean endSign = taskInstance.getTargetCode().matches("\\d+");
                    boolean endSign = new WarehouseLocationRetrievalUtil().retrieveMissionmMergeReservoirAreaIsItAvailable(taskInstance.getTargetCode());
                    if (endSign){
                        WarehouseAreas warehouseAreas = warehouseAreasService.getById(Long.parseLong(taskInstance.getTargetCode()));
                        if (Cools.isEmpty(warehouseAreas)){
                            BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, taskInstance.getTargetCode()).last("limit 1"));
                            if (Cools.isEmpty(basStation)){
                                basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                        .apply("station_alias != '[]'")  // 不是空数组
                                        .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", taskInstance.getTargetCode())
                                        .eq(BasStation::getDeleted, 0)  // 通常需要加上未删除条件
                                        .last("LIMIT 1"));                                }
                            if (Cools.isEmpty(basStation)){
                                flowStepInstance.setRetryTimes(flowStepInstance.getRetryTimes() + 1);
                                if (flowStepInstance.getRetryTimes()>5){
                                    flowStepInstance.setStatus((short)4);
                                    flowStepInstanceService.updateById(flowStepInstance);
                                    log.error("任务下发失败,目标点未查询到,重试次数大于等于五次,标记为失败!!!");
                                } else {
                                    flowStepInstanceService.updateById(flowStepInstance);
                                    log.error("任务下发失败,目标点未查询到,等待重试....");
                                }
                                continue;
                            } else {
                                missionTaskIssueParam.setTargetCode(basStation.getStationName());
                            }
                        } else {
                            missionTaskIssueParam.setTargetCode(taskInstance.getTargetCode());
                        }
                    } else {
                        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, taskInstance.getTargetCode()).last("limit 1"));
                        if (Cools.isEmpty(basStation)){
                            basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                    .apply("station_alias != '[]'")  // 不是空数组
                                    .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", taskInstance.getTargetCode())
                                    .eq(BasStation::getDeleted, 0)  // 通常需要加上未删除条件
                                    .last("LIMIT 1"));                                  }
                        BasStation basStation = new WarehouseLocationRetrievalUtil().retrieveMissionmMergeSizeIsItAvailable(taskInstance.getTargetCode());
                        if (Cools.isEmpty(basStation)){
                            flowStepInstance.setRetryTimes(flowStepInstance.getRetryTimes() + 1);
                            if (flowStepInstance.getRetryTimes()>5){
                                flowStepInstance.setStatus((short)4);
                                flowStepInstanceService.updateById(flowStepInstance);
                                log.error("任务下发失败,目标点未查询到,重试次数大于等于五次,标记为失败!!!");
                                log.error("任务下发失败,源点未查询到,重试次数大于等于五次,标记为失败!!!");
                            } else {
                                flowStepInstanceService.updateById(flowStepInstance);
                                log.error("任务下发失败,目标点未查询到,等待重试....");
                                log.error("任务下发失败,源点未查询到目标点未查询到,等待重试....");
                            }
                            continue;
                        } else {
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BasStationTypeService.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.BasStationType;
public interface BasStationTypeService extends IService<BasStationType> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrRestrictionWarehouseService.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.MatnrRestrictionWarehouse;
public interface MatnrRestrictionWarehouseService extends IService<MatnrRestrictionWarehouse> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -14,7 +14,7 @@
    R generateFlatWarehouseTasks(WaitPakin waitPakins, String locCode, Long loginUserId);
    R generateAGVTasks(WaitPakin waitPakins, String locCode, String orgSta, String targSite, Long loginUserId);
    R generateAGVTasks(WaitPakin waitPakins, String locCode, String orgSta, Long loginUserId,String areaId);
    void completeTask(List<Task> task) throws Exception;
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BasStationTypeServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.BasStationTypeMapper;
import com.vincent.rsf.server.manager.entity.BasStationType;
import com.vincent.rsf.server.manager.service.BasStationTypeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("basStationTypeService")
public class BasStationTypeServiceImpl extends ServiceImpl<BasStationTypeMapper, BasStationType> implements BasStationTypeService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java
@@ -12,6 +12,7 @@
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.entity.excel.CheckOrderTemplate;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.mapper.BasStationTypeMapper;
import com.vincent.rsf.server.manager.mapper.CheckOrderMapper;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
@@ -45,6 +46,12 @@
    private LocServiceImpl locService;
    @Autowired
    private TaskItemServiceImpl taskItemService;
    @Autowired
    private BasStationTypeMapper basStationTypeMapper;
    @Autowired
    private BasStationTypeServiceImpl basStationTypeService;
    @Autowired
    private BasStationServiceImpl basStationService;
    /**
     * @author Ryan
@@ -212,8 +219,18 @@
    @Override
    public R getSiteNos() {
        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_CHECK_IN.type);
        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list).groupBy(DeviceSite::getSite));
        return R.ok().add(sites);
//        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list).groupBy(DeviceSite::getSite));
        List<BasStationType> basStationTypes = basStationTypeService.list(new LambdaQueryWrapper<BasStationType>().in(BasStationType::getTaskType, list));
        List<BasStation>  basStations = new ArrayList<>();
        for (BasStationType basStationType : basStationTypes) {
            List<BasStation> basStationList = basStationService.list(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationTypeCode, basStationType.getStationTypeCode()));
            if (basStationList == null || basStationList.isEmpty()) {
                continue;
            }
            basStations.addAll(basStationList);
        }
        return R.ok().add(basStations);
    }
    /**
@@ -247,16 +264,28 @@
        List<LocItem> locItems = locItemService.listByMatnr(matnrs);
        if (!locItems.isEmpty()) {
            List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_CHECK_IN.type);
            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                    .in(DeviceSite::getType, list)
                    .groupBy(DeviceSite::getSite)
                    .last("limit 1"));
            if (Objects.isNull(deviceSite)) {
                throw new CoolException("库口不为空!!");
//            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                    .in(DeviceSite::getType, list)
//                    .groupBy(DeviceSite::getSite)
//                    .last("limit 1"));
            List<BasStationType> basStationTypes = basStationTypeService.list(new LambdaQueryWrapper<BasStationType>().in(BasStationType::getTaskType, list));
            List<BasStation>  basStations = new ArrayList<>();
            for (BasStationType basStationType : basStationTypes) {
                List<BasStation> basStationList = basStationService.list(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationTypeCode, basStationType.getStationTypeCode()));
                if (basStationList == null || basStationList.isEmpty()) {
                    continue;
                }
                basStations.addAll(basStationList);
            }
            if (basStations.isEmpty()) {
                throw new CoolException("库口为空!!");
            }
            locItems.forEach(locItem -> {
                locItem.setSiteNo(deviceSite.getSite());
                locItem.setSiteNo(basStations.get(0).getStationName());
            });
//            return R.ok().add(basStations);
        }
        return R.ok().add(locItems);
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/DeviceSiteServiceImpl.java
@@ -37,7 +37,8 @@
    @Transactional(rollbackFor = Exception.class)
    public boolean initSites(DeviceSiteParame param) {
        if (param.getFlagInit() != null && param.getFlagInit() == 1) {
            List<DeviceSite> list = this.list(new LambdaQueryWrapper<DeviceSite>().select(DeviceSite::getId).last("limit 1"));
//            List<DeviceSite> list = this.list(new LambdaQueryWrapper<DeviceSite>().select(DeviceSite::getId).last("limit 1"));
            List<DeviceSite> list = this.list(new LambdaQueryWrapper<DeviceSite>());
            if (!list.isEmpty()) {
                if (!this.remove(new LambdaQueryWrapper<>())) {
                    throw new CoolException("初始化失败: 删除站点失败!!");
@@ -81,17 +82,17 @@
                    String targetVal = truncate(row.getTarget().trim(), TARGET_MAX_LENGTH);
                    String commonName = StringUtils.isNotBlank(param.getName()) ? param.getName().trim() : null;
                    String commonLabel = StringUtils.isNotBlank(param.getLabel()) ? param.getLabel().trim() : null;
                    ds.setType(String.valueOf(typeId))
                            .setSite(siteName)
                            .setDevice(param.getDeviceType())
                            .setDeviceSite(deviceSiteName)
                            .setTarget(targetVal)
                            .setDeviceCode(param.getDeviceCode())
                            .setAreaIdStart(param.getAreaIdStart())
                            .setAreaIdEnd(param.getAreaIdEnd())
                            .setChannel(ch)
                            .setName(commonName != null ? commonName : (deviceSiteName + "-" + siteName + "-" + targetVal + "-" + ch))
                            .setLabel(commonLabel);
//                    ds.setType(String.valueOf(typeId))
//                            .setSite(siteName)
//                            .setDevice(param.getDeviceType())
//                            .setDeviceSite(deviceSiteName)
//                            .setTarget(targetVal)
//                            .setDeviceCode(param.getDeviceCode())
////                            .setAreaIdStart(param.getAreaIdStart())
////                            .setAreaIdEnd(param.getAreaIdEnd())
//                            .setChannel(ch)
//                            .setName(commonName != null ? commonName : (deviceSiteName + "-" + siteName + "-" + targetVal + "-" + ch))
//                            .setLabel(commonLabel);
                    deviceSites.add(ds);
                }
            }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.controller.erp.params.TaskInParam;
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
@@ -18,6 +19,7 @@
import com.vincent.rsf.server.manager.mapper.WaveMapper;
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.Synchronized;
@@ -61,6 +63,8 @@
    private CheckDiffService checkDiffService;
    @Autowired
    private CheckDiffItemService checkDiffItemService;
    @Autowired
    private WarehouseAreasServiceImpl warehouseAreasService;
    /**
@@ -112,15 +116,13 @@
                .setBarcode(loc.getBarcode())
                .setMemo(map.getMemo());
        if (map.getType().equals(Constants.TASK_TYPE_OUT_STOCK_EMPTY)) {
                //空容器出库
                DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                        .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
                        .eq(DeviceSite::getSite, siteNo).eq(DeviceSite::getType, TaskType.TASK_TYPE_EMPTY_OUT.type).last("limit 1"));
                if (Objects.isNull(deviceSite)) {
        if (map.getType().equals(Constants.TASK_TYPE_OUT_STOCK_EMPTY)) {//空容器出库
            boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), siteNo, loc.getBarcode(),TaskType.TASK_TYPE_EMPTY_OUT.type.toString());
            if (!available) {
                    throw new CoolException("站点不支持空容器出库!!");
                }
                task.setTaskType(TaskType.TASK_TYPE_EMPTY_OUT.type).setWarehType(deviceSite.getDevice());
            WarehouseAreas warehouseAreas = warehouseAreasService.getById(loc.getAreaId());
            task.setTaskType(TaskType.TASK_TYPE_EMPTY_OUT.type).setWarehType(warehouseAreas.getType());
        } else {
            throw new CoolException("空容器出库!!其他类型无效,进入类型:"+map.getType());
        }
@@ -219,73 +221,45 @@
                    || map.getType().equals(Constants.TASK_TYPE_WAVE_OUT_STOCK)) {
                if (orgQty.compareTo(outQty) > 0) {
                    //拣料出库 -- 盘点出库
                    DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                            .eq(DeviceSite::getSite, siteNo)
                            .eq(!Objects.isNull(loc.getChannel()),DeviceSite::getChannel, loc.getChannel())
                            .eq(DeviceSite::getType, TaskType.TASK_TYPE_PICK_AGAIN_OUT.type).last("limit 1"),false);
                    if (Objects.isNull(deviceSite)) {
                        throw new CoolException("站点不支持拣料出库!!");
                    boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), siteNo, loc.getBarcode(),TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);
                    if (!available) {
                        throw new CoolException("站点不支持此容器拣选出库!!");
                    }
                    task.setTaskType(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type).setWarehType(deviceSite.getDevice());
                    WarehouseAreas warehouseAreas = warehouseAreasService.getById(loc.getAreaId());
                    task.setTaskType(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type).setWarehType(warehouseAreas.getType());
                } else {
                    if (resouce.equals(TaskResouceType.TASK_RESOUCE_STOCK_NOT_OUT.val)){
                        //全板出库
                        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                                .eq(DeviceSite::getSite, siteNo).eq(DeviceSite::getType, TaskType.TASK_TYPE_CROSS_DOCKING_OUT.type)
                                .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel()).last("limit 1"));
                        if (Objects.isNull(deviceSite)) {
                        boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), siteNo, loc.getBarcode(),TaskType.TASK_TYPE_CROSS_DOCKING_OUT.type);
                        if (!available) {
                            throw new CoolException("站点不支持越库!!");
                        }
                        task.setTaskType(TaskType.TASK_TYPE_CROSS_DOCKING_OUT.type).setWarehType(deviceSite.getDevice());//越库
                        WarehouseAreas warehouseAreas = warehouseAreasService.getById(loc.getAreaId());
                        task.setTaskType(TaskType.TASK_TYPE_CROSS_DOCKING_OUT.type).setWarehType(warehouseAreas.getType());//越库
                    } else {
                        //全板出库
                        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                                .eq(DeviceSite::getSite, siteNo).eq(DeviceSite::getType, TaskType.TASK_TYPE_OUT.type)
                                .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel()).last("limit 1"));
                        if (Objects.isNull(deviceSite)) {
                        boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), siteNo, loc.getBarcode(),TaskType.TASK_TYPE_OUT.type);
                        if (!available) {
                            throw new CoolException("站点不支持全板出库!!");
                        }
                        task.setTaskType(TaskType.TASK_TYPE_OUT.type).setWarehType(deviceSite.getDevice());
                        WarehouseAreas warehouseAreas = warehouseAreasService.getById(loc.getAreaId());
                        task.setTaskType(TaskType.TASK_TYPE_OUT.type).setWarehType(warehouseAreas.getType());
                    }
                }
            } else if (map.getType().equals(Constants.TASK_TYPE_OUT_CHECK)) {
                //盘点出库
                DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                        .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
                        .eq(DeviceSite::getSite, siteNo)
                        .eq(DeviceSite::getType, TaskType.TASK_TYPE_CHECK_OUT.type).last("limit 1"));
                if (Objects.isNull(deviceSite)) {
                boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), siteNo, loc.getBarcode(),TaskType.TASK_TYPE_CHECK_OUT.type);
                if (!available) {
                    throw new CoolException("当前站点不支持盘点出库!!");
                }
                task.setTaskType(TaskType.TASK_TYPE_CHECK_OUT.type).setWarehType(deviceSite.getDevice());
                WarehouseAreas warehouseAreas = warehouseAreasService.getById(loc.getAreaId());
                task.setTaskType(TaskType.TASK_TYPE_CHECK_OUT.type).setWarehType(warehouseAreas.getType());
            }
            if (taskMapper.insert(task) <= 0) {
                throw new CoolException("任务创建失败!!");
            }
//            if (!LocUtils.isShallowLoc(loc.getCode())) {
//                //获取深库位对应浅库位
//                String shallowLoc = LocUtils.getShallowLoc(loc.getCode());
//                Loc one = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, shallowLoc));
//                if (Objects.isNull(one)) {
//                    throw new CoolException("对应库位不存在!!");
//                }
//                Task workTask = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, one.getBarcode()));
//                if (Objects.isNull(workTask)) {
//                    map.setOrgLoc(one.getCode());
//                    //优先生成移库任务
//                    if (one.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) {
//                        moveTask = genMoveTask(map, loginUserId);
//                    }
//                } else {
//                    workTask.setSort(task.getSort() + 1).setParentId(task.getId());
//                    if (!taskService.updateById(workTask)) {
//                        throw new CoolException("优先级修改失败!!");
//                    }
//                }
//            }
            if (!Objects.isNull(moveTask.getId())) {
                moveTask.setParentId(task.getId()).setSort(moveTask.getSort() + 1);
@@ -465,24 +439,39 @@
        Loc targetLoc;
        if (Objects.isNull(map.getTarLoc()) || StringUtils.isBlank(map.getTarLoc())) {
            //目标库位为空,自动获取新库位
            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                    .eq(DeviceSite::getType, TaskType.TASK_TYPE_LOC_MOVE.type)
                    .eq(!Objects.isNull(orgLoc.getChannel()), DeviceSite::getChannel, orgLoc.getChannel()).last("limit 1"), false);
            if (Objects.isNull(deviceSite)) {
                throw new CoolException("站点信息不存在!!");
            List<String> outWarehouseAreasByReservoirAreaAndContainer = new WarehouseLocationRetrievalUtil().getOutWarehouseAreasByReservoirAreaAndContainer(orgLoc.getAreaId(), orgLoc.getBarcode(), TaskType.TASK_TYPE_LOC_MOVE.type);
            if (!Cools.isEmpty(outWarehouseAreasByReservoirAreaAndContainer) || outWarehouseAreasByReservoirAreaAndContainer.isEmpty()) {
                throw new CoolException("未找到可用目标库区!!!源库区:"+orgLoc.getAreaId());
            }
            InTaskMsgDto locNo = null;
            for (String areaId : outWarehouseAreasByReservoirAreaAndContainer) {
                List<LocItem> locItems = this.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocCode, orgLoc.getCode()));
                boolean sign = false;
                for (LocItem locItem : locItems) {
                    if (!new WarehouseLocationRetrievalUtil().retrieveMatnrIsItAvailable(areaId, locItem.getMatnrId())){
                        sign = true;
                        break;
                    }
                }
                if (sign) {
                    continue;
            }
            TaskInParam param = new TaskInParam();
            param.setIoType(TaskType.TASK_TYPE_OUT.type)
                    .setOrgLoc(map.getOrgLoc())
                    .setSourceStaNo(deviceSite.getSite())
                        .setAreaId(Long.parseLong(areaId))
                    .setLocType1(Integer.parseInt(orgLoc.getType())
                    );
            InTaskMsgDto locNo;
            try {
                locNo = wcsService.getLocNo(param);
                    locNo = wcsService.getLocNoArea(param);
                    break;
            } catch (Exception e) {
                log.error("<UNK>", e);
                throw new CoolException(e.getMessage());
                }
            }
            if (Cools.isEmpty(locNo)){
                throw new CoolException("移库未找到可用库位!!!");
            }
            targetLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locNo.getLocNo()));
        } else {
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrRestrictionWarehouseServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.MatnrRestrictionWarehouseMapper;
import com.vincent.rsf.server.manager.entity.MatnrRestrictionWarehouse;
import com.vincent.rsf.server.manager.service.MatnrRestrictionWarehouseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("matnrRestrictionWarehouseService")
public class MatnrRestrictionWarehouseServiceImpl extends ServiceImpl<MatnrRestrictionWarehouseMapper, MatnrRestrictionWarehouse> implements MatnrRestrictionWarehouseService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -19,6 +19,7 @@
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.manager.utils.OptimalAlgorithmUtil;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
@@ -78,6 +79,8 @@
    private WaveOrderRelaServiceImpl waveOrderRelaService;
    @Autowired
    private AsnOrderService asnOrderService;
    @Autowired
    private BasStationServiceImpl basStationService;
    /**
@@ -747,12 +750,13 @@
     */
    @Override
    public R getSiteNos() {
        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_MERGE_OUT.type,
                TaskType.TASK_TYPE_OUT.type,
                TaskType.TASK_TYPE_MERGE_OUT.type,
                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);
        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list).groupBy(DeviceSite::getSite));
        return R.ok(sites);
//        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_MERGE_OUT.type,
//                TaskType.TASK_TYPE_OUT.type,
//                TaskType.TASK_TYPE_MERGE_OUT.type,
//                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);sites
//        List<DeviceSite>  = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list).groupBy(DeviceSite::getSite));
        List<BasStation> basStationList = basStationService.list(new LambdaQueryWrapper<BasStation>().eq(BasStation::getOutAble, true));
        return R.ok(basStationList);
    }
    @Override
@@ -828,24 +832,18 @@
                        OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
//                        orderOutItemDto.setLocItem(locItem);
                        orderOutItemDto.getLocItemList().add(locItem);
                        List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                .eq(DeviceSite::getChannel, loc.getChannel())
                                .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                        );
                        if (!deviceSites.isEmpty()) {
                        List<String> outboundSiteByReservoirAreaAndContainer = new WarehouseLocationRetrievalUtil().getOutboundSiteByReservoirAreaAndContainer(loc.getAreaId(), loc.getBarcode(),itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type.toString() : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type.toString());
                        if (!outboundSiteByReservoirAreaAndContainer.isEmpty()) {
                            List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                            for (DeviceSite sta : deviceSites) {
                            for (String staNo : outboundSiteByReservoirAreaAndContainer) {
                                OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                staListDto.setStaNo(sta.getSite());
                                staListDto.setStaName(sta.getSite());
                                staListDto.setStaNo(staNo);
                                staListDto.setStaName(staNo);
                                maps.add(staListDto);
                            }
                            orderOutItemDto.setStaNos(maps);
                            //默认获取第一站点
                            DeviceSite deviceSite = deviceSites.stream().findFirst().get();
                            orderOutItemDto.setSiteNo(deviceSite.getSite());
                            orderOutItemDto.setSiteNo(outboundSiteByReservoirAreaAndContainer.get(0));
                        }
                        list.add(orderOutItemDto);
@@ -918,26 +916,19 @@
                        locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue());
                        locItem.setBarcode(loc.getBarcode());
                        OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
//                        orderOutItemDto.setLocItem(locItem);
                        orderOutItemDto.getLocItemList().add(locItem);
                        List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                .eq(DeviceSite::getChannel, loc.getChannel())
                                .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                        );
                        if (!deviceSites.isEmpty()) {
                        List<String> outboundSiteByReservoirAreaAndContainer = new WarehouseLocationRetrievalUtil().getOutboundSiteByReservoirAreaAndContainer(loc.getAreaId(), loc.getBarcode(),itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);
                        if (!outboundSiteByReservoirAreaAndContainer.isEmpty()) {
                            List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                            for (DeviceSite sta : deviceSites) {
                            for (String staNo : outboundSiteByReservoirAreaAndContainer) {
                                OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                staListDto.setStaNo(sta.getSite());
                                staListDto.setStaName(sta.getSite());
                                staListDto.setStaNo(staNo);
                                staListDto.setStaName(staNo);
                                maps.add(staListDto);
                            }
                            orderOutItemDto.setStaNos(maps);
                            //默认获取第一站点
                            DeviceSite deviceSite = deviceSites.stream().findFirst().get();
                            orderOutItemDto.setSiteNo(deviceSite.getSite());
                            orderOutItemDto.setSiteNo(outboundSiteByReservoirAreaAndContainer.get(0));
                        }
                        list.add(orderOutItemDto);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -28,6 +28,7 @@
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.manager.utils.WarehouseLocationRetrievalUtil;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.manager.enums.LocStsType;
@@ -131,7 +132,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized R generateAGVTasks(WaitPakin pakins, String locCode, String orgSta,String targSite, Long loginUserId) {
    public synchronized R generateAGVTasks(WaitPakin pakins, String locCode, String orgSta, Long loginUserId,String areaId) {
        if (Cools.isEmpty(pakins) || Cools.isEmpty(locCode)) {
            throw new CoolException("参数不能为空!!");
        }
@@ -201,6 +202,10 @@
                throw new CoolException("任务明细保存失败!!");
            }
            waitPakinItems.forEach(item -> {
                boolean b = new WarehouseLocationRetrievalUtil().retrieveMatnrIsItAvailable(areaId, item.getMatnrId());
                if (!b){
                    throw new CoolException("入库失败!!物料Id:"+item.getMatnrId()+"不支持此目标库区:"+areaId);
                }
                if (!waitPakinItemService.update(new LambdaUpdateWrapper<WaitPakinItem>()
                        .set(WaitPakinItem::getWorkQty, item.getAnfme())
                        .eq(WaitPakinItem::getId, item.getId()))) {
@@ -307,11 +312,11 @@
            throw new CoolException("参数不能为空!!");
        }
        DeviceSite deviceSite = deviceSiteService.getById(waitPakin.getSiteId());
        if (Objects.isNull(deviceSite)) {
            throw new CoolException("站点不存在!!");
        }
        DeviceBind deviceBind = deviceBindService.getById(LocUtils.getAreaType(deviceSite.getSite()));
//        DeviceSite deviceSite = deviceSiteService.getById();
//        if (Objects.isNull(deviceSite)) {
//            throw new CoolException("站点不存在!!");
//        }
        DeviceBind deviceBind = deviceBindService.getById(LocUtils.getAreaType(waitPakin.getSiteNo()));
        if (Cools.isEmpty(deviceBind)) {
            throw new CoolException("库位规则未知");
        }
@@ -336,7 +341,7 @@
//            }
            //验证基础信息
            checkStaStatus(pakin.getBarcode(), deviceSite.getSite(),warehouseArea.getId().toString());
            checkStaStatus(pakin.getBarcode(),waitPakin.getSiteNo(),warehouseArea.getId().toString());
            /**获取库位*/
            String targetLoc = LocManageUtil.getTargetLoc(warehouseArea.getId(), null);
            if (Cools.isEmpty(targetLoc)) {
@@ -355,8 +360,8 @@
                    .setResource(TaskResouceType.TASK_RESOUCE_PAKIN_TYPE.val)
                    .setTargLoc(targetLoc)
                    .setBarcode(pakin.getBarcode())
                    .setOrgSite(deviceSite.getSite())
                    .setTargSite(deviceSite.getDeviceSite())
                    .setOrgSite(waitPakin.getSiteNo())
                    .setTargSite(waitPakin.getSiteNo())
                    .setCreateBy(loginUserId)
                    .setUpdateBy(loginUserId);
//            if (!Objects.isNull(waitPakin.getSiteId()) && waitPakin.getSiteId() > 0) {
@@ -380,7 +385,7 @@
                throw new CoolException("任务保存失败!!");
            }
            BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                    .eq(BasStation::getStationName, deviceSite.getSite()));
                    .eq(BasStation::getStationName, waitPakin.getSiteNo()));
            if (Objects.isNull(station) || !station.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) {
                throw new CoolException("站点不存在或站点不处于空库状态!!");
            }
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java
@@ -88,21 +88,6 @@
        return !Objects.isNull(loc) ? loc.getCode() : null;
    }
    /**
     * @param
     * @return
     * @author Ryan
     * @description 获取目标站点
     * @time 2025/3/31 09:49
     */
    public static String getTargetSite() {
        //TODO 站点策略后续排期
        DeviceSiteService deviceSite = SpringUtils.getBean(DeviceSiteService.class);
        DeviceSite loc = deviceSite.getOne(new LambdaQueryWrapper<DeviceSite>().eq(DeviceSite::getStatus, 1), false);
        return !Objects.isNull(loc) ? loc.getSite() : null;
    }
    /**
     * 出库策略:--〈效率优化〉
     *
@@ -175,9 +160,7 @@
    public static List<OrderOutItemDto> getOutOrderList(List<WaveToLocParams> params, WaveRule waveRule,String stationId,String locCode) {
        LocService locService = SpringUtils.getBean(LocService.class);
        LocItemService locItemService = SpringUtils.getBean(LocItemService.class);
        DeviceSiteService deviceSiteService = SpringUtils.getBean(DeviceSiteService.class);
        BasStationAreaService basStationAreaService = SpringUtils.getBean(BasStationAreaService.class);
//        List<BasStationArea> basStationAreas = basStationAreaService.list(new LambdaQueryWrapper<>());//
        List<Loc> locList = new  ArrayList<>();
        List<OrderOutItemDto> list = new ArrayList<>();
        //不让站点重复使用问题
@@ -236,7 +219,7 @@
//                        orderOutItemDto.setLocItem(locItem);
                        orderOutItemDto.setLoc(loc);
                        orderOutItemDto.getLocItemList().add(locItem);
                        BasContainer containerType = getContainerType(loc.getBarcode());
                        BasContainer containerType = new WarehouseLocationRetrievalUtil().getContainerByBarcode(loc.getBarcode());
                        if (Cools.isEmpty(containerType)){
                            continue;
                        }
@@ -328,25 +311,11 @@
                            if (Objects.isNull(basStation)) {
                                throw new CoolException("绑定站點不存在!!");
                            }
                            List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                    .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
                                    .eq(!Objects.isNull(loc.getAreaId()), DeviceSite::getAreaIdStart, loc.getAreaId())
                                    .eq( DeviceSite::getSite, stationId)
                                    .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                            );
                            if (!deviceSites.isEmpty()) {
                                List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                                for (DeviceSite sta : deviceSites) {
                                    OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                    staListDto.setStaNo(sta.getSite());
                                    staListDto.setStaName(sta.getSite());
                                    maps.add(staListDto);
                            boolean available = new WarehouseLocationRetrievalUtil().queryPathIsItAvailableOutArea(loc.getAreaId().toString(), stationId, loc.getBarcode(),"out");
                            if (!available) {
                                throw new CoolException("未找到符合条件路径!!!请检查路径配置!!!");
                                }
                                orderOutItemDto.setStaNos(maps);
                                orderOutItemDto.setSiteNo(basStation.getStationName());
                            } else {
                                throw new CoolException("未找到符合条件站点路径!!!请检查路径管理!!!");
                            }
                            orderOutItemDto.setSource(item.getItemId().toString())
                                    .setTargSiteAreaList(new ArrayList<>())
@@ -355,85 +324,15 @@
                            locList.add(loc);
                            issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                        } else {
                            List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                    .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
                                    .eq(!Objects.isNull(loc.getAreaId()), DeviceSite::getAreaIdStart, loc.getAreaId())
                                    .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                            );
                            if (!deviceSites.isEmpty()) {
                                List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                                for (DeviceSite sta : deviceSites) {
                                    OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                    staListDto.setStaNo(sta.getSite());
                                    staListDto.setStaName(sta.getSite());
                                    maps.add(staListDto);
                            throw new CoolException("未找到符合条件出库站点区域!!!请检查库区配置!!!");
                                }
                                orderOutItemDto.setStaNos(maps);
                                //获取满足条件站点
                                Set<String> stationSet = deviceSites.stream().map(DeviceSite::getSite).collect(Collectors.toSet());
                                //已使用站点
                                Set<String> stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet());
                                BasStationService basStationService = SpringUtils.getBean(BasStationService.class);
                                BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                        .apply("cross_zone_area != '[]'")  // 不是空数组
                                        .apply("container_type != '[]'")
                                        .apply("JSON_CONTAINS(cross_zone_area, {0}) = 1", loc.getAreaId().toString())//可执行库区区区域id
                                        .apply("JSON_CONTAINS(container_type, {0}) = 1", containerType.getContainerType().toString())//容器类型
                                        .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                                        .in(BasStation::getStationName, stationSet)
                                        .notIn(!stas.isEmpty(), BasStation::getStationName, stas)
                                        .last("LIMIT 1"));
                                if (Objects.isNull(basStation)) {
                                    throw new CoolException("站點不存在!!");
                                }
                                if (basStation.getType()!=0){
                                    stations.add(basStation);
                                }
                                orderOutItemDto.setSiteNo(basStation.getStationName());
                            } else {
                                throw new CoolException("未找到符合条件站点!!!请检查路径管理!!!");
                            }
                            orderOutItemDto.setSource(item.getItemId().toString())
                                    .setTargSiteAreaList(new ArrayList<>())
                                    .setSourceId(item.getWaveId().toString());
                            list.add(orderOutItemDto);
                            locList.add(loc);
                            issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                        }
//                         if (true){
////                            throw new CoolException("未找到符合条件站点!!!请检查库区配置!!!");
//                        }
                    }
                }
            }
        }
        return list;
    }
    //根据条码获取规则
    private static BasContainer getContainerType(String barcode) {
        BasContainerService basContainerService = SpringUtils.getBean(BasContainerService.class);
        if (Cools.isEmpty(barcode)) {
            throw new CoolException("容器码不能为空");
        }
        List<BasContainer> containers = basContainerService.list(new LambdaQueryWrapper<>());
        for (BasContainer container : containers) {
            String codeType = container.getCodeType();  // 获取正则表达式
            if (barcode.matches(codeType)) {  // 判断条码是否符合这个正则
                return container;
            }
        }
        throw new CoolException("容器码:"+barcode+"异常==>未找到匹配的规则");
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/WarehouseLocationRetrievalUtil.java
New file
@@ -0,0 +1,534 @@
package com.vincent.rsf.server.manager.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.system.entity.TaskPathTemplateMerge;
import com.vincent.rsf.server.system.service.TaskPathTemplateMergeService;
import lombok.extern.slf4j.Slf4j;
import routeR.calculationR.RouteWmsStepFlow;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Slf4j
public class WarehouseLocationRetrievalUtil {
    private BasStationService basStationService;
    private WarehouseAreasService warehouseAreasService;
    public WarehouseLocationRetrievalUtil() {
         basStationService = SpringUtils.getBean(BasStationService.class);
         warehouseAreasService = SpringUtils.getBean(WarehouseAreasService.class);
    }
    //判断目标是否是库区
    public boolean retrieveMissionmMergeReservoirAreaIsItAvailable(String missionArea) {
        boolean matches = missionArea.matches("\\d+");
        if (!matches) {
            return false;
        }
        WarehouseAreas warehouseAreas = warehouseAreasService.getById(Long.parseLong(missionArea));
        if (Cools.isEmpty(warehouseAreas)){
            return false;
        }
        return true;
    }
    //判断目标是否是站点
    public BasStation retrieveMissionmMergeSizeIsItAvailable(String missionSize) {
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, missionSize).last("limit 1"));
        if (Cools.isEmpty(basStation)){
            basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                    .apply("station_alias != '[]'")  // 不是空数组
                    .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", missionSize)
                    .eq(BasStation::getDeleted, 0)  // 通常需要加上未删除条件
                    .last("LIMIT 1"));
        }
        if (Cools.isEmpty(basStation)){
            return null;
        }
        return basStation;
    }
    //根据条码获取规则
    public BasContainer getContainerByBarcode(String barcode) {
        if (Cools.isEmpty(barcode)) {
            throw new CoolException("容器码不能为空");
        }
        BasContainerService basContainerService = SpringUtils.getBean(BasContainerService.class);
        List<BasContainer> containers = basContainerService.list(new LambdaQueryWrapper<>());
        for (BasContainer container : containers) {
            String codeType = container.getCodeType();  // 获取正则表达式
            if (barcode.matches(codeType)) {  // 判断条码是否符合这个正则
                return container;
            }
        }
        throw new CoolException("容器码:"+barcode+"异常==>未找到匹配的规则");
    }
    //根据物料ID获取物料
    public Matnr getMatnrByMatnrId(Long matnrId) {
        if (Cools.isEmpty(matnrId)) {
            throw new CoolException("物料ID不能为空");
        }
        MatnrService matnrService = SpringUtils.getBean(MatnrService.class);
        Matnr matnr = matnrService.selectMatnrById(matnrId);
        if (matnr == null) {
            throw new CoolException("物料ID:"+matnrId+"异常==>未找到对应物料");
        }
        return matnr;
    }
    //判断物料是否可用此仓库
    public boolean retrieveMatnrIsItAvailable(String areaId, Long matnrId) {
        return retrieveMatnrIsItAvailable(Long.parseLong(areaId),matnrId);
    }
    public boolean retrieveMatnrIsItAvailable(Long areaId, Long matnrId) {
        Matnr matnrByMatnrId = getMatnrByMatnrId(matnrId);
        if (matnrByMatnrId.getWarehouseRestrictionCode() == null ||  matnrByMatnrId.getWarehouseRestrictionCode().equals("") || matnrByMatnrId.getWarehouseRestrictionCode().equals("all")) {
            return true;
        }
        //判断是否兼容
        String warehouseRestrictionCode = matnrByMatnrId.getWarehouseRestrictionCode();
        //根据code获取
        MatnrRestrictionWarehouseService matnrRestrictionWarehouseService = SpringUtils.getBean(MatnrRestrictionWarehouseService.class);
        MatnrRestrictionWarehouse serviceOne = matnrRestrictionWarehouseService.getOne(new LambdaQueryWrapper<MatnrRestrictionWarehouse>().eq(MatnrRestrictionWarehouse::getMatnrRestrictionCode, warehouseRestrictionCode).last("limit 1"));
        if (Objects.isNull(serviceOne)) {
            return false;
        }
        //查询area是否在
        return serviceOne.getProductionLineCode().contains(areaId.intValue());
    }
    // 根据库区、容器检索符合条件移库库区
    public List<String> getOutWarehouseAreasByReservoirAreaAndContainer(Long sourceCode, String barcode,Integer type) {
        return getOutWarehouseAreasByReservoirAreaAndContainer(sourceCode,barcode,type.toString());
    }
    public List<String> getOutWarehouseAreasByReservoirAreaAndContainer(Long sourceCode, String barcode,String type) {
        List<String> outboundSite = new ArrayList<>();
        List<String> outboundSiteByReservoirAreaAndContainer = getOutWarehouseAreasByReservoirAreaAndContainer(sourceCode, barcode);
        for (String areaId : outboundSiteByReservoirAreaAndContainer) {
            WarehouseAreas warehouseAreas = warehouseAreasService.getById(Long.parseLong(areaId));
            if (!Cools.isEmpty(warehouseAreas)){
                outboundSite.add(areaId);
            }
        }
        return outboundSite;
    }
    // 根据库区、容器检索符合条件出库站点
    private List<String> getOutWarehouseAreasByReservoirAreaAndContainer(Long sourceCode, String barcode) {
        return getTargetTypeByReservoirAreaAndContainer(String.valueOf(sourceCode), barcode,1,false);
    }
    // 根据库区、容器检索符合条件出库站点
    public List<String> getOutboundSiteByReservoirAreaAndContainer(Long sourceCode, String barcode,Integer type) {
        return getOutboundSiteByReservoirAreaAndContainer(sourceCode,barcode,type.toString());
    }
    public List<String> getOutboundSiteByReservoirAreaAndContainer(Long sourceCode, String barcode,String type) {
        List<String> outboundSite = new ArrayList<>();
        List<String> outboundSiteByReservoirAreaAndContainer = getOutboundSiteByReservoirAreaAndContainer(sourceCode, barcode);
        for (String site : outboundSiteByReservoirAreaAndContainer) {
            BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                    .eq(BasStation::getStationName, site).last("limit 1"));
            if (!Cools.isEmpty(basStation)){
                BasStationTypeService basStationTypeService = SpringUtils.getBean(BasStationTypeService.class);
                BasStationType one = basStationTypeService.getOne(new LambdaQueryWrapper<BasStationType>().eq(BasStationType::getStationTypeCode, basStation.getContainerType()).last("limit 1"));
                if (!Cools.isEmpty(one)) {
                    if (one.getTaskType().contains(type)){
                        outboundSite.add(site);
                    }
                }
            }
        }
        return outboundSite;
    }
    // 根据库区、容器检索符合条件出库站点
    private List<String> getOutboundSiteByReservoirAreaAndContainer(Long sourceCode, String barcode) {
        return getTargetTypeByReservoirAreaAndContainer(String.valueOf(sourceCode), barcode,1,true);
    }
    // 根据库区、容器检索符合条件站点或库区
    private List<String> getTargetTypeByReservoirAreaAndContainer(String code, String barcode,int type,boolean isInOrOut) {
        List<String> obtainOutboundStations = new ArrayList<>();
        BasContainer containerByBarcode = getContainerByBarcode(barcode);
        if (containerByBarcode == null) {
            log.error("容器码:"+barcode+"异常==>未找到匹配的规则");
            return obtainOutboundStations;
        }
        Long containerType = containerByBarcode.getContainerType();
        TaskPathTemplateMergeService taskPathTemplateMergeService = SpringUtils.getBean(TaskPathTemplateMergeService.class);
        if (isInOrOut) {//根据起点检索终点
            List<TaskPathTemplateMerge> taskPathTemplateMergeList = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>()
                    .eq(TaskPathTemplateMerge::getSourceType, code)
                    .eq(TaskPathTemplateMerge::getContainerType, containerType)
            );
            if (taskPathTemplateMergeList.isEmpty()) {
                return obtainOutboundStations;
            }
            for (TaskPathTemplateMerge taskPathTemplateMerge : taskPathTemplateMergeList) {
                switch (type){
                    case 1://站点
                        if (retrieveBarcodeIsItAvailableBySite(containerByBarcode,taskPathTemplateMerge.getTargetType())){
                            obtainOutboundStations.add(taskPathTemplateMerge.getTargetType());
                        }
                        break;
                    case 2://库区
                        if (retrieveMissionmMergeReservoirAreaIsItAvailable(taskPathTemplateMerge.getTargetType())){
                            obtainOutboundStations.add(taskPathTemplateMerge.getTargetType());
                        }
                        break;
                }
            }
        } else {//根据终点检索起点
            List<TaskPathTemplateMerge> taskPathTemplateMergeList = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>()
                    .eq(TaskPathTemplateMerge::getTargetType, code)
                    .eq(TaskPathTemplateMerge::getContainerType, containerType)
            );
            if (taskPathTemplateMergeList.isEmpty()) {
                return obtainOutboundStations;
            }
            for (TaskPathTemplateMerge taskPathTemplateMerge : taskPathTemplateMergeList) {
                switch (type){
                    case 1://站点
                        if (retrieveBarcodeIsItAvailableBySite(containerByBarcode,taskPathTemplateMerge.getSourceType())){
                            obtainOutboundStations.add(taskPathTemplateMerge.getSourceType());
                        }
                        break;
                    case 2://库区
                        if (retrieveMissionmMergeReservoirAreaIsItAvailable(taskPathTemplateMerge.getSourceType())){
                            obtainOutboundStations.add(taskPathTemplateMerge.getSourceType());
                        }
                        break;
                }
            }
        }
        return obtainOutboundStations;
    }
    // 根据站点检索容器是否可行至此站点
    public boolean retrieveBarcodeIsItAvailableBySite(BasContainer containerByBarcode,BasStation basStation) {
        if (basStation.getContainerType().contains(containerByBarcode.getContainerType())) {
            return true;
        }
        return false;
    }
    // 根据站点检索容器是否可行至此站点
    public boolean retrieveBarcodeIsItAvailableBySite(String barcode,BasStation basStation) {
        BasContainer containerByBarcode = getContainerByBarcode(barcode);
        if (basStation.getContainerType().contains(containerByBarcode.getContainerType())) {
            return true;
        }
        return false;
    }
    // 根据站点检索容器是否可行至此站点
    public boolean retrieveBarcodeIsItAvailableBySite(BasContainer containerByBarcode,String siteCode) {
        BasStation basStation = retrieveMissionmMergeSizeIsItAvailable(siteCode);
        if (Cools.isEmpty(basStation)){
            return false;
        }
        if (basStation.getContainerType().contains(containerByBarcode.getContainerType())) {
            return true;
        }
        return false;
    }
    // 根据站点检索容器是否可行至此站点
    public boolean retrieveBarcodeIsItAvailableBySite(String barcode,String siteCode) {
        BasStation basStation = retrieveMissionmMergeSizeIsItAvailable(siteCode);
        if (Cools.isEmpty(basStation)){
            return false;
        }
        BasContainer containerByBarcode = getContainerByBarcode(barcode);
        if (basStation.getContainerType().contains(containerByBarcode.getContainerType())) {
            return true;
        }
        return false;
    }
    // 根据站点检索库区是否可入至此站点
    public boolean retrieveWarehouseAreasIsItAvailableInBySite(String warehouseCode,BasStation basStation) {
        // TODO: 实现逻辑
        return false;
    }
    // 根据站点检索库区是否可入至此站点
    public boolean retrieveWarehouseAreasIsItAvailableInBySite(String warehouseCode,String siteCode) {
        // TODO: 实现逻辑
        return false;
    }
    // 根据站点检索库区是否可出至此站点
    public boolean retrieveWarehouseAreasIsItAvailableOutBySite(String warehouseCode,BasStation basStation) {
        // TODO: 实现逻辑
        return false;
    }
    // 根据站点检索库区是否可出至此站点
    public boolean retrieveWarehouseAreasIsItAvailableOutBySite(String warehouseCode,String siteCode) {
        // TODO: 实现逻辑
        return false;
    }
    // 根据站点检索符合条件库区
    public List<String> getWarehouseAreasBySite(String siteCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点检索符合条件容器
    public List<BasContainer> getContainersBySite(String siteCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点检索符合条件任务类型
    public List<String> getTaskTypesBySite(String siteCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据物料检索符合条件库区
    public List<String> getWarehouseAreasByMaterial(String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据物料检索符合条件容器
    public List<BasContainer> getContainersByMaterial(String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据物料检索符合条件站点
    public List<String> getSitesByMaterial(String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据库区检索符合条件站点
    public List<String> getSitesByWarehouseArea(String warehouseAreaCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\物料检索符合条件容器
    public List<BasContainer> getContainersBySiteAndMaterial(String siteCode, String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\物料检索符合条件库区
    public List<String> getWarehouseAreasBySiteAndMaterial(String siteCode, String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\物料检索符合条件路径
    public List<String> getPathsBySiteAndMaterial(String siteCode, String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\物料检索符合条件任务类型
    public List<String> getTaskTypesBySiteAndMaterial(String siteCode, String materialCode) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\物料\容器检索符合条件库区
    public List<String> getWarehouseAreasBySiteMaterialContainer(String siteCode, String materialCode, String containerType) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\物料\容器检索符合条件任务类型
    public List<String> getTaskTypesBySiteMaterialContainer(String siteCode, String materialCode, String containerType) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\容器检索符合条件容器
    public List<BasContainer> getContainersBySiteAndContainerType(String siteCode, String containerType) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\容器检索符合条件库区
    public List<String> getWarehouseAreasBySiteAndContainer(String siteCode, String containerType) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\容器检索符合条件路径
    public List<String> getPathsBySiteAndContainer(String siteCode, String containerType) {
        // TODO: 实现逻辑
        return null;
    }
    // 根据站点\容器检索符合条件任务类型
    public List<String> getTaskTypesBySiteAndContainer(String siteCode, String containerType) {
        // TODO: 实现逻辑
        return null;
    }
    // 出库校验:根据源库区\目标站点\容器判断是否存在路径
    public boolean queryPathIsItAvailableOutArea(Long sourceCode, String targetCode, String barcode,Integer type) {
        return queryPathIsItAvailableOutArea(sourceCode.toString(),targetCode,barcode,type.toString());
    }
    public boolean queryPathIsItAvailableOutArea(String sourceCode, String targetCode, String barcode,Integer type) {
        return queryPathIsItAvailableOutArea(sourceCode,targetCode,barcode,type.toString());
    }
    public boolean queryPathIsItAvailableOutArea(String sourceCode, String targetCode, String barcode,String type) {
        if (queryPathIsItAvailable(sourceCode, targetCode, barcode)){
            BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                    .eq(BasStation::getStationName, targetCode).last("limit 1"));
            if (!Cools.isEmpty(basStation)){
                if (type.equals("in")){
                    if (basStation.getInAble()==1){
                        return true;
                    }
                } else if (type.equals("out")){
                    if (basStation.getOutAble()==1){
                        return true;
                    }
                }
                BasStationTypeService basStationTypeService = SpringUtils.getBean(BasStationTypeService.class);
                BasStationType one = basStationTypeService.getOne(new LambdaQueryWrapper<BasStationType>().eq(BasStationType::getStationTypeCode, basStation.getContainerType()).last("limit 1"));
                if (!Cools.isEmpty(one)) {
                    if (one.getTaskType().contains(type)){
                        return true;
                    }
                    log.error("目标站点:" + targetCode+" 不支持作业此任务类型:"+type);
                }
                log.error("目标站点:" + targetCode+" 不支持作业此任务类型:"+type);
            }
            log.error("queryPathIsItAvailableInArea: error");
        }
        return false;
    }
    // 出库校验:根据源站点\目标库区\容器判断是否存在路径
    public boolean queryPathIsItAvailableInArea(String sourceCode, Long targetCode, String barcode,String type) {
        return queryPathIsItAvailableInArea(sourceCode,targetCode.toString(),barcode,type);
    }
    public boolean queryPathIsItAvailableInArea(String sourceCode, Long targetCode, String barcode,Integer type) {
        return queryPathIsItAvailableInArea(sourceCode,targetCode.toString(),barcode,type.toString());
    }
    public boolean queryPathIsItAvailableInArea(String sourceCode, String targetCode, String barcode,Integer type) {
        return queryPathIsItAvailableInArea(sourceCode,targetCode,barcode,type.toString());
    }
    public boolean queryPathIsItAvailableInArea(String sourceCode, String targetCode, String barcode,String type) {
        if (queryPathIsItAvailable(sourceCode, targetCode, barcode)){
            BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                    .eq(BasStation::getStationName, sourceCode).last("limit 1"));
            if (!Cools.isEmpty(basStation)){
                if (type.equals("in")){
                    if (basStation.getInAble()==1){
                        return true;
                    }
                } else if (type.equals("out")){
                    if (basStation.getOutAble()==1){
                        return true;
                    }
                }
                BasStationTypeService basStationTypeService = SpringUtils.getBean(BasStationTypeService.class);
                BasStationType one = basStationTypeService.getOne(new LambdaQueryWrapper<BasStationType>().eq(BasStationType::getStationTypeCode, basStation.getContainerType()).last("limit 1"));
                if (!Cools.isEmpty(one)) {
                    if (one.getTaskType().contains(type)){
                        return true;
                    }
                    log.error("当前站点:" + sourceCode+" 不支持作业此任务类型:"+type);
                }
                log.error("当前站点:" + sourceCode+" 不支持作业此任务类型:"+type);
            }
            log.error("queryPathIsItAvailableInArea: error");
        }
        return false;
    }
    // 校验:根据起点\目标点\容器判断是否存在路径
    private boolean queryPathIsItAvailable(String sourceCode, String targetCode, String barcode) {
        BasContainer containerByBarcode = getContainerByBarcode(barcode);
        if (containerByBarcode == null) {
            return false;
        }
        if (retrieveMissionmMergeReservoirAreaIsItAvailable(sourceCode)){
            BasStation basStation = retrieveMissionmMergeSizeIsItAvailable(targetCode);
            if (!Cools.isEmpty(basStation)){
                return queryPathIsItAvailable(sourceCode, targetCode, containerByBarcode);
            } else {
                if (retrieveMissionmMergeReservoirAreaIsItAvailable(targetCode)){
                    return queryPathIsItAvailable(sourceCode, targetCode, containerByBarcode);
                }
                log.error("路径校验:根据起点:"+sourceCode+"、目标点:"+targetCode+"、容器规则:" +containerByBarcode.getCodeType()+ "判断是否存在路径==>终点类型未知!!!");
            }
        } else if (retrieveMissionmMergeReservoirAreaIsItAvailable(targetCode)){
            BasStation basStation = retrieveMissionmMergeSizeIsItAvailable(sourceCode);
            if (!Cools.isEmpty(basStation)){
                return queryPathIsItAvailable(sourceCode, targetCode, containerByBarcode);
            }
            log.error("路径校验:根据起点:"+sourceCode+"、目标点:"+targetCode+"、容器规则:" +containerByBarcode.getCodeType()+ "判断是否存在路径==>起点类型未知!!!");
        } else {
            BasStation basStationS = retrieveMissionmMergeSizeIsItAvailable(sourceCode);
            BasStation basStationT = retrieveMissionmMergeSizeIsItAvailable(targetCode);
            if (!Cools.isEmpty(basStationS) &&  !Cools.isEmpty(basStationT)){
                return queryPathIsItAvailable(sourceCode, targetCode, containerByBarcode);
            }
            log.error("路径校验:根据起点:"+sourceCode+"、目标点:"+targetCode+"、容器规则:" +containerByBarcode.getCodeType()+ "判断是否存在路径==>起点与终点类型未知!!!");
        }
        return false;
    }
    // 校验:根据起点\目标点\容器判断是否存在路径
    private boolean queryPathIsItAvailable(String sourceCode, String targetCode, BasContainer containerByBarcode) {
        try{
            TaskPathTemplateMergeService taskPathTemplateMergeService = SpringUtils.getBean(TaskPathTemplateMergeService.class);
            List<TaskPathTemplateMerge> taskPathTemplateMergeList = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>()
                    .eq(TaskPathTemplateMerge::getSourceType, sourceCode)
                    .eq(TaskPathTemplateMerge::getTargetType, targetCode)
                    .apply("container_type != '[]'")  // 不是空数组
                    .apply("JSON_CONTAINS(container_type, {0}) = 1", containerByBarcode.getContainerType().toString())
            );
            if (Objects.isNull(taskPathTemplateMergeList) || taskPathTemplateMergeList.isEmpty()) {
                List<TaskPathTemplateMerge> list = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>()
                        .eq(TaskPathTemplateMerge::getStepSize, 1)
                        .apply("container_type != '[]'")  // 不是空数组
                        .apply("JSON_CONTAINS(container_type, {0}) = 1", containerByBarcode.getContainerType().toString())
                );
                if (!Cools.isEmpty(list)) {
                    List<String[]> stationList = new ArrayList<>();
                    list.forEach(taskPathTemplate -> {
                        stationList.add(taskPathTemplate.route());
                    });
                    List<Long> longs = RouteWmsStepFlow.routeGet(stationList, targetCode, sourceCode);
                    if (longs != null && !longs.isEmpty()) {
                        return true;
                    }
                }
                log.error("路径校验:根据起点:"+sourceCode+"、目标点:"+targetCode+"、容器规则:" +containerByBarcode.getCodeType()+ "判断是否存在路径==>未找到路径!!!");
            } else {
                return true;
            }
        } catch (Exception e) {
            log.error("路径校验:根据起点:"+sourceCode+"、目标点:"+targetCode+"、容器规则:" +containerByBarcode.getCodeType()+ "判断是否存在路径==>异常:"+e.getMessage());
        }
        return false;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskPathTemplateMerge.java
@@ -197,6 +197,13 @@
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<String> targetTypeR;
    /**
     * 容器类型
     */
    @ApiModelProperty(value = "容器类型")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<Integer> containerType;
    public TaskPathTemplateMerge() {}
    public String getEffectiveTime$(){
rsf-server/src/main/java/matnrRestrictionWarehouse.sql
New file
@@ -0,0 +1,24 @@
-- save matnrRestrictionWarehouse record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.matnrRestrictionWarehouse', '0', '/manager/matnrRestrictionWarehouse', 'matnrRestrictionWarehouse', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 物料限制', '', '1', 'manager:matnrRestrictionWarehouse:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 物料限制', '', '1', 'manager:matnrRestrictionWarehouse:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 物料限制', '', '1', 'manager:matnrRestrictionWarehouse:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 物料限制', '', '1', 'manager:matnrRestrictionWarehouse:remove', '3', '1', '1');
-- locale menu name
matnrRestrictionWarehouse: 'MatnrRestrictionWarehouse',
-- locale field
matnrRestrictionWarehouse: {
    productionLineCode: "productionLineCode",
    productionLineName: "productionLineName",
    matnrRestrictionCode: "matnrRestrictionCode",
},
-- ResourceContent
import matnrRestrictionWarehouse from './matnrRestrictionWarehouse';
case 'matnrRestrictionWarehouse':
    return matnrRestrictionWarehouse;
rsf-server/src/main/resources/mapper/manager/BasStationTypeMapper.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.BasStationTypeMapper">
</mapper>
rsf-server/src/main/resources/mapper/manager/MatnrRestrictionWarehouseMapper.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.MatnrRestrictionWarehouseMapper">
</mapper>