c5bee307ac9ab10b524bbccce2fde3190723f467..f41c5fb9fffd73f2c39cd9280d72ff89c5e4ee02
2025-05-10 skyouc
质检修改数据来源
f41c5f 对比 | 目录
2025-05-10 skyouc
Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop
b3c1bf 对比 | 目录
2025-05-10 skyouc
收货单打印功能优化
0345d3 对比 | 目录
2025-05-10 zjj
#人工入库
adcda0 对比 | 目录
16个文件已修改
1个文件已添加
489 ■■■■■ 已修改文件
rsf-admin/package-lock.json 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/qlyInspect/AsnSelModal.jsx 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/params/ManualShelvingParams.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/params/PublicToStockParams.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/MobileController.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/QlyInspectController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/QlyInspectService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyInspectServiceImpl.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/package-lock.json
@@ -38,7 +38,7 @@
        "react-router": "^6.22.0",
        "react-router-dom": "^6.26.1",
        "react-syntax-highlighter": "^15.5.0",
        "react-to-print": "^3.0.5",
        "react-to-print": "^2.14.11",
        "svgpath": "^2.6.0",
        "three": "^0.155.0",
        "tweedle.js": "^2.1.0"
@@ -6625,12 +6625,16 @@
      }
    },
    "node_modules/react-to-print": {
      "version": "3.1.0",
      "resolved": "https://registry.npmmirror.com/react-to-print/-/react-to-print-3.1.0.tgz",
      "integrity": "sha512-hiJZVmJtaRm9EHoUTG2bordyeRxVSGy9oFVV7fSvzOWwctPp6jbz2R6NFkaokaTYBxC7wTM/fMV5eCXsNpEwsA==",
      "version": "2.14.11",
      "resolved": "https://registry.npmmirror.com/react-to-print/-/react-to-print-2.14.11.tgz",
      "integrity": "sha512-sePHBaCtZLp8/g4d/gRyI9XQZkveZq6xoukanAHfkzlXOa7sTuXCEQOYq37lIa5MkUoxySdJxYuyClaXPa9Zpg==",
      "license": "MIT",
      "dependencies": {
        "prop-types": "^15.8.1"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19"
        "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
        "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
      }
    },
    "node_modules/react-transition-group": {
rsf-admin/package.json
@@ -42,7 +42,7 @@
    "react-router": "^6.22.0",
    "react-router-dom": "^6.26.1",
    "react-syntax-highlighter": "^15.5.0",
    "react-to-print": "^3.0.5",
    "react-to-print": "^2.14.11",
    "svgpath": "^2.6.0",
    "three": "^0.155.0",
    "tweedle.js": "^2.1.0"
rsf-admin/src/i18n/zh.js
@@ -353,8 +353,8 @@
            },
            warehouseAreasItem: {
                asnCode: '单号',
                areaId: "仓库区域",
                areaName: "区域名称    ",
                areaId: "库区ID",
                areaName: "库区名称    ",
                matnrId: "物料标识",
                matnrName: "物料名称",
                matnrCode: "物料编码",
rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
@@ -116,6 +116,7 @@
  const [modalType, setmodalType] = useState(0);
  const [printOrder, setPrintOrder] = useState(false);
  const [select, setSelect] = useState({});
  const invoiceRef = useRef();
  const billReload = useRef();
  const notify = useNotify();
  const refresh = useRefresh();
rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx
@@ -36,6 +36,7 @@
import { styled } from '@mui/material/styles';
import { QRCodeSVG, QRCodeCanvas } from 'qrcode.react';  // 现在必须这样用
import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined';
import { useReactToPrint } from "react-to-print";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -60,8 +61,8 @@
const OrderPrintPreview = (props) => {
    const { open, setOpen, record } = props;
    const notify = useNotify();
    const invoiceRef = useRef();
    const translate = useTranslate();
    const [drawerVal, setDrawerVal] = useState(false);
    const [disabled, setDisabled] = useState(false)
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_order_type')) || [];
    const business = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || [];
@@ -70,88 +71,119 @@
        setOpen(false);
    };
    const printOrders = useReactToPrint({
        content: () => {
            return invoiceRef.current
        },
        documentTitle: `订单:${record?.code}`,
        pageStyle: `
        @page {
            size: A4 landscape;  // 关键设置:A4横向
            margin: 10mm;
        }
        @media print {
             html, body {
                width: 297mm;     // A4横向宽度
                height: 210mm;    // A4横向高度
            }
        }`,
        onAfterPrint: () => alert('已发送至打印机!')
    })
    // @page {
    //     // size: A4;
    // }
    // @media print {
    //     // body {
    //     // -webkit-print-color-adjust: exact;
    //     // }
    return (
        <>
            <Dialog
                open={open}
                onClose={handleClose}
                aria-labelledby="form-dialog-title"
                aria-hidden
                fullWidth
                disableRestoreFocus
                maxWidth="xl"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
            >
                <DialogTitle id="form-dialog-title" sx={{
                    position: 'sticky',
                    top: 0,
                    textAlign: 'center',
                    backgroundColor: 'background.paper',
                    zIndex: 1000
                }}>
                    {translate('menu.asnOrder')}
                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                        <DialogCloseButton onClose={handleClose} />
                    </Box>
                </DialogTitle>
                <DialogContent sx={{ mt: 2 }}>
                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                        <Form defaultValues={record}>
                            <Grid container spacing={2} sx={{ justifyContent: 'space-between', }}>
                                <Grid item md={2}>
                                    <Box sx={{ display: 'flex', justifyContent: 'center' }}>
                                        <Typography>单据类型:</Typography>
                                        <Typography>{record?.type$}</Typography>
                                    </Box>
                                    <Box sx={{ display: 'flex', justifyContent: 'center', padding: 1 }}></Box>
                                    <Box sx={{ display: 'flex', justifyContent: 'center' }}>
                                        <Typography>业务类型:</Typography>
                                        <Typography>{record?.wkType$}</Typography>
                                    </Box>
                                </Grid>
                                <Grid item md={2}>
                                    <QRCodeSVG value={record?.code} />
                                    <Typography>{record.code}</Typography>
                                </Grid>
                                {/* <Grid item md={2}>
                                    <TextInput source="code" label={"table.field.asnOrder.code"} />
                                </Grid> */}
                            </Grid>
                        </Form>
                        <List
                            resource="asnOrderItem"
                            sx={{
                                flexGrow: 1,
                                transition: (theme) =>
                                    theme.transitions.create(['all'], {
                                        duration: theme.transitions.duration.enteringScreen,
                                    }),
                                marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                            }}
                            title={"menu.asnOrderItem"}
                            empty={false}
                            filter={{ asnId: record?.id }}
                            sort={{ field: "create_time", order: "desc" }}
                            actions={(
                                <></>
                            )}
                            perPage={DEFAULT_ITEM_PAGE_SIZE}
                        >
                            <DynamicFields />
                        </List>
                    </Box>
                </DialogContent>
                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                    <Toolbar sx={{ width: '100%', justifyContent: 'end' }}  >
                        <Button disabled={disabled} variant="contained" startIcon={<PrintOutlinedIcon />} label={'toolbar.print'}>
                        </Button>
                    </Toolbar>
                </DialogActions>
            </Dialog>
        </>
        <Dialog
            className="orderPrintPerview"
            // ref={invoiceRef}
            open={open}
            onClose={handleClose}
            aria-labelledby="form-dialog-title"
            aria-hidden
            fullWidth
            disableRestoreFocus
            maxWidth="xl"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
        >
            <DialogTitle id="form-dialog-title" sx={{
                position: 'sticky',
                top: 0,
                textAlign: 'center',
                backgroundColor: 'background.paper',
                zIndex: 1000
            }}>
                {translate('menu.asnOrder')}
                <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                    <DialogCloseButton onClose={handleClose} />
                </Box>
            </DialogTitle>
            <DialogContent sx={{ mt: 2 }}>
                <OrderPreview ref={invoiceRef} record={record} />
            </DialogContent>
            <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                <Toolbar sx={{ width: '100%', justifyContent: 'end' }}  >
                    <Button disabled={disabled} variant="contained" startIcon={<PrintOutlinedIcon />} label={'toolbar.print'} onClick={printOrders}></Button>
                </Toolbar>
            </DialogActions>
        </Dialog>
    )
}
export default OrderPrintPreview;
const OrderPreview = React.forwardRef(({ record }, ref) => (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }} ref={ref}>
        <Form defaultValues={record}>
            <Grid container spacing={2} sx={{ justifyContent: 'space-between', }}>
                <Grid item md={2}>
                    <Box sx={{ display: 'flex', justifyContent: 'start' }}>
                        <Typography>ASN单:</Typography>
                        <Typography>{record?.code}</Typography>
                    </Box>
                    <Box sx={{ display: 'flex', justifyContent: 'start' }}>
                        <Typography>PO单:</Typography>
                        <Typography>{record?.poCode}</Typography>
                    </Box>
                    <Box sx={{ display: 'flex', justifyContent: 'start' }}>
                        <Typography>单据类型:</Typography>
                        <Typography>{record?.type$}</Typography>
                    </Box>
                    <Box sx={{ display: 'flex', justifyContent: 'center', padding: 1 }}></Box>
                    <Box sx={{ display: 'flex', justifyContent: 'start' }}>
                        <Typography>业务类型:</Typography>
                        <Typography>{record?.wkType$}</Typography>
                    </Box>
                    <Box sx={{ display: 'flex', justifyContent: 'center', padding: 1 }}></Box>
                </Grid>
                <Grid item md={2}>
                    <QRCodeSVG value={record?.code} />
                    <Typography>{record.code}</Typography>
                </Grid>
            </Grid>
        </Form>
        <List
            resource="asnOrderItem"
            title={"menu.asnOrderItem"}
            empty={false}
            filter={{ asnId: record?.id }}
            sort={{ field: "create_time", order: "desc" }}
            actions={(
                <></>
            )}
            perPage={DEFAULT_ITEM_PAGE_SIZE}
        >
            <DynamicFields />
        </List>
    </Box>
));
const DynamicFields = (props) => {
    const translate = useTranslate();
@@ -167,7 +199,6 @@
        const { data: { code, data, msg }, } = await request.get("/fields/enable/list");
        if (code == 200) {
            const arr = [
                <NumberField source="id" />,
                <NumberField source="asnId" label="table.field.asnOrderItem.asnId" />,
                <TextField source="asnCode" label="table.field.asnOrderItem.asnCode" />,
                <TextField source="poDetlId" label="table.field.asnOrderItem.poDetlId" />,
@@ -179,9 +210,10 @@
                <TextField source="splrBatch" label="table.field.asnOrderItem.splrBatch" />,
                <NumberField source="anfme" label="table.field.asnOrderItem.anfme" />,
                <NumberField source="qty" label="table.field.asnOrderItem.qty" />,
                <TextField source="splrName" label="table.field.asnOrderItem.splrName" />,
                <NumberField source="purQty" label="table.field.asnOrderItem.purQty" />,
                // <TextField source="splrName" label="table.field.asnOrderItem.splrName" />,
                <TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />,
                <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />,
                // <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />,
                <TextField source="packName" label="table.field.asnOrderItem.packName" />,
            ]
            const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />)
@@ -214,7 +246,7 @@
                    preferenceKey='asnOrderItem'
                    bulkActionButtons={false}
                    rowClick={(id, resource, record) => false}
                    omit={['id', 'asnId', 'poDetlId', 'poDetlCode', 'matnrId', 'purQty', 'purUnit', 'qrcode', 'trackCode']}
                    omit={['id', 'asnId', 'poDetlId', 'platItemId', 'poDetlCode', 'matnrId', 'purQty', 'splrName', 'purUnit', 'qrcode', 'packName', 'trackCode']}
                >
                    {columns.map((column) => column)}
                </StyledDatagrid>}
