package com.vincent.rsf.server.manager.service.impl; 
 | 
  
 | 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 
 | 
import com.vincent.rsf.framework.exception.CoolException; 
 | 
import com.vincent.rsf.server.api.controller.erp.params.TaskInParam; 
 | 
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto; 
 | 
import com.vincent.rsf.server.api.service.WcsService; 
 | 
import com.vincent.rsf.server.api.utils.LocUtils; 
 | 
import com.vincent.rsf.server.common.constant.Constants; 
 | 
import com.vincent.rsf.server.manager.controller.params.CheckLocQueryParams; 
 | 
import com.vincent.rsf.server.manager.controller.params.LocToTaskParams; 
 | 
import com.vincent.rsf.server.manager.entity.*; 
 | 
import com.vincent.rsf.server.manager.enums.*; 
 | 
import com.vincent.rsf.server.manager.mapper.LocItemMapper; 
 | 
import com.vincent.rsf.server.manager.service.*; 
 | 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
 | 
import com.vincent.rsf.server.system.constant.SerialRuleCode; 
 | 
import com.vincent.rsf.server.system.utils.SerialRuleUtils; 
 | 
import lombok.Synchronized; 
 | 
import org.apache.commons.lang3.StringUtils; 
 | 
import org.slf4j.Logger; 
 | 
import org.slf4j.LoggerFactory; 
 | 
import org.springframework.beans.BeanUtils; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
import org.springframework.stereotype.Service; 
 | 
import org.springframework.transaction.annotation.Transactional; 
 | 
  
 | 
import java.util.*; 
 | 
import java.util.stream.Collectors; 
 | 
  
 | 
@Service("locItemService") 
 | 
public class LocItemServiceImpl extends ServiceImpl<LocItemMapper, LocItem> implements LocItemService { 
 | 
  
 | 
    Logger logger = LoggerFactory.getLogger(LocItemServiceImpl.class); 
 | 
  
