package com.vincent.rsf.server.api.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.framework.exception.CoolException; import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto; import com.vincent.rsf.server.api.entity.dto.LocTypeDto; import com.vincent.rsf.server.api.controller.params.TaskInParam; import com.vincent.rsf.server.api.entity.enums.OrderType; import com.vincent.rsf.server.api.entity.enums.TaskStsType; import com.vincent.rsf.server.api.entity.enums.TaskType; import com.vincent.rsf.server.api.service.WcsService; import com.vincent.rsf.server.api.utils.LocUtils; import com.vincent.rsf.server.api.utils.SlaveProperties; import com.vincent.rsf.server.manager.entity.*; import com.vincent.rsf.server.manager.enums.PakinIOStatus; import com.vincent.rsf.server.manager.service.*; import com.vincent.rsf.server.manager.service.impl.LocServiceImpl; import com.vincent.rsf.server.manager.utils.LocManageUtil; import com.vincent.rsf.server.system.constant.SerialRuleCode; import com.vincent.rsf.server.system.enums.LocStsType; import com.vincent.rsf.server.system.utils.SerialRuleUtils; import org.apache.commons.lang3.StringUtils; 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.Objects; @Service public class WcsServiceImpl implements WcsService { @Autowired private DeviceSiteService deviceSiteService; @Autowired private WaitPakinService waitPakinService; @Autowired private DeviceBindService deviceBindService; @Autowired private LocServiceImpl locService; @Autowired private LocItemService locItemService; @Autowired private SlaveProperties slaveProperties; @Autowired private WarehouseAreasService warehouseAreasService; @Autowired private TaskService taskService; @Autowired private TaskItemService taskItemService; @Autowired private WaitPakinItemService waitPakinItemService; @Override public InTaskMsgDto createInTask(TaskInParam param, Long loginUserId) { InTaskMsgDto locNo = getLocNo(param); DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper() .eq(DeviceSite::getSite, param.getSourceStaNo()) .eq(DeviceSite::getType,param.getIoType()) ); if (Objects.isNull(deviceSite)) { throw new CoolException("站点不存在!!"); } WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper() .eq(WaitPakin::getBarcode, param.getBarcode()) .eq(WaitPakin::getIoStatus, Short.parseShort(PakinIOStatus.PAKIN_IO_STATUS_DONE.val))); if (Cools.isEmpty(waitPakin)) { throw new CoolException("请检查组拖状态是否完成!!"); } List taskItems = new ArrayList<>(); String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null); if (StringUtils.isBlank(ruleCode)) { throw new CoolException("编码错误:请确认编码「SYS_TASK_CODE」是否已生成!!"); } Task task = new Task(); task.setTaskCode(ruleCode) .setTaskStatus(TaskStsType.GENERATE_IN.id.shortValue()) .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue()) .setTargLoc(locNo.getLocNo()) .setBarcode(waitPakin.getBarcode()) .setTargSite(deviceSite.getDeviceSite()) .setCreateBy(loginUserId) .setUpdateBy(loginUserId) .setOrgSite(param.getSourceStaNo().toString()); if (!taskService.save(task)) { throw new CoolException("任务保存失败!!"); } if (!locService.update(new LambdaUpdateWrapper().eq(Loc::getCode, task.getTargLoc()) .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_S.type).set(Loc::getBarcode, waitPakin.getBarcode()))) { throw new CoolException("库位预约失败!!"); } /**获取组拖明细**/ List waitPakinItems = waitPakinItemService.list(new LambdaQueryWrapper().eq(WaitPakinItem::getPakinId, waitPakin.getId())); if (waitPakinItems.isEmpty()) { throw new CoolException("数据错误:组拖明细不存在"); } waitPakinItems.forEach(item -> { TaskItem taskItem = new TaskItem(); BeanUtils.copyProperties(item, taskItem); // AsnOrder order = asnOrderService.getOne(new LambdaQueryWrapper().eq(AsnOrder::getId, item.getAsnId())); // if (Objects.isNull(order)) { // throw new CoolException("数据错误: 单据不存在!!"); // } taskItem.setTaskId(task.getId()) .setOrderType(OrderType.ORDER_RECEIPT.type) .setSource(item.getId()) .setTrackCode(item.getTrackCode()) .setCreateBy(loginUserId) .setUpdateBy(loginUserId) .setOrderId(item.getAsnId()) .setOrderItemId(item.getAsnItemId()); taskItems.add(taskItem); }); if (!taskItemService.saveBatch(taskItems)) { throw new CoolException("任务明细保存失败!!"); } if (!waitPakinService.update(new LambdaUpdateWrapper() .eq(WaitPakin::getBarcode, param.getBarcode()) .set(WaitPakin::getUpdateBy, loginUserId) .set(WaitPakin::getCreateBy, loginUserId) .set(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val))) { throw new CoolException("组托状态修改失败!!"); } locNo.setWorkNo(ruleCode); return locNo; } public InTaskMsgDto getLocNo(TaskInParam param) { String matnr = null; String batch = null; List waitPakins = waitPakinService.list(new LambdaQueryWrapper().eq(WaitPakin::getBarcode, param.getBarcode())); if (Cools.isEmpty(waitPakins) && param.getIoType().equals(TaskType.TASK_TYPE_IN.type)) { throw new CoolException("未找到组托信息,请组托"); }else if (!Cools.isEmpty(waitPakins)) { matnr = waitPakins.get(0).getCode(); batch = waitPakins.get(0).getCode(); } List deviceSites = deviceSiteService.list(new LambdaQueryWrapper() .eq(DeviceSite::getSite, param.getSourceStaNo()) .eq(DeviceSite::getType,param.getIoType()) ); if (Cools.isEmpty(deviceSites)) { throw new CoolException("未找到站点路径信息"); } WarehouseAreas warehouseArea = warehouseAreasService.getById(param.getArea()); if (Cools.isEmpty(warehouseArea)) { throw new CoolException("未找到所属库区信息"); } LocTypeDto locTypeDto = new LocTypeDto(param); InTaskMsgDto dto = null; switch (warehouseArea.getType()) { case "CRN": //堆垛机 dto = getLocNoCrn(param.getArea(), param.getSourceStaNo(), matnr,batch, locTypeDto, 0, param.getIoType()); break; case "SXC": //四向库 break; case "CTU": //四向库 break; } return dto; } private InTaskMsgDto getLocNoCrn(Integer area,Integer sourceStaNo, String matnr, String batch,LocTypeDto locTypeDto, int times,Integer ioType){ if (Cools.isEmpty(matnr)) { //物料号 matnr = ""; } if (Cools.isEmpty(batch)) { //批次 batch = ""; } // 初始化参数 int deviceNo = 0; //堆垛机号 int nearRow = 0; //最浅库位排 int curRow = 0; //最深库位排 int rowCount = 0; //轮询轮次 Loc loc = null; // 目标库位 InTaskMsgDto inTaskMsgDto = new InTaskMsgDto(); DeviceBind deviceBind = deviceBindService.getById(LocUtils.getAreaType(sourceStaNo)); if (Cools.isEmpty(deviceBind)) { throw new CoolException("数据异常,请联系管理员===>库位规则未知"); } int sRow = deviceBind.getStartRow(); int eRow = deviceBind.getEndRow(); int deviceQty = deviceBind.getDeviceQty(); // ===============>>>> 开始执行 curRow = deviceBind.getCurrentRow(); //此程序用于优化堆垛机异常时的运行时间 for (int i = times; i <= deviceQty * 2; i++) { int[] locNecessaryParameters = LocUtils.LocNecessaryParameters(deviceBind, curRow, deviceQty); curRow = locNecessaryParameters[1]; deviceNo = locNecessaryParameters[2]; rowCount = locNecessaryParameters[0]; nearRow = locNecessaryParameters[3]; break; } if (nearRow == 0) { throw new CoolException("无可用堆垛机"); } //入库靠近摆放 if (ioType== 1 && deviceBind.getBeSimilar().equals("1") && !Cools.isEmpty(matnr)) { if (nearRow != curRow) { List locItems = locItemService.list(new LambdaQueryWrapper().eq(LocItem::getMatnrCode, matnr)); for (LocItem locItem : locItems) { Loc loc1 = locService.getById(locItem.getLocId()); if (LocUtils.isShallowLoc(slaveProperties, loc1.getCode())) { continue; } String shallowLocNo = LocUtils.getShallowLoc(slaveProperties, loc1.getCode()); // 检测目标库位是否为空库位 Loc shallowLoc = locService.getOne(new LambdaQueryWrapper().eq(Loc::getCode,shallowLocNo)); if (shallowLoc != null && shallowLoc.getUseStatus().equals("O")) { if (LocUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) { loc = shallowLoc; deviceNo = shallowLoc.getDeviceNo(); break; } } } } } // // 靠近摆放规则 --- 空托 //互通版 // if (ioType == 10 && deviceBind.getEmptySimilar().equals("1")) { // List locMasts = locMastService.selectList(new EntityWrapper() // .eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow).eq("whs_type", rowLastnoType.getType().longValue())); // if (!locMasts.isEmpty()) { // for (LocMast loc : locMasts) { // if (Utils.isShallowLoc(slaveProperties, loc.getLocNo())) { // continue; // } // String shallowLocNo = Utils.getShallowLoc(slaveProperties, loc.getLocNo()); // // 检测目标库位是否为空库位 // LocMast shallowLoc = locMastService.selectById(shallowLocNo); // if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) { // if (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) { // if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) { // locMast = shallowLoc; // crnNo = locMast.getCrnNo(); // break; // } // } // } // } // } // } //查找路径 DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper() .eq(DeviceSite::getType, ioType) .eq(DeviceSite::getSite, sourceStaNo) .eq(DeviceSite::getDeviceCode, deviceNo) ); if (Cools.isEmpty(deviceSite)){ deviceNo = 0; }else { inTaskMsgDto.setStaNo(Integer.parseInt(deviceSite.getDeviceSite())); } //更新当前排 deviceBind.setCurrentRow(curRow); deviceBindService.updateById(deviceBind); // 开始查找库位 ==============================>> // 1.按规则查找库位 if (Cools.isEmpty(loc) && deviceNo != 0) { List locMasts = null; locMasts = locService.list(new LambdaQueryWrapper() .eq(Loc::getRow, nearRow) .eq(Loc::getUseStatus, "O") .eq(Loc::getType, locTypeDto.getLocType1()) .eq(Loc::getAreaId,area) .orderByAsc(Loc::getLev) .orderByAsc(Loc::getCol) ); for (Loc locMast1 : locMasts) { if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { continue; } String shallowLoc = LocUtils.getDeepLoc(slaveProperties, locMast1.getCode()); if ((ioType== 1 && deviceBind.getBeSimilar().equals("1"))) { //相似物料打开,判断深库位有没有货,没货就放深库位,有货就不操作 Loc locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getRow, shallowLoc) .eq(Loc::getUseStatus, "O") .eq(Loc::getAreaId,area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast2; break; } } else { //相似物料关闭,判断深库位有没有货,有货就放浅库位,无货就不操作 Loc locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .in(Loc::getUseStatus, "D","F") .eq(Loc::getAreaId,area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast1; break; }else{ locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .eq(Loc::getUseStatus, "O") .eq(Loc::getAreaId,area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast2; break; } } } } if (Cools.isEmpty(loc) && deviceBind.getBeSimilar().equals("1")) { for (Loc locMast1 : locMasts) { if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { continue; } if (deviceBind.getBeSimilar().equals("1")) { String shallowLoc = LocUtils.getDeepLoc(slaveProperties, locMast1.getCode()); Loc locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .eq(Loc::getUseStatus, "O") .eq(Loc::getAreaId,area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast2; break; } else { locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .in(Loc::getUseStatus, "D","F") .eq(Loc::getAreaId,area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast1; break; } } } else { if (!Cools.isEmpty(locMast1)) { loc = locMast1; break; } } } } } //查询当前库位类型空库位 小于5个则locmast = null List locTypeLocMasts = locService.list(new LambdaQueryWrapper() .eq(Loc::getUseStatus, "O") .eq(Loc::getDeviceNo, deviceNo) .eq(Loc::getType, locTypeDto.getLocType1()) .eq(Loc::getAreaId,area) ); if (null !=locTypeLocMasts && locTypeLocMasts.size()<=5){ loc = null; } // 递归查询 if (Cools.isEmpty(loc) || !loc.getUseStatus().equals("O")) { // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 if (times < rowCount * 2) { times = times + 1; return getLocNoCrn(area,sourceStaNo,matnr,batch,locTypeDto,times, ioType); } // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位 if (locTypeDto.getLocType1() < 3) { int i = locTypeDto.getLocType1() + 1; locTypeDto.setLocType1(i); return getLocNoCrn(area,sourceStaNo,matnr,batch,locTypeDto,0, ioType); } throw new CoolException("没有空库位"); } String locNo = loc.getCode(); // 返回dto inTaskMsgDto.setDeviceNo(deviceNo); inTaskMsgDto.setSourceStaNo(sourceStaNo); // inTaskMsgDto.setStaNo(); inTaskMsgDto.setLocNo(locNo); return inTaskMsgDto; } }