| | |
| | | package com.zy.asrs.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.mapper.Wrapper; |
| | | import com.core.common.BaseRes; |
| | |
| | | import com.core.common.SnowflakeIdWorker; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.entity.param.EmptyPlateOutParam; |
| | | import com.zy.asrs.entity.param.FullStoreParam; |
| | | import com.zy.asrs.entity.param.LocDetlAdjustParam; |
| | | import com.zy.asrs.entity.param.StockOutParam; |
| | | import com.zy.asrs.entity.param.*; |
| | | import com.zy.asrs.entity.result.FindLocNoAttributeVo; |
| | | import com.zy.asrs.entity.result.WrkCancel; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.model.*; |
| | |
| | | import com.zy.common.model.enums.WorkNoType; |
| | | import com.zy.common.properties.SlaveProperties; |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import com.zy.common.web.WcsController; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.text.DateFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | private SlaveProperties slaveProperties; |
| | | @Autowired |
| | | private WaitPakinService waitPakinService; |
| | | @Autowired |
| | | private ApiLogService apiLogService; |
| | | @Value("${wcs-slave.cancel}") |
| | | private String cancel; |
| | | @Value("${wcs-slave.url}") |
| | | private String url; |
| | | @Value("${wcs-slave.warehouse}") |
| | | private String warehouse; |
| | | |
| | | @Override |
| | | @Transactional |
| | |
| | | List<String> matnrs = param.getList().stream().map(FullStoreParam.MatCodeStore::getMatnr).distinct().collect(Collectors.toList()); |
| | | // List<String> batchs = param.getList().stream().map(FullStoreParam.MatCodeStore::getBatch).distinct().collect(Collectors.toList()); |
| | | StartupDto dto = commonService.getLocNo(1, param.getDevpNo(), matnrs.get(0), null, null,locTypeDto); |
| | | if (Cools.isEmpty(dto)){ |
| | | throw new CoolException("查询库位失败!!==》startupFullPutStore ==》 commonService.getLocNo"); |
| | | } |
| | | // 生成工作号 |
| | | int workNo = dto.getWorkNo(); |
| | | // 生成工作档 |
| | |
| | | } |
| | | } |
| | | if (!locDetlDtos.isEmpty()) { |
| | | LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", locDetlDtos.get(0).getLocDetl().getLocNo())); |
| | | if (locMast.getLocSts().equals("F") || locMast.getLocSts().equals("D") ){ |
| | | // 启动出库开始 101.出库 |
| | | stockOut(staNo, locDetlDtos, null, userId); |
| | | }else { |
| | | throw new CoolException("所选库位存在状态不为F、D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$()); |
| | | } |
| | | // 启动出库开始 101.出库 |
| | | stockOut(staNo, locDetlDtos, null, userId); |
| | | } else { |
| | | throw new CoolException("库存不存在"); |
| | | } |
| | | } |
| | | private boolean isInNormalRule(LocMast lm) { |
| | | List<LocGroupOrder> locGroupAscOrder = slaveProperties.getLocGroupAscOrder(); |
| | | if (locGroupAscOrder == null || locGroupAscOrder.isEmpty()) { |
| | | return false; |
| | | } |
| | | Integer row = lm.getRow1(); |
| | | if (row == null) return false; |
| | | |
| | | return locGroupAscOrder.stream() |
| | | .anyMatch(group -> |
| | | group.getRowList() != null && |
| | | group.getRowList().contains(row) |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 检查正常库位前方是否堵塞(深库位规则:前方排是否有货或入库任务) |
| | | * |
| | | * 只对属于出库分组规则内的库位进行检查 |
| | | * 如果库位不在分组规则内,则视为不需要严格检查(返回 false,不触发补齐) |
| | | * |
| | | * @param normalMasts 需要检查的正常库位列表(已通过 isInNormalRule 过滤) |
| | | * @return true = 前方有堵塞(需要补齐),false = 前方清空或无需检查 |
| | | */ |
| | | private boolean checkDeepLocationBlocked(List<LocMast> normalMasts) { |
| | | if (normalMasts == null || normalMasts.isEmpty()) { |
| | | return false; |
| | | } |
| | | // 获取出库分组配置(用于确认规则范围) |
| | | List<LocGroupOrder> locGroupAscOrder = slaveProperties.getLocGroupAscOrder(); |
| | | if (locGroupAscOrder == null || locGroupAscOrder.isEmpty()) { |
| | | return false; // 无配置时默认不检查 |
| | | } |
| | | |
| | | // 遍历每个正常库位 |
| | | for (LocMast lm : normalMasts) { |
| | | Integer currentRow = lm.getRow1(); |
| | | Integer bay1 = lm.getBay1(); |
| | | Integer lev1 = lm.getLev1(); |
| | | |
| | | if (currentRow == null || bay1 == null || lev1 == null) { |
| | | continue; |
| | | } |
| | | |
| | | // 深库位检查方向:假设 row 越大越深(前方是更大 row 的位置) |
| | | // 你可以根据实际出库方向调整循环条件(例如从小 row 到大 row 或反之) |
| | | for (int row = currentRow + 1; row <= 5; row++) { // 假设深库位范围到 5 排,可调整 |
| | | LocMast front = getLocMastByRow(row, bay1, lev1); |
| | | if (front == null) { |
| | | continue; |
| | | } |
| | | |
| | | // 有货(F状态) → 堵塞 |
| | | if ("F".equals(front.getLocSts())) { |
| | | return true; |
| | | } |
| | | |
| | | // 有入库任务 → 堵塞 |
| | | WrkMast frontTask = wrkMastService.selectOne( |
| | | new EntityWrapper<WrkMast>() |
| | | .eq("source_loc_no", front.getLocNo()) |
| | | .eq("io_type", 100) // 假设 100 为入库类型,可调整 |
| | | ); |
| | | if (frontTask != null) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 所有正常库位前方都清空(或无前方) |
| | | return false; |
| | | } |
| | | @Override |
| | | @Transactional |
| | | public void stockOut(BasDevp staNo, List<LocDetlDto> locDetlDtos, IoWorkType ioWorkType, Long userId) { |
| | | Date now = new Date(); |
| | | // 合并同类项 |
| | | |
| | | // 保留:合并同类项(同一库位合并明细) |
| | | Set<String> locNos = new HashSet<>(); |
| | | List<OutLocDto> dtos = new ArrayList<>(); |
| | | for (LocDetlDto locDetlDto : locDetlDtos) { |
| | |
| | | dtos.add(new OutLocDto(locNo, locDetlDto)); |
| | | } |
| | | } |
| | | Integer ioType = null; |
| | | // 生成工作档 |
| | | for (OutLocDto dto : dtos) { |
| | | // 判断入出库类型:101.全板出库 or 103.拣料出库 |
| | | if (ioWorkType == null) { |
| | | ioType = dto.isAll() ? 101 : 103; |
| | | } else if (ioWorkType.equals(IoWorkType.CHECK_OUT)) { |
| | | ioType = 107; |
| | | } |
| | | assert ioType != null; |
| | | // 获取库位 |
| | | LocMast locMast = locMastService.selectById(dto.getLocNo()); |
| | | // 使用出库专用分组配置 |
| | | List<LocGroupOrder> locGroupAscOrder = slaveProperties.getLocGroupAscOrder(); |
| | | // 确定正常出库类型(和原来保持类似) |
| | | int ioTypeNormal = 101; // 默认整托出库 |
| | | if (ioWorkType != null && ioWorkType.equals(IoWorkType.CHECK_OUT)) { |
| | | ioTypeNormal = 107; |
| | | } else if (!dtos.isEmpty() && !dtos.get(0).isAll()) { |
| | | ioTypeNormal = 103; // 部分出库 |
| | | } |
| | | |
| | | // 1. 查询所有选中的库位主信息 |
| | | List<LocMast> allSelectedMasts = locMastService.selectList( |
| | | new EntityWrapper<LocMast>().in("loc_no", locNos) |
| | | ); |
| | | |
| | | if (allSelectedMasts.size() != locNos.size()) { |
| | | throw new CoolException("部分选中库位不存在或数据异常"); |
| | | } |
| | | |
| | | // 2. 区分正常库位(需要严格深库位检查)与补充库位 |
| | | List<LocMast> normalMasts = new ArrayList<>(); |
| | | List<LocMast> supplementMasts = new ArrayList<>(); |
| | | |
| | | // 假设我们有某种“分组规则”(如按列层或排范围),这里简化用一个示例判断 |
| | | // 你可以替换成实际的规则(如 getLocGroupOrderOut() 或其他) |
| | | for (LocMast lm : allSelectedMasts) { |
| | | boolean isNormal = isInNormalRule(lm); // ← 你需要实现这个判断方法 |
| | | if (isNormal) { |
| | | normalMasts.add(lm); |
| | | } else { |
| | | supplementMasts.add(lm); |
| | | } |
| | | } |
| | | |
| | | // 3. 对正常库位进行深库位前方检查(类似之前的连续段 + 清空) |
| | | AtomicReference<Boolean> isLeftSideSupplement = new AtomicReference<>(false); |
| | | |
| | | if (!normalMasts.isEmpty()) { |
| | | // 这里模拟深库位前方检查(你可以替换成你实际的检查方法) |
| | | boolean hasBlockage = checkDeepLocationBlocked(normalMasts); |
| | | |
| | | if (hasBlockage) { |
| | | // 前方堵塞 → 自动补充最少一侧 |
| | | supplementBothSidesBlocked(normalMasts, locGroupAscOrder, supplementMasts, isLeftSideSupplement); |
| | | } |
| | | } |
| | | |
| | | // 4. 合并所有要出库的库位 |
| | | List<LocMast> allMasts = new ArrayList<>(); |
| | | allMasts.addAll(normalMasts); |
| | | allMasts.addAll(supplementMasts); |
| | | |
| | | if (allMasts.isEmpty()) { |
| | | throw new CoolException("没有有效的出库库位"); |
| | | } |
| | | |
| | | // 5. 统一按排号(row)倒序排序(高排先出) |
| | | List<LocMast> sortedAll = allMasts.stream() |
| | | .sorted(Comparator.comparing(LocMast::getRow1, Comparator.reverseOrder())) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 6. 生成任务(从后往前遍历) |
| | | double basePriority = 100.0; |
| | | for (int index = sortedAll.size() - 1; index >= 0; index--) { |
| | | LocMast locMast = sortedAll.get(index); |
| | | String locNo = locMast.getLocNo(); |
| | | |
| | | boolean isSupplement = supplementMasts.contains(locMast); |
| | | int ioType = isSupplement ? 11 : ioTypeNormal; |
| | | // 优先级计算 |
| | | double priority; |
| | | if (isSupplement) { |
| | | if (Boolean.TRUE.equals(isLeftSideSupplement.get())) { |
| | | // 左侧补充 → 晚出 |
| | | priority = basePriority - index * 1.0; |
| | | } else { |
| | | // 右侧补充 → 早出 |
| | | priority = basePriority + index * 1.0; |
| | | } |
| | | } else { |
| | | priority = basePriority - index * 1.0; |
| | | } |
| | | OutLocDto dto; |
| | | Integer outSta = staNo.getDevNo(); |
| | | // //2号堆垛机全板出库站指定为204站,拣料站指定为202 |
| | | // if(locMast.getCrnNo()==2){ |
| | | // outSta = ioType == 101 ? 204 : 202; |
| | | // } |
| | | |
| | | // 获取路径 |
| | | StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), outSta); |
| | | // 生成工作号 |
| | | int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType)); |
| | | // 生成工作档 |
| | | WrkMast wrkMast = new WrkMast(); |
| | | wrkMast.setWrkNo(workNo); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID |
| | | wrkMast.setIoType(ioType); // 入出库状态 |
| | | wrkMast.setIoPri(13D); // 优先级:13 |
| | | wrkMast.setCrnNo(locMast.getCrnNo()); |
| | | wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站 |
| | | wrkMast.setStaNo(staDesc.getStnNo()); // 目标站 |
| | | wrkMast.setSourceLocNo(dto.getLocNo()); // 源库位 |
| | | wrkMast.setFullPlt("Y"); // 满板:Y |
| | | wrkMast.setPicking("N"); // 拣料 |
| | | wrkMast.setExitMk("N"); // 退出 |
| | | wrkMast.setEmptyMk("N"); // 空板 |
| | | wrkMast.setLinkMis("N"); |
| | | wrkMast.setBarcode(locMast.getBarcode()); |
| | | wrkMast.setAppeUser(userId); // 操作人员数据 |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | if (!wrkMastService.insert(wrkMast)) { |
| | | throw new CoolException("保存工作档失败,出库库位号:"+dto.getLocNo()); |
| | | StaDesc staDesc = null; |
| | | if(ioType != 11){ |
| | | staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), outSta); |
| | | } |
| | | // 生成工作档明细 |
| | | for (LocDetlDto detlDto : dto.getLocDetlDtos()) { |
| | | if (detlDto.getCount()==null || detlDto.getCount() <= 0.0D) {continue;} |
| | | WrkDetl wrkDetl = new WrkDetl(); |
| | | wrkDetl.sync(detlDto.getLocDetl()); |
| | | wrkDetl.setOrderNo(""); // 手动出库不需要带出库存中的单据编号 |
| | | wrkDetl.setWrkNo(workNo); |
| | | wrkDetl.setIoTime(now); |
| | | Double anfme = ioType==101?detlDto.getLocDetl().getAnfme():detlDto.getCount(); |
| | | wrkDetl.setAnfme(anfme); // 数量 |
| | | wrkDetl.setAppeTime(now); |
| | | wrkDetl.setAppeUser(userId); |
| | | wrkDetl.setModiTime(now); |
| | | wrkDetl.setModiUser(userId); |
| | | if (!wrkDetlService.insert(wrkDetl)) { |
| | | throw new CoolException("保存工作档明细失败"); |
| | | LocMast locMastNew = null; |
| | | WrkMast wrkMast = new WrkMast(); |
| | | String locSts; |
| | | int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType)); |
| | | String pick = (ioType == 101) ? "N" : "Y"; |
| | | if((ioType == 101 || ioType == 103 || ioType == 107) && staDesc != null) { |
| | | // 找到对应的 OutLocDto |
| | | dto = dtos.stream() |
| | | .filter(d -> d.getLocNo().equals(locNo)) |
| | | .findFirst() |
| | | .orElseThrow(() -> new CoolException("找不到对应的出库明细:" + locNo)); |
| | | // 生成工作档 |
| | | wrkMast.setWrkNo(workNo); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setWrkSts(0L); |
| | | wrkMast.setIoType(ioType); |
| | | wrkMast.setIoPri(priority); |
| | | wrkMast.setCrnNo(locMast.getCrnNo()); |
| | | wrkMast.setSourceStaNo(staDesc.getCrnStn()); |
| | | wrkMast.setStaNo(staDesc.getStnNo()); |
| | | wrkMast.setSourceLocNo(locNo); |
| | | wrkMast.setFullPlt("Y"); |
| | | wrkMast.setPicking(pick); |
| | | wrkMast.setExitMk("N"); |
| | | wrkMast.setEmptyMk("N"); |
| | | wrkMast.setLinkMis("N"); |
| | | wrkMast.setBarcode(locMast.getBarcode()); |
| | | wrkMast.setAppeUser(userId); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | locSts = ioType != 101? "R" : "P"; |
| | | // 生成工作档明细(保留原逻辑) |
| | | for (LocDetlDto detlDto : dto.getLocDetlDtos()) { |
| | | if (detlDto.getCount() == null || detlDto.getCount() <= 0.0D) { |
| | | continue; |
| | | } |
| | | WrkDetl wrkDetl = new WrkDetl(); |
| | | wrkDetl.sync(detlDto.getLocDetl()); |
| | | wrkDetl.setOrderNo(""); |
| | | wrkDetl.setWrkNo(workNo); |
| | | wrkDetl.setIoTime(now); |
| | | Double anfme = ioType == 101 ? detlDto.getLocDetl().getAnfme() : detlDto.getCount(); |
| | | wrkDetl.setAnfme(anfme); |
| | | wrkDetl.setAppeTime(now); |
| | | wrkDetl.setAppeUser(userId); |
| | | wrkDetl.setModiTime(now); |
| | | wrkDetl.setModiUser(userId); |
| | | if (!wrkDetlService.insert(wrkDetl)) { |
| | | throw new CoolException("保存工作档明细失败"); |
| | | } |
| | | } |
| | | }else{ |
| | | List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no",locNo)); |
| | | FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(); |
| | | findLocNoAttributeVo.setMatnr(locDetls.get(0).getMatnr()); |
| | | findLocNoAttributeVo.setBatch(locDetls.get(0).getBatch()); |
| | | LocTypeDto locTypeDto = new LocTypeDto(); |
| | | locTypeDto.setLocType1(locMast.getLocType1()); |
| | | locMastNew = commonService.searchMaxPallet(findLocNoAttributeVo,locTypeDto); |
| | | // 生成工作档 |
| | | wrkMast.setWrkNo(workNo); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setWrkSts(0L); |
| | | wrkMast.setIoType(ioType); |
| | | wrkMast.setIoPri(priority); |
| | | wrkMast.setCrnNo(locMast.getCrnNo()); |
| | | wrkMast.setSourceStaNo(null); |
| | | wrkMast.setStaNo(null); |
| | | wrkMast.setSourceLocNo(locNo); |
| | | wrkMast.setLocNo(locMastNew.getLocNo()); |
| | | wrkMast.setFullPlt("Y"); |
| | | wrkMast.setPicking(pick); |
| | | wrkMast.setExitMk("N"); |
| | | wrkMast.setEmptyMk("N"); |
| | | wrkMast.setLinkMis("N"); |
| | | wrkMast.setBarcode(locMast.getBarcode()); |
| | | wrkMast.setAppeUser(userId); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | locSts = "R"; |
| | | // 生成工作档明细(保留原逻辑) |
| | | if(locDetls != null && locDetls.size() > 0) { |
| | | for (LocDetl locDetl : locDetls) { |
| | | WrkDetl wrkDetl = new WrkDetl(); |
| | | wrkDetl.sync(locDetl); |
| | | wrkDetl.setWrkNo(workNo); |
| | | wrkDetl.setIoTime(now); |
| | | |
| | | wrkDetl.setAppeTime(now); |
| | | wrkDetl.setAppeUser(userId); |
| | | wrkDetl.setModiTime(now); |
| | | wrkDetl.setModiUser(userId); |
| | | if (!wrkDetlService.insert(wrkDetl)) { |
| | | throw new CoolException("保存工作档明细失败"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 修改库位状态: F.在库 ====>>> R.出库预约/P.拣料/盘点/并板出库中 |
| | | locMast = locMastService.selectById(dto.getLocNo()); |
| | | if (locMast.getLocSts().equals("F")) { |
| | | locMast.setLocSts(ioType==101?"R":"P"); |
| | | if (!wrkMastService.insert(wrkMast)) { |
| | | throw new CoolException("保存工作档失败,库位:" + locNo); |
| | | } |
| | | |
| | | if(locMastNew != null){ |
| | | if ("O".equals(locMastNew.getLocSts())) { |
| | | locMastNew.setLocSts("S"); |
| | | locMastNew.setModiUser(userId); |
| | | locMastNew.setModiTime(now); |
| | | if (!locMastService.updateById(locMastNew)) { |
| | | throw new CoolException("更新库位状态失败,库位:" + locNo); |
| | | } |
| | | } else { |
| | | throw new CoolException("库位状态异常,非空板状态:" + locNo); |
| | | } |
| | | } |
| | | // 更新库位状态 |
| | | locMast = locMastService.selectById(locNo); |
| | | if ("F".equals(locMast.getLocSts())) { |
| | | locMast.setLocSts(locSts); |
| | | locMast.setModiUser(userId); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | throw new CoolException("预约库位状态失败,库位号:"+dto.getLocNo()); |
| | | throw new CoolException("预约库位状态失败,库位号:" + locNo); |
| | | } |
| | | } else { |
| | | throw new CoolException(dto.getLocNo() + "库位不是在库状态"); |
| | | throw new CoolException(locNo + " 库位不是在库状态"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void supplementBothSidesBlocked( |
| | | List<LocMast> normalMasts, |
| | | List<LocMast> supplementMasts, |
| | | AtomicReference<Boolean> isLeftSideSupplement) { |
| | | |
| | | if (normalMasts.isEmpty()) { |
| | | isLeftSideSupplement.set(true); // 默认左侧 |
| | | return; |
| | | } |
| | | |
| | | // 假设所有 normalMasts 在同一 bay/lev(多组情况可循环处理) |
| | | LocMast rep = normalMasts.get(0); |
| | | Integer bay1 = rep.getBay1(); |
| | | Integer lev1 = rep.getLev1(); |
| | | |
| | | if (bay1 == null || lev1 == null) { |
| | | throw new CoolException("库位 bay1 或 lev1 为空,无法补齐前方"); |
| | | } |
| | | |
| | | // 找出选中段的最小/最大排号 |
| | | int minRow = normalMasts.stream() |
| | | .mapToInt(LocMast::getRow1) |
| | | .min() |
| | | .orElseThrow(() -> new CoolException("正常库位列表为空,无法获取最小排号")); |
| | | |
| | | int maxRow = normalMasts.stream() |
| | | .mapToInt(LocMast::getRow1) |
| | | .max() |
| | | .orElseThrow(() -> new CoolException("正常库位列表为空,无法获取最大排号")); |
| | | |
| | | // 假设深库位范围:1~5 排(可根据实际调整) |
| | | final int MIN_ROW = 1; |
| | | final int MAX_ROW = 5; |
| | | |
| | | // ---------------- 计算左侧(小排号方向,较浅位置)需要补多少 ---------------- |
| | | int leftCount = 0; |
| | | List<LocMast> leftToAdd = new ArrayList<>(); |
| | | for (int r = minRow - 1; r >= MIN_ROW; r--) { |
| | | LocMast loc = getLocMastByRow(r, bay1, lev1); |
| | | if (loc == null) continue; |
| | | |
| | | // 只补空板(D状态) |
| | | if ("D".equals(loc.getLocSts())) { |
| | | leftCount++; |
| | | leftToAdd.add(loc); |
| | | } |
| | | // 可选:遇到其他阻塞状态可停止(视业务需求) |
| | | // else if ("F".equals(loc.getLocSts()) || "其他阻塞".equals(...)) break; |
| | | } |
| | | |
| | | // ---------------- 计算右侧(大排号方向,更深位置)需要补多少 ---------------- |
| | | int rightCount = 0; |
| | | List<LocMast> rightToAdd = new ArrayList<>(); |
| | | for (int r = maxRow + 1; r <= MAX_ROW; r++) { |
| | | LocMast loc = getLocMastByRow(r, bay1, lev1); |
| | | if (loc == null) continue; |
| | | |
| | | if ("D".equals(loc.getLocSts())) { |
| | | rightCount++; |
| | | rightToAdd.add(loc); |
| | | } |
| | | // else if (阻塞状态) break; |
| | | } |
| | | |
| | | // ---------------- 选择补哪一边 ---------------- |
| | | List<LocMast> chosen; |
| | | boolean chooseLeft; |
| | | |
| | | if (leftCount == 0 && rightCount == 0) { |
| | | // 两侧都没空板可补 → 无法打通 |
| | | throw new CoolException("前方两侧均无空板可补充,无法打通出库路径"); |
| | | } |
| | | |
| | | if (leftCount <= rightCount) { |
| | | // 左侧补更少(或相等默认左侧) |
| | | chosen = leftToAdd; |
| | | chooseLeft = true; |
| | | log.info("选择补充左侧(小排方向),共 {} 个空板库位", leftCount); |
| | | } else { |
| | | chosen = rightToAdd; |
| | | chooseLeft = false; |
| | | log.info("选择补充右侧(大排方向),共 {} 个空板库位", rightCount); |
| | | } |
| | | |
| | | // 设置标记(用于后续优先级调整) |
| | | isLeftSideSupplement.set(chooseLeft); |
| | | |
| | | // 加入补充列表(去重) |
| | | for (LocMast supp : chosen) { |
| | | if (!supplementMasts.contains(supp) && !normalMasts.contains(supp)) { |
| | | supplementMasts.add(supp); |
| | | } |
| | | } |
| | | } |
| | |
| | | return dto.getLocNo(); |
| | | } |
| | | |
| | | /** |
| | | * 检查空板出库分组内选中连续段的双向前方清空情况,并返回出库方向与排序后的库位列表 |
| | | * |
| | | * @param selectedLocNos 选中的库位号列表 |
| | | * @param locGroupAscOrder 出库分组配置 |
| | | * @return LockingCheckResultParam 包含校验结果、方向、排序后库位列表 |
| | | */ |
| | | private LockingCheckResultParam checkEmptyPlateBlocking( |
| | | List<String> selectedLocNos, |
| | | List<LocGroupOrder> locGroupAscOrder) { |
| | | |
| | | if (Cools.isEmpty(selectedLocNos)) { |
| | | return LockingCheckResultParam.success(Collections.emptyList()); |
| | | } |
| | | |
| | | // 1. 查询所有选中的库位信息 |
| | | List<LocMast> selectedMasts = locMastService.selectList( |
| | | new EntityWrapper<LocMast>().in("loc_no", selectedLocNos) |
| | | ); |
| | | |
| | | if (selectedMasts.size() != selectedLocNos.size()) { |
| | | return LockingCheckResultParam.fail("部分选中库位不存在或数据异常"); |
| | | } |
| | | |
| | | // 2. 按分组聚合选中的库位(支持多分组) |
| | | Map<LocGroupOrder, List<LocMast>> groupSelected = new HashMap<>(); |
| | | for (LocMast lm : selectedMasts) { |
| | | LocGroupOrder group = locGroupAscOrder.stream() |
| | | .filter(g -> g.getRowList().contains(lm.getRow1())) |
| | | .findFirst() |
| | | .orElseThrow(() -> new CoolException("排不在出库分组配置中: row=" + lm.getRow1())); |
| | | |
| | | groupSelected.computeIfAbsent(group, k -> new ArrayList<>()).add(lm); |
| | | } |
| | | |
| | | // 由于通常一次请求在一个分组内,这里取第一个分组的结果 |
| | | // 如果需要支持多分组同时出库,可改为返回 Map<LocGroupOrder, LockingCheckResultParam> |
| | | LockingCheckResultParam result = null; |
| | | |
| | | for (Map.Entry<LocGroupOrder, List<LocMast>> entry : groupSelected.entrySet()) { |
| | | LocGroupOrder group = entry.getKey(); |
| | | List<LocMast> selected = entry.getValue(); |
| | | |
| | | List<Integer> fullRows = group.getRowList(); // 如 [3,4,5,6,7,8,9,10] |
| | | |
| | | // 获取选中的 row,并按分组顺序排序 |
| | | List<Integer> selectedRows = selected.stream() |
| | | .map(LocMast::getRow1) |
| | | .distinct() |
| | | .sorted(Comparator.comparingInt(fullRows::indexOf)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 检查是否重复或无效 |
| | | if (selectedRows.size() != selected.size()) { |
| | | return LockingCheckResultParam.fail("选中库位存在重复或无效排"); |
| | | } |
| | | |
| | | int minIndex = fullRows.indexOf(selectedRows.get(0)); |
| | | int maxIndex = fullRows.indexOf(selectedRows.get(selectedRows.size() - 1)); |
| | | |
| | | // 1. 必须是连续段(无缺口) |
| | | if (maxIndex - minIndex + 1 != selectedRows.size()) { |
| | | return LockingCheckResultParam.fail( |
| | | "选中排必须连续,无缺口。从 " + fullRows.get(minIndex) + " 到 " + fullRows.get(maxIndex) |
| | | ); |
| | | } |
| | | |
| | | // 2. 检查左前方(正序方向:从左到右,前方是索引小的位置) |
| | | boolean leftClear = true; |
| | | for (int i = 0; i < minIndex; i++) { |
| | | LocMast prev = getLocMastByRow(fullRows.get(i), selected.get(0).getBay1(), selected.get(0).getLev1()); |
| | | if (prev != null && ("D".equals(prev.getLocSts()) || "F".equals(prev.getLocSts()))) { |
| | | leftClear = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // // 3. 检查右前方(倒序方向:从右到左,前方是索引大的位置) |
| | | // boolean rightClear = true; |
| | | // for (int i = maxIndex + 1; i < fullRows.size(); i++) { |
| | | // LocMast prev = getLocMastByRow(fullRows.get(i), selected.get(0).getBay1(), selected.get(0).getLev1()); |
| | | // if (prev != null && ("D".equals(prev.getLocSts()) || "F".equals(prev.getLocSts()))) { |
| | | // rightClear = false; |
| | | // break; |
| | | // } |
| | | // } |
| | | |
| | | // 4. 至少有一侧清空才允许出库(修改:放宽,如果两侧都堵,返回特定错误码或继续) |
| | | // if (!leftClear && !rightClear) { |
| | | // return LockingCheckResultParam.fail( |
| | | // "选中段 " + fullRows.get(minIndex) + "~" + fullRows.get(maxIndex) + |
| | | // " 两侧前方都有空板/故障,无法出库(正序或倒序方向都堵塞)" |
| | | // ); |
| | | // } |
| | | if (!leftClear ) { |
| | | return LockingCheckResultParam.fail( |
| | | "选中段 " + fullRows.get(minIndex) + "~" + fullRows.get(maxIndex) + |
| | | " 两侧前方都有空板/故障,无法出库(正序或倒序方向都堵塞)" |
| | | ); |
| | | } |
| | | |
| | | // 5. 选中段内所有库位必须是 D 状态 |
| | | for (LocMast lm : selected) { |
| | | if (!"D".equals(lm.getLocSts())) { |
| | | return LockingCheckResultParam.fail("选中库位非空板状态: " + lm.getLocNo()); |
| | | } |
| | | } |
| | | |
| | | // 6. 决定出库方向和排序顺序 |
| | | String direction; |
| | | List<LocMast> sortedSelected; |
| | | |
| | | // 优先选择正序(如果两侧都清空,默认正序) |
| | | if (leftClear) { |
| | | direction = "ASC"; |
| | | sortedSelected = selected.stream() |
| | | .sorted(Comparator.comparingInt(m -> fullRows.indexOf(m.getRow1()))) |
| | | .collect(Collectors.toList()); |
| | | } else { |
| | | direction = "DESC"; |
| | | sortedSelected = selected.stream() |
| | | .sorted(Comparator.comparingInt(m -> -fullRows.indexOf(m.getRow1()))) // 倒序 |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | result = LockingCheckResultParam.success(direction, sortedSelected); |
| | | } |
| | | |
| | | // 如果没有分组(理论上不会发生),返回默认成功 |
| | | return result != null ? result : LockingCheckResultParam.success(Collections.emptyList()); |
| | | } |
| | | |
| | | // 辅助方法:根据 row 获取 LocMast |
| | | private LocMast getLocMastByRow(Integer row, Integer bay1, Integer lev1) { |
| | | return locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("bay1", bay1) |
| | | .eq("lev1", lev1) |
| | | .eq("row1", row)); |
| | | } |
| | | |
| | | /** |
| | | * 当选中段两侧前方都堵塞时,判断补哪一侧需要的空板最少,并把那些库位加入补充列表 |
| | | */ |
| | | private void supplementBothSidesBlocked( |
| | | List<LocMast> normalMasts, |
| | | List<LocGroupOrder> locGroupAscOrder, |
| | | List<LocMast> supplementMasts, |
| | | AtomicReference<Boolean> isLeftSideSupplement) { |
| | | |
| | | // 假设所有 normalMasts 在同一个分组(如果多分组,可循环处理每个分组) |
| | | LocGroupOrder group = locGroupAscOrder.stream() |
| | | .filter(g -> g.getRowList().contains(normalMasts.get(0).getRow1())) |
| | | .findFirst() |
| | | .orElseThrow(() -> new CoolException("分组异常")); |
| | | |
| | | List<Integer> fullRows = group.getRowList(); |
| | | |
| | | // 取选中段的 min/max row |
| | | Set<Integer> selectedRowSet = normalMasts.stream() |
| | | .map(LocMast::getRow1) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | int minRow = Collections.min(selectedRowSet); |
| | | int maxRow = Collections.max(selectedRowSet); |
| | | |
| | | int minIndex = fullRows.indexOf(minRow); |
| | | int maxIndex = fullRows.indexOf(maxRow); |
| | | |
| | | // 假设所有库位在同 bay 和 lev |
| | | Integer bay1 = normalMasts.get(0).getBay1(); |
| | | Integer lev1 = normalMasts.get(0).getLev1(); |
| | | |
| | | // 计算左侧前方需要补充的 D 状态库位数量(从 0 到 minIndex-1 的 D 状态库位) |
| | | int leftSupplementCount = 0; |
| | | List<LocMast> leftSupplementLocs = new ArrayList<>(); |
| | | for (int i = 0; i < minIndex; i++) { |
| | | LocMast loc = getLocMastByRow(fullRows.get(i), bay1, lev1); |
| | | if (loc != null && ("D".equals(loc.getLocSts()) || "F".equals(loc.getLocSts()))) { |
| | | leftSupplementCount++; |
| | | leftSupplementLocs.add(loc); |
| | | } |
| | | } |
| | | |
| | | // // 计算右侧前方需要补充的 D 状态库位数量(从 maxIndex+1 到 end 的 D 状态库位) |
| | | // int rightSupplementCount = 0; |
| | | // List<LocMast> rightSupplementLocs = new ArrayList<>(); |
| | | // for (int i = maxIndex + 1; i < fullRows.size(); i++) { |
| | | // LocMast loc = getLocMastByRow(fullRows.get(i), bay1, lev1); |
| | | // if (loc != null && "D".equals(loc.getLocSts())) { |
| | | // rightSupplementCount++; |
| | | // rightSupplementLocs.add(loc); |
| | | // } |
| | | // } |
| | | |
| | | // 选择需要补充最少的一侧(如果相等,优先左侧) |
| | | List<LocMast> chosenSupplementLocs; |
| | | boolean isLeft = false; |
| | | if (true) { |
| | | chosenSupplementLocs = leftSupplementLocs; |
| | | isLeft = true; |
| | | log.info("选择补充左侧前方,共 {} 个库位", leftSupplementCount); |
| | | } |
| | | // else { |
| | | // chosenSupplementLocs = rightSupplementLocs; |
| | | // isLeft = false; |
| | | // log.info("选择补充右侧前方,共 {} 个库位", rightSupplementCount); |
| | | // } |
| | | // 记录选择的侧 |
| | | isLeftSideSupplement.set(isLeft); |
| | | // 添加到 supplementMasts(避免重复添加) |
| | | for (LocMast supp : chosenSupplementLocs) { |
| | | if (!supplementMasts.contains(supp) && !normalMasts.contains(supp)) { |
| | | supplementMasts.add(supp); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public void emptyPlateOut(EmptyPlateOutParam param, Long userId) { |
| | | if (Cools.isEmpty(param.getOutSite())) { |
| | | throw new CoolException("站点不存在"); |
| | | } |
| | | for (String locNo : param.getLocNos()) { |
| | | |
| | | // 使用出库专用分组配置 |
| | | List<LocGroupOrder> locGroupAscOrder = slaveProperties.getLocGroupAscOrder(); |
| | | |
| | | // 1. 查询所有选中的库位信息 |
| | | List<LocMast> selectedMasts = locMastService.selectList( |
| | | new EntityWrapper<LocMast>().in("loc_no", param.getLocNos()) |
| | | ); |
| | | |
| | | if (selectedMasts.size() != param.getLocNos().size()) { |
| | | throw new CoolException("部分选中库位不存在或数据异常"); |
| | | } |
| | | |
| | | // 2. 区分正常分组内的库位 和 需要补充的库位(规则外的) |
| | | List<LocMast> normalMasts = new ArrayList<>(); |
| | | List<LocMast> supplementMasts = new ArrayList<>(); |
| | | for (LocMast lm : selectedMasts) { |
| | | boolean inAnyGroup = locGroupAscOrder.stream() |
| | | .anyMatch(g -> g.getRowList().contains(lm.getRow1())); |
| | | if (inAnyGroup) { |
| | | normalMasts.add(lm); |
| | | } else { |
| | | supplementMasts.add(lm); |
| | | } |
| | | } |
| | | // 新增:记录是否因为左侧前方被补充 |
| | | AtomicReference<Boolean> isLeftSideSupplement = new AtomicReference<>(false); |
| | | // 3. 对正常分组内的库位进行检查(放宽两侧堵塞规则) |
| | | if (!normalMasts.isEmpty()) { |
| | | List<String> normalLocNos = normalMasts.stream() |
| | | .map(LocMast::getLocNo) |
| | | .collect(Collectors.toList()); |
| | | |
| | | LockingCheckResultParam checkResult = checkEmptyPlateBlocking( |
| | | normalLocNos, |
| | | locGroupAscOrder |
| | | ); |
| | | |
| | | if (!checkResult.isSuccess()) { |
| | | String errMsg = checkResult.getErrorMessage(); |
| | | if (errMsg.contains("两侧前方都有空板/故障")) { |
| | | // 两侧都堵 → 进入补齐逻辑 |
| | | supplementBothSidesBlocked(normalMasts, locGroupAscOrder, supplementMasts, isLeftSideSupplement); |
| | | } else { |
| | | // 其他错误(如不连续、非D状态)抛出 |
| | | throw new CoolException(errMsg); |
| | | } |
| | | } |
| | | // 如果有一侧清空,则正常继续 |
| | | } |
| | | |
| | | // 4. 合并所有库位(正常 + 补充的,包括规则外的和前方补的) |
| | | List<LocMast> allMasts = new ArrayList<>(); |
| | | allMasts.addAll(normalMasts); |
| | | allMasts.addAll(supplementMasts); |
| | | |
| | | if (allMasts.isEmpty()) { |
| | | throw new CoolException("没有有效的空板库位可出库"); |
| | | } |
| | | |
| | | // 5. 统一按 row → bay → lev 排序(从小到大) |
| | | List<LocMast> sortedAll = allMasts.stream() |
| | | .sorted(Comparator.comparing(LocMast::getRow1) |
| | | .thenComparing(LocMast::getBay1) |
| | | .thenComparing(LocMast::getLev1)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | Date now = new Date(); |
| | | |
| | | // 6. 按排序后的顺序生成出库任务(从后往前生成) |
| | | for (int index = 0; index <sortedAll.size() ; index ++) { |
| | | LocMast locMast = sortedAll.get(index); |
| | | String locNo = locMast.getLocNo(); |
| | | |
| | | // 判断是否为补充库位(规则外的 或 前方补的) |
| | | boolean isSupplement = supplementMasts.contains(locMast); |
| | | |
| | | int ioType = isSupplement ? 11 : 110; |
| | | |
| | | // 获取工作号 |
| | | int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type); |
| | | // 获取库位 |
| | | LocMast locMast = locMastService.selectById(locNo); |
| | | if (Cools.isEmpty(locMast)) { |
| | | throw new CoolException(locNo+"库位不存在"); |
| | | } |
| | | if (!locMast.getLocSts().equals("D")){ |
| | | throw new CoolException("所选库位存在状态不为D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$()); |
| | | } |
| | | |
| | | // 获取源站 |
| | | Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>() |
| | | .eq("type_no", 110) |
| | | .eq("stn_no", param.getOutSite()) |
| | | .eq("crn_no", locMast.getCrnNo()); |
| | | StaDesc staDesc = staDescService.selectOne(wrapper); |
| | | Integer sourceStaNo = staDesc.getCrnStn(); |
| | | Integer sourceStaNo = staDesc != null ? staDesc.getCrnStn() : null; |
| | | |
| | | if (Cools.isEmpty(sourceStaNo)) { |
| | | throw new CoolException("检索源站失败"); |
| | | throw new CoolException("检索源站失败,库位:" + locNo); |
| | | } |
| | | Date now = new Date(); |
| | | // 保存工作档 |
| | | |
| | | // 计算优先级(示例:补充的优先级稍低) |
| | | double BASE_PRI = 200.0; |
| | | double ioPri; |
| | | WrkMast wrkMast = new WrkMast(); |
| | | wrkMast.setWrkNo(workNo); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID |
| | | wrkMast.setIoType(110); // 入出库状态: 110.空板出库 |
| | | wrkMast.setIoPri(10D); |
| | | wrkMast.setSourceStaNo(sourceStaNo); // 源站 |
| | | wrkMast.setStaNo(param.getOutSite()); // 目标站 |
| | | wrkMast.setCrnNo(locMast.getCrnNo()); |
| | | wrkMast.setSourceLocNo(locNo); // 源库位 |
| | | wrkMast.setFullPlt("N"); // 满板:Y |
| | | wrkMast.setPicking("N"); // 拣料 |
| | | wrkMast.setExitMk("N"); // 退出 |
| | | wrkMast.setEmptyMk("Y"); // 空板 |
| | | wrkMast.setLinkMis("N"); |
| | | wrkMast.setAppeUser(userId); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | boolean res = wrkMastService.insert(wrkMast); |
| | | if (!res) { |
| | | throw new CoolException("保存工作档失败"); |
| | | LocMast locMastNew = null; |
| | | if(isSupplement){ |
| | | // 补充的库位:根据是左侧还是右侧补充,决定优先级方向 |
| | | if (Boolean.TRUE.equals(isLeftSideSupplement.get())) { |
| | | // 左侧补充 → 优先级较低(晚出) |
| | | ioPri = BASE_PRI + index * 1.0; |
| | | } else { |
| | | // 右侧补充 → 优先级较高(早出) |
| | | ioPri = BASE_PRI - index * 1.0; |
| | | } |
| | | locMastNew = commonService.searchEmptyPallet(null); |
| | | wrkMast.setWrkNo(workNo); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setWrkSts(0L); |
| | | wrkMast.setIoType(ioType); |
| | | wrkMast.setIoPri(ioPri); |
| | | wrkMast.setSourceStaNo(null); |
| | | wrkMast.setLocNo(locMastNew.getLocNo()); |
| | | wrkMast.setStaNo(null); |
| | | wrkMast.setCrnNo(locMast.getCrnNo()); |
| | | wrkMast.setSourceLocNo(locNo); |
| | | wrkMast.setFullPlt("N"); |
| | | wrkMast.setPicking("N"); |
| | | wrkMast.setExitMk("N"); |
| | | wrkMast.setEmptyMk("Y"); |
| | | wrkMast.setLinkMis("N"); |
| | | wrkMast.setAppeUser(userId); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | }else{ |
| | | ioPri = BASE_PRI + index * 1.0; |
| | | wrkMast.setWrkNo(workNo); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setWrkSts(0L); |
| | | wrkMast.setIoType(ioType); |
| | | wrkMast.setIoPri(ioPri); |
| | | wrkMast.setSourceStaNo(sourceStaNo); |
| | | wrkMast.setStaNo(param.getOutSite()); |
| | | wrkMast.setCrnNo(locMast.getCrnNo()); |
| | | wrkMast.setSourceLocNo(locNo); |
| | | wrkMast.setFullPlt("N"); |
| | | wrkMast.setPicking("N"); |
| | | wrkMast.setExitMk("N"); |
| | | wrkMast.setEmptyMk("Y"); |
| | | wrkMast.setLinkMis("N"); |
| | | wrkMast.setAppeUser(userId); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | } |
| | | // 更新库位状态 D.空板 -> R.出库预约 |
| | | if (locMast.getLocSts().equals("D")){ |
| | | |
| | | if (!wrkMastService.insert(wrkMast)) { |
| | | throw new CoolException("保存工作档失败,库位:" + locNo); |
| | | } |
| | | |
| | | if(locMastNew != null){ |
| | | if ("O".equals(locMastNew.getLocSts())) { |
| | | locMastNew.setLocSts("S"); |
| | | locMastNew.setModiUser(userId); |
| | | locMastNew.setModiTime(now); |
| | | if (!locMastService.updateById(locMastNew)) { |
| | | throw new CoolException("更新库位状态失败,库位:" + locNo); |
| | | } |
| | | } else { |
| | | throw new CoolException("库位状态异常,非空板状态:" + locNo); |
| | | } |
| | | } |
| | | |
| | | // 更新库位状态 D → R |
| | | if ("D".equals(locMast.getLocSts())) { |
| | | locMast.setLocSts("R"); |
| | | locMast.setModiUser(userId); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | throw new CoolException("更新库位状态失败"); |
| | | throw new CoolException("更新库位状态失败,库位:" + locNo); |
| | | } |
| | | } else { |
| | | throw new CoolException("库位状态异常,非空板状态:" + locNo); |
| | | } |
| | | } |
| | | } |
| | |
| | | if (wrkMast.getWrkSts() == 4 || wrkMast.getWrkSts() == 14) { |
| | | throw new CoolException("当前工作档已完成"); |
| | | } |
| | | // 入库 + 库位转移 |
| | | if (wrkMast.getWrkSts() < 4 || (wrkMast.getWrkSts() > 10 && wrkMast.getIoType()==11)) { |
| | | wrkMast.setWrkSts(4L); |
| | | // 出库 |
| | | } else if (wrkMast.getWrkSts() > 10) { |
| | | if (wrkMast.getIoType() > 100) { |
| | | wrkMast.setWrkSts(14L); |
| | | // 入库 + 库位转移 |
| | | } else if (wrkMast.getIoType()==1 || wrkMast.getIoType()==10 || wrkMast.getIoType()==11) { |
| | | wrkMast.setWrkSts(4L); |
| | | |
| | | } |
| | | Date now = new Date(); |
| | | wrkMast.setCrnStrTime(DateUtils.calculate(now, 1L, TimeUnit.SECONDS, true)); |
| | |
| | | String locNo = ""; // 待修改目标库位 |
| | | String locSts = ""; // 待修改目标库位状态 |
| | | // 入库取消(修改目标库位) |
| | | if (wrkMast.getWrkSts() < 4) { |
| | | if (wrkMast.getIoType() < 100) { |
| | | locNo = wrkMast.getLocNo(); |
| | | locSts = "O"; |
| | | |
| | |
| | | locMastService.updateById(locMast); |
| | | } |
| | | // 出库取消(修改源库位) |
| | | } else if (wrkMast.getWrkSts() > 10 && wrkMast.getWrkSts() != 14) { |
| | | } else if (wrkMast.getIoType() > 100 && wrkMast.getWrkSts() != 14) { |
| | | locNo = wrkMast.getSourceLocNo(); |
| | | // 出库 ===>> F.在库 |
| | | if (wrkMast.getIoType() > 100 && wrkMast.getIoType() != 110) { |
| | | if (wrkMast.getIoType() == 101 || wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107) { |
| | | locSts = "F"; |
| | | // 空板出库 ===>> D.空桶/空栈板 |
| | | } else if (wrkMast.getIoType() == 110) { |
| | |
| | | waitPakinService.update(waitPakin, new EntityWrapper<WaitPakin>() |
| | | // .eq("order_no", waitPakin.getOrderNo()) |
| | | .eq("zpallet",waitPakin.getZpallet()) |
| | | .eq("matnr", waitPakin.getMatnr()) |
| | | .eq("batch", waitPakin.getBatch())); |
| | | .eq("matnr", waitPakin.getMatnr())); |
| | | } |
| | | } |
| | | } |
| | |
| | | if (!wrkMastRes || !locMastRes) { |
| | | throw new CoolException("保存数据失败"); |
| | | } |
| | | |
| | | //wms取消任务 同时调用wcs任务取消接口通知wcs |
| | | WrkCancel wrkCancel = new WrkCancel(); |
| | | Date date = new Date(); |
| | | DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | wrkCancel.setTaskId(workNo); // 任务号 |
| | | wrkCancel.setMsgTime(dateFormat.format(date)); // 取消时间 |
| | | wrkCancel.setWarehouse(warehouse); // 仓库编码 |
| | | |
| | | String response = ""; |
| | | boolean flag = false; |
| | | try { |
| | | response = new HttpHandler.Builder() |
| | | .setUri(url) |
| | | .setPath(cancel) |
| | | .setJson(JSON.toJSONString(wrkCancel)) |
| | | .build() |
| | | .doPost(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if (jsonObject.getInteger("returnStatus") == 0){ |
| | | flag = true; |
| | | }else { |
| | | log.error("wms取消任务下发wcs失败--->url:{};request:{};response:{}", url+"/"+cancel, JSON.toJSONString(wrkCancel), response); |
| | | throw new CoolException("wms取消任务下发wcs失败"); |
| | | } |
| | | }catch (Exception e){ |
| | | log.error("fail", e); |
| | | }finally { |
| | | try { |
| | | //保存接口日志 |
| | | apiLogService.save( |
| | | "wms下发任务给wcs", |
| | | url+"/"+cancel, |
| | | null, |
| | | "127.0.0.1", |
| | | JSON.toJSONString(wrkCancel), |
| | | response, |
| | | flag |
| | | ); |
| | | }catch (Exception e){ |
| | | log.error("",e); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | @Override |