35个文件已修改
27个文件已添加
2695 ■■■■■ 已修改文件
rsf-admin/.env 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/ResourceContent.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/BasStationCreate.jsx 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/BasStationEdit.jsx 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/BasStationList.jsx 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/BasStationPanel.jsx 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/WarehouseAreaField.jsx 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/WarehouseAreaSelect.jsx 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/basStation/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/qlyInspect/InspectModal.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/qlyInspect/QlyInspectList.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/qlyInspect/QlyIsptItemList.jsx 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/qlyInspect/QlyIsptItemResult.jsx 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/warehouseAreasItem/WarehouseIsptResult.jsx 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/basStation.sql 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/AgvController.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/MobileController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/AgvService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/MobileService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/QlyInspectController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/QlyIsptItemController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaitPakinController.java 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasItemController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderItem.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStation.java 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/QlyInspectResult.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/QlyIsptItem.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/AsnOrderTemplate.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/StaUseStatusType.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WarehouseAreasType.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BasStationMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/QlyInspectResultMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/QlyIsptItemMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/WarehouseAreasItemMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java 118 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BasStationService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/QlyInspectResultService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/QlyIsptItemService.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WarehouseAreasItemService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BasStationServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyInspectResultServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyInspectServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyIsptItemServiceImpl.java 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WarehouseAreasItemServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/qlyInspectResult.sql 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/BasStationMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/QlyInspectResultMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/QlyIsptItemMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/WarehouseAreasItemMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/.env
@@ -1,3 +1,3 @@
VITE_BASE_IP=192.168.4.50
VITE_BASE_IP=192.168.4.56
# VITE_BASE_IP=47.76.147.249
VITE_BASE_PORT=8080
rsf-admin/src/i18n/zh.js
@@ -189,9 +189,25 @@
        deviceBind: '设备绑定',
        tasks: '任务管理',
        wave: '波次管理',
        basStation: '站点信息'
    },
    table: {
    table: {
        field: {
            basStation: {
                stationName: '站点名称',
                inAble: '能入',
                outAble: '能出',
                useStatus: '状态',
                status: '状态',
                area: '所属库区类型',
                isCrossZone: '是否跨区',
                crossZoneArea: '可跨区类型',
                isWcs: '是否WCS站站点',
                wcsData: 'wcs数据',
                containerType: '容器类型',
                barcode: '条码',
                autoTransfer: '自动调拨',
            },
            host: {
            },
@@ -482,7 +498,7 @@
                dlyQty: "送货数量",
                disQty: "不合数量",
                safeQty: "合格数量",
                anfme: '数量',
                anfme: '已检数量',
                picPath: "图片路径",
                trackCode: "条形码",
            },
rsf-admin/src/page/ResourceContent.js
@@ -46,6 +46,7 @@
import deviceBind from './deviceBind';
import wave from './orders/wave';
import locItem from './locItem'
import basStation from './basicInfo/basStation';
const ResourceContent = (node) => {
    switch (node.component) {
@@ -133,6 +134,8 @@
            return wave;
        case 'locItem':
            return locItem;
        case 'basStation':
            return basStation;
        default:
            return {
                list: ListGuesser,
rsf-admin/src/page/basicInfo/basStation/BasStationCreate.jsx
New file
@@ -0,0 +1,188 @@
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 BasStationCreate = (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.basStation.stationName"
                                        source="stationName"
                                        parse={v => v}
                                        autoFocus
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.inAble"
                                        source="inAble"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.outAble"
                                        source="outAble"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basStation.useStatus"
                                        source="useStatus"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.area"
                                        source="area"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.isCrossZone"
                                        source="isCrossZone"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basStation.crossZoneArea"
                                        source="crossZoneArea"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.isWcs"
                                        source="isWcs"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basStation.wcsData"
                                        source="wcsData"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.containerType"
                                        source="containerType"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basStation.barcode"
                                        source="barcode"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basStation.autoTransfer"
                                        source="autoTransfer"
                                    />
                                </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 BasStationCreate;
rsf-admin/src/page/basicInfo/basStation/BasStationEdit.jsx
New file
@@ -0,0 +1,183 @@
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,
    SelectArrayInput,
} from 'react-admin';
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../../components/EditBaseAside";
import CustomerTopToolBar from "../../components/EditTopToolBar";
import MemoInput from "../../components/MemoInput";
import StatusSelectInput from "../../components/StatusSelectInput";
import DictionarySelect from "../../components/DictionarySelect";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const BasStationEdit = () => {
    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.basStation.stationName"
                                source="stationName"
                                parse={v => v}
                                autoFocus
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                    label="table.field.basStation.inAble"
                                    source="inAble"
                                    choices={[
                                        { id: 0, name: '否' },
                                        { id: 1, name: '是' },
                                    ]}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                    label="table.field.basStation.outAble"
                                    source="outAble"
                                    choices={[
                                        { id: 0, name: '否' },
                                        { id: 1, name: '是' },
                                    ]}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <DictionarySelect
                                label={translate("table.field.basStation.useStatus")}
                                name="useStatus"
                                size="small"
                                validate={[required()]}
                                dictTypeCode="sys_sta_use_stas"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <ReferenceInput source="area" reference="warehouseAreas">
                                <SelectInput
                                    label="table.field.basStation.area"
                                    optionText="name"
                                    optionValue="id"
                                    fullWidth
                                    validate={[required()]}
                                />
                            </ReferenceInput>
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                    label="table.field.basStation.isCrossZone"
                                    source="isCrossZone"
                                    choices={[
                                        { id: 0, name: '否' },
                                        { id: 1, name: '是' },
                                    ]}
                                    validate={[required()]}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <ReferenceArrayInput source="areaIds" reference="warehouseAreas">
                                <SelectArrayInput
                                    label="table.field.basStation.crossZoneArea"
                                    optionText="name"
                                    optionValue="id"
                                    fullWidth
                                />
                            </ReferenceArrayInput>
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                    label="table.field.basStation.isWcs"
                                    source="isWcs"
                                    choices={[
                                        { id: 0, name: '否' },
                                        { id: 1, name: '是' },
                                    ]}
                                    validate={[required()]}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <DictionarySelect
                                label={translate("table.field.basStation.containerType")}
                                name="containerType"
                                size="small"
                                validate={[required()]}
                                dictTypeCode="sys_container_type"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                    label="table.field.basStation.autoTransfer"
                                    source="autoTransfer"
                                    choices={[
                                        { id: 0, name: '否' },
                                        { id: 1, name: '是' },
                                    ]}
                            />
                        </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 BasStationEdit;
rsf-admin/src/page/basicInfo/basStation/BasStationList.jsx
New file
@@ -0,0 +1,193 @@
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 BasStationCreate from "./BasStationCreate";
import BasStationPanel from "./BasStationPanel";
import EmptyData from "../../components/EmptyData";
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import PageDrawer from "../../components/PageDrawer";
import MyField from "../../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import WarehouseAreaField from "./WarehouseAreaField";
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="stationName" label="table.field.basStation.stationName" />,
    <NumberInput source="inAble" label="table.field.basStation.inAble" />,
    <NumberInput source="outAble" label="table.field.basStation.outAble" />,
    <TextInput source="useStatus" label="table.field.basStation.useStatus" />,
    <NumberInput source="area" label="table.field.basStation.area" />,
    <NumberInput source="isCrossZone" label="table.field.basStation.isCrossZone" />,
    <TextInput source="crossZoneArea" label="table.field.basStation.crossZoneArea" />,
    <NumberInput source="isWcs" label="table.field.basStation.isWcs" />,
    <TextInput source="wcsData" label="table.field.basStation.wcsData" />,
    <NumberInput source="containerType" label="table.field.basStation.containerType" />,
    <TextInput source="barcode" label="table.field.basStation.barcode" />,
    <NumberInput source="autoTransfer" label="table.field.basStation.autoTransfer" />,
    <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 BasStationList = () => {
    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.basStation"}
                empty={false}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='basStation' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='basStation'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="stationName" label="table.field.basStation.stationName" />
                    <FunctionField
                        source="inAble"
                        label="table.field.basStation.inAble"
                        render={record => record.inAble === 1 ? '是' : '否'}
                    />
                    <FunctionField
                        source="outAble"
                        label="table.field.basStation.outAble"
                        render={record => record.inAble === 1 ? '是' : '否'}
                    />
                    <TextField source="useStatus$" label="table.field.basStation.useStatus" />
                    <NumberField source="area$" label="table.field.basStation.area" />
                    <FunctionField
                        source="isCrossZone"
                        label="table.field.basStation.isCrossZone"
                        render={record => record.inAble === 1 ? '是' : '否'}
                    />
                    <TextField source="crossZoneArea" label="table.field.basStation.crossZoneArea" />
                    <FunctionField
                        source="isWcs"
                        label="table.field.basStation.isWcs"
                        render={record => record.inAble === 1 ? '是' : '否'}
                    />
                    <NumberField source="containerType$" label="table.field.basStation.containerType" />
                    <TextField source="barcode" label="table.field.basStation.barcode" />
                    <FunctionField
                        source="autoTransfer"
                        label="table.field.basStation.autoTransfer"
                        render={record => record.inAble === 1 ? '是' : '否'}
                    />
                    <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 />
                    <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>
            <BasStationCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='BasStation Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default BasStationList;
rsf-admin/src/page/basicInfo/basStation/BasStationPanel.jsx
New file
@@ -0,0 +1,123 @@
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 BasStationPanel = () => {
    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.basStation.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.basStation.stationName"
                                property={record.stationName}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.inAble"
                                property={record.inAble}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.outAble"
                                property={record.outAble}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.useStatus"
                                property={record.useStatus}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.area"
                                property={record.area}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.isCrossZone"
                                property={record.isCrossZone}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.crossZoneArea"
                                property={record.crossZoneArea}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.isWcs"
                                property={record.isWcs}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.wcsData"
                                property={record.wcsData}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.containerType"
                                property={record.containerType}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.barcode"
                                property={record.barcode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basStation.autoTransfer"
                                property={record.autoTransfer}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default BasStationPanel;
rsf-admin/src/page/basicInfo/basStation/WarehouseAreaField.jsx
New file
@@ -0,0 +1,28 @@
import * as React from 'react';
import { Stack, Chip } from '@mui/material';
import { useTranslate, useRecordContext } from 'react-admin';
const WarehouseAreaField = () => {
    const translate = useTranslate();
    const record = useRecordContext();
    React.useEffect(() => {
    }, [record]);
    return (
        <Stack direction="row" gap={1} flexWrap="wrap">
            {record.areaIds?.map((item, idx) => {
                if (item) {
                    return <Chip
                        size="small"
                        key={item.id}
                        label={item.id}
                    />;
                }
            })}
        </Stack>
    )
}
export default WarehouseAreaField;
rsf-admin/src/page/basicInfo/basStation/WarehouseAreaSelect.jsx
New file
@@ -0,0 +1,35 @@
import * as React from 'react';
import { SelectArrayInput, useRecordContext } from 'react-admin';
import request from '@/utils/request'
const WarehouseAreaSelect = (props) => {
    const [arr, setArr] = React.useState([]);
    const [loading, setLoading] = React.useState(true);
    React.useEffect(() => {
        setLoading(true);
        request.post('/warehouseAreas/list', {}).then(res => {
            if (res?.data?.code === 200) {
                setArr(res.data.data.map(item => {
                    return {
                        id: item.id,
                        name: item.name
                    }
                }));
            }
            setLoading(false);
        }).catch(() => {
            setLoading(false);
        });
    }, []);
    return (
        <SelectArrayInput
            {...props}
            choices={arr}
            disabled={loading}
        />
    );
};
export default WarehouseAreaSelect;
rsf-admin/src/page/basicInfo/basStation/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import BasStationList from "./BasStationList";
import BasStationEdit from "./BasStationEdit";
export default {
    list: BasStationList,
    edit: BasStationEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-admin/src/page/orders/qlyInspect/InspectModal.jsx
@@ -80,7 +80,7 @@
    const getData = async () => {
        const res = await request.post(`/qlyIsptItem/page`, { ispectId, isptStatus: '0' });
        const res = await request.post(`/qlyIsptItem/ispts/page`, { ispectId });
        if (res?.data?.code === 200) {
            const data = res.data.data.records.map(item => {
                return {
@@ -221,10 +221,10 @@
            ),
        },
        {
            field: 'isptResult', headerName: translate('table.field.qlyIsptItem.isptResult'), width: 150, type: 'singleSelect',
            editable: true, valueOptions: [{ value: '1', label: '合格' }, { value: '2', label: '不合格' }, { value: '3', label: '待定' }, { value: '4', label: '部分合格' }],
        },
        // {
        //     field: 'isptResult', headerName: translate('table.field.qlyIsptItem.isptResult'), width: 150, type: 'singleSelect',
        //     editable: true, valueOptions: [{ value: '1', label: '合格' }, { value: '2', label: '不合格' }, { value: '3', label: '待定' }, { value: '4', label: '部分合格' }],
        // },
    ])
    const processRowUpdate = (newRow, oldRow) => {
rsf-admin/src/page/orders/qlyInspect/QlyInspectList.jsx
@@ -116,7 +116,7 @@
                actions={(
                    <TopToolbar>
                        <AsnCreatButton />
                        <MyCreateButton onClick={() => { setOpCreateDialog(true) }} />
                        {/* <MyCreateButton onClick={() => { setOpCreateDialog(true) }} /> */}
                        <FilterButton />
                        <SelectColumnsButton preferenceKey='qlyInspect' />
                        <MyExportButton />
@@ -172,6 +172,12 @@
export default QlyInspectList;
const PrintLabelButton = () => {
    const record = useRecordContext();
}
const InspectionButton = () => {
    const record = useRecordContext();
    const notify = useNotify();
rsf-admin/src/page/orders/qlyInspect/QlyIsptItemList.jsx
@@ -43,6 +43,8 @@
import MyExportButton from '../../components/MyExportButton';
import PageDrawer from "../../components/PageDrawer";
import request from '@/utils/request';
import MyField from "@/page/components/MyField";
import QlyIsptItemResult from "./QlyIsptItemResult";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
@@ -89,6 +91,7 @@
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const [itemInfo, setItemInfo] = useState({})
    const isptId = useGetRecordId();
    const { data: dicts, isPending, error } = useGetOne('qlyInspect', { id: isptId });
    if (dicts == null) { return }
@@ -96,16 +99,9 @@
    return (
        <Box display="flex">
            <List
                storeKey="qlyIsptItem"
                resource="qlyIsptItem"
                filter={{ ispectId: isptId }}
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.qlyIsptItem"}
                empty={false}
                filters={filters}
@@ -119,19 +115,24 @@
                )}
                perPage={DEFAULT_ITEM_PAGE_SIZE}
            >
               <DynamicFields />
                <DynamicFields
                    drawerVal={drawerVal}
                    setDrawerVal={setDrawerVal}
                    itemInfo={itemInfo}
                    setItemInfo={setItemInfo} />
            </List>
            <QlyIsptItemCreate
                open={createDialog}
                record={dicts}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='QlyIsptItem Detail'
            <QlyIsptItemResult
                record={itemInfo}
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
            </QlyIsptItemResult>
        </Box>
    )
}
@@ -141,6 +142,7 @@
const DynamicFields = (props) => {
    const { drawerVal, setDrawerVal, itemInfo, setItemInfo } = props
    const translate = useTranslate();
    const notify = useNotify();
    const [columns, setColumns] = useState([]);
@@ -163,7 +165,13 @@
                <TextField source="stockBatch" label="table.field.qlyIsptItem.stockBatch" />,
                <NumberField source="rcptQty" label="table.field.qlyIsptItem.rcptQty" />,
                <NumberField source="dlyQty" label="table.field.qlyIsptItem.dlyQty" />,
                <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" />,
                <MyField source="anfme" label="table.field.qlyIsptItem.anfme"
                    onClick={(event, record, val) => {
                        event.stopPropagation();
                        setItemInfo(record)
                        setDrawerVal(!!drawerVal && drawerVal === val ? null : val);
                    }}
                />,
                <TextField source="splrName" label="table.field.qlyIsptItem.splrName" />,
                <NumberField source="isptResult$" label="table.field.qlyIsptItem.isptResult" />,
            ]
rsf-admin/src/page/orders/qlyInspect/QlyIsptItemResult.jsx
New file
@@ -0,0 +1,130 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
    useGetOne,
    Button,
    useRefresh,
    useGetRecordId,
} from 'react-admin';
import { Box, Typography, Card, Stack, LinearProgress, Dialog, DialogActions, DialogContent, DialogTitle, } from '@mui/material';
import { styled } from '@mui/material/styles';
import QlyIsptItemCreate from "./QlyIsptItemCreate";
import EmptyData from "../../components/EmptyData";
import MyCreateButton from "../../components/MyCreateButton";
import MyExportButton from '../../components/MyExportButton';
import PageDrawer from "../../components/PageDrawer";
import DialogCloseButton from "../../components/DialogCloseButton";
import request from '@/utils/request';
import MyField from "@/page/components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
}));
const QlyIsptItemResult = (props) => {
    const { record, drawerVal, setDrawerVal, from } = props
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setDrawerVal(false);
        }
    };
    return (
        <Dialog
            open={drawerVal}
            onClose={handleClose}
            aria-labelledby="form-dialog-title"
            fullWidth
            disableRestoreFocus
            maxWidth="lg"
        >
            <DialogTitle id="form-dialog-title" sx={{
                position: 'sticky',
                top: 0,
                backgroundColor: 'background.paper',
                zIndex: 1000
            }}>
                <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                    <DialogCloseButton onClose={handleClose} />
                </Box>
            </DialogTitle>
            <DialogContent sx={{ mt: 2 }}>
                <List
                    storeKey="IsptItem"
                    resource="qlyIsptItem/ispt/result"
                    filter={{ id: record?.id, type: '1' }}
                    empty={false}
                    filters={false}
                    sort={{ field: "create_time", order: "desc" }}
                    actions={false}
                    perPage={DEFAULT_ITEM_PAGE_SIZE}
                >
                    <StyledDatagrid
                        preferenceKey='IsptItem'
                        bulkActionButtons={false}
                        rowClick={false}
                        omit={['id', 'memo', 'dlyQty', 'label', 'stockBatch', 'picPath', 'ispectId']}
                    >
                        <NumberField source="id" />
                        <NumberField source="ispectId" label="table.field.qlyIsptItem.ispectId" />
                        <TextField source="matnrCode" label="table.field.qlyIsptItem.matnrCode" />
                        <TextField source="maktx" label="table.field.qlyIsptItem.maktx" />
                        <TextField source="label" label="table.field.qlyIsptItem.label" />
                        <TextField source="splrBatch" label="table.field.qlyIsptItem.splrBatch" />
                        <NumberField source="dlyQty" label="table.field.qlyIsptItem.dlyQty" />
                        <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" />
                        <TextField source="splrName" label="table.field.qlyIsptItem.splrName" />
                        <NumberField source="isptResult$" label="table.field.qlyIsptItem.isptResult" />
                    </StyledDatagrid>
                </List>
            </DialogContent>
        </Dialog>
    )
}
export default QlyIsptItemResult;
rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx
@@ -45,6 +45,8 @@
import MyField from "../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import WarehouseIsptResult from "./WarehouseIsptResult"
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -96,47 +98,56 @@
const WarehouseAreasItemList = () => {
    const translate = useTranslate();
    const [itemInfo, setItemInfo] = useState({})
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    return (
        <Box display="flex">
            <List
                title={"menu.warehouseAreasItem"}
                empty={false}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.warehouseAreasItem"}
                empty={false}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */}
                        <SelectColumnsButton preferenceKey='warehouseAreasItem' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
               <DynamicFields />
                <DynamicFields
                    drawerVal={drawerVal}
                    setDrawerVal={setDrawerVal}
                    itemInfo={itemInfo}
                    setItemInfo={setItemInfo} />
            </List>
            <WarehouseAreasItemCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
            <WarehouseIsptResult
                record={itemInfo}
                drawerVal={drawerVal}
                from="warehosueItem"
                setDrawerVal={setDrawerVal}
            >
            </WarehouseIsptResult>
            {/* <PageDrawer
                title='WarehouseAreasItem Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
            </PageDrawer> */}
        </Box>
    )
}
@@ -145,6 +156,7 @@
const DynamicFields = (props) => {
    const { drawerVal, setDrawerVal, itemInfo, setItemInfo } = props
    const translate = useTranslate();
    const notify = useNotify();
    const [columns, setColumns] = useState([]);
@@ -169,6 +181,13 @@
                <NumberField source="anfme" label="table.field.warehouseAreasItem.anfme" />,
                <NumberField source="workQty" label="table.field.warehouseAreasItem.workQty" />,
                <NumberField source="qty" label="table.field.warehouseAreasItem.qty" />,
                // <MyField source="isptQty" label="table.field.qlyIsptItem.anfme"
                //     onClick={(event, record, val) => {
                //         event.stopPropagation();
                //         setItemInfo(record)
                //         setDrawerVal(!!drawerVal && drawerVal === val ? null : val);
                //     }}
                // />,
                <TextField source="splrBatch" label="table.field.warehouseAreasItem.splrBtch" />,
                <TextField source="batch" label="table.field.warehouseAreasItem.batch" />,
                <TextField source="unit" label="table.field.warehouseAreasItem.unit" />,
rsf-admin/src/page/warehouseAreasItem/WarehouseIsptResult.jsx
New file
@@ -0,0 +1,125 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
    useGetOne,
    Button,
    useRefresh,
    useGetRecordId,
} from 'react-admin';
import { Box, Typography, Card, Stack, LinearProgress, Dialog, DialogActions, DialogContent, DialogTitle, } from '@mui/material';
import { styled } from '@mui/material/styles';
import DialogCloseButton from "../components/DialogCloseButton";
import request from '@/utils/request';
import MyField from "@/page/components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
}));
const WarehouseIsptResult = (props) => {
    const { record, drawerVal, setDrawerVal, from } = props
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setDrawerVal(false);
        }
    };
    return (
        <Dialog
            open={drawerVal}
            onClose={handleClose}
            aria-labelledby="form-dialog-title"
            fullWidth
            disableRestoreFocus
            maxWidth="lg"
        >
            <DialogTitle id="form-dialog-title" sx={{
                position: 'sticky',
                top: 0,
                backgroundColor: 'background.paper',
                zIndex: 1000
            }}>
                <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                    <DialogCloseButton onClose={handleClose} />
                </Box>
            </DialogTitle>
            <DialogContent sx={{ mt: 2 }}>
                <List
                    storeKey="ReceiptIsptItem"
                    resource="warehouseAreasItem/ispts"
                    filter={{ id: record?.id}}
                    empty={false}
                    filters={false}
                    sort={{ field: "create_time", order: "desc" }}
                    actions={false}
                    perPage={DEFAULT_ITEM_PAGE_SIZE}
                >
                    <StyledDatagrid
                        preferenceKey='ReceiptIsptItem'
                        bulkActionButtons={false}
                        rowClick={false}
                        omit={['id', 'memo', 'dlyQty', 'label', 'stockBatch', 'picPath', 'ispectId']}
                    >
                        <NumberField source="id" />
                        <NumberField source="ispectId" label="table.field.qlyIsptItem.ispectId" />
                        <TextField source="matnrCode" label="table.field.qlyIsptItem.matnrCode" />
                        <TextField source="maktx" label="table.field.qlyIsptItem.maktx" />
                        <TextField source="label" label="table.field.qlyIsptItem.label" />
                        <TextField source="splrBatch" label="table.field.qlyIsptItem.splrBatch" />
                        <NumberField source="dlyQty" label="table.field.qlyIsptItem.dlyQty" />
                        <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" />
                        <TextField source="splrName" label="table.field.qlyIsptItem.splrName" />
                        <NumberField source="isptResult$" label="table.field.qlyIsptItem.isptResult" />
                    </StyledDatagrid>
                </List>
            </DialogContent>
        </Dialog>
    )
}
export default WarehouseIsptResult;
rsf-server/src/main/java/basStation.sql
New file
@@ -0,0 +1,33 @@
-- save basStation record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.basStation', '0', '/manager/basStation', 'basStation', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 站点信息', '', '1', 'manager:basStation:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 站点信息', '', '1', 'manager:basStation:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 站点信息', '', '1', 'manager:basStation:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 站点信息', '', '1', 'manager:basStation:remove', '3', '1', '1');
-- locale menu name
basStation: 'BasStation',
-- locale field
basStation: {
    stationName: "stationName",
    inAble: "inAble",
    outAble: "outAble",
    useStatus: "useStatus",
    area: "area",
    isCrossZone: "isCrossZone",
    crossZoneArea: "crossZoneArea",
    isWcs: "isWcs",
    wcsData: "wcsData",
    containerType: "containerType",
    barcode: "barcode",
    autoTransfer: "autoTransfer",
},
-- ResourceContent
import basStation from './basStation';
case 'basStation':
    return basStation;
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/AgvController.java
New file
@@ -0,0 +1,56 @@
package com.vincent.rsf.server.api.controller.pda;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.api.controller.params.OpStockParams;
import com.vincent.rsf.server.api.service.AgvService;
import com.vincent.rsf.server.system.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.Objects;
@Api(tags = "PDA操作接口")
@RequestMapping("/pda")
@RestController
public class AgvController extends BaseController {
    @Autowired
    private AgvService agvService;
    @ApiOperation("站点绑定查询")
    @PreAuthorize("hasAuthority('manager:qlyInspect:list')")
    @PostMapping("/staBind/list")
    public R getStaBindList(@RequestBody Map<String, Object> params) {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return agvService.getStaBindList(params);
    }
    @PreAuthorize("hasAuthority('manager:basStation:list')")
    @ApiOperation("站点绑定")
    @PostMapping("/AGV/staBind")
    public R getAGVStaBind(@RequestBody Map<String, Object> params) {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return agvService.getAGVStaBind(params);
    }
    @PreAuthorize("hasAuthority('manager:asnOrderItem:list')")
    @ApiOperation("站点解绑")
    @PostMapping("/AGV/staUnBind")
    public R getAGVStaUnBind(@RequestBody Map<String, Object> params) {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return agvService.AGVStaUnBind(params);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/MobileController.java
@@ -225,7 +225,7 @@
        if (Objects.isNull(params) || params.isEmpty()) {
            return R.error("参数不能为空!!");
        }
        return mobileService.checkUpdate(params);
        return mobileService.checkUpdate(params, getLoginUserId());
    }
    @ApiOperation("获取上架信息")
rsf-server/src/main/java/com/vincent/rsf/server/api/service/AgvService.java
New file
@@ -0,0 +1,13 @@
package com.vincent.rsf.server.api.service;
import com.vincent.rsf.framework.common.R;
import java.util.Map;
public interface AgvService {
    R getAGVStaBind(Map<String, Object> params);
    R getStaBindList(Map<String, Object> params);
    R AGVStaUnBind(Map<String, Object> params);
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/MobileService.java
@@ -49,7 +49,7 @@
    R checkObjs(CheckObjParams params);
    R checkUpdate(List<QlyIsptItem> params);
    R checkUpdate(List<QlyIsptItem> params, Long loginUserId);
    R operateToStock(OpStockParams params);
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java
New file
@@ -0,0 +1,152 @@
package com.vincent.rsf.server.api.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.service.AgvService;
import com.vincent.rsf.server.manager.entity.BasStation;
import com.vincent.rsf.server.manager.entity.WaitPakin;
import com.vincent.rsf.server.manager.entity.WaitPakinItem;
import com.vincent.rsf.server.manager.enums.PakinIOStatus;
import com.vincent.rsf.server.manager.enums.StaUseStatusType;
import com.vincent.rsf.server.manager.service.BasStationService;
import com.vincent.rsf.server.manager.service.WaitPakinItemService;
import com.vincent.rsf.server.manager.service.WaitPakinService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@Service
public class AgvServiceImpl implements AgvService {
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private BasStationService basStationService;
    @Autowired
    private WaitPakinItemService waitPakinItemService;
    @Override
    public R AGVStaUnBind(Map<String, Object> params) {
        String sta = params.get("sta").toString();
        if (Cools.isEmpty(sta)){
            throw new CoolException("接驳位条码不能为空");
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
                .eq(BasStation::getUseStatus,StaUseStatusType.TYPE_F.type)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到接驳站点信息,请检查站点状态");
        }
        if (Cools.isEmpty(basStation.getBarcode())){
            throw new CoolException("数据错误,接驳站无条码信息");
        }
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, basStation.getBarcode())
                .eq(WaitPakin::getIoStatus,PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
        );
        if (Cools.isEmpty(waitPakin)){
            throw new CoolException("未找到组托数据,请检查状态");
        }
        basStation.setBarcode(null);
        basStation.setUseStatus(StaUseStatusType.TYPE_O.type);
        if (!basStationService.updateById(basStation)){
            throw new CoolException("更新站点状态失败");
        }
        return R.ok("解绑成功");
    }
    @Override
    public R getStaBindList(Map<String, Object> params) {
        String sta = params.get("sta").toString();
        if (Cools.isEmpty(sta)){
            throw new CoolException("接驳位条码不能为空");
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
                .eq(BasStation::getUseStatus,StaUseStatusType.TYPE_F.type)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到接驳站点信息,请检查站点状态");
        }
        if (Cools.isEmpty(basStation.getBarcode())){
            throw new CoolException("数据错误,接驳站无条码信息");
        }
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, basStation.getBarcode())
                .eq(WaitPakin::getIoStatus,PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
        );
        if (Cools.isEmpty(waitPakin)){
            throw new CoolException("未找到组托数据,请检查状态");
        }
        List<WaitPakinItem> waitPakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
        if (Cools.isEmpty(waitPakinItems)){
            throw new CoolException("数据错误,未找到组托明细");
        }
        return R.ok(Cools
                .add("barcode", basStation.getBarcode())
                .add("list", waitPakinItems)
        );
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R getAGVStaBind(Map<String, Object> params) {
        String barcode = params.get("barcode").toString();
        String sta = params.get("sta").toString();
        //验证基础信息
        BasStation basStation = checkStaStatus(barcode, sta);
        //更新站点状态
        basStation.setUseStatus(StaUseStatusType.TYPE_F.type);
        basStation.setBarcode(barcode);
        if (!basStationService.updateById(basStation)){
            throw new CoolException("更新站点状态失败");
        }
        return R.ok("绑定成功");
    }
    private BasStation checkStaStatus(String barcode, String sta){
        if (Cools.isEmpty(barcode)){
            throw new CoolException("容器码不能为空");
        }
        if (Cools.isEmpty(sta)){
            throw new CoolException("接驳位条码不能为空");
        }
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, barcode)
                .eq(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
        );
        if (Cools.isEmpty(waitPakin)){
            throw new CoolException("容器码未找到组托信息,请检查组托状态");
        }
        BasStation isBarcodeSta = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                        .eq(BasStation::getBarcode, barcode)
                ,false
        );
        if (!Cools.isEmpty(isBarcodeSta)){
            throw new CoolException("该条码已被"+isBarcodeSta.getStationName()+"站绑定");
        }
        BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                .eq(BasStation::getStationName, sta)
        );
        if (Cools.isEmpty(basStation)){
            throw new CoolException("未找到站点信息");
        }
        if (!basStation.getUseStatus().equals("O")){
            throw new CoolException("站点状态不为空闲");
        }
        return basStation;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -2,7 +2,6 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