 | 
    @Autowired 
 | 
    private LocService locService; 
 | 
    @Autowired 
 | 
    private TaskService taskService; 
 | 
    @Autowired 
 | 
    private TaskItemService taskItemService; 
 | 
    @Autowired 
 | 
    private LocItemService locItemService; 
 | 
    @Autowired 
 | 
    private DeviceSiteService deviceSiteService; 
 | 
    @Autowired 
 | 
    private WcsService wcsService; 
 | 
    @Autowired 
 | 
    private OutStockService outStockService; 
 | 
    @Autowired 
 | 
    private WaveService waveService; 
 | 
    @Autowired 
 | 
    private BasStationService basStationService; 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 库存出库生成出库任务 
 | 
     * type: check 盘点, stock: 库存出库 
 | 
     * 
 | 
     * @param resouce 
 | 
     * @param map 
 | 
     * @param loginUserId 
 | 
     * @return 
 | 
     */ 
 | 
    @Override 
 | 
    @Synchronized 
 | 
    @Transactional(rollbackFor = Exception.class) 
 | 
    public void generateTask(Short resouce, LocToTaskParams map, Long loginUserId) throws Exception { 
 | 
        if (Objects.isNull(map.getSiteNo())) { 
 | 
            throw new CoolException("站点不能为空!"); 
 | 
        } 
 | 
        if (Objects.isNull(map.getItems()) || map.getItems().isEmpty()) { 
 | 
            throw new CoolException("明细不能为空!"); 
 | 
        } 
 | 
        String siteNo = map.getSiteNo(); 
 | 
        List<LocItem> items = map.getItems(); 
 | 
        Map<Long, List<LocItem>> listMap = items.stream().collect(Collectors.groupingBy(LocItem::getLocId)); 
 | 
        WkOrder order; 
 | 
        Wave wave; 
 | 
        if (!Objects.isNull(map.getSourceId())) { 
 | 
            if (map.getType().equals(Constants.TASK_TYPE_WAVE_OUT_STOCK)) { 
 | 
                order = new WkOrder(); 
 | 
                wave = waveService.getById(map.getSourceId()); 
 | 
            } else { 
 | 
                wave = new Wave(); 
 | 
                order = outStockService.getById(map.getSourceId()); 
 | 
            } 
 | 
        } else { 
 | 
            wave = new Wave(); 
 | 
            order = new WkOrder(); 
 | 
        } 
 | 
  
 | 
        listMap.keySet().forEach(key -> { 
 | 
            Task task = new Task(); 
 | 
            Loc loc = locService.getById(key); 
 | 
            logger.info("库位:>{}", loc.getCode()); 
 | 
            if (Objects.isNull(loc)) { 
 | 
                throw new CoolException("数据错误:所选库存信息不存在!!"); 
 | 
            } 
 | 
            if (!loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) { 
 | 
                throw new CoolException("库位:" + loc.getCode() + ",不处于F.在库状态,不可执行R.出库预约操作!!"); 
 | 
            } 
 | 
  
 | 
            loc.setUseStatus(LocStsType.LOC_STS_TYPE_R.type); 
 | 
  
 | 
            if (!locService.updateById(loc)) { 
 | 
                throw new CoolException("库位状态更新失败!!"); 
 | 
            } 
 | 
            Task moveTask = new Task(); 
 | 
            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null); 
 | 
            task.setOrgLoc(loc.getCode()) 
 | 
                    .setTaskCode(ruleCode) 
 | 
                    .setResource(resouce) 
 | 
                    .setTargSite(siteNo) 
 | 
                    .setSort(Constants.TASK_SORT_DEFAULT_VALUE) 
 | 
                    .setUpdateBy(loginUserId) 
 | 
                    .setCreateBy(loginUserId) 
 | 
                    .setCreateTime(new Date()) 
 | 
                    .setUpdateTime(new Date()) 
 | 
                    .setTaskStatus(TaskStsType.GENERATE_OUT.id) 
 | 
                    .setBarcode(loc.getBarcode()) 
 | 
                    .setMemo(map.getMemo()); 
 | 
  
 | 
            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 (map.getType().equals(Constants.TASK_TYPE_OUT_STOCK) 
 | 
                    || map.getType().equals(Constants.TASK_TYPE_ORDER_OUT_STOCK) 
 | 
                    || map.getType().equals(Constants.TASK_TYPE_WAVE_OUT_STOCK)) { 
 | 
                if (orgQty.compareTo(outQty) > 0) { 
 | 
                    //拣料出库 -- 盘点出库 
 | 
                    DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>() 
 | 
                            .eq(DeviceSite::getSite, siteNo) 
 | 
                            .eq(!Objects.isNull(loc.getChannel()),DeviceSite::getChannel, loc.getChannel()) 
 | 
                            .eq(DeviceSite::getType, TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)); 
 | 
                    if (Objects.isNull(deviceSite)) { 
 | 
                        throw new CoolException("站点不支持拣料出库!!"); 
 | 
                    } 
 | 
                    task.setTaskType(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type).setWarehType(deviceSite.getDevice()); 
 | 
                } else { 
 | 
                    //全板出库 
 | 
                    DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>() 
 | 
                            .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel()) 
 | 
                            .eq(DeviceSite::getSite, siteNo).eq(DeviceSite::getType, TaskType.TASK_TYPE_OUT.type)); 
 | 
                    if (Objects.isNull(deviceSite)) { 
 | 
                        throw new CoolException("站点不支持全板出库!!"); 
 | 
                    } 
 | 
                    task.setTaskType(TaskType.TASK_TYPE_OUT.type).setWarehType(deviceSite.getDevice()); 
 | 
  
 | 
                } 
 | 
            } else if (map.getType().equals(Constants.TASK_TYPE_OUT_CHECK)) { 
 | 
                //盘点出库 
 | 
                DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>() 
 | 
                        .eq(!Objects.isNull(loc.getChannel()), DeviceSite::getChannel, loc.getChannel()) 
 | 
                        .eq(DeviceSite::getSite, siteNo) 
 | 
                        .eq(DeviceSite::getType, TaskType.TASK_TYPE_CHECK_OUT.type)); 
 | 
                if (Objects.isNull(deviceSite)) { 
 | 
                    throw new CoolException("当前站点不支持盘点出库!!"); 
 | 
                } 
 | 
                task.setTaskType(TaskType.TASK_TYPE_CHECK_OUT.type).setWarehType(deviceSite.getDevice()); 
 | 
            } 
 | 
  
 | 
            if (!taskService.save(task)) { 
 | 
                throw new CoolException("任务创建失败!!"); 
 | 
            } 
 | 
  
 | 
            if (!LocUtils.isShallowLoc(loc.getCode())) { 
 | 
                //获取深库位对应浅库位 
 | 
                String shallowLoc = LocUtils.getShallowLoc(loc.getCode()); 
 | 
                Loc one = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, shallowLoc)); 
 | 
                if (Objects.isNull(one)) { 
 | 
                    throw new CoolException("对应库位不存在!!"); 
 | 
                } 
 | 
                Task workTask = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, one.getBarcode())); 
 | 
                if (Objects.isNull(workTask)) { 
 | 
                    map.setOrgLoc(one.getCode()); 
 | 
                    //优先生成移库任务 
 | 
                    if (one.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) { 
 | 
                        moveTask = genMoveTask(map, loginUserId); 
 | 
                    } 
 | 
                } else { 
 | 
                    workTask.setSort(task.getSort() + 1).setParentId(task.getId()); 
 | 
                    if (!taskService.updateById(workTask)) { 
 | 
                        throw new CoolException("优先级修改失败!!"); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
  
 | 
            if (!Objects.isNull(moveTask.getId())) { 
 | 
                moveTask.setParentId(task.getId()).setSort(moveTask.getSort() + 1); 
 | 
                if (!taskService.saveOrUpdate(moveTask)) { 
 | 
                    throw new CoolException("任务信息修改失败!!"); 
 | 
                } 
 | 
                task.setParentId(moveTask.getId()); 
 | 
                if (!taskService.updateById(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()) 
 | 
                        .setUpdateBy(loginUserId) 
 | 
                        .setCreateBy(loginUserId) 
 | 
                        .setCreateTime(new Date()) 
 | 
                        .setUpdateTime(new Date()) 
 | 
                        .setOrderType(OrderType.ORDER_OUT.type); 
 | 
                if (map.getType().equals(Constants.TASK_TYPE_ORDER_OUT_STOCK)) { 
 | 
                    taskItem.setWkType(Short.parseShort(order.getWkType())) 
 | 
                            .setSourceCode(order.getCode()) 
 | 
                            .setSourceId(order.getId()); 
 | 
                } else if (map.getType().equals(Constants.TASK_TYPE_WAVE_OUT_STOCK)) { 
 | 
                    taskItem.setSourceId(wave.getId()) 
 | 
                            .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_OTHER.type)) 
 | 
                            .setSourceCode(wave.getCode()) 
 | 
                            .setSource(item.getSource()); 
 | 
                } else if (map.getType().equals(Constants.TASK_TYPE_OUT_CHECK) || map.getType().equals(Constants.TASK_TYPE_OUT_STOCK)) { 
 | 
                    taskItem.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type)) 
 | 
                            .setSource(item.getId()) 
 | 
                            .setSourceId(item.getLocId()) 
 | 
                            .setSourceCode(item.getLocCode()); 
 | 
                } 
 | 
                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 (item.getOutQty().compareTo(0.0) < 0) { 
 | 
                    throw new CoolException("出库数里不能小于0!!"); 
 | 
                } 
 | 
  
 | 
                if (locItem.getAnfme().compareTo(qty) < 0) { 
 | 
                    Double minusQty = Math.round((locItem.getAnfme() - locItem.getWorkQty()) * 10000) / 10000.0; 
 | 
                    item.setWorkQty(minusQty); 
 | 
                } else { 
 | 
                    item.setWorkQty(qty); 
 | 
                } 
 | 
                item.setUpdateBy(loginUserId).setUpdateTime(new Date()); 
 | 
  
 | 
                if (!locItemService.updateById(item)) { 
 | 
                    throw new CoolException("库存信息修改失败!!"); 
 | 
                } 
 | 
            }); 
 | 
  
 | 
            if (!taskItemService.saveBatch(taskItems)) { 
 | 
                throw new CoolException("任务明细生成失败!!"); 
 | 
            } 
 | 
        }); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 生成移库任务 
 | 
     * 
 | 
     * @param map 
 | 
     * @param loginUserId 
 | 
     * @return 
 | 
     */ 
 | 
    @Override 
 | 
    @Transactional(rollbackFor = Exception.class) 
 | 
    public Task genMoveTask(LocToTaskParams map, Long loginUserId) { 
 | 
        if (Objects.isNull(map.getOrgLoc()) || StringUtils.isBlank(map.getOrgLoc())) { 
 | 
            throw new CoolException("源库位不能为空!"); 
 | 
        } 
 | 
        Loc orgLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, map.getOrgLoc())); 
 | 
        if (Objects.isNull(orgLoc)) { 
 | 
            throw new CoolException("源库位不存在!!"); 
 | 
        } 
 | 
