| | |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.support.TransactionSynchronization; |
| | | import org.springframework.transaction.support.TransactionSynchronizationManager; |
| | | import org.springframework.web.client.HttpStatusCodeException; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | |
| | | throw new CoolException("组托明细修执行数量修改失败!!"); |
| | | } |
| | | }); |
| | | syncAsnOrderItemBarcodeByPakin(waitPakinItems, pakin.getBarcode(), loginUserId); |
| | | }); |
| | | |
| | | if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>() |
| | |
| | | throw new CoolException("组托明细修执行数量修改失败!!"); |
| | | } |
| | | }); |
| | | syncAsnOrderItemBarcodeByPakin(waitPakinItems, pakin.getBarcode(), loginUserId); |
| | | }); |
| | | |
| | | if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>() |
| | |
| | | throw new CoolException("组托明细修执行数量修改失败!!"); |
| | | } |
| | | }); |
| | | syncAsnOrderItemBarcodeByPakin(waitPakinItems, pakin.getBarcode(), loginUserId); |
| | | }); |
| | | |
| | | if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>() |
| | |
| | | throw new CoolException("组拖状态修改失败!!"); |
| | | } |
| | | return R.ok("任务生成完毕!"); |
| | | } |
| | | |
| | | /** 组托后将通知单明细条码回写为料箱码 */ |
| | | private void syncAsnOrderItemBarcodeByPakin(List<WaitPakinItem> waitPakinItems, String pakinBarcode, Long loginUserId) { |
| | | if (waitPakinItems == null || waitPakinItems.isEmpty() || StringUtils.isBlank(pakinBarcode)) { |
| | | return; |
| | | } |
| | | Set<Long> asnItemIds = waitPakinItems.stream() |
| | | .map(WaitPakinItem::getAsnItemId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | if (asnItemIds.isEmpty()) { |
| | | return; |
| | | } |
| | | if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>() |
| | | .in(WkOrderItem::getId, asnItemIds) |
| | | .set(WkOrderItem::getBarcode, pakinBarcode) |
| | | .set(WkOrderItem::getUpdateBy, loginUserId) |
| | | .set(WkOrderItem::getUpdateTime, new Date()))) { |
| | | throw new CoolException("通知单明细条码回写失败!!"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | if (StringUtils.isNotBlank(task.getTaskCode())) { |
| | | rcsBusTaskNoticeService.notifyTaskStatus(task.getTaskCode(), task.getTaskStatus()); |
| | | } |
| | | final Long taskIdForFinish = task.getId(); |
| | | if (TransactionSynchronizationManager.isSynchronizationActive()) { |
| | | TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { |
| | | @Override |
| | | public void afterCommit() { |
| | | taskService.runStockFinishAfterManualComplete(taskIdForFinish); |
| | | } |
| | | }); |
| | | } |
| | | return task; |
| | | } |
| | | |
| | | @Override |
| | | public void runStockFinishAfterManualComplete(Long taskId) { |
| | | if (taskId == null) { |
| | | return; |
| | | } |
| | | try { |
| | | Task t = taskService.getById(taskId); |
| | | if (t == null) { |
| | | return; |
| | | } |
| | | if (Objects.equals(t.getTaskStatus(), TaskStsType.COMPLETE_IN.id)) { |
| | | taskService.complateInTask(Collections.singletonList(t)); |
| | | } else if (Objects.equals(t.getTaskStatus(), TaskStsType.COMPLETE_OUT.id)) { |
| | | taskService.completeTask(Collections.singletonList(t)); |
| | | } |
| | | } catch (Exception e) { |
| | | log.warn("手动完结后立即库存收尾失败,将由定时任务重试,taskId={}:{}", taskId, e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 全版出库完结:扣除库位数量,将库位状态设为空 |
| | | * 全板出库完结:扣除库位数量,将库位状态设为空 |
| | | * |
| | | * @param id 任务ID |
| | | * @param loginUserId 登录用户ID |
| | | * @param notifyRcsFromAdmin 管理后台全版出库完结接口为 true 时通知 RCS;定时/PDA 等为 false |
| | | * @param notifyRcsFromAdmin 管理后台全板出库完结接口为 true 时通知 RCS;定时/PDA 等为 false |
| | | * @return 任务对象 |
| | | */ |
| | | @Override |
| | |
| | | throw new CoolException("任务不存在!!"); |
| | | } |
| | | |
| | | // 检查任务类型是否为全版出库 |
| | | // 检查任务类型是否为全板出库 |
| | | if (!task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) { |
| | | throw new CoolException("当前任务不是全版出库任务,无法执行此操作!!"); |
| | | throw new CoolException("当前任务不是全板出库任务,无法执行此操作!!"); |
| | | } |
| | | |
| | | // 检查任务状态:必须是199(WAVE_SEED)状态才能手动完结 |
| | |
| | | .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type))) { |
| | | throw new CoolException("源库位状态修改失败!!"); |
| | | } |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_EMPITY_OUT.type)) { |
| | | // 空板出库:建单时 D→R,取消恢复为空板 D |
| | | if (!locService.update(new LambdaUpdateWrapper<Loc>() |
| | | .eq(Loc::getCode, task.getOrgLoc()) |
| | | .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_R.type) |
| | | .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type))) { |
| | | throw new CoolException("空板出库源库位恢复空板失败!!"); |
| | | } |
| | | } |
| | | |
| | | if (!Objects.isNull(task.getWarehType()) && task.getWarehType().equals(WarehType.WAREHOUSE_TYPE_AGV.val)) { |
| | |
| | | throw new CoolException("库位信息修改失败!!"); |
| | | } |
| | | //出库 |
| | | if (item.getWkType().equals(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type))) { |
| | | if (Objects.equals(item.getWkType(), OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type)) { |
| | | //库存出库 |
| | | } else if (task.getResource().equals(TaskResouceType.TASK_RESOUCE_WAVE_TYPE.val)) { |
| | | WaveItem waveItem = waveItemService.getById(item.getSource()); |
| | |
| | | throw new CoolException("波次更新失败!!"); |
| | | } |
| | | |
| | | } else if (item.getWkType().equals(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_OTHER.type))) { |
| | | } else if (Objects.equals(item.getWkType(), OrderWorkType.ORDER_WORK_TYPE_OTHER.type)) { |
| | | //其它出库 |
| | | |
| | | } else { |
| | |
| | | try { |
| | | // 根据任务类型更新库位明细 |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) { |
| | | // 全版出库:不删除库位明细,等待PDA快速拣货确认时再删除 |
| | | // 全板出库:不删除库位明细,等待PDA快速拣货确认时再删除 |
| | | // subtractLocItem(loc); // 已移除,改为在completeFullOutStock中删除 |
| | | } else if (!TaskType.TASK_TYPE_PICK_AGAIN_OUT.type.equals(task.getTaskType())) { |
| | | // 部分出库(如盘点出库):根据TaskItem数量扣减库位明细;拣料出库在生成拣料入库单时扣减 |
| | |
| | | } |
| | | |
| | | //添加出入库记录信息 |
| | | Map<Short, List<TaskItem>> listMap = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getWkType)); |
| | | Map<String, List<TaskItem>> listMap = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getWkType)); |
| | | /***获取库存出库值,如果为空表示正常单据出库,非空表明是库存出库 |
| | | * 1. 库存出库没有单据信息,单据信息默认为空 |
| | | * 2. 单据库存需通过波次查询原始单据信息,将单据信息填入stock中 |
| | | * */ |
| | | List<TaskItem> list = listMap.get(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type)); |
| | | List<TaskItem> list = listMap.get(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type); |
| | | if (Objects.isNull(list) || list.isEmpty()) { |
| | | Map<Long, List<TaskItem>> maps = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getSource)); |
| | | maps.keySet().forEach(key -> { |
| | |
| | | // 拣料出库/盘点出库:在未生成拣料入库单之前保持 R.预约出库,否则下发任务时查不到该库位(只查 F+R)导致“库存不足” |
| | | // 等 PDA 确认并生成拣料入库任务时,再在 pickOrCheckTask 中将目标库位改为 S.预约入库 |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) { |
| | | // 全版出库:不更新库位状态为O,等待PDA快速拣货确认时再更新 |
| | | // 全板出库:不更新库位状态为O,等待PDA快速拣货确认时再更新 |
| | | // 库位状态保持原样(R.出库预约状态) |
| | | } else { |
| | | /**修改为库位状态为O.空库*/ |
| | |
| | | if (!asnOrderService.updateById(wkOrder)) { |
| | | throw new CoolException("出库单更新失败!!"); |
| | | } |
| | | stock.setWkType(Short.parseShort(wkOrder.getWkType())) |
| | | stock.setWkType(wkOrder.getWkType()) |
| | | .setType(OrderType.ORDER_OUT.type); |
| | | } else if (!Objects.isNull(diffItem)) { |
| | | stock.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.type)) |
| | | stock.setWkType(OrderWorkType.ORDER_WORK_TYPE_STOCK_CHECK.type) |
| | | .setType(OrderType.ORDER_CHECK.type); |
| | | } else { |
| | | stock.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type)) |
| | | stock.setWkType(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type) |
| | | .setMemo("库存出库,无单据信息!!") |
| | | .setType(OrderType.ORDER_OUT.type); |
| | | } |
| | |
| | | log.error("========== RCS任务下发失败 =========="); |
| | | log.error("站点不存在!!任务编码:{},目标站点:{}", task.getTaskCode(), task.getTargSite()); |
| | | continue; |
| | | } |
| | | // 出库下发前校验站点状态与出库能力 |
| | | if (task.getTaskType() >= TaskType.TASK_TYPE_OUT.type) { |
| | | if (!Integer.valueOf(1).equals(station.getStatus()) || !Integer.valueOf(1).equals(station.getOutAble())) { |
| | | log.error("========== RCS任务下发失败 =========="); |
| | | log.error("站点不可出库下发!!任务编码:{},目标站点:{},站点状态(status):{},能出(outAble):{}", |
| | | task.getTaskCode(), task.getTargSite(), station.getStatus(), station.getOutAble()); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/5/20 |
| | | * @description: 扣减库存明细(全版出库:删除所有库位明细) |
| | | * @description: 扣减库存明细(全板出库:删除所有库位明细) |
| | | * @version 1.0 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | WkOrder o = asnOrderService.getById(e.getKey()); |
| | | if (o != null) { |
| | | Double newQty = QuantityUtils.roundToScale(QuantityUtils.add(o.getQty() != null ? o.getQty() : 0.0, e.getValue())); |
| | | Double planQty = QuantityUtils.roundToScale(o.getAnfme() != null ? o.getAnfme() : 0.0); |
| | | if (QuantityUtils.compare(newQty, planQty) > 0) { |
| | | newQty = planQty; |
| | | } |
| | | o.setQty(newQty); |
| | | if (!asnOrderService.updateById(o)) { |
| | | throw new CoolException("入库单完成数量更新失败!!"); |
| | |
| | | WkOrderItem oi = asnOrderItemService.getById(e.getKey()); |
| | | if (oi != null) { |
| | | Double newQty = QuantityUtils.roundToScale(QuantityUtils.add(oi.getQty() != null ? oi.getQty() : 0.0, e.getValue())); |
| | | Double planQty = QuantityUtils.roundToScale(oi.getAnfme() != null ? oi.getAnfme() : 0.0); |
| | | if (QuantityUtils.compare(newQty, planQty) > 0) { |
| | | newQty = planQty; |
| | | } |
| | | oi.setQty(newQty); |
| | | if (!asnOrderItemService.updateById(oi)) { |
| | | throw new CoolException("入库单明细完成数量更新失败!!"); |
| | |
| | | * @return |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public synchronized void saveStockItems(List<TaskItem> items, Task task, Long id, String code, Short wkType, String type, Long loginUserId) { |
| | | public synchronized void saveStockItems(List<TaskItem> items, Task task, Long id, String code, String wkType, String type, Long loginUserId) { |
| | | Stock stock = new Stock(); |
| | | String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_STOCK_CODE, null); |
| | | if (StringUtils.isBlank(ruleCode)) { |
| | |
| | | } |
| | | } |
| | | } |
| | | // 入/出库均仅云仓来源单据参与上报(明细需带 platOrderCode 或 platWorkCode) |
| | | boolean hasCloudSource = taskItems.stream().anyMatch(this::hasCloudOrderRef); |
| | | if (!hasCloudSource) { |
| | | log.info("入/出库结果上报待办跳过:无云仓来源单据,taskId={}", task.getId()); |
| | | return; |
| | | } |
| | | ObjectMapper om = new ObjectMapper(); |
| | | Date now = new Date(); |
| | | for (TaskItem item : taskItems) { |
| | | if (!hasCloudOrderRef(item)) { |
| | | continue; |
| | | } |
| | | String orderNo = isInbound ? sourceToOrderNo.get(item.getSource()) : (item.getPlatOrderCode() != null ? item.getPlatOrderCode() : item.getPlatWorkCode()); |
| | | if (orderNo == null && isInbound) { |
| | | orderNo = item.getPlatOrderCode() != null ? item.getPlatOrderCode() : item.getPlatWorkCode(); |
| | |
| | | log.warn("入/出库结果上报待办失败,taskId={},isInbound={}:{}", task.getId(), isInbound, e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | private boolean hasCloudOrderRef(TaskItem item) { |
| | | if (item == null) { |
| | | return false; |
| | | } |
| | | return StringUtils.isNotBlank(item.getPlatOrderCode()) |
| | | || StringUtils.isNotBlank(item.getPlatWorkCode()); |
| | | } |
| | | } |