chen.lin
2 天以前 a488088a18a9b8808bc57124681cee8c4ada7299
Merge remote-tracking branch 'origin/devlop-phyz' into devlop-phyz
1个文件已添加
18个文件已修改
677 ■■■■ 已修改文件
rsf-admin/src/i18n/en.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/task/FlowStepInstanceModal.jsx 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaOutStockController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/params/PdaGeneralParam.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/dto/OrderOutItemPdaDto.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskCacheLocSchedules.java 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/FlowStepInstanceController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/service/FlowStepInstanceService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/FlowStepInstanceServiceImpl.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js
@@ -1530,6 +1530,7 @@
        modiftySite: 'Modify SiteNo',
        selectWave: 'Select Wave Rule',
        flowStep: "Flow Step",
        jumpCurrent: "Jump To Current",
    },
    placeholder: {
rsf-admin/src/i18n/zh.js
@@ -1598,6 +1598,7 @@
        selectWave: '波次规则',
        transformation: "转换",
        flowStep: "流程步骤",
        jumpCurrent: "跳转到当前",
    },
    placeholder: {
        warehouseAreasCode: "用于库位编码前缀占位符",
rsf-admin/src/page/task/FlowStepInstanceModal.jsx
@@ -25,6 +25,7 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
import MyLocationIcon from '@mui/icons-material/MyLocation';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -34,7 +35,7 @@
        cursor: 'auto'
    },
    '& .opt': {
        width: 150
        width: 220
    },
}));
@@ -109,6 +110,20 @@
        }
    };
    const handleJumpCurrent = async (item) => {
        try {
            const res = await request.post(`/flowStepInstance/jumpCurrent/${item.id}`);
            if (res.data.code === 200) {
                notify(res.data.msg || translate('common.response.success'), { type: 'success' });
                fetchData();
            } else {
                notify(res.data.msg, { type: 'error' });
            }
        } catch (error) {
            notify('Jump current failed', { type: 'error' });
        }
    };
    const handleFormClose = () => {
        setFormOpen(false);
        setFormData({});
@@ -177,7 +192,7 @@
                        <TextField source="taskNo" label={translate("table.field.flowStepInstance.taskNo")} />
                        <DateField source="createTime" label={translate("table.field.flowStepInstance.createTime")} showTime />
                        <WrapperField cellClassName="opt" label="common.field.opt" onClick={(e) => e.stopPropagation()} >
                            <RowActions onEdit={handleEdit} onDelete={handleDelete} />
                            <RowActions onEdit={handleEdit} onDelete={handleDelete} onJumpCurrent={handleJumpCurrent} />
                        </WrapperField>
                    </StyledDatagrid>
                </DialogContent>
@@ -215,8 +230,9 @@
    );
};
const RowActions = ({ onEdit, onDelete }) => {
const RowActions = ({ onEdit, onDelete, onJumpCurrent }) => {
    const record = useRecordContext();
    const translate = useTranslate();
    return (
        <Box display="flex">
            <Tooltip title="Edit">
@@ -224,6 +240,11 @@
                    <EditIcon fontSize="small" />
                </IconButton>
            </Tooltip>
            <Tooltip title={translate("toolbar.jumpCurrent")}>
                <IconButton onClick={() => onJumpCurrent(record)} size="small" color="secondary">
                    <MyLocationIcon fontSize="small" />
                </IconButton>
            </Tooltip>
            {/* If there's an issue with event propagation you might need to handle it in onClick */}
            <Tooltip title="Delete">
                <IconButton onClick={() => onDelete(record)} size="small" color="error">
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaOutStockController.java
@@ -10,6 +10,7 @@
import com.vincent.rsf.server.api.entity.params.OrderOutGeneralParam;
import com.vincent.rsf.server.api.entity.params.PdaGeneralParam;
import com.vincent.rsf.server.api.service.PdaOutStockService;
import com.vincent.rsf.server.manager.controller.params.GenWaveParams;
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.Loc;
@@ -184,6 +185,15 @@
        return outStockService.genOutStockTask(tasks,getLoginUserId(), orderItem.getOrderId());
    }
    //q
    @PostMapping("/orderOut/all/in")//波次整托出库
    public R orderOutGetOutLocRunAllIn(@RequestBody GenWaveParams params) {
//        GenWaveParams genWaveParams = new GenWaveParams();
        return outStockService.generateWaves(params);
    }
    @PostMapping("/orderOut/taskItemList")
    @ApiOperation("备货容器页面查询任务明细")
    public R taskItemList(@RequestBody PdaGeneralParam param) {
@@ -196,4 +206,18 @@
       return pdaOutStockService.containerRebinding(param,getLoginUserId());
    }
    @PostMapping("/orderOut/buffStore/callEmpty")
    @ApiOperation("灌桶入库呼叫空桶")
    public R buffStoreCallEmpty(@RequestBody PdaGeneralParam param) {
        param.getSta1();
        return R.ok();
    }
    @PostMapping("/orderOut/buffStore/callNewMat")
    @ApiOperation("灌桶入库呼叫新料")
    public R buffStoreCallNewMat(@RequestBody PdaGeneralParam param) {
        param.getSta2();
        return R.ok();
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/params/PdaGeneralParam.java
@@ -36,4 +36,8 @@
    private List<TaskItem> taskItemList;
    //灌桶入库
    private String sta1;
    private String sta2;
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/AgvServiceImpl.java
@@ -279,7 +279,7 @@
            throw new CoolException("未找到站点信息");
        }
        if (!Cools.isEmpty(basStation.getContainerType())) {
            List<Long> longs1 = basStation.getCrossZoneArea().stream()
            List<Long> longs1 = basStation.getContainerType().stream()
                    .map(Integer::longValue)
                    .collect(Collectors.toList());
            List<BasContainer> containers = basContainerService.list(
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
@@ -19,10 +19,7 @@
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.dto.LocStockDto;
import com.vincent.rsf.server.manager.controller.dto.OrderOutItemDto;
import com.vincent.rsf.server.manager.controller.params.OrderOutTaskParam;
import com.vincent.rsf.server.manager.controller.params.OutStockToTaskParams;
import com.vincent.rsf.server.manager.controller.params.PakinItem;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.controller.params.*;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.service.*;
@@ -556,19 +553,22 @@
                    // 立即触发异步任务,不等待结果
                    if (!Cools.isEmpty(palletId.get()) && StringUtils.isNotBlank(syncOrder.getOrderNo()) && !Cools.isEmpty(syncOrder.getStationId())) {
                        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, palletId.get()));
                        if (!Cools.isEmpty(loc)) {
                        if (!Cools.isEmpty(loc) && loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) {
//                            outStockService.getOrderOutTaskItem(orderOutTaskParam,param.getOrderItemId());
                            //出库
//                        boolean itemsCheck = waitPakinService.mergeItemsCheck(pakinParam, loginUserId);
//                            if (true) {
                            CompletableFuture.runAsync(() -> {
                                try {
                                    asyncOutboundExecutionWcs(syncOrder.getStationId(), wkOrder.getId(), loginUserId);
                                    asyncOutboundExecutionWcs(syncOrder.getStationId(), wkOrder.getId(), loginUserId,loc.getCode());
                                } catch (Exception e) {
                                    log.warn("订单 {} 开始自动出库", syncOrder.getOrderNo());
                                }
                            });
//                            }
                        } else {
                            log.warn("订单 {} 自动出库失败!!未查询到指定库存!!", syncOrder.getOrderNo());
                            throw new CoolException("自动出库失败!!未查询到指定库存!!");
                        }
                    }
                }
@@ -612,35 +612,52 @@
    }
    @Async
    public void asyncOutboundExecutionWcs(String stationId ,Long orderId, Long loginUserId) {
    public void asyncOutboundExecutionWcs(String stationId ,Long orderId, Long loginUserId,String locCode) {
        try {
            OrderOutTaskParam orderOutTaskParam = new OrderOutTaskParam();
            orderOutTaskParam.setOrderId(orderId);
            orderOutTaskParam.setWaveId(16L);
            List<OrderOutItemDto> orderOutTaskItemAuto = outStockService.getOrderOutTaskItemAuto(orderOutTaskParam);
            List<OutStockToTaskParams> tasks = new ArrayList<>();
            for (OrderOutItemDto orderOutItemDto : orderOutTaskItemAuto){
                for (LocItem locItem : orderOutItemDto.getLocItemList()) {
                    OutStockToTaskParams outStockToTaskParams = new OutStockToTaskParams(orderOutItemDto,locItem);
                    outStockToTaskParams.setId(locItem.getId());
                    outStockToTaskParams.setOutQty(locItem.getOutQty());
                    outStockToTaskParams.setLocCode(locItem.getLocCode());
                    outStockToTaskParams.setBarcode(locItem.getBarcode());
                    outStockToTaskParams.setSiteNo(stationId);
                    tasks.add(outStockToTaskParams);
            int i = 0;
            while (true) {
                i++;
                if (i > 5) return;
                Thread.sleep(3000);
                WkOrder byId = asnOrderService.getById(orderId);
                if (Cools.isEmpty(byId)) {
                    continue;
                }
                break;
            }
            if (tasks.isEmpty()){
                log.warn("订单ID {} 没有找到可出库明细,跳过自动出库", orderId);
                return;
            }
            outStockService.genOutStockTask(tasks, loginUserId, orderId);
            log.info("订单ID {} 自动出库,共处理 {} 个明细", orderId, tasks.size());
            GenWaveParams genWaveParams = new GenWaveParams();
            List<Long> ids = new ArrayList<>();
            ids.add(orderId);
            genWaveParams.setIds(ids);
            genWaveParams.setWaveRuleId(16L);
//            OrderOutTaskParam orderOutTaskParam = new OrderOutTaskParam();
//            orderOutTaskParam.setOrderId(orderId);
//            orderOutTaskParam.setWaveId(16L);
//            List<OrderOutItemDto> orderOutTaskItemAuto = outStockService.getOrderOutTaskItemAuto(orderOutTaskParam);
//
//            List<OutStockToTaskParams> tasks = new ArrayList<>();
//            for (OrderOutItemDto orderOutItemDto : orderOutTaskItemAuto){
//                for (LocItem locItem : orderOutItemDto.getLocItemList()) {
//                    OutStockToTaskParams outStockToTaskParams = new OutStockToTaskParams(orderOutItemDto,locItem);
//                    outStockToTaskParams.setId(locItem.getId());
//                    outStockToTaskParams.setOutQty(locItem.getOutQty());
//                    outStockToTaskParams.setLocCode(locItem.getLocCode());
//                    outStockToTaskParams.setBarcode(locItem.getBarcode());
//                    outStockToTaskParams.setSiteNo(stationId);
//                    tasks.add(outStockToTaskParams);
//                }
//            }
//            if (tasks.isEmpty()){
//                log.warn("订单ID {} 没有找到可出库明细,跳过自动出库", orderId);
//                return;
//            }
//            outStockService.genOutStockTask(tasks, loginUserId, orderId);
            R r = outStockService.generateWavesOrderAuto(genWaveParams, stationId,locCode);
            log.info("订单ID {} 自动转波次", orderId);
        } catch (Exception e) {
            log.error("订单ID {} 自动出库: {}", orderId, e.getMessage(), e);
            log.error("订单ID {} 自动转波次: {}", orderId, e.getMessage(), e);
        }
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/dto/OrderOutItemPdaDto.java
New file
@@ -0,0 +1,47 @@
package com.vincent.rsf.server.manager.controller.dto;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.entity.LocItem;
import com.vincent.rsf.server.manager.utils.Synchro;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.experimental.Delegate;
import java.util.ArrayList;
import java.util.List;
@Data
@Accessors(chain = true)
public class OrderOutItemPdaDto {
    @Delegate(types = LocItem.class)
    private LocItem locItem;
//    @Delegate(types = Loc.class)
//    private Loc loc;
//    private List<LocItem> locItemList = new ArrayList<>();
    private List<staListDto> staNos;
    private List<String> targSiteAreaList;
    private String targSiteAreaNow;
    private String siteNo;
    private String sourceId;
    private String source;
    @Data
    public static class staListDto{
        private String staNo;
        private String staName;
    }
    public void sync(Object source) {
        Synchro.Copy(source, this);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Wave.java
@@ -141,6 +141,18 @@
    @ApiModelProperty(value= "备注")
    private String memo;
    /**
     * 指定站点
     */
    @ApiModelProperty(value= "指定站点")
    private String stationId;
    /**
     * 指定库位
     */
    @ApiModelProperty(value= "指定库位")
    private String locCode;
    public Wave() {}
    public Wave(String code,Short type,Short exceStatus,Double anfme,Double qty,Integer orderNum,Integer status,Long tenantId,Date createTime,Long createBy,Date updateTime,Long updateBy,Integer deleted,String memo) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskCacheLocSchedules.java
@@ -23,8 +23,10 @@
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
 * @author Munch D. Luffy
@@ -145,85 +147,122 @@
        if (Cools.isEmpty(autoRunContainerEndYz)) {
            return;
        }
        String autoRunContainerEndYzCount = configService.getVal("AUTO_RUN_CHECK_OUT_YZ_COUNT", String.class);
        if (Cools.isEmpty(autoRunContainerEndYzCount)) {
            return;
        }
        int autoOutCount = Integer.parseInt(autoRunContainerEndYzCount);
        if (autoOutCount <= 0) {
            return;
        }
        List<Long> souLocArea = new ArrayList<>();
        List<Long> endLocArea = new ArrayList<>();
        String curLoc = null;
        String deepLoc = null;
        try{
            String[] split = autoRunAreaStartYz.split(";");
            for (String c : split) {
            for (String c :  autoRunAreaStartYz.split(";")) {
                WarehouseAreas byId = warehouseAreasService.getById(Integer.parseInt(c));
                if (!Cools.isEmpty(byId)) {
                    Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getAreaId, byId.getId()).eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type)
                            .last("LIMIT 1"));
                    if (!Objects.isNull(loc)) {
                        curLoc = loc.getCode();
                        break;
                    souLocArea.add(byId.getId());
                    }
                }
            }
        } catch (Exception e){
            log.error("配置参数AUTO_RUN_AREA_START_YZ解析失败,请检查!!!");
        }
        //容器集合
        //每个容器对应的容器码类型
        //
        try{
//            String[] containerList = autoRunContainerEndYz.split(";");
//            ArrayList<Long> CONTAINER_IDS = new ArrayList<>();
//            for (String c : containerList) {
//                CONTAINER_IDS.add(Long.parseLong(c));
//            }
            BasContainer basContainer = basContainerService.getOne(new LambdaQueryWrapper<BasContainer>()
                    .in(BasContainer::getContainerType, 1, false));
//            if (Cools.isEmpty(basContainer)){
//                throw new CoolException("未查询到相关容器规则");
//            }
//
//
            List<Long> areaList = new ArrayList<>();//所有库区
//            List<Long> areaList1 = new ArrayList<>();//所有容器类型
//            List<Long> areaList2 = new ArrayList<>();//所有库区
//            List<Long> areaList3 = new ArrayList<>();//所有库区
            boolean sign = true;
//            //容器类型查询  起点
            String[] split = autoRunAreaEndYz.split(";");
            for (String c : split) {
                WarehouseAreas byId = warehouseAreasService.getById(Integer.parseInt(c));
                if (!Cools.isEmpty(byId)) {
                    if (sign){
                        areaList.add(byId.getId());
                        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getAreaId, byId.getId()).eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                                .last("LIMIT 1"));
                        if (!Objects.isNull(loc)) {
                            deepLoc = loc.getCode();
                            sign = false;
                        }
                    }
                }
            }
            String barcodeType = "barcode REGEXP '"+basContainer.getCodeType()+"'";
            List<Loc> loc1 = locService.list(new LambdaQueryWrapper<Loc>()
                    .apply(barcodeType)
                    .eq(Loc::getDeleted, 0)
                    .eq(Loc::getStatus, 1)
                    .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type)
                    .in(Loc::getAreaId, areaList)
                    .orderByDesc(Loc::getId));
        } catch (Exception e){
            log.error("配置参数AUTO_RUN_AREA_START_YZ解析失败,请检查!!!");
        }
        if (curLoc == null ||  deepLoc == null) {
            if (souLocArea.isEmpty()) {
            return;
        }
        LocToTaskParams params = new LocToTaskParams();
        params.setOrgLoc(curLoc).setTarLoc(deepLoc);
        } catch (Exception e){
            log.error("配置参数AUTO_RUN_AREA_START_YZ解析失败,请检查!!!");
            return;
        }
        try{
            for (String c : autoRunAreaEndYz.split(";")) {
                WarehouseAreas byId = warehouseAreasService.getById(Integer.parseInt(c));
                if (!Cools.isEmpty(byId)) {
                    endLocArea.add(byId.getId());
                }
            }
            if (endLocArea.isEmpty()) {
                return;
            }
        } catch (Exception e){
            log.error("配置参数AUTO_RUN_OUT_END_YZ解析失败,请检查!!!");
            return;
        }
        ConcurrentHashMap<String,Integer> CONTAINER_IDS = new ConcurrentHashMap<>();//需要补充的容器查询条件
//        ArrayList<String> CONTAINER_IDS = new ArrayList<>();//需要补充的容器查询条件
        try{
            String[] containerList = autoRunContainerEndYz.split(";");
            for (String c : containerList) {//容器集合
                long parseLong = Long.parseLong(c);
                BasContainer basContainer = basContainerService.getOne(new LambdaQueryWrapper<BasContainer>()
                        .eq(BasContainer::getContainerType, parseLong).last("LIMIT 1"));
                if (Cools.isEmpty(basContainer)){
                    throw new CoolException("未查询到相关容器规则,容器编码CONTAINER_ID:"+c);
                }
                //查询终点是否需要补充此容器
                String barcodeType = "barcode REGEXP '"+basContainer.getCodeType()+"'";
                int count = locService.count(new LambdaQueryWrapper<Loc>()
                        .apply(barcodeType)
                        .in(Loc::getUseStatus, new ArrayList<>(Arrays.asList(
                                LocStsType.LOC_STS_TYPE_D.type,
                                LocStsType.LOC_STS_TYPE_S.type
                        )))
                        .in(Loc::getAreaId, endLocArea)
                        .eq(Loc::getDeleted, 0)
                        .eq(Loc::getStatus, 1)
                        .orderByDesc(Loc::getId));
                if (!Cools.isEmpty(count) && count<autoOutCount){
                    CONTAINER_IDS.put(barcodeType, autoOutCount-count);
                }
            }
        } catch (Exception e){
            log.error("配置参数AUTO_RUN_AREA_START_YZ解析失败,请检查!!!");
            return;
        }
        List<LocToTaskParams> locMove = new  ArrayList<>();
        List<String> locList = new  ArrayList<>();
        for (ConcurrentHashMap.Entry<String,Integer> entry : CONTAINER_IDS.entrySet()) {
            String barcodeType = entry.getKey();// 获取String键
            Integer entryValue = entry.getValue();// 获取数量
            List<Loc> souLocList = locService.list(new LambdaQueryWrapper<Loc>()
                    .apply(barcodeType)
                    .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type)
                    .in(Loc::getAreaId, souLocArea)
                    .eq(Loc::getDeleted, 0)
                    .eq(Loc::getStatus, 1)
                    .orderByDesc(Loc::getId));
            for (Loc souLoc : souLocList) {
                if (entryValue<=0){
                    break;
                }
                entryValue--;
                Loc endLoc = locService.getOne(new LambdaQueryWrapper<Loc>()
                        .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                        .in(Loc::getAreaId, endLocArea)
                        .notIn(!locList.isEmpty(), Loc::getCode, locList)
                        .eq(Loc::getDeleted, 0)
                        .eq(Loc::getStatus, 1)
                        .orderByDesc(Loc::getId).last("LIMIT 1"));
                if (Cools.isEmpty(souLoc)){
                    continue;
                }
                locMove.add(new LocToTaskParams().setOrgLoc(souLoc.getCode()).setTarLoc(endLoc.getCode()));
                locList.add(endLoc.getCode());
            }
        }
        if (locMove.isEmpty()) {
            return;
        }
        for (LocToTaskParams locToTaskParams : locMove) {
        //生成移库位任务
        locItemService.genMoveTask(params, 9999L);
            try{
                locItemService.genMoveTask(locToTaskParams, 9999L);
            }catch (Exception e){
                log.error("生成移库位任务失败,请检查!!!"+locToTaskParams.toString());
            }
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java
@@ -20,6 +20,7 @@
    R genOutStock(List<DeliveryItem> ids, Long loginUserId);
    R generateWaves(GenWaveParams ids);
    R generateWavesOrderAuto(GenWaveParams ids,String stationId,String locCode);
    R saveOutStock(AsnOrderAndItemsParams params, Long loginUserId);
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -492,6 +492,7 @@
        }
        targetLoc.setUseStatus(LocStsType.LOC_STS_TYPE_S.type);
        targetLoc.setBarcode(orgLoc.getBarcode());
        if (!locService.updateById(targetLoc)) {
            throw new CoolException("目标库位预约失败!!");
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -11,6 +11,7 @@
import com.vincent.rsf.server.common.constant.Constants;
import com.vincent.rsf.server.manager.controller.dto.ExistDto;
import com.vincent.rsf.server.manager.controller.dto.OrderOutItemDto;
import com.vincent.rsf.server.manager.controller.dto.OrderOutItemPdaDto;
import com.vincent.rsf.server.manager.controller.params.*;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.entity.*;
@@ -275,6 +276,107 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R generateWavesOrderAuto(GenWaveParams params,String stationId,String locCode) {
        if (Objects.isNull(params.getIds()) || params.getIds().isEmpty()) {
            throw new CoolException("参数不能为空!!");
        }
        List<WkOrder> orders = this.list(new LambdaQueryWrapper<WkOrder>()
                .eq(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val)
                .in(WkOrder::getId, params.getIds()));
        if (orders.isEmpty()) {
            throw new CoolException("当前单据状态不能执行波次生成操作!!");
        }
        Double sum = orders.stream().mapToDouble(WkOrder::getAnfme).sum();
        Double workQty = orders.stream().mapToDouble(WkOrder::getWorkQty).sum();
        Double anfme = Math.round((sum - workQty) * 10000) / 10000.0;
        Wave wave = new Wave();
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_WAVE_TYPE, null);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("编码规则错误:请要查看「SYS_WAVE_TYPE」是否设置成功!!");
        }
        wave.setOrderNum(params.getIds().size())
                .setType(Short.parseShort("1"))
                .setCode(ruleCode)
                .setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_INIT.val)
                .setAnfme(anfme);
        if (!waveService.save(wave)) {
            throw new CoolException("波次保存失败!!");
        }
        List<Long> list = orders.stream().map(WkOrder::getId).collect(Collectors.toList());
        List<WkOrderItem> orderItems = asnOrderItemService
                .list(new LambdaQueryWrapper<WkOrderItem>()
                        .in(WkOrderItem::getOrderId, list).apply("anfme > work_qty"));
        if (orderItems.isEmpty()) {
            throw new CoolException("单据不存在!!");
        }
        //合并物料,生成波次明细
        List<WaveItem> waveItems = mergeWave(orderItems, wave);
        if (!waveItemService.saveBatch(waveItems)) {
            throw new CoolException("波次明细保存失败!!");
        }
        double sum1 = waveItems.stream().mapToDouble(WaveItem::getAnfme).sum();
        wave.setAnfme(sum1).setGroupQty(waveItems.size());
        wave.setStationId(stationId);
        wave.setLocCode(locCode);
        if (!waveService.saveOrUpdate(wave)) {
            throw new CoolException("主单修改失败!!");
        }
        for (int i = 0; i < orderItems.size(); i++) {
            orderItems.get(i).setWorkQty(orderItems.get(i).getAnfme());
        }
        /**
         *订单信息存储至逻辑关联表
         */
        for (WaveItem item : waveItems) {
            List<WkOrderItem> items = orderItems.stream()
                    .filter(orderItem -> item.getMatnrId()
                            .equals(orderItem.getMatnrId()))
                    .collect(Collectors.toList());
            items.forEach(orderItem -> {
                WaveOrderRela orderRela = new WaveOrderRela();
                orderRela.setId(null)
                        .setOrderId(orderItem.getOrderId())
                        .setOrderItemId(orderItem.getId())
                        .setWaveId(wave.getId())
                        .setWaveItemId(item.getId());
                if (!waveOrderRelaService.saveOrUpdate(orderRela)) {
                    throw new CoolException("<UNK>");
                }
            });
        }
        if (!asnOrderItemService.saveOrUpdateBatch(orderItems)) {
            throw new CoolException("出库单执行数量修改失败!!");
        }
        for (WkOrder order : orders) {
            Double wkQty = Math.round((order.getWorkQty() + order.getAnfme()) * 10000) / 10000.0;
            if (!this.update(new LambdaUpdateWrapper<WkOrder>()
                    .set(WkOrder::getWaveId, wave.getId())
                    .set(WkOrder::getWorkQty, wkQty)
                    .set(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val)
                    .eq(WkOrder::getId, order.getId()))) {
                throw new CoolException("执行状态修改修改失败!!");
            }
        }
        return R.ok("操作完成!!");
    }
    /**
     * @param
     * @return
     * @author Ryan
     * @description 生成波次
     * @time 2025/4/24 15:04
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R generateWaves(GenWaveParams params) {
        if (Objects.isNull(params.getIds()) || params.getIds().isEmpty()) {
            throw new CoolException("参数不能为空!!");
@@ -480,7 +582,15 @@
        List<Long> itemIds = new ArrayList<>();
        itemIds.add(orderItemId);
        locItems = getOutOrderList(param.getOrderId(), waveRule,itemIds);
        return R.ok(locItems);
        List<OrderOutItemPdaDto> locItemList = new ArrayList<>();
        for (OrderOutItemDto locItem : locItems) {
            for (LocItem locItem1 : locItem.getLocItemList()) {
                OrderOutItemPdaDto orderOutItemPdaDto = new OrderOutItemPdaDto();
                orderOutItemPdaDto.setLocItem(locItem1);
                locItemList.add(orderOutItemPdaDto);
            }
        }
        return R.ok(locItemList);
    }
    @Override
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -762,7 +762,7 @@
                    //移库
                    moveInStock(task, loginUserId);
                } else if (task.getTaskType().equals(TaskType.TASK_TYPE_EMPTY_IN.type)) {
                    //移库
                    //空板入库
                    complateInstockE(task, loginUserId);
                } else if (task.getTaskType().equals(TaskType.TASK_TYPE_CROSS_DOCKING_OUT.type)) {
                    //越库
@@ -930,7 +930,7 @@
        }
        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId()));
        String type = LocStsType.LOC_STS_TYPE_F.type;
        if (!taskItems.isEmpty()) {
            //移库有可能是空板
            try {
@@ -943,12 +943,14 @@
            if (!locItemService.remove(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocCode, task.getOrgLoc()))) {
                throw new CoolException("源库位明细删除失败!");
            }
        } else {
            type = LocStsType.LOC_STS_TYPE_D.type;
        }
        /**修改库位状态为F.在库*/
        if (!locService.update(new LambdaUpdateWrapper<Loc>()
                .set(Loc::getBarcode, task.getBarcode())
                .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type)
                .set(Loc::getUseStatus, type)
                .set(Loc::getUpdateBy, loginUserId)
                .set(Loc::getUpdateTime, new Date())
                .eq(Loc::getCode, task.getTargLoc()))) {
@@ -1458,7 +1460,7 @@
                    if (!task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
                        minQty = Math.round((working.getAnfme() - taskItem.getAnfme()) * 1000000) / 1000000.0;
                    }
                    if (minQty.compareTo(0.0) >= 0) {
                    if (!minQty.equals(0D) && minQty>0D) {
                        taskItem.setAnfme(minQty);
                        if (!taskItemService.updateById(taskItem)) {
                            throw new CoolException("任务明细修改失败!!");
@@ -1557,21 +1559,21 @@
            throw new CoolException("库位明细不存在!!");
        }
        List<LocItemWorking> workings = new ArrayList<>();
        for (LocItem item : locItems) {
            LocItemWorking working = new LocItemWorking();
            BeanUtils.copyProperties(item, working);
            working.setId(null)
                    .setTaskId(task.getId())
                    .setLocItemId(item.getId())
                    .setUpdateBy(loginUserId)
                    .setUpdateTime(new Date());
            workings.add(working);
        }
        if (!locItemWorkingService.saveBatch(workings)) {
            throw new CoolException("临时库存保存失败!!");
        }
//        List<LocItemWorking> workings = new ArrayList<>();
//        for (LocItem item : locItems) {
//            LocItemWorking working = new LocItemWorking();
//            BeanUtils.copyProperties(item, working);
//            working.setId(null)
//                    .setTaskId(task.getId())
//                    .setLocItemId(item.getId())
//                    .setUpdateBy(loginUserId)
//                    .setUpdateTime(new Date());
//            workings.add(working);
//        }
//
//        if (!locItemWorkingService.saveBatch(workings)) {
//            throw new CoolException("临时库存保存失败!!");
//        }
        try {
            //更新库位明细
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaveServiceImpl.java
@@ -94,7 +94,7 @@
                        .setWaveId(item.getWaveId());
                params.add(locParams);
            }
            List<OrderOutItemDto> results = LocManageUtil.getOutOrderList(params, null);
            List<OrderOutItemDto> results = LocManageUtil.getOutOrderList(params, null,waves.getStationId(),waves.getLocCode());
            generateOutTask(results, loginUserId, waves);
        } catch (Exception e) {
            log.error(e.getMessage());
@@ -161,7 +161,7 @@
                        .setWaveId(item.getWaveId());
                params.add(locParams);
            }
            List<OrderOutItemDto> results = LocManageUtil.getOutOrderList(params, waveRule);
            List<OrderOutItemDto> results = LocManageUtil.getOutOrderList(params, waveRule,wave.getStationId(),wave.getLocCode());
            if (results.isEmpty()) {
                wave.setUpdateBy(loginUserId).setUpdateTime(new Date());
                if (wave.getAnfme().compareTo(wave.getWorkQty()) == 0) {
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java
@@ -172,7 +172,7 @@
     * @param waveRule
     * @return
     */
    public static List<OrderOutItemDto> getOutOrderList(List<WaveToLocParams> params, WaveRule waveRule) {
    public static List<OrderOutItemDto> getOutOrderList(List<WaveToLocParams> params, WaveRule waveRule,String stationId,String locCode) {
        LocService locService = SpringUtils.getBean(LocService.class);
        LocItemService locItemService = SpringUtils.getBean(LocItemService.class);
        DeviceSiteService deviceSiteService = SpringUtils.getBean(DeviceSiteService.class);
@@ -203,6 +203,11 @@
            }
            for (LocItem locItem : locItems) {
                Loc loc = locService.getById(locItem.getLocId());
                if (!Cools.isEmpty(locCode) || !Cools.isEmpty(stationId)) {
                    if (!loc.getCode().equals(locCode)){
                        continue;
                    }
                }
                List<LocItem> itemList = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId()));
                if (issued.doubleValue() > 0 && locList.contains(loc)) {
@@ -243,7 +248,7 @@
                                .apply("JSON_CONTAINS(container_type, {0}) = 1", containerType.getContainerType().toString())//容器类型
                                .eq(BasStationArea::getDeleted, 0));
//                                .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", null)//区域包含站点集
                        if (!basStationAreas.isEmpty()){
                        if (!basStationAreas.isEmpty() && Cools.isEmpty(stationId)){
                            List<String> targSiteAreaList = new ArrayList<>();
                            for (BasStationArea basStationArea : basStationAreas) {
                                if (basStationArea.getStationAliasStaNo().isEmpty()){
@@ -317,6 +322,40 @@
                                issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                                break;
                            }
                        } else if (!Cools.isEmpty(stationId)){
                            BasStationService basStationService = SpringUtils.getBean(BasStationService.class);
                            BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, stationId));
                            if (Objects.isNull(basStation)) {
                                throw new CoolException("绑定站點不存在!!");
                            }
                            List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                    .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
                                    .eq(!Objects.isNull(loc.getAreaId()), DeviceSite::getAreaIdStart, loc.getAreaId())
                                    .eq( DeviceSite::getSite, stationId)
                                    .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);
                                orderOutItemDto.setSiteNo(basStation.getStationName());
                            } else {
                                throw new CoolException("未找到符合条件站点路径!!!请检查路径管理!!!");
                            }
                            orderOutItemDto.setSource(item.getItemId().toString())
                                    .setTargSiteAreaList(new ArrayList<>())
                                    .setSourceId(item.getWaveId().toString());
                            list.add(orderOutItemDto);
                            locList.add(loc);
                            issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                        } else {
                            List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                                    .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel())
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/FlowStepInstanceController.java
@@ -74,6 +74,16 @@
        return R.ok("Update Success").add(flowStepInstance);
    }
    @PreAuthorize("hasAuthority('manager:task:update')")
    @OperationLog("Jump Current 子流程步骤实例")
    @PostMapping("/flowStepInstance/jumpCurrent/{id}")
    public R jumpCurrent(@PathVariable("id") Long id) {
        if (!flowStepInstanceService.jumpCurrent(id)) {
            return R.error("跳转异常");
        }
        return R.ok("跳转成功").add(id);
    }
    @PreAuthorize("hasAuthority('manager:task:remove')")
    @OperationLog("Delete 子流程步骤实例")
    @PostMapping("/flowStepInstance/remove/{ids}")
rsf-server/src/main/java/com/vincent/rsf/server/system/service/FlowStepInstanceService.java
@@ -5,4 +5,6 @@
public interface FlowStepInstanceService extends IService<FlowStepInstance> {
    boolean jumpCurrent(Long id);
}
rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/FlowStepInstanceServiceImpl.java
@@ -1,12 +1,102 @@
package com.vincent.rsf.server.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.server.manager.entity.Task;
import com.vincent.rsf.server.manager.service.TaskService;
import com.vincent.rsf.server.system.entity.FlowInstance;
import com.vincent.rsf.server.system.mapper.FlowStepInstanceMapper;
import com.vincent.rsf.server.system.entity.FlowStepInstance;
import com.vincent.rsf.server.system.service.FlowInstanceService;
import com.vincent.rsf.server.system.service.FlowStepInstanceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@Service("flowStepInstanceService")
public class FlowStepInstanceServiceImpl extends ServiceImpl<FlowStepInstanceMapper, FlowStepInstance> implements FlowStepInstanceService {
    @Autowired
    private TaskService taskService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean jumpCurrent(Long id) {
        try{
            FlowStepInstance flowStepInstance = getById(id);
            if (flowStepInstance == null || flowStepInstance.getFlowInstanceId() == null) {
                return false;
            }
            Date now = new Date();
            String taskNo = flowStepInstance.getTaskNo();
            Task one = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, taskNo));
            //检测当前步骤
            FlowStepInstance flowStepInstanceNow = getOne(new LambdaQueryWrapper<FlowStepInstance>()
                    .eq(FlowStepInstance::getWmsNowTaskStatus, one.getTaskStatus())
                    .eq(FlowStepInstance::getTaskNo, taskNo)
                    .eq(FlowStepInstance::getFlowInstanceNo, flowStepInstance.getFlowInstanceNo())
                    .ge(FlowStepInstance::getStatus, (short) 1)
                    .ne(FlowStepInstance::getStatus, (short) 3).last("limit 1"));
            if (flowStepInstanceNow == null) {
                return false;
            }
            int stepOrderDifference = flowStepInstanceNow.getStepOrder() - flowStepInstance.getStepOrder();
            if (stepOrderDifference>0) {//回退
                for (int i = 1; i <= stepOrderDifference; i++) {
                    FlowStepInstance flowStepInstanceUpdate = getOne(new LambdaQueryWrapper<FlowStepInstance>()
                            .eq(FlowStepInstance::getTaskNo, taskNo)
                            .eq(FlowStepInstance::getStepOrder, flowStepInstance.getStepOrder()+i)
                            .eq(FlowStepInstance::getFlowInstanceNo, flowStepInstance.getFlowInstanceNo())
                            .last("limit 1"));
                    if (flowStepInstanceUpdate==null) {
                        return false;
                    }
                    flowStepInstanceUpdate.setStatus((short)0);
                    flowStepInstanceUpdate.setErrorMessage(flowStepInstanceUpdate.getErrorMessage()+now+"人工调整;");
                    flowStepInstanceUpdate.setErrorCode(now.toString());
                    flowStepInstanceUpdate.setUpdateTime(now);
                    updateById(flowStepInstanceUpdate);
                }
            } else if (stepOrderDifference<0) {//跳转
                for (int i = 1; i <= -stepOrderDifference; i++) {
                    FlowStepInstance flowStepInstanceUpdate = getOne(new LambdaQueryWrapper<FlowStepInstance>()
                            .eq(FlowStepInstance::getTaskNo, taskNo)
                            .eq(FlowStepInstance::getStepOrder, flowStepInstance.getStepOrder()-i)
                            .eq(FlowStepInstance::getFlowInstanceNo, flowStepInstance.getFlowInstanceNo())
                            .last("limit 1"));
                    if (flowStepInstanceUpdate==null) {
                        return false;
                    }
                    flowStepInstanceUpdate.setStatus((short)3);
                    flowStepInstanceUpdate.setErrorMessage(flowStepInstanceUpdate.getErrorMessage()+now+"人工调整;");
                    flowStepInstanceUpdate.setErrorCode(now.toString());
                    flowStepInstanceUpdate.setUpdateTime(now);
                    updateById(flowStepInstanceUpdate);
                }
            }
            flowStepInstance.setErrorMessage(flowStepInstance.getErrorMessage()+now+"人工调整;");
            flowStepInstance.setErrorCode(now.toString());
            flowStepInstance.setUpdateTime(now);
            flowStepInstance.setStatus((short)1);
            updateById(flowStepInstance);
            one.setTaskStatus(flowStepInstance.getWmsNowTaskStatus());
            taskService.updateById(one);
        } catch (Exception e) {
            throw new RuntimeException("人工调整出错:" + e);
        }
//        FlowInstance flowInstance = new FlowInstance();
//        flowInstance.setId(flowStepInstance.getFlowInstanceId());
//        flowInstance.setCurrentStepCode(flowStepInstance.getStepCode());
//        flowInstance.setCurrentStepOrder(flowStepInstance.getStepOrder());
//        flowInstance.setUpdateTime(new java.util.Date());
//        flowInstanceService.updateById(flowInstance);
        return true;
    }
}