//        if (orgLoc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_R.type) 
 | 
//                || orgLoc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_S.type) 
 | 
//                || orgLoc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_X.type ) ) { 
 | 
//            throw new CoolException("源库位有任务正在执行中..."); 
 | 
//        } 
 | 
        orgLoc.setUseStatus(LocStsType.LOC_STS_TYPE_R.type); 
 | 
  
 | 
        if (!locService.updateById(orgLoc)) { 
 | 
            throw new CoolException("出库预约失败!!"); 
 | 
        } 
 | 
  
 | 
        Loc targetLoc; 
 | 
        if (Objects.isNull(map.getTarLoc()) || StringUtils.isBlank(map.getTarLoc())) { 
 | 
            //目标库位为空,自动获取新库位 
 | 
            DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>() 
 | 
                    .eq(DeviceSite::getType, TaskType.TASK_TYPE_LOC_MOVE.type) 
 | 
                    .eq(!Objects.isNull(orgLoc.getChannel()), DeviceSite::getChannel, orgLoc.getChannel()), false); 
 | 
            if (Objects.isNull(deviceSite)) { 
 | 
                throw new CoolException("站点信息不存在!!"); 
 | 
            } 
 | 
            TaskInParam param = new TaskInParam(); 
 | 
            param.setIoType(TaskType.TASK_TYPE_OUT.type) 
 | 
                    .setOrgLoc(map.getOrgLoc()) 
 | 
                    .setSourceStaNo(deviceSite.getSite()) 
 | 
                    .setLocType1(Integer.parseInt(orgLoc.getType()) 
 | 
                    ); 
 | 
            InTaskMsgDto locNo; 
 | 
            try { 
 | 
                locNo = wcsService.getLocNo(param); 
 | 
            } catch (Exception e) { 
 | 
                log.error("<UNK>", e); 
 | 
                throw new CoolException(e.getMessage()); 
 | 
            } 
 | 
            targetLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locNo.getLocNo())); 
 | 
        } else { 
 | 
            targetLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, map.getTarLoc())); 
 | 
        } 
 | 
  
 | 
        if (Objects.isNull(targetLoc)) { 
 | 
            throw new CoolException("目标库位不存在!!"); 
 | 
        } 
 | 
  
 | 
        targetLoc.setUseStatus(LocStsType.LOC_STS_TYPE_S.type); 
 | 
  
 | 
        if (!locService.updateById(targetLoc)) { 
 | 
            throw new CoolException("目标库位预约失败!!"); 
 | 
        } 
 | 
  
 | 
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null); 
 | 
        Task task = new Task(); 
 | 
        task.setOrgLoc(orgLoc.getCode()) 
 | 
                .setTaskCode(ruleCode) 
 | 
                .setTaskType(TaskType.TASK_TYPE_LOC_MOVE.type) 
 | 
                .setTargLoc(targetLoc.getCode()) 
 | 
                .setUpdateBy(loginUserId) 
 | 
                .setSort(Constants.TASK_SORT_DEFAULT_VALUE) 
 | 
                .setUpdateTime(new Date()) 
 | 
                .setTaskStatus(TaskStsType.GENERATE_IN.id) 
 | 
                .setBarcode(orgLoc.getBarcode()) 
 | 
                .setMemo(map.getMemo()); 
 | 
  
 | 
        if (!taskService.save(task)) { 
 | 
            throw new CoolException("新建移库任务失败!!"); 
 | 
        } 
 | 
  
 | 
        List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, orgLoc.getId())); 
 | 
        if (!locItems.isEmpty()) { 
 | 
            List<TaskItem> taskItems = new ArrayList<>(); 
 | 
            for (LocItem item : locItems) { 
 | 
                TaskItem taskItem = new TaskItem(); 
 | 
                BeanUtils.copyProperties(item, taskItem); 
 | 
                taskItem.setTaskId(task.getId()) 
 | 
                        .setAnfme(item.getAnfme()) 
 | 
                        .setBatch(item.getBatch()) 
 | 
                        .setUpdateBy(loginUserId) 
 | 
                        .setSourceId(item.getLocId()) 
 | 
                        .setSourceCode(item.getLocCode()) 
 | 
                        .setSource(item.getId()) 
 | 
                        .setUpdateTime(new Date()) 
 | 
                        .setOrderType(OrderType.ORDER_IN.type) 
 | 
                        .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type)); 
 | 
                taskItems.add(taskItem); 
 | 
            } 
 | 
            if (!taskItemService.saveBatch(taskItems)) { 
 | 
                throw new CoolException("任务明细生成失败!!"); 
 | 
            } 
 | 
        } 
 | 
        return task; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @author Ryan 
 | 
     * @date 2025/7/16 
 | 
     * @description: 获取当前物料所有库存信息 
 | 
     * @version 1.0 
 | 
     */ 
 | 
    @Override 
 | 
    public List<LocItem> listByMatnr(CheckLocQueryParams matnr) { 
 | 
        LambdaQueryWrapper<LocItem> wrapper = new LambdaQueryWrapper<LocItem>() 
 | 
                .eq(StringUtils.isNotBlank(matnr.getLocCode()), LocItem::getLocCode, matnr.getLocCode()) 
 | 
//                .eq(StringUtils.isNotBlank(matnr.getChannel()), LocItem::getChannel, matnr.getChannel()) 
 | 
                .in(!matnr.getMatnrCode().isEmpty(), LocItem::getMatnrCode, matnr.getMatnrCode()); 
 | 
        return  this.baseMapper.listByMatnr(LocStsType.LOC_STS_TYPE_F.type, matnr.getChannel(), wrapper); 
 | 
    } 
 | 
} 
 |