package com.huaheng.pc.task.taskHeader.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.huaheng.common.constant.QuantityConstant; import com.huaheng.common.exception.service.ServiceException; import com.huaheng.common.utils.StringUtils; import com.huaheng.common.utils.security.ShiroUtils; import com.huaheng.framework.web.domain.AjaxResult; import com.huaheng.pc.config.container.domain.Container; import com.huaheng.pc.config.container.service.ContainerService; import com.huaheng.pc.config.location.domain.Location; import com.huaheng.pc.config.location.service.LocationService; import com.huaheng.pc.config.material.domain.Material; import com.huaheng.pc.config.materialWarnning.domain.MaterialWarning; import com.huaheng.pc.config.materialWarnning.service.IMaterialWarningService; import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail; import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService; import com.huaheng.pc.inventory.inventoryHeader.domain.InventoryHeader; import com.huaheng.pc.inventory.inventoryHeader.service.InventoryHeaderService; import com.huaheng.pc.inventory.inventoryTransaction.domain.InventoryTransaction; import com.huaheng.pc.inventory.inventoryTransaction.service.InventoryTransactionService; import com.huaheng.pc.shipment.shipmentContainerDetail.domain.ShipmentContainerDetail; import com.huaheng.pc.shipment.shipmentContainerDetail.service.ShipmentContainerDetailService; import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentContainerHeader; import com.huaheng.pc.shipment.shipmentContainerHeader.service.ShipmentContainerHeaderService; import com.huaheng.pc.shipment.shipmentDetail.domain.ShipmentDetail; import com.huaheng.pc.shipment.shipmentDetail.service.ShipmentDetailService; import com.huaheng.pc.shipment.shipmentHeader.domain.ShipmentHeader; import com.huaheng.pc.shipment.shipmentHeader.service.ShipmentHeaderService; import com.huaheng.pc.task.taskDetail.domain.TaskDetail; import com.huaheng.pc.task.taskDetail.service.TaskDetailService; import com.huaheng.pc.task.taskHeader.domain.ShipmentTaskCreateModel; import com.huaheng.pc.task.taskHeader.domain.TaskHeader; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.*; /** * 入库任务创建和完成 * @author mahua * @date 2020/7/14 */ @Service public class ShipmentTaskService { @Resource private ShipmentContainerHeaderService containerHeaderService; @Resource private ShipmentContainerDetailService shipmentContainerDetailService; @Resource private LocationService locationService; @Resource private InventoryDetailService inventoryDetailService; @Resource private TaskHeaderService taskHeaderService; @Resource private TaskDetailService taskDetailService; @Resource private ShipmentDetailService shipmentDetailService; @Resource private ShipmentHeaderService shipmentHeaderService; @Resource private InventoryHeaderService inventoryHeaderService; @Resource private InventoryTransactionService inventoryTransactionService; @Resource private ContainerService containerService; @Resource private IMaterialWarningService materialWarningService; /** * 创建出库任务 * @param shipmentTaskCreateModel * @return */ @Transactional(rollbackFor = Exception.class) public AjaxResult createTaskFromShipmentContainers(ShipmentTaskCreateModel shipmentTaskCreateModel){ Integer taskId; Integer preTaskNo = 0; Integer shipmentContainerHeaderId = shipmentTaskCreateModel.getShipmentContainerHeaderIds(); //获取表头 ShipmentContainerHeader shipmentContainerHeader = containerHeaderService.getById(shipmentContainerHeaderId); if (shipmentContainerHeader == null) { return AjaxResult.error("出库货箱" + shipmentContainerHeaderId + "未找到,操作中止"); } if (shipmentContainerHeader.getStatus() >= QuantityConstant.SHIPMENT_CONTAINER_TASK) { return AjaxResult.error("出库货箱" + shipmentContainerHeader.getContainerCode() + "已经生成任务,请不要重复生成,操作中止"); } //获取所有子货箱 List<ShipmentContainerDetail> shipmentContainerDetails = shipmentContainerDetailService.selectByShippingContainerId(shipmentContainerHeader.getId()); if (shipmentContainerDetails.isEmpty()) { return AjaxResult.error("货箱" + shipmentContainerHeader.getContainerCode() + "没有子任务,操作中止"); } //检测库位 LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); locationLambdaQueryWrapper.eq(Location::getCode, shipmentContainerHeader.getLocationCode()) .eq(Location::getWarehouseCode, ShiroUtils.getWarehouseCode()) .eq(Location::getDeleted, false); Location location = locationService.getOne(locationLambdaQueryWrapper); if (StringUtils.isNull(location)) { return AjaxResult.error("库位禁用或不存在!"); } if(location.getRowFlag() == 1) { Location location1 = locationService.getNear(location); if(location1 != null) { String locationCode = location1.getCode(); LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery(); taskHeaderLambdaQueryWrapper.eq(TaskHeader::getToLocation, locationCode) .lt(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED); List<TaskHeader> taskHeaderList = taskHeaderService.list(taskHeaderLambdaQueryWrapper); if(taskHeaderList != null && taskHeaderList.size() > 0) { preTaskNo = taskHeaderList.get(0).getPreTaskNo(); } } } LambdaQueryWrapper<Container> containerLambdaQueryWrapper = Wrappers.lambdaQuery(); containerLambdaQueryWrapper.eq(Container::getCode, shipmentContainerHeader.getContainerCode()) .eq(Container::getWarehouseCode, ShiroUtils.getWarehouseCode()); Container container = containerService.getOne(containerLambdaQueryWrapper); if (StringUtils.isNull(container)) { return AjaxResult.error("托盘不存在!"); } if(container.getStatus().equals("lock")) { return AjaxResult.error("托盘已经锁定!"); } container.setStatus("lock"); containerService.update(container, containerLambdaQueryWrapper); //创建任务头 TaskHeader task = new TaskHeader(); task.setTaskType(QuantityConstant.TASK_TYPE_SORTINGSHIPMENT); task.setFromLocation(shipmentContainerHeader.getLocationCode()); task.setToLocation(shipmentContainerHeader.getLocationCode()); //判断是否整出任务,钱柜和AGV不能整出 //表示整出优先 //判断当前子货箱所有数量是否等于该托盘对应的所有库存的数量, //这里必须与库存的在库数量对比,后期可能存在一个配盘在执行任务,后一个配盘又在配这个的情况(这个时候不能整出) //如果相等,则说明这个货箱包含了所有的数量,则可以整出,否则,创建拣选任务; //查询所有库存 LambdaQueryWrapper<InventoryDetail> inventoryDetailLambdaQueryWrapper = Wrappers.lambdaQuery(); inventoryDetailLambdaQueryWrapper.eq(InventoryDetail::getLocationCode, shipmentContainerHeader.getLocationCode()) .eq(InventoryDetail::getWarehouseCode, ShiroUtils.getWarehouseCode()); List<InventoryDetail> inventories = inventoryDetailService.list(inventoryDetailLambdaQueryWrapper); BigDecimal inventoryTotal = new BigDecimal("0"); for (InventoryDetail item : inventories) { inventoryTotal = inventoryTotal.add(item.getQty()); } BigDecimal containerTotal = new BigDecimal("0"); for (ShipmentContainerDetail item : shipmentContainerDetails) { containerTotal = containerTotal.add(item.getQty()); } if (inventoryTotal.compareTo(containerTotal) == 0) { //整盘出库 task.setTaskType(QuantityConstant.TASK_TYPE_WHOLESHIPMENT); task.setToLocation(""); } task.setInternalTaskType(QuantityConstant.TASK_INTENERTYPE_PICKING); task.setAllocationHeadId(shipmentContainerHeader.getId()); task.setWarehouseCode(shipmentContainerHeader.getWarehouseCode()); task.setAssignedUser(ShiroUtils.getLoginName()); task.setConfirmedBy(ShiroUtils.getLoginName()); task.setStationCode(shipmentContainerHeader.getStationCode()); task.setStatus(QuantityConstant.TASK_STATUS_BUILD); task.setContainerCode(shipmentContainerHeader.getContainerCode()); task.setCompanyCode(shipmentContainerHeader.getCompanyCode()); task.setPreTaskNo(preTaskNo); if (!taskHeaderService.save(task)){ throw new ServiceException("生成任务失败"); } taskId = task.getId(); for (ShipmentContainerDetail shipmentContainerDetail : shipmentContainerDetails) { TaskDetail taskDetail = new TaskDetail(); taskDetail.setTaskId(task.getId()); taskDetail.setInternalTaskType(task.getInternalTaskType()); taskDetail.setWarehouseCode(task.getWarehouseCode()); taskDetail.setCompanyCode(task.getCompanyCode()); taskDetail.setTaskType(task.getTaskType()); taskDetail.setToInventoryId(shipmentContainerDetail.getInventoryId()); taskDetail.setAllocationId(shipmentContainerDetail.getId()); taskDetail.setBillCode(shipmentContainerDetail.getShipmentCode()); taskDetail.setBillDetailId(shipmentContainerDetail.getShipmentDetailId()); taskDetail.setMaterialCode(shipmentContainerDetail.getMaterialCode()); taskDetail.setMaterialName(shipmentContainerDetail.getMaterialName()); taskDetail.setMaterialSpec(shipmentContainerDetail.getMaterialSpec()); taskDetail.setMaterialUnit(shipmentContainerDetail.getMaterialUnit()); taskDetail.setFromInventoryId(shipmentContainerDetail.getInventoryId()); taskDetail.setQty(shipmentContainerDetail.getQty()); taskDetail.setContainerCode(task.getContainerCode()); taskDetail.setFromLocation(task.getFromLocation()); taskDetail.setToLocation(task.getToLocation()); taskDetail.setLot(shipmentContainerDetail.getLot()); taskDetail.setBatch(shipmentContainerDetail.getBatch()); taskDetail.setProjectNo(shipmentContainerDetail.getProjectNo()); taskDetail.setStatus(QuantityConstant.TASK_STATUS_BUILD); taskDetail.setWaveId(shipmentContainerDetail.getWaveId()); taskDetail.setInventorySts(shipmentContainerDetail.getInventorySts()); if (!taskDetailService.save(taskDetail)) { throw new ServiceException("新建任务明细失败,sql报错"); } shipmentContainerDetail.setStatus(QuantityConstant.SHIPMENT_CONTAINER_TASK); if (!shipmentContainerDetailService.updateById(shipmentContainerDetail)) { throw new ServiceException("修改组盘明细状态失败"); } } //更新货位状态 shipmentContainerHeader.setStatus(QuantityConstant.SHIPMENT_CONTAINER_TASK); if (!containerHeaderService.updateById(shipmentContainerHeader)) { throw new ServiceException("修改组盘头状态失败,sql报错"); } return AjaxResult.success(taskId); } /** * 完成出库任务 * @param task */ @Transactional(rollbackFor = Exception.class) public void completeShipmentTask(TaskHeader task) { //获取任务明细 List<TaskDetail> taskDetails = taskDetailService.findByTaskId(task.getId()); List<Integer> shipmentHeadIds = new ArrayList<>(); for (TaskDetail taskDetail : taskDetails) { if (taskDetail.getStatus() < QuantityConstant.TASK_STATUS_RUNNING) { //获取出库子货箱 ShipmentContainerDetail shipmentContainerDetail = shipmentContainerDetailService.getById(taskDetail.getAllocationId()); //取出子单据 ShipmentDetail shipmentDetail = shipmentDetailService.getById(taskDetail.getBillDetailId()); //暂存id,为更新单据状态准备 shipmentHeadIds.add(shipmentDetail.getShipmentId()); //获取对应库存记录 InventoryDetail inventoryDetail = inventoryDetailService.getById(taskDetail.getToInventoryId()); if (inventoryDetail == null) { throw new ServiceException("任务明细对应的库存ID【" + taskDetail.getToInventoryId().toString() + "】不存在!"); } //减扣库存单 InventoryHeader inventoryHeader = inventoryHeaderService.getById(inventoryDetail.getInventoryHeaderId()); //扣减库存明细 inventoryDetail.setTaskQty(inventoryDetail.getTaskQty().subtract(taskDetail.getQty())); inventoryDetail.setQty(inventoryDetail.getQty().subtract(taskDetail.getQty())); if (inventoryDetail.getQty().signum() == -1) { throw new ServiceException("扣减库存大于wms库存"); } if (inventoryDetail.getQty().signum() == 0 && inventoryDetail.getTaskQty().signum() == 0) { //如果库存没有了,就删除这个库存 inventoryDetailService.removeById(inventoryDetail.getId()); inventoryHeader.setTotalQty(inventoryHeader.getTotalQty().subtract(taskDetail.getQty())); inventoryHeader.setTotalLines(inventoryHeader.getTotalLines() - 1); if (inventoryHeader.getTotalQty().signum() == 0){ inventoryHeaderService.removeById(inventoryHeader.getId()); } else { inventoryHeaderService.updateById(inventoryHeader); } } else { //否则更新这个库存 inventoryDetailService.updateById(inventoryDetail); inventoryHeader.setTotalQty(inventoryHeader.getTotalQty().subtract(taskDetail.getQty())); inventoryHeaderService.updateById(inventoryHeader); inventoryHeaderService.updateById(inventoryHeader); } //设置子任务状态为已执行 taskDetail.setStatus(QuantityConstant.TASK_STATUS_COMPLETED); taskDetailService.updateById(taskDetail); //修改出库组盘明细状态 shipmentContainerDetail.setStatus(QuantityConstant.SHIPMENT_CONTAINER_FINISHED); shipmentContainerDetailService.updateById(shipmentContainerDetail); //记录库存交易记录 InventoryTransaction inventoryTransaction = new InventoryTransaction(); inventoryTransaction.setWarehouseCode(task.getWarehouseCode()); inventoryTransaction.setCompanyCode(shipmentDetail.getCompanyCode()); inventoryTransaction.setLocationCode(inventoryDetail.getLocationCode()); inventoryTransaction.setContainerCode(inventoryDetail.getContainerCode()); inventoryTransaction.setTransactionType(QuantityConstant.INVENTORY_TRANSACTION_SHIPMENT); inventoryTransaction.setMaterialCode(shipmentDetail.getMaterialCode()); inventoryTransaction.setMaterialName(shipmentDetail.getMaterialName()); inventoryTransaction.setMaterialSpec(shipmentDetail.getMaterialSpec()); inventoryTransaction.setMaterialUnit(shipmentDetail.getMaterialUnit()); inventoryTransaction.setBillCode(taskDetail.getBillCode()); inventoryTransaction.setBillDetailId(shipmentDetail.getId()); inventoryTransaction.setBatch(shipmentDetail.getBatch()); inventoryTransaction.setLot(shipmentDetail.getLot()); inventoryTransaction.setProjectNo(shipmentDetail.getProjectNo()); inventoryTransaction.setQcCheck(inventoryDetail.getQcCheck()); inventoryTransaction.setSupplierCode(inventoryDetail.getSupplierCode()); inventoryTransaction.setManufactureDate(shipmentDetail.getManufactureDate()); inventoryTransaction.setExpirationDate(shipmentDetail.getExpirationDate()); inventoryTransaction.setInventorySts(inventoryDetail.getInventorySts()); //这里取反,更符合出库的语义,同时方便对记录进行统计 inventoryTransaction.setTaskQty(taskDetail.getQty()); inventoryTransactionService.save(inventoryTransaction); materialWarningService.materialWarning(taskDetail.getMaterialCode(), taskDetail.getCompanyCode()); } } //设置主任务为已执行 task.setStatus(QuantityConstant.TASK_STATUS_COMPLETED); taskHeaderService.updateById(task); /* 更新库位和容器*/ updateShipmentLocationContainer(task.getFromLocation(), task.getToLocation(), task.getContainerCode(), task.getTaskType()); //设置出库货箱表头状态为拣货任务完成 LambdaUpdateWrapper<ShipmentContainerHeader> shipmentContainerHeaderLambdaUpdateWrapper = Wrappers.lambdaUpdate(); shipmentContainerHeaderLambdaUpdateWrapper.eq(ShipmentContainerHeader::getId, task.getAllocationHeadId()) .set(ShipmentContainerHeader::getStatus, QuantityConstant.SHIPMENT_CONTAINER_REVIEWSUCCESS); if (!containerHeaderService.update(shipmentContainerHeaderLambdaUpdateWrapper)) { throw new ServiceException("更新组盘头状态失败"); } //修改出库单状态 List<TaskDetail> taskDetailList = taskDetailService.findByTaskId(task.getId()); HashSet<Integer> ids = new HashSet<>(); for (TaskDetail taskDetail : taskDetailList) { ShipmentDetail shipmentDetail = shipmentDetailService.getById(taskDetail.getBillDetailId()); if (StringUtils.isNull(shipmentDetail)) { throw new ServiceException("查找出库单明细失败"); } if (shipmentDetail.getShipQty().compareTo(shipmentDetail.getRequestQty()) == 0) { shipmentDetail.setStatus(QuantityConstant.SHIPMENT_HEADER_COMPLETED); shipmentDetailService.updateById(shipmentDetail); } ids.add(shipmentDetail.getShipmentId()); } /*更新出库单状态*/ for (Integer id : ids) { ShipmentHeader shipmentHeader = shipmentHeaderService.getById(id); if (shipmentHeader != null) { Map<String, Integer> status = shipmentDetailService.selectStatus(shipmentHeader.getId()); Integer maxStatus = status.get("maxStatus"); Integer minStatus = status.get("minStatus"); if (maxStatus.equals(QuantityConstant.SHIPMENT_HEADER_COMPLETED)) { shipmentHeader.setFirstStatus(QuantityConstant.SHIPMENT_HEADER_COMPLETED); } if (minStatus.equals(QuantityConstant.SHIPMENT_HEADER_COMPLETED)) { shipmentHeader.setLastStatus(QuantityConstant.SHIPMENT_HEADER_COMPLETED); } shipmentHeader.setLastUpdatedBy(ShiroUtils.getLoginName()); shipmentHeader.setLastUpdated(new Date()); shipmentHeaderService.updateById(shipmentHeader); } } } /** * 出库任务完成时更新库位和容器状态 * @param fromLocation 源库位 * @param toLocation 目标库位 * @param containerCode 容器编码 * @param taskType 任务类型 */ public void updateShipmentLocationContainer(String fromLocation, String toLocation, String containerCode, Integer taskType){ //将库位状态改为空闲,如果是整出的对应的容器也清空 Location fromLocationRecord = locationService.findLocationByCode(fromLocation); if (StringUtils.isNull(fromLocationRecord)) { throw new ServiceException("系统没有" + fromLocation + "库位"); } /* 如果目标库位与源库位不一样时,需要更新两个库位*/ if (StringUtils.isNotEmpty(toLocation) && !fromLocation.equals(toLocation)) { Location toLocationRecord = locationService.findLocationByCode(toLocation); if (StringUtils.isNull(fromLocationRecord)) { throw new ServiceException("系统没有" + toLocation + "库位"); } toLocationRecord.setStatus("empty"); if (taskType.equals(QuantityConstant.TASK_TYPE_WHOLESHIPMENT)) { toLocationRecord.setContainerCode(""); } locationService.updateById(toLocationRecord); fromLocationRecord.setContainerCode(""); } fromLocationRecord.setStatus("empty"); if (taskType.equals(QuantityConstant.TASK_TYPE_WHOLESHIPMENT)) { fromLocationRecord.setContainerCode(""); } locationService.updateById(fromLocationRecord); Container container = containerService.findAllByCode(containerCode); if (StringUtils.isEmpty(containerCode)) { throw new ServiceException("系统无"+container+"容器"); } if (taskType.equals(QuantityConstant.TASK_TYPE_WHOLESHIPMENT)) { if ("LS".equals(container.getContainerType())) { if (!containerService.removeById(container.getId())) { throw new ServiceException("删除临时容器失败"); } } else { containerService.updateLocationCodeAndStatus(containerCode, "", "empty"); } } else { //查询是否存在关联的库存,入如果没有就修改容器状态为empty LambdaQueryWrapper<InventoryDetail> inventoryDetaillambdaQueryWrapper = Wrappers.lambdaQuery(); inventoryDetaillambdaQueryWrapper.eq(InventoryDetail::getContainerCode, containerCode); List<InventoryDetail> detailList = inventoryDetailService.list(inventoryDetaillambdaQueryWrapper); //库存查询不到该容器就把容器状态改为可用 if (detailList.isEmpty()) { containerService.updateLocationCodeAndStatus(containerCode, toLocation, "empty"); } else { containerService.updateLocationCodeAndStatus(containerCode, toLocation, "some"); } } } }