28个文件已修改
276 ■■■■ 已修改文件
rsf-admin/src/config/setting.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/loc/BindModal.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/whMat/WhMatListAside.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/whMat/whMatCreate.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/BatchButton.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/delivery/DeliveryList.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutOrderList.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutOrderModal.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx 122 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/purchase/PurchaseCreate.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/wave/WaveItemList.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/TaskList.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/waitPakin/SelectSiteModel.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/outBound/OutBoundList.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockItemController.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/DeliveryTemplate.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/OutStockTemplate.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockItemServiceImpl.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/AsnOrderItemMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/config/setting.js
@@ -39,4 +39,6 @@
export const LOGIN_BACKGROUND = 'media';  // image | media
export const CUSTOM_PAGES_DATA_INTERVAL = 1000;
export const CUSTOM_PAGES_DATA_INTERVAL = 1000;
export const DEFAULT_TYPE = 15; //默认效率优化  15:效率优化 16:先进先出
rsf-admin/src/i18n/en.js
@@ -44,6 +44,7 @@
                main: 'Main',
                common: 'Common',
                changePwd: 'Change Password',
                insuffInventory: 'Insufficient inventory'
            },
            side: {
                title: 'More Info'
@@ -1168,7 +1169,7 @@
        recover: "recover",
        createWave: "Create Wave",
        order: 'Orders',
        modiftySite: 'Modify SiteNo',
    },
    request: {
        error: {
rsf-admin/src/i18n/zh.js
@@ -45,6 +45,7 @@
                main: '主要',
                common: '通用',
                changePwd: '重置密码',
                insuffInventory: '库存不足'
            },
            side: {
                title: '更多'
@@ -1171,6 +1172,7 @@
        publicWorking: '下发执行',
        createWave: "生成波次",
        recover: "继续收货",
        modiftySite: '修改库口',
    },
    request: {
        error: {
rsf-admin/src/page/basicInfo/loc/BindModal.jsx
@@ -246,7 +246,6 @@
const SelectMatnrs = () => {
    const { selectedIds, data, isPending, onUnselectItems } = useListContext();
    const clickMatnrs = () => {
        console.log(selectedIds);
        onUnselectItems()
    }
rsf-admin/src/page/basicInfo/whMat/WhMatListAside.jsx
@@ -58,7 +58,6 @@
  ]);
  const handleInput = (value) => {
    console.log(value);
    setSearchVal(value);
  };
rsf-admin/src/page/basicInfo/whMat/whMatCreate.jsx
@@ -377,8 +377,6 @@
  };
  useEffect(() => {
    console.log(selAll);
    const setAllChecked = (nodes, checked) => {
      nodes.forEach((node) => {
        node.checked = !checked;
rsf-admin/src/page/components/BatchButton.jsx
@@ -6,7 +6,6 @@
const ImportButton = (props) => {
    const [modalOpen, setModalOpen] = useState(false);
    const { selectedIds } = useListContext();
    console.log(selectedIds)
    const handleOpenModal = () => {
        setModalOpen(true);
    };
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
@@ -106,7 +106,6 @@
            ...prevData,
            [name]: value
        }));
        console.log(formData);
    };
    const resetData = () => {
@@ -344,7 +343,6 @@
        } = await request.post("companys/page", parmas);
        if (code === 200) {
            setFormData(data.records)
            console.log(data.records)
        } else {
            notify(msg);
        }
@@ -447,7 +445,6 @@
        } = await request.post("companys/page", parmas);
        if (code === 200) {
            setFormData(data.records)
            console.log(data.records)
        } else {
            notify(msg);
        }
@@ -676,9 +673,7 @@
    };
    const handleSelectionChange = (ids) => {
        console.log(ids);
    const handleSelectionChange = (ids) => {
        setSelectedRows(ids)
    };
rsf-admin/src/page/orders/delivery/DeliveryList.jsx
@@ -122,7 +122,7 @@
                    rowClick={(id, resource, record) => false}
                    expand={false}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'platId', 'platCode', 'memo', 'startTime', 'endTime', 'updateBy', 'createTime']}
                    omit={['id', 'createTime', 'createBy', 'platId', 'platCode', 'memo', 'startTime','qty', 'endTime', 'updateBy', 'createTime']}
                >
                    <NumberField source="id" />
                    <TextField source="code" label="table.field.delivery.code" />