rsf-admin/src/page/orders/qlyInspect/AsnSelModal.jsx
@@ -8,7 +8,6 @@
    Grid,
    TextField,
    Box,
    Button,
    Paper,
    styled,
    RadioGroup,
@@ -16,13 +15,10 @@
    FormControlLabel,
} from '@mui/material';
import DialogCloseButton from "../../components/DialogCloseButton";
import ConfirmButton from "../../components/ConfirmButton";
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import { useTranslate, useNotify, useRefresh , Button} from 'react-admin';
import request from '@/utils/request';
import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
import SaveIcon from '@mui/icons-material/Save';
import TreeSelectInput from "@/page/components/TreeSelectInput";
import { throttle } from 'lodash';
const AsnSelModal = (props) => {
    const { open, setOpen } = props;
@@ -103,7 +99,7 @@
                backgroundColor: 'background.paper',
                zIndex: 1000
            }}>
                选择asn单
                {/* 选择asn单 */}
                <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                    <DialogCloseButton onClose={handleClose} />
                </Box>
@@ -113,19 +109,15 @@
                    <Grid container spacing={2}>
                        <Grid item md={4}>
                            <TextField
                                label={translate('table.field.asnOrder.code')}
                                label={translate('table.field.warehouseAreasItem.asnCode')}
                                name="asnCode"
                                value={formData.asnCode}
                                onChange={handleChange}
                                size="small"
                            />
                        </Grid>
                        <Grid item md={7} sx={{margin: 'auto'}}> <Button variant="contained" onClick={handleSearch} label={'toolbar.query'}></Button></Grid>
                    </Grid>
                </Box>
                <Box sx={{ mt: 2 }}>
                    <Stack direction="row" spacing={2}>
                        <Button variant="contained" onClick={handleSearch}>搜索</Button>
                    </Stack>
                </Box>
                <Box sx={{ mt: 2, height: 400, width: '100%' }}>
                    <AsnSelModalTable
