| | |
| | | import com.vincent.rsf.server.api.entity.params.WcsTaskParams; |
| | | import com.vincent.rsf.server.api.service.WcsService; |
| | | import com.vincent.rsf.server.common.constant.Constants; |
| | | import com.vincent.rsf.server.common.utils.QuantityUtils; |
| | | import com.vincent.rsf.server.manager.controller.params.LocToTaskParams; |
| | | import com.vincent.rsf.server.manager.controller.params.PakinItem; |
| | | import com.vincent.rsf.server.manager.enums.*; |
| | |
| | | throw new CoolException("任务明细不存在!!"); |
| | | } |
| | | |
| | | if (TaskType.TASK_TYPE_PICK_IN.type.equals(task.getTaskType())) { |
| | | // 拣料再入库:出库时已在 pickOrCheckTask 中扣减原库位(1100 -> 1089.899), |
| | | // 入库完成时不再回写/累加库位明细,保持 1 条 1089.899,避免出现两条 1100 |
| | | // 仅更新库位状态、清理 LocItemWorking、任务状态及流水 |
| | | } else { |
| | | // 盘点入库等:沿用原逻辑,从 LocItemWorking 回写并 saveBatch |
| | | List<LocItem> items = new ArrayList<>(); |
| | | for (TaskItem taskItem : taskItems) { |
| | | LocItem locItem = new LocItem(); |
| | |
| | | } |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { |
| | | locWorking.setAnfme(taskItem.getAnfme()); |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type) && taskItem.getQty() != null && taskItem.getQty().compareTo(0.0) > 0) { |
| | | // 拣料再入库:入库数量为本次拣料数量(taskItem.qty),保证与出库扣减一致 |
| | | locWorking.setAnfme(taskItem.getQty()); |
| | | } |
| | | BeanUtils.copyProperties(locWorking, locItem); |
| | | locItem.setWorkQty(0.0).setQty(0.0).setLocCode(loc.getCode()).setLocId(loc.getId()).setId(null).setUpdateBy(loginUserId).setUpdateTime(new Date()); |
| | |
| | | } |
| | | } |
| | | |
| | | if (!locItemService.saveBatch(items)) { |
| | | if (!items.isEmpty() && !locItemService.saveBatch(items)) { |
| | | // throw new CoolException("作业库存回写失败!!"); |
| | | } |
| | | } |
| | | |
| | | TaskItem taskItem = taskItems.stream().findFirst().get(); |
| | |
| | | // if (Objects.isNull(locInfo)) { |
| | | // throw new CoolException("获取库位失败!!"); |
| | | // } |
| | | //希日上报物有情况,不需要获取新库位 |
| | | //上报物有情况,不需要获取新库位 |
| | | task.setTargLoc(task.getOrgLoc()) |
| | | .setOrgSite(task.getTargSite()); |
| | | |
| | |
| | | } |
| | | //获取因当前任务出库的所有物料信息 |
| | | List<LocItemWorking> tempLocs = locItemWorkingService.list(new LambdaQueryWrapper<LocItemWorking>().eq(LocItemWorking::getTaskId, task.getId())); |
| | | if (tempLocs.isEmpty()) { |
| | | throw new CoolException("数据错误,作业中库存数据丢失!!"); |
| | | } |
| | | List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | if (taskItems.isEmpty()) { |
| | | throw new CoolException("数据错误:任务明细为空!!"); |
| | | } |
| | | // 与查询一致:若无作业中库存但存在任务明细,用任务明细在内存中兜底,避免“能查到却无法确认” |
| | | if (tempLocs.isEmpty()) { |
| | | tempLocs = taskItems.stream().map(ti -> { |
| | | LocItemWorking w = new LocItemWorking(); |
| | | w.setTaskId(task.getId()); |
| | | w.setFieldsIndex(ti.getFieldsIndex()); |
| | | w.setAnfme(ti.getAnfme()); |
| | | w.setMatnrId(ti.getMatnrId()); |
| | | w.setMaktx(ti.getMaktx()); |
| | | w.setMatnrCode(ti.getMatnrCode()); |
| | | w.setSpec(ti.getSpec()); |
| | | w.setBatch(ti.getBatch()); |
| | | w.setUnit(ti.getUnit()); |
| | | w.setModel(ti.getModel()); |
| | | return w; |
| | | }).collect(Collectors.toList()); |
| | | } |
| | | |
| | | // 拣料入库:在生成拣料入库单时扣减原库位数量,不依赖出库完成时库位状态为R |
| | | // 拣料入库:先算剩余数量并更新 taskItem.anfme,已拣数量 taskItem.qty = 原库位 - 剩余(保证 数量=100、已拣数量=1、库存明细=100) |
| | | if (TaskType.TASK_TYPE_PICK_IN.type.equals(type)) { |
| | | log.debug("[拣料入库] 开始处理 taskId={}, taskCode={}, orgLoc={}, tempLocs.size={}, taskItems.size={}", |
| | | task.getId(), task.getTaskCode(), task.getOrgLoc(), tempLocs.size(), taskItems.size()); |
| | | tempLocs.forEach(working -> { |
| | | taskItems.forEach(taskItem -> { |
| | | if (Objects.equals(taskItem.getFieldsIndex(), working.getFieldsIndex())) { |
| | | // 已拣数量:优先用 taskItem.qty;为 0 时从出库单明细取 执行数(workQty) 或 订单数量(anfme),避免手动完结未填 qty 导致不扣减 |
| | | Double pickedQty = taskItem.getQty() != null && QuantityUtils.isPositive(taskItem.getQty()) |
| | | ? taskItem.getQty() |
| | | : 0.0; |
| | | log.debug("[拣料入库] taskItemId={}, fieldsIndex={}, working.anfme={}, taskItem.qty={}, taskItem.orderItemId={}, pickedQty(初)={}", |
| | | taskItem.getId(), taskItem.getFieldsIndex(), working.getAnfme(), taskItem.getQty(), taskItem.getOrderItemId(), pickedQty); |
| | | if (pickedQty <= 0 && taskItem.getOrderItemId() != null) { |
| | | WkOrderItem orderItem = asnOrderItemService.getById(taskItem.getOrderItemId()); |
| | | log.debug("[拣料入库] 查出库单明细 orderItemId={}, orderItem={}, workQty={}, anfme={}", |
| | | taskItem.getOrderItemId(), orderItem != null ? "存在" : "null", |
| | | orderItem != null ? orderItem.getWorkQty() : null, orderItem != null ? orderItem.getAnfme() : null); |
| | | if (orderItem != null) { |
| | | if (orderItem.getWorkQty() != null && QuantityUtils.isPositive(orderItem.getWorkQty())) { |
| | | pickedQty = orderItem.getWorkQty(); |
| | | } else if (orderItem.getAnfme() != null && QuantityUtils.isPositive(orderItem.getAnfme())) { |
| | | pickedQty = orderItem.getAnfme(); |
| | | } |
| | | } |
| | | } |
| | | Double minQty = QuantityUtils.subtract(working.getAnfme(), pickedQty); |
| | | log.debug("[拣料入库] 计算后 pickedQty={}, minQty(剩余)={}, 将更新 taskItem.anfme={}, taskItem.qty={}", |
| | | pickedQty, minQty, minQty, pickedQty); |
| | | if (QuantityUtils.isNonNegative(minQty)) { |
| | | taskItem.setAnfme(minQty); |
| | | taskItem.setQty(pickedQty); |
| | | if (!taskItemService.updateById(taskItem)) { |
| | | throw new CoolException("任务明细修改失败!!"); |
| | | } |
| | | } else { |
| | | log.warn("[拣料入库] minQty<0 未更新 taskItem, taskItemId={}", taskItem.getId()); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | log.debug("[拣料入库] 即将扣减库位 locId={}, locCode={}", loc.getId(), loc.getCode()); |
| | | subtractLocItemByTaskItems(loc, taskItems, SystemAuthUtils.getLoginUserId()); |
| | | } |
| | | |
| | |
| | | if (Objects.equals(taskItem.getFieldsIndex(), working.getFieldsIndex())) { |
| | | Double minQty = taskItem.getAnfme(); |
| | | if (!task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { |
| | | // 计算剩余数量:从LocItemWorking中减去TaskItem的拣料数量 |
| | | minQty = Math.round((working.getAnfme() - taskItem.getQty()) * 1000000) / 1000000.0; |
| | | // 计算剩余数量 |
| | | minQty = QuantityUtils.subtract(working.getAnfme(), taskItem.getQty()); |
| | | } |
| | | if (minQty.compareTo(0.0) >= 0) { |
| | | if (QuantityUtils.isNonNegative(minQty)) { |
| | | // 更新TaskItem的剩余数量 |
| | | taskItem.setAnfme(minQty); |
| | | if (!taskItemService.updateById(taskItem)) { |
| | | throw new CoolException("任务明细修改失败!!"); |
| | | } |
| | | // 更新LocItemWorking的剩余数量(非盘点入库时需要更新) |
| | | // 更新LocItemWorking的剩余数量(非盘点入库时需要更新);仅持久化记录才写库 |
| | | if (!task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { |
| | | working.setAnfme(minQty); |
| | | if (!locItemWorkingService.updateById(working)) { |
| | | if (working.getId() != null && !locItemWorkingService.updateById(working)) { |
| | | throw new CoolException("作业库存数量更新失败!!"); |
| | | } |
| | | } |
| | |
| | | .setQty(0.0) |
| | | .setLocId(loc1.getId()) |
| | | .setLocCode(loc1.getCode()); |
| | | // 拣料再入库:目标库位数量应为本次拣料数量(taskItem.qty),不是原库位剩余数量(taskItem.anfme) |
| | | if (TaskType.TASK_TYPE_PICK_IN.type.equals(task.getTaskType()) && taskItem.getQty() != null && taskItem.getQty().compareTo(0.0) > 0) { |
| | | itemWorking.setAnfme(taskItem.getQty()); |
| | | // 拣料再入库:目标库位数量应为回库的剩余数量(taskItem.anfme),即原库位减掉本次拣出后的数量(如 1000 出库 10 → 990) |
| | | if (TaskType.TASK_TYPE_PICK_IN.type.equals(task.getTaskType()) && taskItem.getAnfme() != null && taskItem.getAnfme().compareTo(0.0) > 0) { |
| | | itemWorking.setAnfme(taskItem.getAnfme()); |
| | | } |
| | | workings.add(itemWorking); |
| | | }); |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void subtractLocItemByTaskItems(Loc loc, List<TaskItem> taskItems, Long loginUserId) { |
| | | for (TaskItem taskItem : taskItems) { |
| | | // 查询对应的库位明细 |
| | | LocItem locItem = locItemService.getOne(new LambdaQueryWrapper<LocItem>() |
| | | LambdaQueryWrapper<LocItem> locItemWrapper = new LambdaQueryWrapper<LocItem>() |
| | | .eq(LocItem::getLocId, loc.getId()) |
| | | .eq(LocItem::getMatnrId, taskItem.getMatnrId()) |
| | | .eq(StringUtils.isNotBlank(taskItem.getBatch()), LocItem::getBatch, taskItem.getBatch()) |
| | | .eq(StringUtils.isNotBlank(taskItem.getFieldsIndex()), LocItem::getFieldsIndex, taskItem.getFieldsIndex())); |
| | | .eq(LocItem::getMatnrId, taskItem.getMatnrId()); |
| | | if (StringUtils.isNotBlank(taskItem.getBatch())) { |
| | | locItemWrapper.eq(LocItem::getBatch, taskItem.getBatch()); |
| | | } else { |
| | | locItemWrapper.and(w -> w.isNull(LocItem::getBatch).or().eq(LocItem::getBatch, "")); |
| | | } |
| | | if (StringUtils.isNotBlank(taskItem.getFieldsIndex())) { |
| | | locItemWrapper.eq(LocItem::getFieldsIndex, taskItem.getFieldsIndex()); |
| | | } else { |
| | | locItemWrapper.and(w -> w.isNull(LocItem::getFieldsIndex).or().eq(LocItem::getFieldsIndex, "")); |
| | | } |
| | | LocItem locItem = locItemService.getOne(locItemWrapper); |
| | | |
| | | log.info("[拣料入库-扣减库位] taskItemId={}, locId={}, matnrId={}, batch={}, fieldsIndex={}, locItem={}, locItem.anfme={}, taskItem.qty={}, taskItem.anfme={}", |
| | | taskItem.getId(), loc.getId(), taskItem.getMatnrId(), taskItem.getBatch(), taskItem.getFieldsIndex(), |
| | | locItem != null ? "存在" : "null", locItem != null ? locItem.getAnfme() : null, taskItem.getQty(), taskItem.getAnfme()); |
| | | |
| | | if (Objects.nonNull(locItem)) { |
| | | // 计算扣减后的数量 |
| | | Double newAnfme = Math.round((locItem.getAnfme() - taskItem.getQty()) * 1000000) / 1000000.0; |
| | | // 扣减量:优先用本次拣料数量 taskItem.getQty();若为 0 且 taskItem.anfme 已为剩余数量,则扣减 = 原库位 - 剩余(用 BigDecimal 避免 Double 精度问题) |
| | | Double deductQty = QuantityUtils.isPositive(taskItem.getQty()) |
| | | ? taskItem.getQty() |
| | | : (taskItem.getAnfme() != null && QuantityUtils.compare(taskItem.getAnfme(), locItem.getAnfme()) < 0 |
| | | ? QuantityUtils.subtract(locItem.getAnfme(), taskItem.getAnfme()) |
| | | : 0.0); |
| | | Double newAnfme = QuantityUtils.subtract(locItem.getAnfme(), deductQty); |
| | | log.info("[拣料入库-扣减库位] locItemId={}, deductQty={}, 原anfme={}, newAnfme={}, 操作={}", |
| | | locItem.getId(), deductQty, locItem.getAnfme(), newAnfme, QuantityUtils.isNonPositive(newAnfme) ? "删除" : "更新"); |
| | | |
| | | if (newAnfme.compareTo(0.0) <= 0) { |
| | | if (QuantityUtils.isNonPositive(newAnfme)) { |
| | | // 数量小于等于0,删除库位明细 |
| | | locItemService.removeById(locItem.getId()); |
| | | } else { |
| | |
| | | throw new CoolException("库位明细数量扣减失败!!"); |
| | | } |
| | | } |
| | | } else { |
| | | log.warn("[拣料入库-扣减库位] 未查到库位明细 locId={}, matnrId={}, batch={}, fieldsIndex={},未扣减", |
| | | loc.getId(), taskItem.getMatnrId(), taskItem.getBatch(), taskItem.getFieldsIndex()); |
| | | } |
| | | } |
| | | } |