@@ -350,6 +349,7 @@
                .eq(WarehouseAreasItem::getAsnCode, item.getAsnCode())
                .eq(!Cools.isEmpty(item.getIsptResult()), WarehouseAreasItem::getIsptResult, item.getIsptResult())
                .eq(StringUtils.isNotBlank(item.getSplrBatch()), WarehouseAreasItem::getSplrBatch, item.getSplrBatch()));
        if (!Objects.isNull(serviceOne)) {
            item.setId(serviceOne.getId());
            item.setAnfme(item.getAnfme() + serviceOne.getAnfme());
@@ -630,16 +630,17 @@
     * 快速质检
     *
     * @param params
     * @param loginUserId
     * @return
     */
    @Override
    public R checkUpdate(List<QlyIsptItem> params) {
    public R checkUpdate(List<QlyIsptItem> params, Long loginUserId) {
        if (Objects.isNull(params) || params.isEmpty()) {
            throw new CoolException("参数不能为空!!");
        }
        IsptItemsParams itemsParams = new IsptItemsParams();
        itemsParams.setIsptItem(params).setType("0");
        if (qlyIsptItemService.batchUpdate(itemsParams)) {
        if (qlyIsptItemService.batchUpdate(itemsParams, loginUserId)) {
            return R.ok();
        } else {
            return R.error("保存失败!!");
@@ -694,7 +695,8 @@
        /**获取平库订单*/
        AsnOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<AsnOrder>()
                .eq(AsnOrder::getId, OrderId)
                .eq(AsnOrder::getType, OrderType.ORDER_PLAT_IN.type));
                        .eq(AsnOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type)
                .eq(AsnOrder::getType, OrderType.ORDER_IN.type));
        if (Objects.isNull(order)) {
            throw new CoolException("非平库单据不可执行人工上架!!");
        }
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
@@ -54,7 +54,7 @@
            BeanUtils.copyProperties(ors, purchase);
            String wkVal = SerialRuleUtils.generateRuleCode(SerialRuleCode.PURCHASE_CODE, purchase);
            purchase.setCode(wkVal)
                    .setType(OrderType.ORDER_PURCHASE_IN.type);
                    .setType(OrderType.ORDER_IN.type);
            if (!purchaseService.save(purchase)) {
                throw new CoolException("采购单据保存失败");
            }
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -186,7 +186,7 @@
            BeanUtils.copyProperties(item, taskItem);
            return taskItem.setTaskId(taskId)
                    .setOrderType(OrderType.ORDER_RECEIPT.type)
                    .setOrderType(OrderType.ORDER_IN.type)
                    .setSource(item.getId())
                    .setTrackCode(item.getTrackCode())
                    .setCreateBy(loginUserId)
rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java
@@ -48,7 +48,8 @@
                        "sys_user_role",
                        "sys_role_menu",
                        "sys_menu",
                        "man_loc_type_rela"
                        "man_loc_type_rela",
                        "man_qly_inspect_result"
                ).contains(tableName);
            }
        };
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java
New file
@@ -0,0 +1,138 @@
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.BasStation;
import com.vincent.rsf.server.manager.service.BasStationService;
import com.vincent.rsf.server.system.controller.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
@RestController
public class BasStationController extends BaseController {
    @Autowired
    private BasStationService basStationService;
    @PreAuthorize("hasAuthority('manager:basStation:list')")
    @PostMapping("/basStation/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<BasStation, BaseParam> pageParam = new PageParam<>(baseParam, BasStation.class);
        PageParam<BasStation, BaseParam> page = basStationService.page(pageParam, pageParam.buildWrapper(true));
        for (BasStation station : page.getRecords()) {
            String content = station.getCrossZoneArea().substring(1, station.getCrossZoneArea().length() - 1);
            String[] parts = content.split(",");
            Long[] longArray = new Long[parts.length];
            for (int i = 0; i < parts.length; i++) {
                longArray[i] = Long.parseLong(parts[i].trim());
            }
            station.setAreaIds(longArray);
        }
        return R.ok().add(page);
    }
    @PreAuthorize("hasAuthority('manager:basStation:list')")
    @PostMapping("/basStation/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(basStationService.list());
    }
    @PreAuthorize("hasAuthority('manager:basStation:list')")
    @PostMapping({"/basStation/many/{ids}", "/basStations/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(basStationService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:basStation:list')")
    @GetMapping("/basStation/{id}")
    public R get(@PathVariable("id") Long id) {
        BasStation basStation = basStationService.getById(id);
        String content = basStation.getCrossZoneArea().substring(1, basStation.getCrossZoneArea().length() - 1);
        String[] parts = content.split(",");
        Long[] longArray = new Long[parts.length];
        for (int i = 0; i < parts.length; i++) {
            longArray[i] = Long.parseLong(parts[i].trim());
        }
        basStation.setAreaIds(longArray);
        return R.ok().add(basStation);
    }
    @PreAuthorize("hasAuthority('manager:basStation:save')")
    @OperationLog("Create 站点信息")
    @PostMapping("/basStation/save")
    public R save(@RequestBody BasStation basStation) {
        basStation.setCreateBy(getLoginUserId());
        basStation.setCreateTime(new Date());
        basStation.setUpdateBy(getLoginUserId());
        basStation.setUpdateTime(new Date());
        BasStation serviceOne = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, basStation.getStationName()));
        if (!Cools.isEmpty(serviceOne)) {
            return R.error(basStation.getStationName()+"站已被初始化");
        }
        if (!basStationService.save(basStation)) {
            return R.error("保存失败");
        }
        return R.ok("保存成功").add(basStation);
    }
    @PreAuthorize("hasAuthority('manager:basStation:update')")
    @OperationLog("Update 站点信息")
    @PostMapping("/basStation/update")
    public R update(@RequestBody BasStation basStation) {
        basStation.setUpdateBy(getLoginUserId());
        basStation.setUpdateTime(new Date());
        if (null !=basStation.getAreaIds()){
            basStation.setCrossZoneArea(Arrays.toString(basStation.getAreaIds()));
        }
        if (!basStationService.updateById(basStation)) {
            return R.error("更新失败");
        }
        return R.ok("更新成功").add(basStation);
    }
    @PreAuthorize("hasAuthority('manager:basStation:remove')")
    @OperationLog("Delete 站点信息")
    @PostMapping("/basStation/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!basStationService.removeByIds(Arrays.asList(ids))) {
            return R.error("删除失败");
        }
        return R.ok("删除成功").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:basStation:list')")
    @PostMapping("/basStation/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<BasStation> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(BasStation::getId, condition);
        }
        basStationService.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:basStation:list')")
    @PostMapping("/basStation/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(basStationService.list(), BasStation.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/QlyInspectController.java
@@ -13,12 +13,15 @@
import com.vincent.rsf.server.manager.controller.params.IsptOrderParam;
import com.vincent.rsf.server.manager.controller.params.QlyInspectAndItem;
import com.vincent.rsf.server.manager.entity.QlyInspect;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
import com.vincent.rsf.server.manager.service.QlyInspectService;
import com.vincent.rsf.server.manager.service.QlyIsptItemService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -27,12 +30,15 @@
import javax.servlet.http.HttpServletResponse;
import java.util.*;
@Slf4j
@Api(tags = "质检信息")
@RestController
public class QlyInspectController extends BaseController {
    @Autowired
    private QlyInspectService qlyInspectService;
    @Autowired
    private QlyIsptItemService qlyIsptItemService;
    @PreAuthorize("hasAuthority('manager:qlyInspect:list')")
    @PostMapping("/qlyInspect/page")
@@ -140,7 +146,11 @@
            return R.error("有明细单据已在质检中!!");
        }
        if (!qlyInspectService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
            return R.error("主单删除失败!!");
        }
        if (!qlyIsptItemService.remove(new LambdaQueryWrapper<QlyIsptItem>().in(QlyIsptItem::getIspectId, ids))) {
            return R.error("明细删除失败!!");
        }
        return R.ok("Delete Success").add(ids);
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/QlyIsptItemController.java
@@ -1,6 +1,8 @@
package com.vincent.rsf.server.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
@@ -12,8 +14,6 @@
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.controller.params.IsptItemsParams;
import com.vincent.rsf.server.manager.controller.params.QlyInspectAndItem;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
import com.vincent.rsf.server.manager.service.QlyIsptItemService;
import com.vincent.rsf.server.system.controller.BaseController;
@@ -38,9 +38,54 @@
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<QlyIsptItem, BaseParam> pageParam = new PageParam<>(baseParam, QlyIsptItem.class);
        QueryWrapper<QlyIsptItem> queryWrapper = pageParam.buildWrapper(true);
        /**拼接扩展字段*/
        PageParam<QlyIsptItem, BaseParam> page = qlyIsptItemService.page(pageParam, pageParam.buildWrapper(true));
        PageParam<QlyIsptItem, BaseParam> page = qlyIsptItemService.page(pageParam, queryWrapper);
        List<QlyIsptItem> records = page.getRecords();
        for (QlyIsptItem record : records) {
            if (!Objects.isNull(record.getFieldsIndex())) {
                Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex());
                record.setExtendFields(fields);
            }
        }
        page.setRecords(records);
        return R.ok(page);
    }
    /**
     * @author Ryan
     * @date 2025/5/12
     * @description: 获取质检信息修改
     * @version 1.0
     */
    @PreAuthorize("hasAuthority('manager:qlyIsptItem:list')")
    @PostMapping("/qlyIsptItem/ispts/page")
    public R getQlyList(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<QlyIsptItem, BaseParam> pageParam = new PageParam<>(baseParam, QlyIsptItem.class);
        QueryWrapper<QlyIsptItem> queryWrapper = pageParam.buildWrapper(true);
        IPage<QlyIsptItem> page = qlyIsptItemService.pageByWrapper(pageParam, queryWrapper);
        List<QlyIsptItem> records = page.getRecords();
        for (QlyIsptItem record : records) {
            if (!Objects.isNull(record.getFieldsIndex())) {
                Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex());
                record.setExtendFields(fields);
            }
        }
        page.setRecords(records);
        return R.ok(page);
    }
    @PreAuthorize("hasAuthority('manager:qlyIsptItem:list')")
    @PostMapping("/qlyIsptItem/ispt/result/page")
    public R getIsptResultList(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<QlyIsptItem, BaseParam> pageParam = new PageParam<>(baseParam, QlyIsptItem.class);
        QueryWrapper<QlyIsptItem> queryWrapper = pageParam.buildWrapper(true);
        IPage<QlyIsptItem> page = qlyIsptItemService.pageByIsptResult(pageParam, queryWrapper);
        List<QlyIsptItem> records = page.getRecords();
        for (QlyIsptItem record : records) {
            if (!Objects.isNull(record.getFieldsIndex())) {
@@ -134,7 +179,7 @@
        if (Objects.isNull(params)) {
            throw new CoolException("参数不能为空!!");
        }
        if (qlyIsptItemService.batchUpdate(params)) {
        if (qlyIsptItemService.batchUpdate(params, getLoginUserId())) {
            return R.ok("修改成功!!");
        } else  {
            return R.error("修改失败!!");
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WaitPakinController.java
@@ -12,13 +12,11 @@
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.params.GenerateTaskParams;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.entity.BasStation;
import com.vincent.rsf.server.manager.entity.TaskItem;
import com.vincent.rsf.server.manager.entity.WaitPakin;
import com.vincent.rsf.server.manager.entity.WaitPakinItem;
import com.vincent.rsf.server.manager.service.TaskItemService;
import com.vincent.rsf.server.manager.service.TaskService;
import com.vincent.rsf.server.manager.service.WaitPakinItemService;
import com.vincent.rsf.server.manager.service.WaitPakinService;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.system.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -41,6 +39,9 @@
    @Autowired
    private WaitPakinItemService waitPakinItemService;
    @Autowired
    private BasStationService basStationService;
    @Autowired
    private TaskService taskService;
@@ -112,6 +113,17 @@
        if (Arrays.asList(ids).isEmpty()) {
            return R.error("参数不能为空!!");
        }
        for (Long id : ids) {
            WaitPakin waitPakin = waitPakinService.getById(id);
            BasStation isBarcodeSta = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                            .eq(BasStation::getBarcode, waitPakin.getBarcode())
                    ,false
            );
            if (!Cools.isEmpty(isBarcodeSta)){
                throw new CoolException("该条码已被"+isBarcodeSta.getStationName()+"站绑定");
            }
        }
        return waitPakinService.removePakin(Arrays.asList(ids));
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasItemController.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
@@ -49,6 +50,26 @@
        return R.ok().add(page);
    }
    @PreAuthorize("hasAuthority('manager:warehouseAreasItem:list')")
    @PostMapping("/warehouseAreasItem/ispts/page")
    public R getIsptPage(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<WarehouseAreasItem, BaseParam> pageParam = new PageParam<>(baseParam, WarehouseAreasItem.class);
        QueryWrapper<WarehouseAreasItem> queryWrapper = pageParam.buildWrapper(true);
        /**拼接扩展字段*/
        IPage<WarehouseAreasItem> page = warehouseAreasItemService.pageByItemId(pageParam, queryWrapper);
        List<WarehouseAreasItem> records = page.getRecords();
        for (WarehouseAreasItem record : records) {
            if (!Objects.isNull(record.getFieldsIndex())) {
                Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex());
                record.setExtendFields(fields);
            }
        }
        page.setRecords(records);
        return R.ok().add(page);
    }
    @PreAuthorize("hasAuthority('manager:warehouseAreasItem:list')")
    @PostMapping("/warehouseAreasItem/list")
    public R list(@RequestBody Map<String, Object> map) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderItem.java
@@ -42,6 +42,8 @@
    @ApiModelProperty(value= "ASN主单标识")
    private Long asnId;
    /**
     * 平台标识(行号)
     */
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStation.java
New file
@@ -0,0 +1,231 @@
package com.vincent.rsf.server.manager.entity;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.server.manager.service.WarehouseAreasService;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.service.DictDataService;
import com.vincent.rsf.server.system.service.DictTypeService;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.entity.User;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("man_bas_station")
public class BasStation 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 stationName;
    /**
     * 可入
     */
    @ApiModelProperty(value= "可入")
    private Integer inAble = 0;
    /**
     * 可出
     */
    @ApiModelProperty(value= "可出")
    private Integer outAble = 0;
    /**
     * 状态
     */
    @ApiModelProperty(value= "状态")
    private String useStatus;
    /**
     * 所属库区id
     */
    @ApiModelProperty(value= "所属库区id")
    private Integer area;
    /**
     * 是否可跨区
     */
    @ApiModelProperty(value= "是否可跨区")
    private Integer isCrossZone = 0;
    /**
     * 可跨区区域id
     */
    @ApiModelProperty(value= "可跨区区域id")
    private String crossZoneArea;
    /**
     * 是否wcs站点
     */
    @ApiModelProperty(value= "是否wcs站点")
    private Integer isWcs = 0;
    /**
     * wcs站点信息
     */
    @ApiModelProperty(value= "wcs站点信息")
    private String wcsData;
    /**
     * 容器类型
     */
    @ApiModelProperty(value= "容器类型")
    private Integer containerType;
    /**
     * 条码
     */
    @ApiModelProperty(value= "条码")
    private String barcode;
    /**
     * 是否自动调拨
     */
    @ApiModelProperty(value= "是否自动调拨")
    private Integer autoTransfer;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    private String memo;
    /**
     * 创建人
     */
    @ApiModelProperty(value= "创建人")
    private Long createBy;
    /**
     * 创建时间
     */
    @ApiModelProperty(value= "创建时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * 更新人
     */
    @ApiModelProperty(value= "更新人")
    private Long updateBy;
    /**
     * 更新时间
     */
    @ApiModelProperty(value= "更新时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 所属机构
     */
    @ApiModelProperty(value= "租户")
    private Long tenantId;
    @TableField(exist = false)
    private Long[] areaIds;
    public BasStation() {}
//    BasStation basStation = new BasStation(
//            null,    // 站点名称
//            null,    // 可入
//            null,    // 可出
//            null,    // 状态
//            null,    // 所属库区id
//            null,    // 是否可跨区
//            null,    // 可跨区区域id
//            null,    // 是否wcs站点
//            null,    // wcs站点信息
//            null,    // 容器类型
//            null,    // 条码
//            null,    // 是否自动调拨
//            null,    // 备注
//            null,    // 创建人
//            null,    // 创建时间
//            null,    // 更新人
//            null    // 更新时间
//    );
    public String getCreateTime$(){
        if (Cools.isEmpty(this.createTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
    }
    public String getUpdateTime$(){
        if (Cools.isEmpty(this.updateTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
    }
    public String getUseStatus$(){
        if (Cools.isEmpty(this.useStatus)){
            return "";
        }
        DictDataService service = SpringUtils.getBean(DictDataService.class);
        DictData dictData = service.getOne(new LambdaQueryWrapper<DictData>()
                .eq(DictData::getDictTypeCode, "sys_sta_use_stas")
                .eq(DictData::getValue, this.useStatus)
        );
        if (!Cools.isEmpty(dictData)){
            return String.valueOf(dictData.getLabel());
        }
        return "";
    }
    public String getContainerType$(){
        if (Cools.isEmpty(this.useStatus)){
            return "";
        }
        DictDataService service = SpringUtils.getBean(DictDataService.class);
        DictData dictData = service.getOne(new LambdaQueryWrapper<DictData>()
                .eq(DictData::getDictTypeCode, "sys_container_type")
                .eq(DictData::getValue, this.containerType)
        );
        if (!Cools.isEmpty(dictData)){
            return String.valueOf(dictData.getLabel());
        }
        return "";
    }
    public String getArea$(){
        if (null == this.area){ return null; }
        WarehouseAreasService service = SpringUtils.getBean(WarehouseAreasService.class);
        WarehouseAreas warehouseAreas = service.getById(this.area);
        if (!Cools.isEmpty(warehouseAreas)){
            return String.valueOf(warehouseAreas.getName());
        }
        return null;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/QlyInspectResult.java
New file
@@ -0,0 +1,70 @@
package com.vincent.rsf.server.manager.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.entity.User;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@Accessors(chain = true)
@TableName("man_qly_inspect_result")
public class QlyInspectResult implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * ID
     */
    @ApiModelProperty(value= "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 质检单ID
     */
    @ApiModelProperty(value= "质检单ID")
    private Long isptId;
    /**
     * 质检明细单ID
     */
    @ApiModelProperty(value= "质检明细单ID")
    private Long isptItemId;
    @ApiModelProperty("收货区库存ID")
    private Long rcptId;
    /**
     * 数量
     */
    @ApiModelProperty(value= "数量")
    private Double anfme;
    /**
     * 质检结论
     */
    @ApiModelProperty(value= "质检结论")
    private Short isptResult;
    public QlyInspectResult() {}
    public QlyInspectResult(Long isptId,Long isptItemId,Double anfme,Short isptResult) {
        this.isptId = isptId;
        this.isptItemId = isptItemId;
        this.anfme = anfme;
        this.isptResult = isptResult;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/QlyIsptItem.java
@@ -47,6 +47,9 @@
    @ApiModelProperty("单据明细ID")
    private Long asnItemId;
    @ApiModelProperty("收货明细ID")
    private Long rcptId;
    /**
     * 编号
     */
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/AsnOrderTemplate.java
@@ -60,7 +60,7 @@
     */
    @Excel(name = "*单据类型")
    @ApiModelProperty(value = "*单据类型")
    @ExcelComment(value = "type", example = "采购入库单")
    @ExcelComment(value = "type", example = "入库单")
    private String type;
    /**
@@ -68,7 +68,7 @@
     */
    @Excel(name = "*业务类型")
    @ApiModelProperty(value = "*业务类型")
    @ExcelComment(value = "wkType", example = "完工入库单")
    @ExcelComment(value = "wkType", example = "采购入库单")
    private String wkType;
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java
@@ -9,12 +9,8 @@
 */
public enum OrderType {
    //订单类型
    ORDER_PURCHASE_IN("purchase", "采购入库单"),
    ORDER_OUT("out", "出库单"),
    ORDER_IN("in", "入库单"),
    ORDER_RECEIPT("receipt", "收货单"),
    ORDER_PLAT_IN("plat in", "平库入库单"),
    ;
    OrderType(String type, String desc) {
@@ -30,12 +26,6 @@
            return OrderType.ORDER_IN.type;
        } else if (desc.equals(OrderType.ORDER_OUT.desc)) {
            return OrderType.ORDER_OUT.type;
        } else if (desc.equals(OrderType.ORDER_PLAT_IN.desc)) {
            return OrderType.ORDER_PLAT_IN.type;
        } else if (desc.equals(OrderType.ORDER_RECEIPT.desc)) {
            return OrderType.ORDER_RECEIPT.type;
        } else if (desc.equals(OrderType.ORDER_PURCHASE_IN.desc)) {
            return OrderType.ORDER_PURCHASE_IN.type;
        }
        return null;
    }
@@ -45,12 +35,12 @@
            return OrderType.ORDER_IN.desc;
        } else if (type.equals(OrderType.ORDER_OUT.type)) {
            return OrderType.ORDER_OUT.desc;
        } else if (type.equals(OrderType.ORDER_PLAT_IN.type)) {
            return OrderType.ORDER_PLAT_IN.desc;
        } else if (type.equals(OrderType.ORDER_RECEIPT.type)) {
            return OrderType.ORDER_RECEIPT.desc;
        } else if (type.equals(OrderType.ORDER_PURCHASE_IN.type)) {
            return OrderType.ORDER_PURCHASE_IN.desc;
//        } else if (type.equals(OrderType.ORDER_PLAT_IN.type)) {
//            return OrderType.ORDER_PLAT_IN.desc;
//        } else if (type.equals(OrderType.ORDER_RECEIPT.type)) {
//            return OrderType.ORDER_RECEIPT.desc;
//        } else if (type.equals(OrderType.ORDER_PURCHASE_IN.type)) {
//            return OrderType.ORDER_PURCHASE_IN.desc;
        }
        return null;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java
@@ -9,14 +9,16 @@
 */
public enum OrderWorkType {
    //订单类型
    ORDER_WORK_TYPE_DONE_IN("1", "完工入库单"),
    ORDER_WORK_TYPE_PROD("2", "生产领料单"),
    ORDER_WORK_TYPE_PURCHASE("3", "外购收货"),
    ORDER_WORK_TYPE_SALE("4", "销售订单"),
    ORDER_WORK_TYPE_RETURN("5", "生产退料单"),
    ORDER_WORK_TYPE_SUPPLIER("6", "退货供应商出货单"),
    ORDER_WORK_TYPE_RETURN_ORDER("7", "销售退货入库单")
    ;
    ORDER_WORK_TYPE_DONE_IN("1", "采购入库单"),
    ORDER_WORK_TYPE_PROD("2", "生产入库单"),
    ORDER_WORK_TYPE_PURCHASE("3", "领料退回入库单"),
    ORDER_WORK_TYPE_SALE("4", "销售退回入库单"),
    ORDER_WORK_TYPE_OTHER_IN("5", "其它入库单"),
    ORDER_WORK_TYPE_SUPPLIER("11", "销售出库单"),
    ORDER_WORK_TYPE_RETURN_ORDER("12", "领料出库单"),
    ORDER_WORK_TYPE_PURCHASE_RETURN("13", "采购退回出库单"),
    ORDER_WORK_TYPE_OTHER("14", "其它出库单");
    OrderWorkType(String type, String desc) {
        this.type = type;
@@ -27,22 +29,26 @@
    public String desc;
    public static String getWorkType(String desc) {
            if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_DONE_IN.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_DONE_IN.type;
            } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_PROD.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_PROD.type;
            } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_PURCHASE.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_PURCHASE.type;
            } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_SALE.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_SALE.type;
            } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_RETURN.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_RETURN.type;
            } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_SUPPLIER.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_SUPPLIER.type;
            }else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.desc)) {
                return OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.type;
            }
            return null;
        if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_DONE_IN.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_DONE_IN.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_PROD.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_PROD.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_PURCHASE.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_PURCHASE.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_SALE.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_SALE.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_SUPPLIER.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_SUPPLIER.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_PURCHASE_RETURN.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_PURCHASE_RETURN.type;
        } else if (desc.equals(OrderWorkType.ORDER_WORK_TYPE_OTHER.desc)) {
            return OrderWorkType.ORDER_WORK_TYPE_OTHER.type;
        }
        return null;
    }
    public static String getWorkDesc(String type) {
@@ -54,12 +60,16 @@
            return OrderWorkType.ORDER_WORK_TYPE_PURCHASE.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_SALE.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_SALE.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_RETURN.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_RETURN.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_SUPPLIER.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_SUPPLIER.desc;
        }else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.type)) {
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_RETURN_ORDER.desc;
        }else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_PURCHASE_RETURN.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_PURCHASE_RETURN.desc;
        } else if (type.equals(OrderWorkType.ORDER_WORK_TYPE_OTHER.type)) {
            return OrderWorkType.ORDER_WORK_TYPE_OTHER.desc;
        }
        return null;
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/StaUseStatusType.java
New file
@@ -0,0 +1,18 @@
package com.vincent.rsf.server.manager.enums;
public enum StaUseStatusType {
    //订单类型
    TYPE_O("O", "空闲"),
    TYPE_F("F", "占用"),
    TYPE_X("X", "禁用"),
    ;
    StaUseStatusType(String type, String desc) {
        this.type = type;
        this.desc = desc;
    }
    public String type;
    public String desc;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/WarehouseAreasType.java
New file
@@ -0,0 +1,19 @@
package com.vincent.rsf.server.manager.enums;
public enum WarehouseAreasType {
    WAREHOUSE_AREAS_TYPE_RECEIPT("receipt", "收货区"),
    WAREHOUSE_AREAS_TYPE_DELIVERY("delivery", "待发区"),
    ORDER_WORK_TYPE_COLLECTION("collection", "集货区"),
    ORDER_WORK_TYPE_CTU("CTU", "CTU库区"),
    ORDER_WORK_TYPE_CRN("CRN", "堆垛机")
    ;
    WarehouseAreasType(String type, String desc) {
        this.type = type;
        this.desc = desc;
    }
    public String type;
    public String desc;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BasStationMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.BasStation;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BasStationMapper extends BaseMapper<BasStation> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/QlyInspectResultMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.QlyInspectResult;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface QlyInspectResultMapper extends BaseMapper<QlyInspectResult> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/QlyIsptItemMapper.java
@@ -1,12 +1,19 @@
package com.vincent.rsf.server.manager.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface QlyIsptItemMapper extends BaseMapper<QlyIsptItem> {
    IPage<QlyIsptItem> pageByWrapper(PageParam<QlyIsptItem, BaseParam> pageParam, @Param(Constants.WRAPPER) QueryWrapper<QlyIsptItem> queryWrapper);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/WarehouseAreasItemMapper.java
@@ -1,12 +1,19 @@
package com.vincent.rsf.server.manager.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.WarehouseAreasItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface WarehouseAreasItemMapper extends BaseMapper<WarehouseAreasItem> {
    IPage<WarehouseAreasItem> pageByItemId(PageParam<WarehouseAreasItem, BaseParam> pageParam, @Param(Constants.WRAPPER) QueryWrapper<WarehouseAreasItem> queryWrapper);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
@@ -1,14 +1,20 @@
package com.vincent.rsf.server.manager.schedules;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.entity.dto.ReceiptDetlsDto;
import com.vincent.rsf.server.common.config.SysStockProperties;
import com.vincent.rsf.server.common.utils.CommonUtil;
import com.vincent.rsf.server.common.utils.DateUtils;
import com.vincent.rsf.server.manager.controller.params.WarehouseAreaParam;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.PakinIOStatus;
import com.vincent.rsf.server.manager.enums.WarehouseAreasType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.WarehouseAreasItemServiceImpl;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.entity.Config;
@@ -60,6 +66,10 @@
    private WaitPakinItemLogService waitPakinItemLogService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private WarehouseAreasService warehouseAreasService;
    @Autowired
    private WarehouseAreasItemServiceImpl warehouseAreasItemService;
    /**
@@ -68,32 +78,114 @@
     * @description: 直接组托开关为true,将收货单直接加入临时库存
     * @version 1.0
     */
//    @Scheduled(cron = "0 0/05 * * * ?  ")
    @Scheduled(cron = "0/25 * * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public synchronized void IgnoreReceipt() {
        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
        if (Objects.isNull(config)) {
            return;
        }
        if (!Boolean.getBoolean(config.getVal())) {
        if (!Boolean.parseBoolean(config.getVal())) {
            return;
        }
        List<AsnOrder> orders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val));
        if (orders.isEmpty()) {
        if (!orders.isEmpty()) {
            for (AsnOrder order : orders) {
                List<AsnOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<AsnOrderItem>().eq(AsnOrderItem::getAsnId, order.getId()));
                if (orderItems.isEmpty()) {
                    return;
                }
                List<WarehouseAreasItem> items = new ArrayList<>();
                for (AsnOrderItem item : orderItems) {
                    WarehouseAreas one = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>()
                            .eq(WarehouseAreas::getType, WarehouseAreasType.WAREHOUSE_AREAS_TYPE_RECEIPT.type), false);
                    Long areaId = Objects.isNull(one) ? null : one.getId();
                    String areaName = Objects.isNull(one) ? null : one.getName();
                    WarehouseAreasItem param = new WarehouseAreasItem();
                    BeanUtils.copyProperties(item, param);
                    param.setAreaId(one.getId())
                            .setAsnCode(order.getCode())
                            .setAreaId(areaId)
                            .setAreaName(areaName)
                            .setAsnId(order.getId());
                    items.add(param);
                    Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getId, item.getMatnrId()));
                    if (Objects.isNull(matnr)) {
                        throw new CoolException("物料不存在!!");
                    }
                    //更新收货区库存
                    extracted(one, item, order, matnr);
                    if (!asnOrderItemService.update(new LambdaUpdateWrapper<AsnOrderItem>().set(AsnOrderItem::getQty, item.getAnfme()).eq(AsnOrderItem::getId, item.getId()))) {
                        throw new CoolException("收货单明细完成数量修改失败!!");
                    }
                }
//                if (!warehouseAreasItemService.saveBatch(items)) {
//                    throw new CoolException("收货单保存至收货区执行失败!!");
//                }
                if (!asnOrderService.update(new LambdaUpdateWrapper<AsnOrder>()
                        .set(AsnOrder::getQty, order.getAnfme())
                        .set(AsnOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val)
                        .eq(AsnOrder::getId, order.getId()))) {
                    throw new CoolException("收货单状态修改失败!!");
                }
            }
        }
    }
    /**
     * @author Ryan
     * @description  根据PO单据生成ASN单,自动生成ASN单为全量生成
     * @throws
     * @date 2025/5/12
     * @description: 收货区库存更新
     * @version 1.0
     */
    private void extracted(WarehouseAreas areasItem, AsnOrderItem orderItem, AsnOrder asnOrder, Matnr matnr) {
        WarehouseAreasItem item = new WarehouseAreasItem();
        item.setTrackCode(orderItem.getBarcode())
                .setAreaName(areasItem.getName())
                .setAreaId(areasItem.getId())
                .setAsnItemId(orderItem.getId())
                .setAsnCode(asnOrder.getCode())
                .setAsnId(asnOrder.getId())
                .setProdTime(orderItem.getProdTime())
                //库存单位为最小单位
                .setUnit(orderItem.getStockUnit())
                .setStockUnit(orderItem.getStockUnit())
                .setMatnrCode(matnr.getCode())
                .setAnfme(orderItem.getAnfme())
                .setMatnrId(matnr.getId())
                .setIsptResult(orderItem.getIsptResult())
                .setMaktx(matnr.getName())
                .setWeight(matnr.getWeight())
                .setFieldsIndex(orderItem.getFieldsIndex())
                .setShipperId(matnr.getShipperId());
        WarehouseAreasItem serviceOne = warehouseAreasItemService.getOne(new LambdaQueryWrapper<WarehouseAreasItem>()
                .eq(WarehouseAreasItem::getMatnrCode, item.getMatnrCode())
                .eq(!Cools.isEmpty(item.getFieldsIndex()), WarehouseAreasItem::getFieldsIndex, item.getFieldsIndex())
                .eq(WarehouseAreasItem::getAsnCode, item.getAsnCode())
                .eq(!Cools.isEmpty(item.getIsptResult()), WarehouseAreasItem::getIsptResult, item.getIsptResult())
                .eq(StringUtils.isNotBlank(item.getSplrBatch()), WarehouseAreasItem::getSplrBatch, item.getSplrBatch()));
        if (!Objects.isNull(serviceOne)) {
            item.setId(serviceOne.getId());
            item.setAnfme(item.getAnfme() + serviceOne.getAnfme());
        }
        //未质检
        if (!warehouseAreasItemService.saveOrUpdate(item)) {
            throw new CoolException("收货失败!!");
        }
    }
    /**
     * @return
     * @throws
     * @author Ryan
     * @description 根据PO单据生成ASN单, 自动生成ASN单为全量生成
     * @time 2025/3/3 15:44
     */
    @Scheduled(cron = "0 0/05 * * * ?  ")