@@ -137,9 +129,8 @@
                </Box>
            </DialogContent>
            <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
                    <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
                        {translate('toolbar.confirm')}
                <Box sx={{ width: '100%', display: 'flex', justifyContent: 'end' }}>
                    <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />} label={'toolbar.confirm'}>
                    </Button>
                </Box>
            </DialogActions>
@@ -159,15 +150,14 @@
    };
    const [columns, setColumns] = useState([
        // { field: 'id', headerName: 'ID', width: 100 },
        { field: 'code', headerName: translate('table.field.asnOrder.code'), width: 200 },
        { field: 'type$', headerName: translate('table.field.asnOrder.type') },
        { field: 'wkType$', headerName: translate('table.field.asnOrder.wkType') },
        { field: 'anfme', headerName: translate('table.field.asnOrder.anfme') },
        { field: 'qty', headerName: translate('table.field.asnOrder.qty') },
        { field: 'logisNo', headerName: translate('table.field.asnOrder.logisNo') },
        { field: 'asnCode', headerName: translate('table.field.warehouseAreasItem.asnCode'), width: 180 },
        // { field: 'areaId', headerName: translate('table.field.warehouseAreasItem.type') },
        { field: 'areaName', headerName: translate('table.field.warehouseAreasItem.areaName'), width: 200 },
        { field: 'anfme', headerName: translate('table.field.warehouseAreasItem.anfme') },
        { field: 'qty', headerName: translate('table.field.warehouseAreasItem.qty') },
        { field: 'unit', headerName: translate('table.field.warehouseAreasItem.unit') },
    ])
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/params/ManualShelvingParams.java
New file
@@ -0,0 +1,26 @@
package com.vincent.rsf.server.api.controller.params;
import com.vincent.rsf.server.manager.entity.WaitPakin;
import com.vincent.rsf.server.manager.entity.WaitPakinItem;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
@ApiModel(value = "ManualShelvingParams", description = "人工上架")
public class ManualShelvingParams implements Serializable {
    @ApiModelProperty("库位编码")
    private String locCode;
    @ApiModelProperty("托盘码")
    private String barcode;
    @ApiModelProperty("单据明细")
    private List<WaitPakinItem> itemList;
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/params/PublicToStockParams.java
@@ -1,6 +1,8 @@
package com.vincent.rsf.server.api.controller.params;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.WaitPakin;
import com.vincent.rsf.server.manager.entity.WaitPakinItem;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/MobileController.java
@@ -1,11 +1,16 @@
package com.vincent.rsf.server.api.controller.pda;
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.controller.params.*;
import com.vincent.rsf.server.api.service.MobileService;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
import com.vincent.rsf.server.manager.entity.WaitPakin;
import com.vincent.rsf.server.manager.service.TaskService;
import com.vincent.rsf.server.manager.service.WaitPakinService;
import com.vincent.rsf.server.system.controller.BaseController;
import com.vincent.rsf.server.system.controller.param.LoginParam;
import io.swagger.annotations.Api;
@@ -34,6 +39,10 @@
    @Autowired
    private MobileService mobileService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private WaitPakinService waitPakinService;
    /**
     * PDA用户登录
     * @param param
@@ -232,11 +241,15 @@
    @ApiOperation("人工上架")
    @PreAuthorize("hasAuthority('manager:qlyInspect:update')")
    @PostMapping("/stock/operate")
    public R publicToStock(@RequestBody PublicToStockParams params) {
        if (Objects.isNull(params)) {
    public R publicToStock(@RequestBody ManualShelvingParams params) {
        if (Cools.isEmpty(params.getItemList()) || Cools.isEmpty(params.getLocCode()) || Cools.isEmpty(params.getBarcode())) {
            return R.error("参数不能为空!!");
        }
        return mobileService.publicToStock(params, getLoginUserId());
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>().eq(WaitPakin::getBarcode, params.getBarcode()));
        return taskService.generateFlatWarehouseTasks(waitPakin, params.getLocCode(), getLoginUserId());
//        return mobileService.publicToStock(params, getLoginUserId());
    }
    @ApiOperation("获取任务信息")
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -656,35 +656,22 @@
    @Override
    public R operateToStock(OpStockParams params) {
        if (org.apache.commons.lang3.StringUtils.isBlank(params.getBarcode())) {
            throw new CoolException("拖盘码不能为空!!");
            throw new CoolException("托盘码不能为空!!");
        }
        if (StringUtils.isBlank(params.getAsnCode())) {
            throw new CoolException("单据不能为空!!");
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, params.getBarcode())
                .eq(WaitPakin::getIoStatus,PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
        );
        if (Cools.isEmpty(waitPakin)){
            throw new CoolException("未找到组托数据,请检查状态");
        }
        if (StringUtils.isBlank(params.getMatnrCode())) {
            throw new CoolException("物料编码不能为空!!");
        List<WaitPakinItem> waitPakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
        if (Cools.isEmpty(waitPakinItems)){
            throw new CoolException("数据错误,未找到组托明细");
        }
        AsnOrder asnOrders = asnOrderMapper.getOne(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getCode, params.getAsnCode()));
        if (Objects.isNull(asnOrders)) {
            throw new CoolException("单据不存在!!");
        }
        List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, params.getBarcode()));
        if (!locs.isEmpty()) {
            throw new CoolException("拖盘已使用");
        }
        List<WaitPakin> waitPakins = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>().eq(WaitPakin::getBarcode, params.getBarcode()));
        if (!waitPakins.isEmpty()) {
            throw new CoolException("拖盘已使用!!");
        }
        AsnOrderItem orderItems = asnOrderItemMapper.selectOne(new LambdaQueryWrapper<AsnOrderItem>()
                .eq(AsnOrderItem::getAsnId, asnOrders.getId())
                .eq(AsnOrderItem::getMatnrCode, params.getMatnrCode()));
        if (Objects.isNull(orderItems)) {
            return R.ok(null);
        }
        orderItems.setBarcode(params.getBarcode());
        return R.ok(orderItems);
        return R.ok(waitPakinItems);
    }
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/QlyInspectController.java
@@ -65,7 +65,7 @@
    @PostMapping("/qlyInspect/asn/list")
    @ApiOperation("获取待质检单")
    @PreAuthorize("hasAuthority('manager:qlyInspect:list')")
    public R getUnInspect(@RequestBody Map<String, Object> map) {
    public R getUnInspect(@RequestBody Map<String, String> map) {
        if (Objects.isNull(map)) {
            return R.error("参数不能为空!!");
        }
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/TaskType.java
@@ -10,6 +10,8 @@
public enum TaskType {
    TASK_TYPE_IN("1", "入库"),
    TASK_TYPE_FLAT_WAREHOUSE_IN("2", "平库上架"),
    TASK_TYPE_AGV_IN("3", "AGV入库"),
    TASK_TYPE_EMPITY_IN("10", "空板入库"),
    TASK_TYPE_LOC_MOVE("11", "库格移载"),
    TASK_TYPE_PICK_IN("53", "拣料再入库"),
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/QlyInspectService.java
@@ -7,6 +7,7 @@
import com.vincent.rsf.server.manager.entity.AsnOrder;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.QlyInspect;
import com.vincent.rsf.server.manager.entity.WarehouseAreasItem;
import java.util.List;
import java.util.Map;
@@ -17,7 +18,7 @@
    R allSave(QlyInspectAndItem params);
    List<AsnOrder> getUnInspect(Map<String, Object> map);
    List<WarehouseAreasItem> getUnInspect(Map<String, String> map);
    R saveSelected(IsptOrderParam param, Long loginUserId);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -4,6 +4,7 @@
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.manager.controller.params.GenerateTaskParams;
import com.vincent.rsf.server.manager.entity.Task;
import com.vincent.rsf.server.manager.entity.WaitPakin;
import java.util.List;
@@ -11,6 +12,8 @@
    R generateTasks(GenerateTaskParams waitPakin, Long loginUserId);
    R generateFlatWarehouseTasks(WaitPakin waitPakins,String locCode, Long loginUserId);
//    R completeTask(String id);
    void completeTask(List<Task> task) throws Exception;
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
@@ -121,7 +121,7 @@
        }
        params.setOrders(orders);
        svaeOrUpdateOrderItem(params,loginUserId);
        svaeOrUpdateOrderItem(params, loginUserId);
        return R.ok("保存成功!!");
    }
@@ -150,20 +150,20 @@
            return R.ok("明细参数不能为空!!");
        }
        svaeOrUpdateOrderItem(params,loginUserId);
        svaeOrUpdateOrderItem(params, loginUserId);
        return R.ok("修改完成!!");
    }
    /**
     * @author Ryan
     * @description 更新或保存明细
     * @param
     * @return
     * @author Ryan
     * @description 更新或保存明细
     * @time 2025/4/7 13:28
     */
    @Transactional(rollbackFor = Exception.class)
    public void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception{
    public void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception {
        AsnOrder orders = params.getOrders();
        params.getItems().forEach(item -> {
            item.put("asnId", orders.getId());
@@ -185,10 +185,10 @@
    }
    /**
     * @author Ryan
     * @description 批量修改
     * @param
     * @return
     * @author Ryan
     * @description 批量修改
     * @time 2025/4/1 07:58
     */
    @Override
@@ -199,11 +199,11 @@
        }
        return this.update(new LambdaUpdateWrapper<AsnOrder>()
                .in(AsnOrder::getId, params.getIds())
                       .set(!Objects.isNull(order.getRleStatus()), AsnOrder::getRleStatus, order.getRleStatus())
                        .set(!Objects.isNull(order.getNtyStatus()), AsnOrder::getNtyStatus, order.getNtyStatus())
                        .set(!Objects.isNull(order.getStatus()),  AsnOrder::getStatus, order.getStatus())
                        .set(!Objects.isNull(order.getWkType()), AsnOrder::getWkType, order.getWkType())
                        .set(!Objects.isNull(order.getExceStatus()), AsnOrder::getExceStatus, order.getExceStatus())
                .set(!Objects.isNull(order.getRleStatus()), AsnOrder::getRleStatus, order.getRleStatus())
                .set(!Objects.isNull(order.getNtyStatus()), AsnOrder::getNtyStatus, order.getNtyStatus())
                .set(!Objects.isNull(order.getStatus()), AsnOrder::getStatus, order.getStatus())
                .set(!Objects.isNull(order.getWkType()), AsnOrder::getWkType, order.getWkType())
                .set(!Objects.isNull(order.getExceStatus()), AsnOrder::getExceStatus, order.getExceStatus())
                .set(AsnOrder::getUpdateBy, userId));
    }
@@ -217,7 +217,7 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public  R completeOrder(Long id, Long loginUserId) {
    public R completeOrder(Long id, Long loginUserId) {
        AsnOrder asnOrder = this.getById(id);
        if (Objects.isNull(asnOrder)) {
            throw new CoolException("单据不存在!!");
@@ -247,14 +247,14 @@
    }
    /**
     * @author Ryan
     * @description 删除原主单及明细,加入历史档
     * @param
     * @return
     * @author Ryan
     * @description 删除原主单及明细,加入历史档
     * @time 2025/3/19 19:53
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized void operateOrderLogs(AsnOrder asrder) throws Exception{
    public synchronized void operateOrderLogs(AsnOrder asrder) throws Exception {
        if (Objects.isNull(asrder) || Objects.isNull(asrder.getId())) {
            throw new CoolException("参数不能为空!!");
        }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/QlyInspectServiceImpl.java
@@ -1,22 +1,17 @@
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.vincent.rsf.framework.exception.CoolException;
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.AsnOrder;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.QlyIsptItem;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.QlyIsptStatus;
import com.vincent.rsf.server.manager.mapper.QlyInspectMapper;
import com.vincent.rsf.server.manager.entity.QlyInspect;
import com.vincent.rsf.server.manager.service.AsnOrderItemService;
import com.vincent.rsf.server.manager.service.AsnOrderService;
import com.vincent.rsf.server.manager.service.QlyInspectService;
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.service.QlyIsptItemService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
@@ -42,6 +37,9 @@
    @Autowired
    private QlyIsptItemService qlyIsptItemService;
    @Autowired
    private WarehouseAreasItemService warehouseAreasItemService;
    @Override
    public List<AsnOrderItem> listByAsn(Map<String, Object> map) {
@@ -103,11 +101,15 @@
    * @time 2025/3/31 10:12
    */
    @Override
    public List<AsnOrder> getUnInspect(Map<String, Object> params) {
        List<AsnOrder> asnOrders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>()
                .eq(AsnOrder::getStatus, 1)
                .eq(!Objects.isNull(params.get("asnCode")) && StringUtils.isNotBlank(params.get("asnCode").toString()), AsnOrder::getCode, StringUtils.isNotBlank(params.get("asnCode").toString()) ? params.get("asnCode").toString() : null));
        return asnOrders;
    public List<WarehouseAreasItem> getUnInspect(Map<String, String> params) {
        String code = params.get("asnCode");
        List<WarehouseAreasItem> warehouseAreasItems = warehouseAreasItemService
                .list(new QueryWrapper<WarehouseAreasItem>()
                        .select("asn_id as id, SUM(anfme) anfme, SUM(qty) qty, area_id, area_name, asn_code, asn_id")
                        .eq(StringUtils.isNotBlank(code), "asn_code", code)
                        .lambda()
                .groupBy(WarehouseAreasItem::getAsnCode));
        return warehouseAreasItems;
    }
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -65,6 +65,90 @@
    private WarehouseAreasItemService warehouseAreasItemService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized R generateFlatWarehouseTasks(WaitPakin pakins,String locCode, Long loginUserId) {
        if (Cools.isEmpty(pakins) || Cools.isEmpty(locCode)) {
            throw new CoolException("参数不能为空!!");
        }
        /**获取组拖*/
//        List<Long> ids = pakins.stream().map(WaitPakin::getId).collect(Collectors.toList());
        List<WaitPakin> waitPakins = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>()
                .in(WaitPakin::getId, pakins.getId())
                .eq(WaitPakin::getIoStatus, Short.parseShort(PakinIOStatus.PAKIN_IO_STATUS_DONE.val)));
        if (waitPakins.isEmpty()) {
            throw new CoolException("请检查组托状态是否完成!!");
        }
        waitPakins.forEach(pakin -> {
            /**获取库位*/
            String targetLoc = locCode;
            if (Cools.isEmpty(targetLoc)) {
                throw new CoolException("该站点对应库区未找到库位");
            }
            List<TaskItem> taskItems = new ArrayList<>();
            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null);
            if (StringUtils.isBlank(ruleCode)) {
                throw new CoolException("编码错误:请确认编码「SYS_TASK_CODE」是否已生成!!");
            }
            Task task = new Task();
            task.setTaskCode(ruleCode)
                    .setTaskStatus(TaskStsType.COMPLETE_IN.id.shortValue())
                    .setTaskType(TaskType.TASK_TYPE_FLAT_WAREHOUSE_IN.type.shortValue())
                    .setTargLoc(targetLoc)
                    .setBarcode(pakin.getBarcode())
                    .setCreateBy(loginUserId)
                    .setUpdateBy(loginUserId);
            if (!this.save(task)) {
                throw new CoolException("任务保存失败!!");
            }
            if (!locService.update(new LambdaUpdateWrapper<Loc>().eq(Loc::getCode, task.getTargLoc())
                    .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_S.type).set(Loc::getBarcode, pakin.getBarcode()))) {
                throw new CoolException("库位预约失败!!");
            }
            /**获取组拖明细**/
            List<WaitPakinItem> waitPakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, pakin.getId()));
            if (waitPakinItems.isEmpty()) {
                throw new CoolException("数据错误:组拖明细不存在");
            }
            waitPakinItems.forEach(item -> {
                TaskItem taskItem = new TaskItem();
                BeanUtils.copyProperties(item, taskItem);
                taskItem.setTaskId(task.getId())
                        .setOrderType(OrderType.ORDER_RECEIPT.type)
                        .setSource(item.getId())
                        .setTrackCode(item.getTrackCode())
                        .setCreateBy(loginUserId)
                        .setUpdateBy(loginUserId)
                        .setExtendFields(item.getExtendFields())
                        .setOrderId(item.getAsnId())
                        .setOrderItemId(item.getAsnItemId());
                taskItems.add(taskItem);
            });
            if (!taskItemService.saveBatch(taskItems)) {
                throw new CoolException("任务明细保存失败!!");
            }
            waitPakinItems.forEach(item -> {
                if (! waitPakinItemService.update(new LambdaUpdateWrapper<WaitPakinItem>()
                        .set(WaitPakinItem::getWorkQty, item.getAnfme())
                        .eq(WaitPakinItem::getId, item.getId()))) {
                    throw new CoolException("组托明细修执行数量修改失败!!");
                }
            });
        });
        if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>()
                .in(WaitPakin::getId, pakins.getId())
                .set(WaitPakin::getUpdateBy, loginUserId)
                .set(WaitPakin::getCreateBy, loginUserId)
                .set(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val))) {
            throw new CoolException("组拖状态修改失败!!");
        }
        return R.ok("任务生成完毕!");
    }
    /**
     * @param
     * @param loginUserId