| 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); | 
|     } | 
| } |