@@ -176,17 +268,17 @@
    }
    /**
     * @author Ryan
     * @description 生成物料标签
     * @param
     * @return
     * @author Ryan
     * @description 生成物料标签
     * @time 2025/3/29 12:35
     */
    @Scheduled(cron = "0 0/05 * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void generateMatnrLabel() {
        List<AsnOrderItem> list = asnOrderItemService.list(new LambdaQueryWrapper<AsnOrderItem>()
                        .isNull(AsnOrderItem::getTrackCode)
                .isNull(AsnOrderItem::getTrackCode)
                .select(AsnOrderItem::getId));
        if (Objects.isNull(list) || list.isEmpty()) {
            return;
@@ -208,16 +300,16 @@
    }
    /**
     * @author Ryan
     * @description 组拖历史档
     * @param
     * @return
     * @author Ryan
     * @description 组拖历史档
     * @time 2025/3/29 12:36
     */
    @Scheduled(cron = "0/25 * * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void pakinLog() {
        List<WaitPakin>  pakinIds = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>()
        List<WaitPakin> pakinIds = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getIoStatus, Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_TASK_DONE.val))
                .select(WaitPakin::getId));
        if (pakinIds.isEmpty()) {
@@ -229,7 +321,7 @@
            throw new CoolException("组拖单为空!!");
        }
        List<WaitPakinLog> pakinLogs = new ArrayList<>();
        pakins.forEach(pakin ->{
        pakins.forEach(pakin -> {
            WaitPakinLog log = new WaitPakinLog();
            BeanUtils.copyProperties(pakin, log);
            log.setPakinId(pakin.getId()).setIoStatus(Short.parseShort("2"));
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BasStationService.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.BasStation;
public interface BasStationService extends IService<BasStation> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/QlyInspectResultService.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.QlyInspectResult;
public interface QlyInspectResultService extends IService<QlyInspectResult> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/QlyIsptItemService.java
@@ -1,12 +1,18 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.params.IsptItemsParams;
import com.vincent.rsf.server.manager.controller.params.QlyInspectAndItem;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
public interface QlyIsptItemService extends IService<QlyIsptItem> {
    boolean batchUpdate(IsptItemsParams params);
    boolean batchUpdate(IsptItemsParams params, Long loginUserId);
    IPage<QlyIsptItem> pageByWrapper(PageParam<QlyIsptItem, BaseParam> pageParam, QueryWrapper<QlyIsptItem> queryWrapper);
    IPage<QlyIsptItem> pageByIsptResult(PageParam<QlyIsptItem, BaseParam> pageParam, QueryWrapper<QlyIsptItem> queryWrapper);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/WarehouseAreasItemService.java
@@ -1,7 +1,11 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.WarehouseAreasItem;
import org.apache.ibatis.annotations.Param;
@@ -11,4 +15,5 @@
    List<WarehouseAreasItem> getList();
    IPage<WarehouseAreasItem> pageByItemId(PageParam<WarehouseAreasItem, BaseParam> pageParam, QueryWrapper<WarehouseAreasItem> queryWrapper);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java
@@ -250,7 +250,7 @@
        try {
            if (Objects.isNull(asnOrderItem.getFieldsIndex()) || StringUtils.isBlank(asnOrderItem.getFieldsIndex())) {
                StringBuffer sb = new StringBuffer();
                if (!asnOrderItem.getExtendFields().isEmpty()) {
                if (!Objects.isNull(asnOrderItem.getExtendFields()) && !asnOrderItem.getExtendFields().isEmpty()) {
                    Map<String, String> fields = asnOrderItem.getExtendFields();
                    asnOrderItem.getExtendFields().keySet().forEach(key -> {
                        sb.append(fields.get(key));
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BasStationServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.BasStationMapper;
import com.vincent.rsf.server.manager.entity.BasStation;
import com.vincent.rsf.server.manager.service.BasStationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("basStationService")
public class BasStationServiceImpl extends ServiceImpl<BasStationMapper, BasStation> implements BasStationService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyInspectResultServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.QlyInspectResultMapper;
import com.vincent.rsf.server.manager.entity.QlyInspectResult;
import com.vincent.rsf.server.manager.service.QlyInspectResultService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("qlyInspectResultService")
public class QlyInspectResultServiceImpl extends ServiceImpl<QlyInspectResultMapper, QlyInspectResult> implements QlyInspectResultService {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyInspectServiceImpl.java
@@ -174,6 +174,7 @@
                isptItem.setAsnItemId(orderItem.getId())
                        .setIspectId(inspect.getId())
                        .setRcptQty(orderItem.getAnfme())
                        .setRcptId(orderItem.getId())
                        .setAnfme(0.0)
                        .setFieldsIndex(orderItem.getFieldsIndex())
                        .setSplrBatch(orderItem.getSplrBatch())
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyIsptItemServiceImpl.java
@@ -1,32 +1,28 @@
package com.vincent.rsf.server.manager.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.common.R;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.params.IsptItemsParams;
import com.vincent.rsf.server.manager.controller.params.QlyInspectAndItem;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.QlyInspect;
import com.vincent.rsf.server.manager.entity.QlyInspectResult;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.QlyIsptResult;
import com.vincent.rsf.server.manager.enums.QlyIsptStatus;
import com.vincent.rsf.server.manager.mapper.QlyIsptItemMapper;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
import com.vincent.rsf.server.manager.service.AsnOrderItemService;
import com.vincent.rsf.server.manager.service.QlyInspectResultService;
import com.vincent.rsf.server.manager.service.QlyInspectService;
import com.vincent.rsf.server.manager.service.QlyIsptItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@Service("qlyIsptItemService")
@@ -39,9 +35,14 @@
    @Autowired
    private QlyInspectResultService qlyInspectResultService;
    @Autowired
    private QlyIsptItemService qlyIsptItemService;
    @Autowired
    private WarehouseAreasItemServiceImpl warehouseAreasItemService;
    /**
     * @param
     * @param loginUserId
     * @return
     * @author Ryan
     * @description 批量修改
@@ -49,7 +50,7 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdate(IsptItemsParams params) {
    public boolean batchUpdate(IsptItemsParams params, Long loginUserId) {
        if (Objects.isNull(params.getIsptItem()) || params.getIsptItem().isEmpty()) {
            throw new CoolException("ID不能为空!!");
        }
@@ -61,111 +62,177 @@
            throw new CoolException("数据错误:明细不存在!!");
        }
        for (QlyIsptItem item : isptItems) {
        for (QlyIsptItem item : isptItem) {
            List<QlyInspectResult> results = qlyInspectResultService.list(new LambdaQueryWrapper<QlyInspectResult>()
                    .eq(QlyInspectResult::getIsptId, item.getIspectId())
                    .eq(QlyInspectResult::getIsptItemId, item.getId()));
            if (!results.isEmpty()) {
                //不为空做更新操作
            } else {
                //为空做新增操作
                QlyInspectResult result = new QlyInspectResult();
                result.setIsptId(item.getIspectId())
                        .setAnfme(item.getSafeQty())
                        .setIsptItemId(item.getId());
                if (item.getDisQty().compareTo(0.00) < 1) {
                    continue;
                }
                result.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_DEFECT.val);
                result.setAnfme(item.getDisQty());
                if (!qlyInspectResultService.save(result)) {
                    throw new CoolException("质检结论保存失败!!");
                }
                if (item.getSafeQty().compareTo(0.00) < 1) {
                    continue;
                }
                result.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val)
                        .setAnfme(item.getSafeQty());
                if (!qlyInspectResultService.save(result)) {
                    throw new CoolException("质检结论保存失败!!");
                if (!qlyInspectResultService.remove(new LambdaUpdateWrapper<QlyInspectResult>()
                        .eq(QlyInspectResult::getIsptItemId, item.getId()))) {
                    throw new CoolException("历史质检结果移出失败!!");
                }
            }
        }
            QlyInspectResult result = new QlyInspectResult();
            result.setIsptId(item.getIspectId())
                    .setRcptId(item.getRcptId())
                    .setIsptItemId(item.getId());
            if (!Objects.isNull(item.getDisQty()) && item.getDisQty().compareTo(0.00) > 0) {
                result.setAnfme(item.getDisQty())
                        .setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_DEFECT.val);
                qlyInspectResultService.saveOrUpdate(result);
            }
            result = new QlyInspectResult();
            result.setIsptId(item.getIspectId())
                    .setRcptId(item.getRcptId())
                    .setIsptItemId(item.getId());
            if (!Objects.isNull(item.getSafeQty()) && item.getSafeQty().compareTo(0.00) > 0) {
                result.setAnfme(item.getSafeQty())
                        .setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val);
                qlyInspectResultService.saveOrUpdate(result);
            }
        if (Short.parseShort(params.getType()) == QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val || Short.parseShort(params.getType()) == QlyIsptResult.QLY_ISPT_RESULT_DEFECT.val) {
            //1:合格, 2:不合格, 0: 其它(默认)
            isptItem.forEach(item -> {
                if (Short.parseShort(params.getType()) == QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val) {
                    //TODO 先捡后收为送货数量,先收后捡为收货数量
//                    item.setSafeQty(item.getDlyQty());
//                    item.setDisQty(0.0);
            List<QlyInspectResult> isptRelt = qlyInspectResultService.list(new LambdaQueryWrapper<QlyInspectResult>()
                    .eq(QlyInspectResult::getIsptId, item.getIspectId())
                    .eq(QlyInspectResult::getIsptItemId, item.getId()));
            Double isptQty = isptRelt.stream().mapToDouble(QlyInspectResult::getAnfme).sum();
            if (!qlyIsptItemService.update(new LambdaUpdateWrapper<QlyIsptItem>()
                    .set(QlyIsptItem::getUpdateBy, loginUserId)
                    .set(QlyIsptItem::getAnfme, isptQty)
                    .eq(QlyIsptItem::getId, item.getId()))) {
                throw new CoolException("单据明细数量修改失败!!");
            }
            WarehouseAreasItem orderItem = warehouseAreasItemService.getById(item.getRcptId());
            if (Objects.isNull(orderItem)) {
                throw new CoolException("收货单据不存在!!");
            }
            Double disQty = Objects.isNull(item.getDisQty()) ? 0 : item.getDisQty();
            Double safeQty = Objects.isNull(item.getSafeQty()) ? 0 : item.getSafeQty();
            Double sum = disQty + safeQty;
            orderItem.setIsptQty(sum);
            if (sum.compareTo(0.0) > 0) {
                if (!warehouseAreasItemService.updateById(orderItem)) {
                    throw new CoolException("收货区库存信息更新失败!!");
                }
                if (Objects.isNull(orderItem.getIsptResult())) {
                    operateReceipt(item, orderItem);
                } else {
//                    item.setSafeQty(0.0);
//                    item.setDisQty(item.getDlyQty());
                }
                if (!this.update(new LambdaUpdateWrapper<QlyIsptItem>()
//                        .set(QlyIsptItem::getSafeQty, item.getSafeQty())
                        .set(QlyIsptItem::getIsptResult, Short.parseShort(params.getType()))
//                        .set(QlyIsptItem::getDisQty, item.getDisQty())
                        .in(QlyIsptItem::getId, item.getId()))) {
                    throw new CoolException("修改失败!!");
                }
            });
        } else {
            if (!this.updateBatchById(isptItem)) {
                throw new CoolException("明细修改失败");
            }
        }
        Map<Long, List<QlyIsptItem>> listMap = isptItems.stream().collect(Collectors.groupingBy(QlyIsptItem::getIspectId));
        for (Long key : listMap.keySet()) {
            QlyInspect inspect = qlyInspectService.getById(key);
            List<QlyIsptItem> items = listMap.get(key);
            items.forEach(qlyIsptItem -> {
                AsnOrderItem orderItem = asnOrderItemService.getById(qlyIsptItem.getAsnItemId());
//                if (qlyIsptItem.getSafeQty().compareTo(orderItem.getAnfme()) >= 0.00) {
//                    orderItem.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val)
//                            .setIsptStatus(QlyIsptStatus.QLY_ISPT_STAS_DONE.val);
//                } else if (qlyIsptItem.getSafeQty().compareTo(0.00) > 0.00 && qlyIsptItem.getSafeQty().compareTo(orderItem.getAnfme()) < 0.00) {
//                    orderItem.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_SECTION.val);
//                    if (Double.compare(qlyIsptItem.getSafeQty() + qlyIsptItem.getDisQty(), orderItem.getAnfme()) >= 0.00 ) {
//                        orderItem.setIsptStatus(QlyIsptStatus.QLY_ISPT_STAS_DONE.val);
//                    } else {
//                        orderItem.setIsptStatus(QlyIsptStatus.QLY_ISPT_STAS_ING.val);
//                    }
//                } else {
//                    orderItem.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_DEFECT.val)
//                            .setIsptStatus(QlyIsptStatus.QLY_ISPT_STAS_DONE.val);
//                }
                if (!asnOrderItemService.updateById(orderItem)) {
                    throw new CoolException("收货单明细修改失败!!");
                }
            });
//            Double safeQty = items.stream().mapToDouble(QlyIsptItem::getSafeQty).sum();
//            Double disQty = items.stream().mapToDouble(QlyIsptItem::getDisQty).sum();
//            Double qlyQty = safeQty + disQty;
//            //安全数量,质检数量
//            inspect.setSafeQty(safeQty)
//                    .setIsptQty(qlyQty);
//            if (Double.compare(disQty, 0) > 0) {
//                inspect.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_SECTION.val);
//            }
//            if (Double.compare(safeQty, inspect.getDlyQty()) == 0) {
////                inspect.setIsptStatus(QlyIsptStatus.QLY_ISPT_STAS_DONE.val);
//                inspect.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val);
//            }
            if (!qlyInspectService.updateById(inspect)) {
                throw new CoolException("质检数量修改失败!!");
            }
        Set<Long> isptIds = isptItem.stream().map(QlyIsptItem::getIspectId).collect(Collectors.toSet());
        List<QlyInspectResult> items = qlyInspectResultService.list(new LambdaQueryWrapper<QlyInspectResult>()
                .in(QlyInspectResult::getIsptId, isptIds));
        Double sum = items.stream().mapToDouble(QlyInspectResult::getAnfme).sum();
        if (sum.compareTo(0.00) > 0) {
            qlyInspectService.update(new LambdaUpdateWrapper<QlyInspect>()
                    .set(QlyInspect::getIsptQty, sum)
                    .set(QlyInspect::getUpdateBy, loginUserId)
                    .eq(QlyInspect::getId, isptItem.stream().findFirst().get().getIspectId()));
        }
//        qlyIsptItemService.pageByIsptResult(null, new QueryWrapper<QlyIsptItem>())
        return true;
    }
    /**
     * @author Ryan
     * @date 2025/5/12
     * @description: 质检后修改收货区存信息
     * @version 1.0
     */
    private void operateReceipt(QlyIsptItem item, WarehouseAreasItem orderItem) {
        Double disQty = Objects.isNull(item.getDisQty()) ? 0 : item.getDisQty();
        Double safeQty = Objects.isNull(item.getSafeQty()) ? 0 : item.getSafeQty();
        Double sum = disQty + safeQty;
        if (sum.compareTo(orderItem.getAnfme()) >= 0) {
            //完成质检,做更新操作
            if (safeQty.compareTo(0.0) > 0) {
                orderItem.setIsptQty(safeQty);
                orderItem.setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val);
                if (!warehouseAreasItemService.updateById(orderItem)) {
                    throw new CoolException("收货区库存明细更新失败!!");
                }
            }
            if (disQty.compareTo(0.0) > 0) {
                orderItem.setIsptQty(disQty)
                        .setId(null)
                        .setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_DEFECT.val);
                if (!warehouseAreasItemService.saveOrUpdate(orderItem)) {
                    throw new CoolException("收货区库存明细更新失败!!");
                }
            }
        } else {
            //未完成做添加操作
            if (safeQty.compareTo(0.0) > 0) {
                orderItem.setIsptQty(safeQty)
                        .setId(null)
                        .setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val);
                if (!warehouseAreasItemService.saveOrUpdate(orderItem)) {
                    throw new CoolException("收货区库存明细更新失败!!");
                }
            }
            if (disQty.compareTo(0.0) > 0) {
                orderItem.setIsptQty(disQty)
                        .setId(null)
                        .setIsptResult(QlyIsptResult.QLY_ISPT_RESULT_DEFECT.val);
                if (!warehouseAreasItemService.saveOrUpdate(orderItem)) {
                    throw new CoolException("收货区库存明细更新失败!!");
                }
            }
        }
    }
    /**
     * @author Ryan
     * @date 2025/5/12
     * @description: 获取自定义Page
     * @version 1.0
     */
    @Override
    public IPage<QlyIsptItem> pageByWrapper(PageParam<QlyIsptItem, BaseParam> pageParam, QueryWrapper<QlyIsptItem> queryWrapper) {
        IPage<QlyIsptItem> page = this.page(pageParam, queryWrapper);
        if (!page.getRecords().isEmpty()) {
            List<QlyIsptItem> records = page.getRecords();
            for (int i = 0; i < records.size(); i++) {
                List<QlyInspectResult> results = qlyInspectResultService.list(new QueryWrapper<QlyInspectResult>()
                        .select("id, ispt_result, SUM(anfme) anfme, ispt_item_id, ispt_id, rcpt_id")
                        .lambda()
                        .eq(QlyInspectResult::getIsptItemId, records.get(i).getId()).groupBy(QlyInspectResult::getIsptResult));
                if (!results.isEmpty()) {
                    for (QlyInspectResult result : results) {
                        if (result.getIsptResult() == QlyIsptResult.QLY_ISPT_RESULT_EXCELLENT.val) {
                            records.get(i).setSafeQty(result.getAnfme());
                        } else {
                            records.get(i).setDisQty(result.getAnfme());
                        }
                    }
                }
            }
            page.setRecords(records);
        }
        return page;
    }
    @Override
    public IPage<QlyIsptItem> pageByIsptResult(PageParam<QlyIsptItem, BaseParam> pageParam, QueryWrapper<QlyIsptItem> queryWrapper) {
        if (Objects.isNull(pageParam)) {
            PageParam<QlyIsptItem, BaseParam> param = new PageParam<>();
            return this.baseMapper.selectPage(param, queryWrapper);
        } else {
            return this.baseMapper.pageByWrapper(pageParam, queryWrapper);
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -116,7 +116,7 @@
                TaskItem taskItem = new TaskItem();
                BeanUtils.copyProperties(item, taskItem);
                taskItem.setTaskId(task.getId())
                        .setOrderType(OrderType.ORDER_RECEIPT.type)
                        .setOrderType(OrderType.ORDER_IN.type)
                        .setSource(item.getId())
                        .setTrackCode(item.getTrackCode())
                        .setCreateBy(loginUserId)
@@ -244,7 +244,7 @@
//                    throw new CoolException("数据错误: 单据不存在!!");
//                }
                taskItem.setTaskId(task.getId())
                        .setOrderType(OrderType.ORDER_RECEIPT.type)
                        .setOrderType(OrderType.ORDER_IN.type)
                        .setSource(item.getId())
                        .setTrackCode(item.getTrackCode())
                        .setCreateBy(loginUserId)
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WarehouseAreasItemServiceImpl.java
@@ -1,5 +1,9 @@
package com.vincent.rsf.server.manager.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.mapper.WarehouseAreasItemMapper;
import com.vincent.rsf.server.manager.entity.WarehouseAreasItem;
@@ -24,4 +28,10 @@
        }
        return areasItems;
    }
    @Override
    public IPage<WarehouseAreasItem> pageByItemId(PageParam<WarehouseAreasItem, BaseParam> pageParam, QueryWrapper<WarehouseAreasItem> queryWrapper) {
        IPage<WarehouseAreasItem> itemIPage = this.baseMapper.pageByItemId(pageParam, queryWrapper);
        return itemIPage;
    }
}
rsf-server/src/main/java/qlyInspectResult.sql
New file
@@ -0,0 +1,25 @@
-- save qlyInspectResult record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.qlyInspectResult', '0', '/manager/qlyInspectResult', 'qlyInspectResult', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 质检结果', '', '1', 'manager:qlyInspectResult:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 质检结果', '', '1', 'manager:qlyInspectResult:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 质检结果', '', '1', 'manager:qlyInspectResult:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 质检结果', '', '1', 'manager:qlyInspectResult:remove', '3', '1', '1');
-- locale menu name
qlyInspectResult: 'QlyInspectResult',
-- locale field
qlyInspectResult: {
    isptId: "isptId",
    isptItemId: "isptItemId",
    anfme: "anfme",
    isptResult: "isptResult",
},
-- ResourceContent
import qlyInspectResult from './qlyInspectResult';
case 'qlyInspectResult':
    return qlyInspectResult;
rsf-server/src/main/resources/application-dev.yml
@@ -14,7 +14,7 @@
    driver-class-name: com.mysql.jdbc.Driver
#    url: jdbc:mysql://47.76.147.249:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    url: jdbc:mysql://192.168.4.56:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    url: jdbc:mysql://127.0.0.1:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
#    username: rsf
    password: 34821015
    type: com.alibaba.druid.pool.DruidDataSource
rsf-server/src/main/resources/mapper/manager/BasStationMapper.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.BasStationMapper">
</mapper>
rsf-server/src/main/resources/mapper/manager/QlyInspectResultMapper.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.QlyInspectResultMapper">
</mapper>
rsf-server/src/main/resources/mapper/manager/QlyIsptItemMapper.xml
@@ -2,4 +2,30 @@
<!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.QlyIsptItemMapper">
    <select id="pageByWrapper" resultType="com.vincent.rsf.server.manager.entity.QlyIsptItem">
        SELECT *
        FROM (SELECT qii.id,
                     ispect_id,
                     asn_item_id,
                     matnr_code,
                     maktx,
                     splr_name,
                     splr_batch,
                     qir.anfme,
                     qir.ispt_result,
                     rcpt_qty,
                     dly_qty,
                     track_code,
                     pic_path,
                     `status`,
                     deleted,
                     tenant_id,
                     create_by,
                     create_time,
                     update_by,
                     update_time,
                     memo
              FROM man_qly_ispt_item qii
                       LEFT JOIN man_qly_inspect_result qir ON qii.id = qir.ispt_item_id) t ${ew.customSqlSegment}
    </select>
</mapper>
rsf-server/src/main/resources/mapper/manager/WarehouseAreasItemMapper.xml
@@ -1,5 +1,43 @@
<?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.WarehouseAreasItemMapper">
    <select id="pageByItemId" resultType="com.vincent.rsf.server.manager.entity.WarehouseAreasItem">
        SELECT *
        FROM (SELECT qai.id,
                     area_id,
                     area_name,
                     asn_id,
                     plat_item_id,
                     po_code,
                     asn_code,
                     asn_item_id,
                     matnr_id,
                     maktx,
                     matnr_code,
                     fields_index,
                     work_qty,
                     qty,
                     splr_batch,
                     unit,
                     stock_unit,
                     brand,
                     splr_id,
                     weight,
                     prod_time,
                     flag_norm,
                     qir.anfme,
                     qir.ispt_result,
                     track_code,
                     `status`,
                     deleted,
                     tenant_id,
                     create_by,
                     create_time,
                     update_by,
                     update_time,
                     memo
              FROM man_warehouse_areas_item qai
                       LEFT JOIN man_qly_inspect_result qir ON qai.id = qir.rcpt_id) t
            ${ew.customSqlSegment}
    </select>
</mapper>