chen.lin
昨天 7e5973a3061989a976e2c19ef588bb2f34f29cf4
下发任务校验
3个文件已修改
160 ■■■■■ 已修改文件
rsf-admin/src/layout/index.jsx 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/outStock/OutStockSiteDialog.jsx 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/layout/index.jsx
@@ -1,3 +1,4 @@
import { createPortal } from 'react-dom';
import { Layout as RALayout, CheckForApplicationUpdate, useSidebarState } from "react-admin";
import AppBar from './AppBar';
import { MyMenu } from './MyMenu';
@@ -7,6 +8,23 @@
const LayoutContent = ({ children }) => {
  const [sidebarIsOpen] = useSidebarState();
  const sidebarWidth = sidebarIsOpen ? 200 : 50;
  const tabsBarEl = (
    <Box sx={{
      position: 'fixed',
      top: 48,
      left: sidebarWidth + 5,
      right: 0,
      zIndex: 1400, // 高于 Dialog/Modal(1300),通过 Portal 挂到 body 才能盖住弹窗
      transition: (theme) =>
        theme.transitions.create('left', {
          easing: theme.transitions.easing.sharp,
          duration: theme.transitions.duration.leavingScreen,
        }),
    }}>
      <TabsBar />
    </Box>
  );
  return (
    <RALayout
@@ -28,20 +46,7 @@
        }
      }}
    >
      <Box sx={{
        position: 'fixed',
        top: 48,
        left: sidebarWidth + 5,
        right: 0,
        zIndex: 1350, // 高于 Dialog(1300),避免菜单内弹窗遮盖标签页
        transition: (theme) =>
          theme.transitions.create('left', {
            easing: theme.transitions.easing.sharp,
            duration: theme.transitions.duration.leavingScreen,
          }),
      }}>
        <TabsBar />
      </Box>
      {createPortal(tabsBarEl, document.body)}
      {children}
      <CheckForApplicationUpdate />
    </RALayout>
