skyouc
3 天以前 456f4f168f615b1d25fcc88f35efe1d7bf933302
库存出库生成任务 优化
9个文件已修改
188 ■■■■■ 已修改文件
rsf-admin/src/i18n/en.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/outWork/outBound/OutBoundList.jsx 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/outWork/outBound/locItemInfoModal.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/WcsController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItem.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocItemService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js
@@ -1155,6 +1155,8 @@
        error: {
            stock: "Insufficient inventory to deliver !!",
            select_error_order: "Please Select Asn Orders",
            out_stock_qty: "The outbound quantity cannot be greater than the inventory quantity",
        }
    }
rsf-admin/src/i18n/zh.js
@@ -1152,6 +1152,8 @@
        error: {
            stock: "库存不足,无法提交!!", 
            select_error_order: "请选择通知单",
            out_stock_qty: "出库数量不能大于库存数量",
        }
    }
rsf-admin/src/page/outWork/outBound/OutBoundList.jsx
@@ -21,6 +21,7 @@
    useListContext,
    useRefresh,
    Edit,    
    useRedirect,
} from 'react-admin';
import {
    Dialog,
@@ -59,6 +60,8 @@
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import StaSelect from "./StaSelect";
import { redirect } from "react-router";
import { number } from "prop-types";
const OutBoundList = () => {    
@@ -135,6 +138,7 @@
                            <SubmitButton 
                                sta={sta}
                                data={tabelData}
                                        setTableData={setTableData}
                            />
                        </Stack>
                    </Box>
@@ -163,7 +167,9 @@
const SubmitButton = (props) =>{
    const translate = useTranslate();
    const notify = useNotify();
    const { sta, data } = props;
    const redirect = useRedirect();
    const refresh = useRefresh();
    const { sta, data, setTableData } = props;
    const check = ()=>{
        if(sta === "" || sta === undefined || sta === null){
            notify("请选择站点");
@@ -174,19 +180,33 @@
            return;
        }
        http(sta,data);
    }    
    const http = async (sta,data) => {
        console.log("提交数据",sta,data);
    const http = async (sta, items) => {
        console.log(items);
        const filter = items.filter(item => (item.outQty + item.workQty) > item.anfme);
        if (filter.length > 0) {
            notify(translate('toolbar.request.error.out_stock_qty'))
            return
        }
        const { data: { code, data, msg } } = await request.post(`/locItem/generate/task`, { siteNo: sta, items: items });
        if (code === 200) {
            notify(msg);
            refresh()
            setTableData([])
            redirect("/task")
        } else {
            notify(msg);
        }
    }
    return (
        <Button
        <ConfirmButton
            variant="contained" 
            color="primary"            
            onClick={check}
            onConfirm={check}
            label={"table.field.outBound.createTask"}
        >
          {translate('table.field.outBound.createTask')}
        </Button>
        </ConfirmButton>
    )
    
}
@@ -200,16 +220,25 @@
            field: 'outQty',
            headerName: translate('table.field.outBound.outQty')+"*",
            width: 100,
            type: 'number',
            editable: true,   
            headerClassName: "custom",         
        },
        {
            field: 'anfme',
            headerName: translate('table.field.locItem.anfme'),
            type: 'number',
            width: 100,
            editable: false,
        }, 
        {
            field: 'workQty',
            headerName: translate('table.field.locItem.workQty'),
            width: 100,
            type: 'number',
            editable: false,
        },
        {
            field: 'matnrCode',
            headerName: translate('table.field.locItem.matnrCode'),
            width: 130,
rsf-admin/src/page/outWork/outBound/locItemInfoModal.jsx
@@ -172,7 +172,7 @@
        { field: 'maktx', headerName: translate('table.field.locItem.maktx'), width: 300 },
        { field: 'batch', headerName: translate('table.field.locItem.batch'), width: 100 },
        { field: 'anfme', headerName: translate('table.field.locItem.anfme'), width: 100 },
        { field: 'workQty', headerName: translate('table.field.locItem.workQty'), width: 100 },
        { field: 'unit', headerName: translate('table.field.locItem.unit'), width: 100 },
        
    ])
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/WcsController.java
@@ -81,8 +81,4 @@
        return R.ok();
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocItemController.java
@@ -78,6 +78,15 @@
    }
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @PostMapping("/locItem/generate/task")
    public R generateTask(@RequestBody Map<String, Object> map) {
        if (Objects.isNull(map)) {
            return R.error("参数不能为空!!");
        }
        return locItemService.generateTask(map);
    }
    @PreAuthorize("hasAuthority('manager:locItem:list')")
    @PostMapping("/locItem/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(locItemService.list());
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocItem.java
@@ -94,6 +94,10 @@
    @ApiModelProperty("项目号")
    private String projectCode;
    @ApiModelProperty("出库数量")
    @TableField(exist = false)
    private Double outQty;
    /**
     * 物料名称
     */
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocItemService.java
@@ -1,8 +1,12 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.manager.entity.LocItem;
import java.util.Map;
public interface LocItemService extends IService<LocItem> {
    R generateTask(Map<String, Object> map);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -1,12 +1,128 @@
package com.vincent.rsf.server.manager.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.entity.Task;
import com.vincent.rsf.server.manager.entity.TaskItem;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.mapper.LocItemMapper;
import com.vincent.rsf.server.manager.entity.LocItem;
import com.vincent.rsf.server.manager.service.LocItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.server.manager.service.TaskItemService;
import com.vincent.rsf.server.manager.service.TaskService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service("locItemService")
public class LocItemServiceImpl extends ServiceImpl<LocItemMapper, LocItem> implements LocItemService {
    @Autowired
    private LocService locService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private TaskItemService taskItemService;
    @Autowired
    private LocItemService locItemService;
    /**
     * 库存出库生成出库任务
     *
     * @param map
     * @return
     */
    @Override
    public R generateTask(Map<String, Object> map) {
        if (Objects.isNull(map.get("siteNo"))) {
            throw new CoolException("站点不能为空!");
        }
        if (Objects.isNull(map.get("items"))) {
            throw new CoolException("明细不能为空!");
        }
        String siteNo = map.get("siteNo").toString();
        List<LocItem> items = JSONArray.parseArray(JSONArray.toJSONString(map.get("items")), LocItem.class);
        Map<Long, List<LocItem>> listMap = items.stream().collect(Collectors.groupingBy(LocItem::getLocId));
        listMap.keySet().forEach(key -> {
            Task task = new Task();
            Loc loc = locService.getById(key);
            if (Objects.isNull(loc)) {
                throw new CoolException("数据错误:所选库存信息不存在!!");
            }
            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null);
            task.setOrgLoc(loc.getCode())
                    .setTaskCode(ruleCode)
                    .setTargSite(siteNo)
                    .setTaskStatus(TaskStsType.GENERATE_OUT.id)
                    .setBarcode(loc.getBarcode());
            List<LocItem> locItems = this.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, key));
            if (locItems.isEmpty()) {
                throw new CoolException("数据错误:所选库存明细不存在!!");
            }
            Double orgQty = locItems.stream().mapToDouble(LocItem::getAnfme).sum();
            List<LocItem> locItemList = listMap.get(key);
            Double outQty = locItemList.stream().mapToDouble(LocItem::getOutQty).sum();
            if (orgQty.compareTo(outQty) > 0) {
                //拣料出库
                task.setTaskType(TaskType.TASK_TYPE_PICK_AGAIN_IN.type);
            } else {
                //全板出库
                task.setTaskType(TaskType.TASK_TYPE_OUT.type);
            }
            if (!taskService.save(task)) {
                throw new CoolException("任务创建失败!!");
            }
            List<TaskItem> taskItems = new ArrayList<>();
            listMap.get(key).forEach(item -> {
                TaskItem taskItem = new TaskItem();
                BeanUtils.copyProperties(item, taskItem);
                taskItem.setTaskId(task.getId())
                        .setAnfme(item.getOutQty())
                        .setBatch(item.getBatch())
                        .setOrderType(OrderType.ORDER_OUT.type)
                        .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type));
                taskItems.add(taskItem);
                Double qty = Math.round((item.getWorkQty() + item.getOutQty()) * 10000) / 10000.0;
                LocItem locItem = locItemService.getById(item.getId());
                if (Objects.isNull(locItem)) {
                    throw new CoolException("库存信息不存在!");
                }
                if (locItem.getAnfme().compareTo(qty) < 0) {
                    Double minusQty = Math.round((locItem.getAnfme() - locItem.getWorkQty()) * 10000) / 10000.0;
                    item.setWorkQty(minusQty);
                } else {
                    item.setWorkQty(qty);
                }
                if (! locItemService.updateById(item)) {
                    throw new CoolException("库存信息修改失败!!");
                }
            });
            if (!taskItemService.saveBatch(taskItems)) {
                throw new CoolException("任务明细生成失败!!");
            }
        });
        return R.ok("任务生成完成!!");
    }
}