/* * Copyright (c) 2018-2025, ztt All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: ztt */ package com.chinaztt.mes.plan.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; import com.chinaztt.mes.plan.dto.*; import com.chinaztt.mes.plan.entity.*; import com.chinaztt.mes.plan.mapper.*; import com.chinaztt.mes.plan.service.CustomerOrderProduceTaskService; import com.chinaztt.mes.plan.service.CustomerOrderService; import com.chinaztt.mes.plan.service.ManufacturingOrderService; import com.chinaztt.mes.plan.state.masterproductionschedule.constant.MasterProductionScheduleStateStringValues; import com.chinaztt.mes.technology.entity.JoinDocumentBomRouting; import com.chinaztt.mes.technology.entity.Operation; import com.chinaztt.mes.technology.mapper.JoinDocumentBomRoutingMapper; import com.chinaztt.mes.technology.mapper.OperationMapper; import com.chinaztt.mes.technology.entity.RoutingOperation; import groovy.util.MapEntry; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * 段长任务单 * * @author shz * @date 2023-03-07 09:28:25 */ @AllArgsConstructor @Transactional(rollbackFor = Exception.class) @Service public class CustomerOrderProduceTaskServiceImpl extends ServiceImpl implements CustomerOrderProduceTaskService { private OperationTaskProduceMapper operationTaskProduceMapper; private CustomerOrderService customerOrderService; private MasterProductionScheduleTheoryQuantityMapper masterProductionScheduleTheoryQuantityMapper; private ManufacturingOrderService manufacturingOrderService; private MasterProductionScheduleMapper masterProductionScheduleMapper; private OperationMapper operationMapper; private ManufacturingOrderSnGenerateMapper manufacturingOrderSnGenerateMapper; private JoinDocumentBomRoutingMapper joinDocumentBomRoutingMapper; @Override public List getPage(QueryWrapper gen) { return this.baseMapper.getPage(gen); } @Override public synchronized boolean submit(List customerOrderProduceTasks) { if (CollectionUtil.isNotEmpty(customerOrderProduceTasks)) { List ids = customerOrderProduceTasks.stream().map(CustomerOrderProduceTask::getId).collect(Collectors.toList()); List taskList = this.baseMapper.selectBatchIds(ids); long count = taskList.stream().filter(task -> CustomerOrderProduceTask.STATUS_SUBMIT.equals(task.getStatus())).count(); if (count > 0) { throw new RuntimeException("存在任务单已提交,请刷新后重试"); } for (CustomerOrderProduceTaskDTO customerOrderProduceTask : customerOrderProduceTasks) { if (CollectionUtil.isEmpty(customerOrderProduceTask.getRoutingOperations())) { throw new RuntimeException("合并缆号->" + customerOrderProduceTask.getMergeSnNo() + ",未设置起始工序!"); } } // 查询合并缆号为相同的任务单一起提交 List leftoverTasks = this.baseMapper.selectList(Wrappers.lambdaQuery() .in(CustomerOrderProduceTask::getMergeSnNo, taskList.stream().map(CustomerOrderProduceTask::getMergeSnNo).distinct().collect(Collectors.toList())) .notIn(CustomerOrderProduceTask::getId, ids)); taskList.addAll(leftoverTasks); // 根据零件id进行分组 Map> taskMapByPart = taskList.stream().collect(Collectors.groupingBy(CustomerOrderProduceTask::getPartId)); for (Map.Entry> taskMapByPartEntry : taskMapByPart.entrySet()) { long checkDocumentCount = taskMapByPartEntry.getValue().stream().map(CustomerOrderProduceTask::getTechnologyDocumentId).distinct().count(); if (checkDocumentCount > 1) { throw new RuntimeException("相同零件的工艺文件不一致,无法一起提交"); } // 生成主生产计划号 // 这里根据销售订单id再分组 List customerOrderDTOList = new ArrayList<>(); Map> taskMapByOrder = taskMapByPartEntry.getValue().stream().collect(Collectors.groupingBy(CustomerOrderProduceTask::getCustomerOrderId)); for (Map.Entry> taskMapByOrderEntry : taskMapByOrder.entrySet()) { // 组装生成主生产计划所需数据 CustomerOrderDTO customerOrderDTO = BeanUtil.copyProperties(customerOrderService.getById(taskMapByOrderEntry.getKey()), CustomerOrderDTO.class); List operationTaskProduces = this.operationTaskProduceMapper.selectBatchIds(taskMapByOrderEntry.getValue().stream().map(CustomerOrderProduceTask::getOperationTaskProduceId).collect(Collectors.toList())); customerOrderDTO.setOutPutBatchList(operationTaskProduces); customerOrderDTO.setQtyPlaned(operationTaskProduces.stream().map(OperationTaskProduce::getQty).reduce(BigDecimal.ZERO, BigDecimal::add)); customerOrderDTO.setPartId(taskMapByPartEntry.getKey()); customerOrderDTOList.add(customerOrderDTO); } // 创建主生产计划,更新任务单状态为已处理 MasterProductionSchedule productionSchedule = customerOrderService.createOneMasterProductionScheduleByCustomerOrders(customerOrderDTOList); masterProductionScheduleMapper.update(null, Wrappers.lambdaUpdate() .set(MasterProductionSchedule::getState, MasterProductionScheduleStateStringValues.PROCESSED) .eq(MasterProductionSchedule::getId, productionSchedule.getId())); // 更新任务单主计划id this.baseMapper.update(null, Wrappers.lambdaUpdate() .set(CustomerOrderProduceTask::getMpsId, productionSchedule.getId()) .in(CustomerOrderProduceTask::getId, taskMapByPartEntry.getValue().stream().map(CustomerOrderProduceTask::getId).collect(Collectors.toList()))); Optional first = customerOrderProduceTasks.stream() .filter(task -> task.getPartId().equals(taskMapByPartEntry.getValue().get(0).getPartId())).findFirst(); if (first.isPresent()) { if (CollectionUtil.isEmpty(first.get().getRoutingOperations())) { throw new RuntimeException("未选择开始工序"); } // 根据主生产计划号创建车间订单 // 1.查询半成品理论用量 List theoryQuantityList = masterProductionScheduleTheoryQuantityMapper.getTheoryQuantity(productionSchedule.getId()); // 2.创建车间订单 List manufacturingOrderList = new ArrayList<>(); // 找出所有开始的节点 List startRoutings = joinDocumentBomRoutingMapper.selectList(Wrappers.lambdaQuery() .eq(JoinDocumentBomRouting::getDocumentId, productionSchedule.getTechnologyDocumentId()) .in(JoinDocumentBomRouting::getRoutingId, first.get().getRoutingOperations().stream().map(RoutingOperation::getRoutingId).collect(Collectors.toList()))); Set totalRoutings = new HashSet<>(); // 递归找出所有的节点 for (JoinDocumentBomRouting startRouting : startRoutings) { totalRoutings.addAll(joinDocumentBomRoutingMapper.findAllParentBomRoutingsById(startRouting.getId())); } // 去重 List collect = totalRoutings.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(JoinDocumentBomRouting::getId))), ArrayList::new)); Map manufacturingOrderMap = new HashMap<>(); for (MasterProductionScheduleTheoryQuantityDTO theoryQuantityDTO : theoryQuantityList) { boolean flag = false; for (JoinDocumentBomRouting joinDocumentBomRouting : collect) { if (joinDocumentBomRouting.getBomId().equals(theoryQuantityDTO.getBomId()) && joinDocumentBomRouting.getRoutingId().equals(theoryQuantityDTO.getRoutingId())) { flag = true; break; } } if (flag) { if (manufacturingOrderMap.containsKey(theoryQuantityDTO.getPartId())) { ManufacturingOrderDTO manufacturingOrderDTO = manufacturingOrderMap.get(theoryQuantityDTO.getPartId()); manufacturingOrderDTO.setQtyRequired(manufacturingOrderDTO.getQtyRequired().add(theoryQuantityDTO.getOrderQuantity())); manufacturingOrderMap.put(theoryQuantityDTO.getPartId(), manufacturingOrderDTO); } else { ManufacturingOrderDTO manufacturingOrderDTO = new ManufacturingOrderDTO(); manufacturingOrderDTO.setMpsId(productionSchedule.getId()); manufacturingOrderDTO.setPartId(theoryQuantityDTO.getPartId()); manufacturingOrderDTO.setPartNo(theoryQuantityDTO.getPartNo()); manufacturingOrderDTO.setPartName(theoryQuantityDTO.getPartName()); manufacturingOrderDTO.setTechnologyRoutingId(theoryQuantityDTO.getRoutingId()); manufacturingOrderDTO.setBomId(theoryQuantityDTO.getBomId()); manufacturingOrderDTO.setQtyRequired(theoryQuantityDTO.getOrderQuantity()); manufacturingOrderDTO.setRequiredDate(productionSchedule.getRequiredDate()); manufacturingOrderDTO.setWorkShop(customerOrderProduceTasks.get(0).getWorkshop()); manufacturingOrderDTO.setWorkshopTypeCode("M"); manufacturingOrderDTO.setScheduleTheoryQuantityId(theoryQuantityDTO.getId()); manufacturingOrderDTO.setManufactureAttr(productionSchedule.getManufactureAttr()); manufacturingOrderDTO.setIsReportOperation(true); manufacturingOrderMap.put(theoryQuantityDTO.getPartId(), manufacturingOrderDTO); } } } manufacturingOrderMap.forEach((k, v) -> { manufacturingOrderList.add(v); }); manufacturingOrderService.addBatchForMerge(manufacturingOrderList, first.get().getRoutingOperations(), first.get().getIsGenerateSn()); List operationIds = first.get().getRoutingOperations().stream().map(RoutingOperation::getOperationId).distinct().collect(Collectors.toList()); List operation = operationMapper.selectBatchIds(operationIds); this.baseMapper.update(null, Wrappers.lambdaUpdate() .set(CustomerOrderProduceTask::getOperationId, StrUtil.join(",", operationIds)) .set(CustomerOrderProduceTask::getOperationName, StrUtil.join(",", operation.stream().map(Operation::getName).collect(Collectors.toList()))) .set(CustomerOrderProduceTask::getWorkshop, first.get().getWorkshop()) .set(CustomerOrderProduceTask::getStatus, CustomerOrderProduceTask.STATUS_SUBMIT) .in(CustomerOrderProduceTask::getId, taskMapByPartEntry.getValue().stream().map(CustomerOrderProduceTask::getId).collect(Collectors.toList()))); } } } return true; } @Override public boolean back(List ids) { if (CollectionUtil.isNotEmpty(ids)) { List customerOrderProduceTasks = this.baseMapper.selectBatchIds(ids); long count = customerOrderProduceTasks.stream().filter(task -> CustomerOrderProduceTask.STATUS_SUBMIT.equals(task.getStatus())).count(); if (count > 0) { throw new RuntimeException("存在任务单已提交,无法退回"); } // 查询合并缆号为相同的任务单 List leftoverTasks = this.baseMapper.selectList(Wrappers.lambdaQuery() .in(CustomerOrderProduceTask::getMergeSnNo, customerOrderProduceTasks.stream().map(CustomerOrderProduceTask::getMergeSnNo).distinct().collect(Collectors.toList())) .notIn(CustomerOrderProduceTask::getId, ids)); if (CollectionUtil.isNotEmpty(leftoverTasks)) { customerOrderProduceTasks.addAll(leftoverTasks); } // 删除任务单数据 this.baseMapper.deleteBatchIds(customerOrderProduceTasks.stream().map(CustomerOrderProduceTask::getId).collect(Collectors.toList())); // 更新批次表状态为未生成任务单 return SqlHelper.retBool(this.operationTaskProduceMapper.update(null, Wrappers.lambdaUpdate() .set(OperationTaskProduce::getIsGenerateTask, false) .in(OperationTaskProduce::getId, customerOrderProduceTasks.stream().map(CustomerOrderProduceTask::getOperationTaskProduceId).collect(Collectors.toList())))); } return false; } @Override public boolean fullUpdate(CustomerOrderProduceTask customerOrderProduceTask) { CustomerOrderProduceTask task = this.getById(customerOrderProduceTask.getId()); if (task == null) { throw new RuntimeException("任务单不存在"); } if (task.getStatus().equals(CustomerOrderProduceTask.STATUS_SUBMIT)) { throw new RuntimeException("任务单已提交,无法修改"); } List leftoverTasks = this.baseMapper.selectList(Wrappers.lambdaQuery() .eq(CustomerOrderProduceTask::getMergeSnNo, task.getMergeSnNo()) .ne(CustomerOrderProduceTask::getId, customerOrderProduceTask.getId())); List ids = new ArrayList<>(); ids.add(customerOrderProduceTask.getId()); if (CollectionUtil.isNotEmpty(leftoverTasks)) { ids.addAll(leftoverTasks.stream().map(CustomerOrderProduceTask::getId).collect(Collectors.toList())); } return this.update(Wrappers.lambdaUpdate() .set(CustomerOrderProduceTask::getOperationProduceQty, customerOrderProduceTask.getOperationProduceQty()) .in(CustomerOrderProduceTask::getId, ids)); } @Override public List getPartsByOrderNo(String otcCustomerOrderNo) { return this.baseMapper.getPartsByOrderNo(otcCustomerOrderNo); } @Override public List getOperationsByTaskIds(List ids) { if (CollectionUtil.isEmpty(ids)) { throw new RuntimeException("未选择数据!"); } List result = new ArrayList<>(); List customerOrderProduceTasks = this.baseMapper.selectBatchIds(ids); if (CollectionUtil.isNotEmpty(customerOrderProduceTasks)) { if (customerOrderProduceTasks.stream().map(CustomerOrderProduceTask::getTechnologyDocumentId).distinct().count() > 1) { throw new RuntimeException("选择的任务单的工艺文件不一致!无法设置相同工序!"); } result = this.baseMapper.getOperationsByTaskIds(ids); } return result; } }