rsf-admin/src/page/orders/outStock/OutStockSiteDialog.jsx
@@ -1,14 +1,16 @@
import { Box, Card, Grid, List, LinearProgress, Select, MenuItem, ListItemText, ListItemAvatar, Avatar, ListItemButton, Dialog, DialogTitle, ListItem } from "@mui/material";
import { Box, Card, Grid, List, LinearProgress, Select, MenuItem, ListItemText, ListItemAvatar, Avatar, ListItemButton, Dialog, DialogTitle, ListItem, CircularProgress } from "@mui/material";
import React, { useState, useRef, useEffect, useMemo } from "react";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting';
import { Delete, Edit, Add } from '@mui/icons-material';
import request from '@/utils/request';
import { useTranslate } from "react-admin";
import { useTranslate, useNotify } from "react-admin";
const OutStockSiteDialog = (props) => {
    const translate = useTranslate();
    const notify = useNotify();
    const { onClose, selectedValue, open } = props;
    const [siteNos, setSiteNos] = useState([]);
    const [loading, setLoading] = useState(false);
    const handleClose = () => {
        onClose(selectedValue);
@@ -19,16 +21,31 @@
    }
    useEffect(() => {
        getSiteNos()
        if (open) {
            getSiteNos();
        } else {
            setSiteNos([]);
        }
    }, [open])
    const getSiteNos = async () => {
        const { data: { code, data, msg } } = await request.get('/outStock/tasks/sites');
        if (code === 200) {
            setSiteNos(data);
        } else {
            notify(msg);
        setLoading(true);
        try {
            const { data: res } = await request.get('/outStock/tasks/sites');
            const code = res?.code;
            const data = res?.data;
            const msg = res?.msg;
            if (code === 200) {
                setSiteNos(Array.isArray(data) ? data : []);
            } else {
                notify(msg || '获取库口列表失败');
                setSiteNos([]);
            }
        } catch (err) {
            notify(err?.message || '获取库口列表失败');
            setSiteNos([]);
        } finally {
            setLoading(false);
        }
    }
@@ -36,17 +53,31 @@
        <Dialog
            onClose={handleClose}
            open={open}
            maxWidth="xs"
            fullWidth
        >
            <DialogTitle>{translate("toolbar.modiftySite")}</DialogTitle>
            <List sx={{ pt: 0 }}>
                {siteNos.map((site) => (
                    <ListItem disableGutters key={site?.id}>
                        <ListItemButton onClick={() => handleListItemClick(site)}>
                            <ListItemText primary={site.site} />
                        </ListItemButton>
                    </ListItem>
                ))}
            </List>
            {loading ? (
                <Box sx={{ display: 'flex', justifyContent: 'center', py: 3 }}>
                    <CircularProgress />
                </Box>
            ) : (
                <List sx={{ pt: 0, minHeight: 120 }}>
                    {siteNos.length === 0 && !loading ? (
                        <ListItem>
                            <ListItemText primary="暂无库口数据" />
                        </ListItem>
                    ) : (
                        siteNos.map((site) => (
                            <ListItem disableGutters key={site?.id}>
                                <ListItemButton onClick={() => handleListItemClick(site)}>
                                    <ListItemText primary={site?.site ?? site?.name ?? '-'} />
                                </ListItemButton>
                            </ListItem>
                        ))
                    )}
                </List>
            )}
        </Dialog>
    );
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -699,37 +699,43 @@
            for (LocItem locItem : locItems) {
                Loc loc = locService.getById(locItem.getLocId());
                List<LocItem> itemList = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocCode, locItem.getLocCode()));
                if (issued.compareTo(ISSUED_TOLERANCE) > 0) {
                    ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
                    if (existDtos.add(existDto)) {
                        locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue());
                        locItem.setBarcode(loc.getBarcode());
                        OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
                        orderOutItemDto.setLocItem(locItem);
                if (issued.compareTo(ISSUED_TOLERANCE) <= 0) {
                    break;
                }
                // 该库位可分配数量:取本行待分配与库位库存的较小值
                double allocatable = Math.min(issued.doubleValue(), locItem.getAnfme() != null ? locItem.getAnfme() : 0);
                ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
                if (existDtos.add(existDto)) {
                    // 首次使用该库位:加入列表并扣减 issued
                    locItem.setOutQty(allocatable);
                    locItem.setBarcode(loc.getBarcode());
                    OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
                    orderOutItemDto.setLocItem(locItem);
                        List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                .eq(DeviceSite::getChannel, loc.getChannel())
                                .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                        );
                    List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                            .eq(DeviceSite::getChannel, loc.getChannel())
                            .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                    );
                        if (!deviceSites.isEmpty()) {
                            List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                            for (DeviceSite sta : deviceSites) {
                                OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                staListDto.setStaNo(sta.getSite());
                                staListDto.setStaName(sta.getSite());
                                maps.add(staListDto);
                            }
                            orderOutItemDto.setStaNos(maps);
                            //默认获取第一站点
                            DeviceSite deviceSite = deviceSites.stream().findFirst().get();
                            orderOutItemDto.setSiteNo(deviceSite.getSite());
                    if (!deviceSites.isEmpty()) {
                        List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                        for (DeviceSite sta : deviceSites) {
                            OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                            staListDto.setStaNo(sta.getSite());
                            staListDto.setStaName(sta.getSite());
                            maps.add(staListDto);
                        }
                        list.add(orderOutItemDto);
                        issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                        orderOutItemDto.setStaNos(maps);
                        //默认获取第一站点
                        DeviceSite deviceSite = deviceSites.stream().findFirst().get();
                        orderOutItemDto.setSiteNo(deviceSite.getSite());
                    }
                    list.add(orderOutItemDto);
                    issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                } else {
                    // 该库位已被前序订单行占用:只扣减 issued,不重复加入列表,避免产生“库存不足”脏数据
                    issued = issued.subtract(new BigDecimal(String.valueOf(allocatable)));
                }
            }
            if (issued.compareTo(ISSUED_TOLERANCE) > 0) {