@@ -131,7 +131,7 @@
                    <TextField source="wkType$" label="table.field.delivery.wkType" />
                    <TextField source="source" label="table.field.delivery.source" />
                    <NumberField source="anfme" label="table.field.delivery.anfme" />
                    <NumberField source="workQty" label="table.field.delivery.workQty" />
                    <NumberField source="workQty" label="table.field.delivery.qty" />
                    <NumberField source="qty" label="table.field.delivery.qty" />
                    <TextField source="platCode" label="table.field.delivery.platCode" />
                    <DateField source="startTime" label="table.field.delivery.startTime" showTime />
rsf-admin/src/page/orders/outStock/OutOrderList.jsx
@@ -5,6 +5,7 @@
  DatagridConfigurable,
  SearchInput,
  TopToolbar,
  Toolbar,
  SelectColumnsButton,
  EditButton,
  FilterButton,
@@ -140,7 +141,7 @@
            <CreateByOrderButton setCreateDialog={setCreateDialog} />
            <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} />
            <SelectColumnsButton preferenceKey='outStock' />
            <ImportButton value={'outStock'} />
            <ImportButton value={'outStockItem'} />
            {/* <MyExportButton /> */}
          </TopToolbar>
        )}
@@ -298,6 +299,6 @@
  }
  return (
    record.exceStatus == 10 ? <ConfirmButton label={"toolbar.publicWorking"} startIcon={<AddTaskIcon />} onConfirm={taskEvent} size={"small"} /> : <></>
    record.workQty < record.anfme ? <ConfirmButton label={"toolbar.publicWorking"} startIcon={<AddTaskIcon />} onConfirm={taskEvent} size={"small"} /> : <></>
  )
}
rsf-admin/src/page/orders/outStock/OutOrderModal.jsx
@@ -5,6 +5,7 @@
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    Toolbar,
    Button,
    SelectColumnsButton,
    EditButton,
@@ -94,7 +95,6 @@
    const [params, setParams] = useState({});
    const [drawerVal, setDrawerVal] = useState(false);
    const refresh = useRefresh();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
