skyouc
5 天以前 c05d4037b04f5182088fcf07835409a6eda83362
下发执行功能优化
9个文件已修改
359 ■■■■■ 已修改文件
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx 272 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocToTaskParams.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/OutStockToTaskParams.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java 8 ●●●●● 补丁 | 查看 | 原始文档 | 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/LocItemServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
@@ -94,7 +94,6 @@
        }));
    };
    gridRef.current = useGridApiRef();
    return (
        <>
@@ -158,27 +157,11 @@
                    <Grid item xl={6.3} gap={2}>
                        <Card>
                            <Box sx={{ height: 500, width: '100%' }}>
                                <DataGrid
                                    rows={rows}
                                    columns={columns}
                                    apiRef={gridRef}
                                    initialState={{
                                        pagination: {
                                            paginationModel: {
                                                pageSize: 15,
                                            },
                                        },
                                    }}
                                    checkboxSelection
                                    pageSizeOptions={[15, 25, 35, 45]}
                                    onRowSelectionModelChange={(ids) => {
                                        setSelectedIds(ids)
                                    }}
                                />
                                <PreviewTable rows={rows} gridRef={gridRef} setRows={setRows} record={record}/>
                            </Box>
                            <Box sx={{ textAlign: 'center' }}>
                                <CloseButton setOpen={setOpen} />
                                <SubmitButton selectedIds={selectedIds} setSelectedIds={setSelectedIds} gridRef={gridRef} />
                                <SubmitButton selectedIds={selectedIds} setSelectedIds={setSelectedIds} gridRef={gridRef} record={record}/>
                            </Box>
                        </Card>
                    </Grid>
@@ -188,15 +171,149 @@
    );
}
const PreviewTable = ({ rows, gridRef, setRows, record }) => {
    gridRef.current = useGridApiRef();
    const columns = [
        { field: 'id', headerName: 'ID', width: 40 },
        { field: 'locCode', headerName: '库位', width: 110 },
        { field: 'barcode', headerName: '容器', width: 120 },
        { field: 'batch', headerName: '批次', width: 90 },
        { field: 'unit', headerName: '单位', width: 90 },
        { field: 'outQty', headerName: '本次出库数量', width: 110 },
        {
            field: 'siteNo',
            headerName: '出库口',
            width: 90,
            type: 'singleSelect',
            editable: true,
            renderCell: (params) => (
                <OutStockSiteNo value={params.value} />
            ),
            renderEditCell: (params) => (
                <OutStockSite {...params} />
            ),
        },
        {
            field: 'actions',
            type: 'actions',
            headerName: '操作',
            with: 120,
            getActions: (params) => [
                <GridActionsCellItem
                    icon={<Delete />}
                    label="Delete"
                    onClick={() => handleDelete(params.row, rows, setRows)}
                />,
            ]
        },
    ]
    /**
     * 删除事件
     * @param {*} params
     */
    const handleDelete = (params, rows, setRows) => {
        const outRows = rows.filter(row => {
             return row.id !== params.id
        })
        setRows(outRows)
    }
    const OutStockSiteNo = React.memo(function OutStockSiteNo(props) {
        const { value } = props;
        if (!value) {
            return null;
        }
        return (
            <Box
                sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
            >
                <span>{value}</span>
            </Box>
        );
    });
    const OutStockSite = (params) => {
        const { id, field, siteNo, row: { staNos } } = params;
        const apiRef = useGridApiContext();
        const handleChange = async (event) => {
            await apiRef.current.setEditCellValue(
                { id, field, value: event.target.value },
                event,
            );
            apiRef.current.stopCellEditMode({ id, field });
        };
        const handleClose = (event, reason) => {
            if (reason === 'backdropClick') {
                apiRef.current.stopCellEditMode({ id, field });
            }
        };
        return (
            <Select
                value={siteNo}
                onChange={handleChange}
                MenuProps={{
                    onClose: handleClose,
                }}
                sx={{
                    height: '100%',
                    '& .MuiSelect-select': {
                        display: 'flex',
                        alignItems: 'center',
                        pl: 1,
                    },
                }}
                autoFocus
                fullWidth
                open
            >
                {staNos.map((option) => {
                    return (
                        <MenuItem
                            key={option}
                            value={option.staNo}
                        >
                            <ListItemText sx={{ overflow: 'hidden' }} primary={option.staNo} />
                        </MenuItem>
                    );
                })}
            </Select >
        )
    }
    return (
        <DataGrid
            rows={rows}
            columns={columns}
            apiRef={gridRef}
            initialState={{
                pagination: {
                    paginationModel: {
                        pageSize: 15,
                    },
                },
            }}
            checkboxSelection
            pageSizeOptions={[15, 25, 35, 45]}
            onRowSelectionModelChange={(ids) => {
                setSelectedIds(ids)
            }}
        />
    )
}
//提交按钮
const SubmitButton = ({ selectedIds, setSelectedIds, gridRef }) => {
const SubmitButton = ({ selectedIds, setSelectedIds, gridRef, record }) => {
    const notify = useNotify();
    const refresh = useRefresh();
    const redirect = useRedirect();
    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 });
        const { data: { code, data, msg } } = await request.post('/outStock/generate/tasks', { items, outId: record?.id });
        if (code == 200) {
            refresh();
            redirect("/task")
@@ -230,117 +347,6 @@
            sx={{ margin: '3.5em' }} />
    )
}
const columns = [
    { field: 'id', headerName: 'ID', width: 40 },
    { field: 'locCode', headerName: '库位', width: 110 },
    { field: 'barcode', headerName: '容器', width: 120 },
    { field: 'batch', headerName: '批次', width: 90 },
    { field: 'unit', headerName: '单位', width: 90 },
    { field: 'outQty', headerName: '本次出库数量', width: 110 },
    {
        field: 'siteNo',
        headerName: '出库口',
        width: 90,
        type: 'singleSelect',
        editable: true,
        renderCell: (params) => (
            <OutStockSiteNo value={params.value} />
        ),
        renderEditCell: (params) => (
            <OutStockSite {...params} />
        ),
    },
    {
        field: 'actions',
        type: 'actions',
        headerName: '操作',
        with: 120,
        getActions: (params) => [
            <GridActionsCellItem
                icon={<Delete />}
                label="Delete"
                onClick={() => handleDelete(params.row.id)}
            />,
        ]
    },
]
/**
 * 删除事件
 * @param {*} params
 */
