| | |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import com.ruoyi.production.mapper.ProductionOperationTaskMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductMainMapper; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.pojo.ProductionOrderRoutingOperation; |
| | | import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam; |
| | | import com.ruoyi.production.pojo.ProductionProductMain; |
| | | import com.ruoyi.production.mapper.*; |
| | | import com.ruoyi.production.util.TaskPlanQuantityUtil; |
| | | import com.ruoyi.technology.mapper.*; |
| | | import com.ruoyi.production.pojo.*; |
| | | import com.ruoyi.production.service.ProductionOrderRoutingOperationService; |
| | | import com.ruoyi.production.service.ProductionProductMainService; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationParamMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyParamMapper; |
| | | import com.ruoyi.technology.pojo.TechnologyOperationParam; |
| | | import com.ruoyi.technology.pojo.TechnologyParam; |
| | | import com.ruoyi.technology.pojo.*; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | |
| | | @Service |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | private final TechnologyOperationParamMapper technologyOperationParamMapper; |
| | | private final TechnologyParamMapper technologyParamMapper; |
| | | private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; |
| | | private final ProductionOrderMapper productionOrderMapper; |
| | | private final ProductionOrderRoutingMapper productionOrderRoutingMapper; |
| | | private final ProductionOrderBomMapper productionOrderBomMapper; |
| | | private final ProductionBomStructureMapper productionBomStructureMapper; |
| | | private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; |
| | | |
| | | @Override |
| | | public R addRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) { |
| | | // 新增工艺路线 |
| | | int insert = productionOrderRoutingOperationMapper.insert(productionOrderRoutingOperation); |
| | | //工序关联的参数需要同步新增 |
| | | List<TechnologyOperationParam> technologyOperationParams = technologyOperationParamMapper.selectList(Wrappers.<TechnologyOperationParam>lambdaQuery() |
| | | .eq(TechnologyOperationParam::getTechnologyOperationId, productionOrderRoutingOperation.getTechnologyOperationId())); |
| | | // 参数与前置条件校验 |
| | | if (CollectionUtils.isNotEmpty(technologyOperationParams)){ |
| | | ArrayList<ProductionOrderRoutingOperationParam> productionOrderRoutingOperationParams = new ArrayList<>(); |
| | | // 遍历处理数据并组装结果 |
| | | for (TechnologyOperationParam technologyOperationParam : technologyOperationParams) { |
| | | TechnologyParam technologyParam = technologyParamMapper.selectById(technologyOperationParam.getTechnologyParamId()); |
| | | ProductionOrderRoutingOperationParam productionOrderRoutingOperationParam = new ProductionOrderRoutingOperationParam(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R updateRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) { |
| | | Long operationId = productionOrderRoutingOperation.getId(); |
| | | |
| | | // 更新工艺路线工序 |
| | | productionOrderRoutingOperationMapper.updateById(productionOrderRoutingOperation); |
| | | |
| | | // 重新查询完整记录(前端可能没有传递所有字段,如 productionOrderId) |
| | | ProductionOrderRoutingOperation updatedOperation = productionOrderRoutingOperationMapper.selectById(operationId); |
| | | if (updatedOperation == null) { |
| | | throw new ServiceException("工艺路线工序不存在"); |
| | | } |
| | | |
| | | // 查询是否存在工单 |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectOne( |
| | | new LambdaQueryWrapper<ProductionOperationTask>() |
| | | .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, operationId) |
| | | .last("limit 1")); |
| | | |
| | | // 根据是否需要生产进行处理 |
| | | Boolean isProduction = updatedOperation.getIsProduction(); |
| | | |
| | | if (Boolean.TRUE.equals(isProduction)) { |
| | | // 需要生产:检查工单是否存在,不存在则生成 |
| | | if (productionOperationTask == null) { |
| | | ProductionOperationTask task = new ProductionOperationTask(); |
| | | task.setProductionOrderRoutingOperationId(updatedOperation.getId()); |
| | | task.setProductionOrderId(updatedOperation.getProductionOrderId()); |
| | | // 获取生产订单 |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(updatedOperation.getProductionOrderId()); |
| | | if (productionOrder == null) { |
| | | throw new ServiceException("生产订单不存在"); |
| | | } |
| | | |
| | | // 获取订单BOM |
| | | ProductionOrderBom orderBom = productionOrderBomMapper.selectOne( |
| | | Wrappers.<ProductionOrderBom>lambdaQuery() |
| | | .eq(ProductionOrderBom::getProductionOrderId, productionOrder.getId())); |
| | | |
| | | // 确定根产品规格ID |
| | | Long rootProductModelId = orderBom != null && orderBom.getProductModelId() != null |
| | | ? orderBom.getProductModelId() |
| | | : productionOrder.getProductModelId(); |
| | | |
| | | // 获取BOM结构列表 |
| | | List<ProductionBomStructure> orderBomStructureList = orderBom == null || orderBom.getId() == null |
| | | ? Collections.emptyList() |
| | | : productionBomStructureMapper.selectList( |
| | | Wrappers.<ProductionBomStructure>lambdaQuery() |
| | | .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId()) |
| | | .orderByAsc(ProductionBomStructure::getId)); |
| | | |
| | | // 构建工序需求量映射 |
| | | Map<String, BigDecimal> operationDemandedQuantityMap = |
| | | TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(orderBomStructureList, rootProductModelId); |
| | | |
| | | // 获取工艺路线工序(用于计算计划数量) |
| | | TechnologyRoutingOperation sourceOperation = technologyRoutingOperationMapper.selectById( |
| | | updatedOperation.getTechnologyRoutingOperationId()); |
| | | // 将原来的私有方法替换为调用工具类 |
| | | BigDecimal planQuantity = TaskPlanQuantityUtil.resolveTaskPlanQuantity( |
| | | sourceOperation, |
| | | operationDemandedQuantityMap, |
| | | productionOrder, |
| | | rootProductModelId); |
| | | task.setPlanQuantity(planQuantity); |
| | | task.setCompleteQuantity(BigDecimal.ZERO); |
| | | task.setWorkOrderNo(generateNextTaskNo()); |
| | | task.setStatus(2); |
| | | productionOperationTaskMapper.insert(task); |
| | | } |
| | | } else { |
| | | // 不需要生产:检查工单是否存在 |
| | | if (productionOperationTask != null) { |
| | | validateTaskCanRemove(productionOperationTask); |
| | | // 没有报工,则删除工单 |
| | | productionOperationTaskMapper.deleteById(productionOperationTask.getId()); |
| | | } |
| | | } |
| | | |
| | | return R.ok(); |
| | | } |
| | | |
| | | private void validateTaskCanRemove(ProductionOperationTask task) { |
| | | if (task == null || task.getId() == null) { |
| | | return; |
| | | } |
| | | if (defaultDecimal(task.getCompleteQuantity()).compareTo(BigDecimal.ZERO) > 0) { |
| | | throw new ServiceException("工序已产生报工记录,无法根据 BOM 变更删除对应工序快照"); |
| | | } |
| | | long reportCount = productionProductMainMapper.selectCount( |
| | | Wrappers.<ProductionProductMain>lambdaQuery() |
| | | .eq(ProductionProductMain::getProductionOperationTaskId, task.getId())); |
| | | if (reportCount > 0) { |
| | | throw new ServiceException("工序已产生报工记录,无法根据 BOM 变更删除对应工单"); |
| | | } |
| | | } |
| | | |
| | | private BigDecimal defaultDecimal(BigDecimal value) { |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | @Override |
| | | public R deleteRouteItem(Long id) { |
| | | // 删除工艺路线 |
| | | try { |
| | | // 查询并准备业务数据 |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectOne( |
| | | new LambdaQueryWrapper<ProductionOperationTask>() |
| | | .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, id) |
| | | .last("limit 1")); |
| | | // 参数与前置条件校验 |
| | | if (productionOperationTask == null) { |
| | | throw new RuntimeException("删除失败:未找到关联的生产工单"); |
| | | } |
| | |
| | | List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList( |
| | | new LambdaQueryWrapper<ProductionProductMain>() |
| | | .eq(ProductionProductMain::getProductionOperationTaskId, productionOperationTask.getId())); |
| | | // 遍历处理数据并组装结果 |
| | | for (ProductionProductMain main : productionProductMains) { |
| | | productionProductMainService.removeProductMain(main.getId()); |
| | | } |
| | |
| | | ProductionOrderRoutingOperation item = operationList.get(i); |
| | | if (!Integer.valueOf(i + 1).equals(item.getDragSort())) { |
| | | item.setDragSort(i + 1); |
| | | // 持久化或输出处理结果 |
| | | productionOrderRoutingOperationMapper.updateById(item); |
| | | } |
| | | } |
| | |
| | | |
| | | @Override |
| | | public int sortRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) { |
| | | // 排序工艺路线 |
| | | ProductionOrderRoutingOperation oldItem = productionOrderRoutingOperationMapper.selectById(productionOrderRoutingOperation.getId()); |
| | | List<ProductionOrderRoutingOperation> operationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | private String generateNextTaskNo() { |
| | | // 生成下一个生产工单号 |
| | | String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); |
| | | String prefix = "GD" + datePrefix; |
| | | ProductionOperationTask lastTask = productionOperationTaskMapper.selectOne( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .likeRight(ProductionOperationTask::getWorkOrderNo, prefix) |
| | | .orderByDesc(ProductionOperationTask::getWorkOrderNo) |
| | | .last("limit 1")); |
| | | int sequence = 1; |
| | | if (lastTask != null && lastTask.getWorkOrderNo() != null && lastTask.getWorkOrderNo().startsWith(prefix)) { |
| | | try { |
| | | sequence = Integer.parseInt(lastTask.getWorkOrderNo().substring(prefix.length())) + 1; |
| | | } catch (NumberFormatException ignored) { |
| | | sequence = 1; |
| | | } |
| | | } |
| | | return prefix + String.format("%03d", sequence); |
| | | } |
| | | } |