@@ -1,4 +1,4 @@
import { Box, Card, Grid, LinearProgress, Select, MenuItem, ListItemText, Tooltip, IconButton } from "@mui/material";
import { Box, Card, Grid, LinearProgress, Select, MenuItem, ListItemText } from "@mui/material";
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    List,
@@ -38,7 +38,7 @@
    useRefresh,
    useRedirect,
} from 'react-admin';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE, DEFAULT_TYPE } from '@/config/setting';
import { styled } from '@mui/material/styles';
import { DataGrid, useGridApiContext, GridActionsCellItem, useGridApiRef } from '@mui/x-data-grid';
import request from '@/utils/request';
@@ -46,6 +46,8 @@
import CloseSharpIcon from '@mui/icons-material/CloseSharp';
import ConfirmButton from '../../components/ConfirmButton';
import { Delete, Edit, Add } from '@mui/icons-material';
import OutStockSiteDialog from "./OutStockSiteDialog";
import { color } from "framer-motion";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -59,27 +61,47 @@
    }
}));
const OutStockPublic = (props) => {
    const { record, open, setOpen } = props;
    const notify = useNotify();
    const gridRef = useGridApiRef();
    const [rows, setRows] = useState({});
    const translate = useTranslate();
    const [selectedIds, setSelectedIds] = React.useState([]);
    const [selectedIds, setSelectedIds] = useState([]);
    const [formData, setFormData] = useState({
        orderId: record?.id
        orderId: record?.id,
        waveId: DEFAULT_TYPE
    });
    const [dialog, setDialog] = useState(false);
    const [selectedValue, setSelectedValue] = useState({});
    const handleClickOpen = () => {
        setDialog(true);
    };
    const handleClose = (value) => {
        setDialog(false);
        setSelectedValue(value);
        const newRows = rows.map(item => {
            return {
                ...item,
                siteNo: value?.site
            }
        })
        setRows(newRows);
    };
    useEffect(() => {
        getWaveRule()
    }, [formData, open])
        if (open) {
            getWaveRule()
        }
    }, [open, formData])
    const getWaveRule = async () => {
        if (formData.waveId == null && formData.waveId == undefined) {
            return
        }
        const { data: { code, data, msg } } = await request.post('/outStock/order/getOutTaskItems', { ...formData });
        if (code === 200) {
            setRows(data)
        } else {
@@ -109,6 +131,7 @@
                                    <AutocompleteInput
                                        label="table.field.waveRule.type"
                                        onChange={(e) => handleChange(e, 'waveId')}
                                        defaultValue={15}
                                        value={formData.type}
                                        validate={required()}
                                    />
@@ -157,30 +180,53 @@
                    <Grid item xl={6.3} gap={2}>
                        <Card>
                            <Box sx={{ height: 500, width: '100%' }}>
                                <PreviewTable rows={rows} gridRef={gridRef} setRows={setRows} record={record}/>
                                <PreviewTable
                                    rows={rows}
                                    gridRef={gridRef}
                                    setRows={setRows}
                                    record={record}
                                    selectedIds={selectedIds}
                                    setDialog={setDialog}
                                    setSelectedIds={setSelectedIds}
                                />
                            </Box>
                            <Box sx={{ textAlign: 'center' }}>
                                <CloseButton setOpen={setOpen} />
                                <SubmitButton selectedIds={selectedIds} setSelectedIds={setSelectedIds} gridRef={gridRef} record={record}/>
                                <SubmitButton selectedIds={selectedIds} setSelectedIds={setSelectedIds} gridRef={gridRef} record={record} />
                            </Box>
                        </Card>
                    </Grid>
                </Grid>
                <Grid>
                    <OutStockSiteDialog
                        selectedValue={selectedValue}
                        open={dialog}
                        onClose={handleClose}
                    />
                </Grid>
            </Box>
        </>
    );
}
const PreviewTable = ({ rows, gridRef, setRows, record }) => {
const PreviewTable = ({ rows, gridRef, setRows, record, selectedIds, setSelectedIds, setDialog }) => {
    gridRef.current = useGridApiRef();
    const translate = useTranslate();
    const columns = [
        { field: 'id', headerName: 'ID', width: 40 },
        // { field: 'id', headerName: 'ID', width: 40 },
        { field: 'locCode', headerName: '库位', width: 110 },
        { field: 'barcode', headerName: '容器', width: 120 },
        { field: 'matnrCode', headerName: '物料编码', width: 120 },
        { field: 'batch', headerName: '批次', width: 90 },
        { field: 'unit', headerName: '单位', width: 90 },
        { field: 'outQty', headerName: '本次出库数量', width: 110 },
        { field: 'unit', headerName: '单位', width: 60 },
        { field: 'outQty', headerName: '出库数量', width: 110, },
        {
            field: 'anfme', headerName: '库存数量', width: 110,
            renderCell: (params) => (
                <OutStockAnfme value={params.value} />
            )
        },
        {
            field: 'siteNo',
            headerName: '出库口',
@@ -214,11 +260,28 @@
     * @param {*} params 
     */
    const handleDelete = (params, rows, setRows) => {
        const outRows = rows.filter(row => {
             return row.id !== params.id
        const outRows = rows.filter(row => {
            return row.id !== params.id
        })
        setRows(outRows)
    }
    const OutStockAnfme = React.memo(function OutStockAnfme(props) {
        const { value } = props;
        return (
            value > 0 ?
                <Box
                    sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
                >
                    <span>{value}</span>
                </Box> :
                <Box
                    sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
                >
                    <span style={{color: 'red'}}>{translate('common.edit.title.insuffInventory')}</span>
                </Box>
        );
    });
    const OutStockSiteNo = React.memo(function OutStockSiteNo(props) {
        const { value } = props;
@@ -233,6 +296,28 @@
            </Box>
        );
    });
    const CustomToolBar = () => {
        const selectSiteNo = () => {
            setDialog(true)
        }
        return (
            selectedIds.length > 0 ? <Box sx={{
                p: 1,
                display: 'flex',
                justifyContent: 'flex-end',
                borderTop: '1px solid rgba(224, 224, 224, 1)'
            }}>
                <Button
                    onClick={selectSiteNo}
                    variant="outlined"
                    label="toolbar.modiftySite"
                    size="medium"
                    sx={{ mr: 1 }} />
            </Box> : <></>
        );
    }
    const OutStockSite = (params) => {
        const { id, field, siteNo, row: { staNos } } = params;
@@ -288,6 +373,7 @@
        <DataGrid
            rows={rows}
            columns={columns}
            slots={{ toolbar: CustomToolBar }}
            apiRef={gridRef}
            initialState={{
                pagination: {
@@ -297,6 +383,7 @@
                },
            }}
            checkboxSelection
            disableRowSelectionOnClick
            pageSizeOptions={[15, 25, 35, 45]}
            onRowSelectionModelChange={(ids) => {
                setSelectedIds(ids)
@@ -305,13 +392,14 @@
    )
}
//提交按钮
const SubmitButton = ({ selectedIds, setSelectedIds, gridRef, record }) => {
    const notify = useNotify();
    const refresh = useRefresh();
    const redirect = useRedirect();
    const submit = async () => {
        console.log(record);
        const items = gridRef.current?.getSortedRows();
        const { data: { code, data, msg } } = await request.post('/outStock/generate/tasks', { items, outId: record?.id });
        if (code == 200) {
rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
@@ -100,7 +100,6 @@
            ...prevData,
            [name]: value
        }));
        console.log(formData);
    };
    const resetData = () => {
@@ -319,7 +318,6 @@
        } = await request.post("companys/page", parmas);
        if (code === 200) {
            setFormData(data.records)
            console.log(data.records)
        } else {
            notify(msg);
        }
@@ -373,7 +371,6 @@
        } = await request.post("companys/page", parmas);
        if (code === 200) {
            setFormData(data.records)
            console.log(data.records)
        } else {
            notify(msg);
        }
rsf-admin/src/page/orders/purchase/PurchaseCreate.jsx
@@ -35,8 +35,6 @@
    const { open, setOpen } = props;
    const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_in_stock_type')) || [];
    const business = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type'))?.filter(data => (data.group == '1')) || [];
    console.log(business);
    const translate = useTranslate();
    const notify = useNotify();
rsf-admin/src/page/orders/wave/WaveItemList.jsx
@@ -177,7 +177,6 @@
const DetailButton = (setEditDialog) => {
    const record = useRecordContext();
    const editClick = (event) => {
        console.log('--========--->');
        event.stopPropagation()
        setEditDialog(true)
    }
rsf-admin/src/page/task/TaskList.jsx
@@ -272,7 +272,6 @@
    };
    //取消任务
    const cancleTask = async (row) => {
        console.log(row);
        const { data: { code, data, msg } } = await request.post(`/task/remove/` + row.id);
        if (code === 200) {
            notify(msg);
rsf-admin/src/page/waitPakin/SelectSiteModel.jsx
@@ -51,7 +51,6 @@
            setOpen(false);
        }
    };
    console.log(source);
    return (
        <Box>
            <Dialog
rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx
@@ -128,7 +128,6 @@
                                        label={translate("table.field.outBound.checkSta")}
                                        onChange={(e) => {
                                            setSta(e.target.value);
                                            console.log("站点已选择:", e.target.value);
                                        }}
                                        size="small"
                                        type="[107]"
rsf-admin/src/page/work/outBound/OutBoundList.jsx
@@ -127,7 +127,6 @@
                                        label={translate("table.field.outBound.outSta")}
                                        onChange={(e) => {
                                            setSta(e.target.value);
                                            console.log("站点已选择:", e.target.value);
                                        }}
                                        size="small"
                                        type="[101,103]"
@@ -181,7 +180,6 @@
        http(sta, data);
    }
    const http = async (sta, items) => {
        console.log(items);
        // const filZores = items.filter(item => item.outQty  <= 0.0);
        // const filter = items.filter(item => (item.outQty + item.workQty) > item.anfme);
        // if (filter.length > 0 || filZores.length > 0) {
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
@@ -125,7 +125,6 @@
                }
                
            })  
            console.log(newData);
            setTarLocList(newData);         
        }
@@ -216,7 +215,6 @@
    const refresh = useRefresh();
    const { orgLoc, tarLoc, tabelData } = props;
    const move = () => {
        console.log(orgLoc, tarLoc);
        if (orgLoc === "" || orgLoc === undefined || orgLoc === null) {
            notify("请输入源库位");
            return;
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java
@@ -10,6 +10,7 @@
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.manager.controller.params.OrderOutTaskParam;
import com.vincent.rsf.server.manager.controller.params.OutStockToTaskParams;
import com.vincent.rsf.server.manager.entity.excel.OutStockTemplate;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.enums.OrderWorkType;
import com.vincent.rsf.server.common.annotation.OperationLog;
@@ -240,6 +241,7 @@
    }
    @PostMapping("/outStock/order/getOutTaskItems")
    @ApiOperation("出库单库位预览")
    @PreAuthorize("hasAuthority('manager:outStock:list')")
    public R getOrderOutTaskItem(@RequestBody OrderOutTaskParam param) {
        if (Cools.isEmpty(param)) {
@@ -271,5 +273,31 @@
        return  outStockService.genOutStockTask(taskParams, getLoginUserId(), Long.parseLong(params.get("outId").toString()));
    }
    /**
     * 获取出库站点
     * @return
     */
    @GetMapping("/outStock/tasks/sites")
    @ApiOperation("获取出库库口")
    @PreAuthorize("hasAuthority('manager:outStock:list')")
    public R getSiteNos() {
        return outStockService.getSiteNos();
    }
    /**
     * @author Ryan
     * @description 下载模板
     * @param
     * @return
     * @time 2025/4/18 08:17
     */
    @PostMapping("/outStock/template/download")
    @ApiOperation("下载收货单模板")
    @PreAuthorize("hasAuthority('manager:outStockItem:update')")
    public void downloadTemplate(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        OutStockTemplate template = ExcelUtil.mockData(OutStockTemplate.class);
        List<OutStockTemplate> list = Arrays.asList(template);
        ExcelUtil.build(ExcelUtil.create(list, OutStockTemplate.class, true), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockItemController.java
@@ -159,7 +159,7 @@
    @PostMapping("/outStockItem/import")
    @ApiOperation("ASN导入接口")
    @PreAuthorize("hasAuthority('manager:outStockItem:update')")
    public R importExcel(@RequestParam(value = "file") MultipartFile file, @RequestParam String asnId) throws Exception {
    public R importExcel(@RequestParam(value = "file") MultipartFile file) throws Exception {
        if (Objects.isNull(file)) {
            R.error("文件不能为空!!");
        }
@@ -167,20 +167,6 @@
        return outStockItemService.excelImport(file, hashMap, getLoginUserId());
    }
    /**
     * @author Ryan
     * @description 下载模板
     * @param
     * @return
     * @time 2025/4/18 08:17
     */
    @PostMapping("/outStockItem/template/download")
    @ApiOperation("下载收货单模板")
    @PreAuthorize("hasAuthority('manager:outStockItem:update')")
    public void downloadTemplate(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        AsnOrderTemplate template = ExcelUtil.mockData(AsnOrderTemplate.class);
        List<AsnOrderTemplate> list = Arrays.asList(template);
        ExcelUtil.build(ExcelUtil.create(list, AsnOrderTemplate.class, true), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/DeliveryTemplate.java
@@ -29,7 +29,7 @@
    @Excel(name = "单据类型")
    @ApiModelProperty(value= "单据类型")
    @ExcelComment(value = "type", example = "入库单")
    @ExcelComment(value = "type", example = "出库单")
    private String type;
    @Excel(name = "单据来源")
@@ -54,7 +54,7 @@
    @Excel(name = "业务类型")
    @ApiModelProperty(value= "业务类型")
    @ExcelComment(value = "wkType", example = "采购入库单")
    @ExcelComment(value = "wkType", example = "销售出库单")
    private String wkType;
    @Excel(name = "项目名称")
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/excel/OutStockTemplate.java
@@ -68,7 +68,7 @@
     */
    @Excel(name = "*单据类型")
    @ApiModelProperty(value = "*单据类型")
    @ExcelComment(value = "type", example = "入库单")
    @ExcelComment(value = "type", example = "出库单")
    private String type;
    /**
@@ -76,7 +76,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/service/OutStockService.java
@@ -24,4 +24,6 @@
    R getOrderOutTaskItem(OrderOutTaskParam param);
    R genOutStockTask(List<OutStockToTaskParams> params, Long loginUserId, Long outId);
    R getSiteNos();
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockItemServiceImpl.java
@@ -11,6 +11,7 @@
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.excel.OutStockTemplate;
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.enums.OrderWorkType;
import com.vincent.rsf.server.common.domain.BaseParam;
@@ -101,9 +102,6 @@
    public R excelImport(MultipartFile file, HashMap<String, Object> hashMap, Long loginUserId) throws Exception {
        ExcelImportResult result = ExcelImportUtil.importExcelMore(file.getInputStream(), OutStockTemplate.class, ExcelUtil.getDefaultImportParams());
        if (result.getList().isEmpty()) {
            throw new CoolException("物料导入失败!!");
        }
        if (result.getList().isEmpty()) {
            throw new CoolException("表格内容不能为空!!");
        }
        List<OutStockTemplate> resultList = result.getList();
@@ -111,7 +109,7 @@
        for (String key : listMap.keySet()) {
            OutStockTemplate template = listMap.get(key).stream().findFirst().get();
            AsnOrder asnOrder = outStockService.getOne(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getCode, template.getCode()));
            if (Objects.isNull(asnOrder)) {
            if (!Objects.isNull(asnOrder)) {
                continue;
            }
            AsnOrder order = new AsnOrder();
@@ -129,7 +127,7 @@
            for (OutStockTemplate orderTemplate : listMap.get(key)) {
                AsnOrderItem orderItem = new AsnOrderItem();
                Matnr matnr = null;
                if (!Objects.isNull(orderTemplate.getMatnrCode()) || StringUtils.isNotBlank(orderTemplate.getMatnrCode())) {
                if (StringUtils.isNotBlank(orderTemplate.getMatnrCode())) {
                    matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>()
                            .eq(Matnr::getCode, orderTemplate.getMatnrCode()));
                }
@@ -151,9 +149,10 @@
                }
            }
            if (!items.isEmpty()) {
                double qty = items.stream().mapToDouble(AsnOrderItem::getQty).sum();
                double purQty = items.stream().mapToDouble(AsnOrderItem::getPurQty).sum();
                if (!outStockService.update(new LambdaUpdateWrapper<AsnOrder>().set(AsnOrder::getQty, qty).set(AsnOrder::getAnfme, purQty).eq(AsnOrder::getId, order.getId()))) {
                double purQty = items.stream().mapToDouble(AsnOrderItem::getAnfme).sum();
                if (!outStockService.update(new LambdaUpdateWrapper<AsnOrder>()
                                .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val)
                        .set(AsnOrder::getAnfme, purQty).eq(AsnOrder::getId, order.getId()))) {
                    throw new CoolException("单据数量修改失败!!");
                }
            }
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -510,6 +510,20 @@
        return R.ok();
    }
    /**
     * 获取出库站点
     * @return
     */
    @Override
    public R getSiteNos() {
        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_MERGE_OUT.type,
                TaskType.TASK_TYPE_OUT.type,
                TaskType.TASK_TYPE_MERGE_OUT.type,
                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);
        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list).groupBy(DeviceSite::getSite));
        return R.ok(sites);
    }
    private List<LocItem> getEfficiencyFirstItemList(AsnOrderItem asnOrderItem) {
        LambdaQueryWrapper<LocItem> locItemQueryWrapper = new LambdaQueryWrapper<>();
@@ -602,8 +616,23 @@
                        issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                    }
                }
                } else {
                }
            }
            if (issued.doubleValue() > 0) {
                LocItem locItem = new LocItem()
                        .setId(new Random().nextLong())
                        .setMatnrCode(asnOrderItem.getMatnrCode())
                        .setMaktx(asnOrderItem.getMaktx())
                        .setAnfme(0.00)
                        .setWorkQty(issued.doubleValue())
                        .setOutQty(issued.doubleValue())
                        .setUnit(asnOrderItem.getStockUnit())
                        .setBatch(asnOrderItem.getSplrBatch());
                OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
                orderOutItemDto.setLocItem(locItem);
                list.add(orderOutItemDto);
            }
        }
rsf-server/src/main/resources/mapper/manager/AsnOrderItemMapper.xml
@@ -13,6 +13,13 @@
                    aoi.asn_code,
                    aoi.plat_item_id,
                    aoi.po_detl_id,
                    aoi.plat_order_code,
                    aoi.project_code,
                    aoi.ispt_status,
                    aoi.ispt_result,
                    aoi.batch,
                    aoi.spec,
                    aoi.model,
                    aoi.plat_work_code,
                    aoi.po_code,
                    aoi.fields_index,