const handleDelete = (params) => {
    console.log(params);
}
const OutStockSiteNo = React.memo(function OutStockSiteNo(props) {
    const { value } = props;
    if (!value) {
        return null;
    }
    return (
        <Box
            sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
        >
            <span>{value}</span>
        </Box>
    );
});
const OutStockSite = (params) => {
    const { id, field, siteNo, row: { staNos } } = params;
    const apiRef = useGridApiContext();
    const handleChange = async (event) => {
        await apiRef.current.setEditCellValue(
            { id, field, value: event.target.value },
            event,
        );
        apiRef.current.stopCellEditMode({ id, field });
    };
    const handleClose = (event, reason) => {
        if (reason === 'backdropClick') {
            apiRef.current.stopCellEditMode({ id, field });
        }
    };
    return (
        <Select
            value={siteNo}
            onChange={handleChange}
            MenuProps={{
                onClose: handleClose,
            }}
            sx={{
                height: '100%',
                '& .MuiSelect-select': {
                    display: 'flex',
                    alignItems: 'center',
                    pl: 1,
                },
            }}
            autoFocus
            fullWidth
            open
        >
            {staNos.map((option) => {
                return (
                    <MenuItem
                        key={option}
                        value={option.staNo}
                    >
                        <ListItemText sx={{ overflow: 'hidden' }} primary={option.staNo} />
                    </MenuItem>
                );
            })}
        </Select >
    )
}
export default OutStockPublic;
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java
@@ -262,9 +262,13 @@
        if (Cools.isEmpty()) {
            return R.error("参数不能为空!!");
        }
        if (Objects.isNull(params.get("outId"))) {
            return R.error("出库参数不能为空!!");
        }
        List<OutStockToTaskParams> taskParams = JSONArray.parseArray(JSONArray.toJSONString(params.get("items")), OutStockToTaskParams.class);
        return  outStockService.genOutStockTask(taskParams, getLoginUserId());
        return  outStockService.genOutStockTask(taskParams, getLoginUserId(), Long.parseLong(params.get("outId").toString()));
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocToTaskParams.java
@@ -17,6 +17,9 @@
    @ApiModelProperty("类型: check:盘点出库, outStock: 库存出库")
    private String type;
    @ApiModelProperty("原单据ID (用户单据出库查找业务类型")
    private Long sourceId;
    @ApiModelProperty("目标站点")
    private String siteNo;
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/OutStockToTaskParams.java
@@ -1,10 +1,13 @@
package com.vincent.rsf.server.manager.controller.params;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Map;
@Data
@Accessors(chain = true)
@@ -26,6 +29,16 @@
    @ApiModelProperty("单位")
    private String unit;
    @ApiModelProperty("客单号")
    private String platOrderCode;
    @ApiModelProperty("字段索引")
    private String fieldsIndex;
    @ApiModelProperty("扩展字段")
    @TableField(exist = false)
    private Map<String, String> extendFields;
    @ApiModelProperty("数量")
    private Double outQty;
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
@@ -26,9 +26,11 @@
    OUT_STOCK_STATUS_TASK_INIT("10", "初始化"),
    OUT_STOCK_STATUS_TASK_EXCE("11", "待处理"),
    OUT_STOCK_STATUS_TASK_WAVE("12", "生成波次"),
    OUT_STOCK_STATUS_TASK_WORKING("13", "作业中")
    ;
    OUT_STOCK_STATUS_TASK_WAVE("11", "生成波次"),
    OUT_STOCK_STATUS_TASK_CREATE("13", "生成工作档"),
    OUT_STOCK_STATUS_TASK_WORKING("14", "作业中")
            ;
    AsnExceStatus(String val, String desc) {
        this.val = Short.parseShort(val);
        this.desc = desc;
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java
@@ -23,5 +23,5 @@
    R getOrderOutTaskItem(OrderOutTaskParam param);
    R genOutStockTask(List<OutStockToTaskParams> params, Long loginUserId);
    R genOutStockTask(List<OutStockToTaskParams> params, Long loginUserId, Long outId);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -45,6 +45,8 @@
    private DeviceSiteService deviceSiteService;
    @Autowired
    private WcsService wcsService;
    @Autowired
    private OutStockService outStockService;
    /**
@@ -69,6 +71,13 @@
        String siteNo = map.getSiteNo();
        List<LocItem> items = map.getItems();
        Map<Long, List<LocItem>> listMap = items.stream().collect(Collectors.groupingBy(LocItem::getLocId));
        AsnOrder order;
        if (!Objects.isNull(map.getSourceId())) {
            order = outStockService.getById(map.getSourceId());
        } else {
            order = new AsnOrder();
        }
        listMap.keySet().forEach(key -> {
            Task task = new Task();
            Loc loc = locService.getById(key);
@@ -202,6 +211,9 @@
                        .setUpdateTime(new Date())
                        .setOrderType(OrderType.ORDER_OUT.type)
                        .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type));
               if (map.getType().equals(Constants.TASK_TYPE_ORDER_OUT_STOCK)) {
                    taskItem.setWkType(Short.parseShort(order.getWkType()));
               }
                taskItems.add(taskItem);
                Double qty = Math.round((item.getWorkQty() + item.getOutQty()) * 10000) / 10000.0;
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -1,7 +1,6 @@
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.framework.common.Cools;
@@ -429,15 +428,15 @@
     * 生成出库任务
     *
     * @param params
     * @param outId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R genOutStockTask(List<OutStockToTaskParams> params, Long loginUserId) {
    public R genOutStockTask(List<OutStockToTaskParams> params, Long loginUserId, Long outId) {
        if (params.isEmpty()) {
            throw new CoolException("参数不能为空!!");
        }
        //优先生成浅库位任务
        List<OutStockToTaskParams> Items = params.stream().sorted(Comparator.comparing(OutStockToTaskParams::getLocCode).thenComparing(item -> {
            return LocUtils.isShallowLoc(item.getLocCode()) ? 1 : 0;
@@ -455,19 +454,53 @@
                locItems.add(locItem);
                LocToTaskParams taskParams = new LocToTaskParams();
                taskParams.setType(Constants.TASK_TYPE_OUT_STOCK)
                taskParams.setType(Constants.TASK_TYPE_ORDER_OUT_STOCK)
                        .setOrgLoc(loc.getCode())
                        .setItems(locItems)
                        .setSourceId(outId)
                        .setSiteNo(param.getSiteNo());
                try {
                    //生成出库任务
                    locItemService.generateTask(taskParams, loginUserId);
                } catch (Exception e) {
                    logger.error("UNK", e);
                    throw new CoolException(e.getMessage());
                }
                AsnOrderItem orderItem = outStockItemService.getOne(new LambdaQueryWrapper<AsnOrderItem>()
                        .eq(AsnOrderItem::getAsnId, outId)
                        .eq(StringUtils.isNotBlank(locItem.getBatch()), AsnOrderItem::getSplrBatch, locItem.getBatch())
                        .eq(StringUtils.isNotBlank(locItem.getFieldsIndex()), AsnOrderItem::getFieldsIndex, locItem.getFieldsIndex())
                        .eq(AsnOrderItem::getMatnrId, locItem.getMatnrId()));
                if (Objects.isNull(orderItem)) {
                    throw new CoolException("单据明细不存在!!");
                }
                Double workQty = Math.round((orderItem.getWorkQty() + locItem.getOutQty()) * 10000) / 10000.0;
                orderItem.setUpdateBy(loginUserId).setUpdateTime(new Date()).setWorkQty(workQty);
                if (!outStockItemService.updateById(orderItem)) {
                    throw new CoolException("单据明细修改失败!!");
                }
            }
        }
        Double sum = Items.stream().mapToDouble(OutStockToTaskParams::getOutQty).sum();
        //更新出库单明细及主单
        AsnOrder outOrder = outStockService.getById(outId);
        if (Objects.isNull(outOrder)) {
            throw new CoolException("出库单据不存在!!");
        }
        Double workQty = Math.round((outOrder.getWorkQty() + sum) * 10000) / 10000.0;
        outOrder.setWorkQty(workQty).setExceStatus( AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val);
        if (!outStockService.updateById(outOrder)) {
            throw new CoolException("出库单状态修改失败!!");
        }
        return R.ok();
    }
rsf-server/src/main/resources/application.yml
@@ -25,7 +25,7 @@
  #  global-config:
  #    field-strategy: 0
  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
    cache-enabled: true
    call-setters-on-nulls: true