/* * 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.production.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.excel.util.CollectionUtils; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; 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.chinaztt.mes.basic.entity.Part; import com.chinaztt.mes.basic.entity.Template; import com.chinaztt.mes.basic.entity.Workstation; import com.chinaztt.mes.basic.mapper.BasicParamTemplateMapper; import com.chinaztt.mes.basic.mapper.PartMapper; import com.chinaztt.mes.basic.mapper.WorkstationMapper; import com.chinaztt.mes.common.constant.Constant; import com.chinaztt.mes.common.handler.StateMachineHandler; import com.chinaztt.mes.common.numgen.NumberGenerator; import com.chinaztt.mes.common.util.StateResult; import com.chinaztt.mes.plan.dto.ManufacturingOrderDTO; import com.chinaztt.mes.plan.dto.ManufacturingOrderOperationTemplateDTO; import com.chinaztt.mes.plan.dto.MoTestStandardDTO; import com.chinaztt.mes.plan.dto.MoTestStandardParamDTO; import com.chinaztt.mes.plan.entity.*; import com.chinaztt.mes.plan.mapper.*; import com.chinaztt.mes.plan.service.ManufacturingOrderService; import com.chinaztt.mes.plan.state.manufacturing.constant.ManufacturingOrderStateStringValues; import com.chinaztt.mes.production.dto.*; import com.chinaztt.mes.production.dto.mould.BasicInfoForPdaFeedDTO; import com.chinaztt.mes.production.entity.*; import com.chinaztt.mes.production.mapper.*; import com.chinaztt.mes.production.service.OperationTaskParamService; import com.chinaztt.mes.production.service.OperationTaskRecordService; import com.chinaztt.mes.production.service.OperationTaskService; import com.chinaztt.mes.production.state.operationtask.OperationTaskStateMachineConfig; import com.chinaztt.mes.production.state.operationtask.constant.OperationTaskEvents; import com.chinaztt.mes.production.state.operationtask.constant.OperationTaskStateStringValues; import com.chinaztt.mes.production.state.operationtask.constant.OperationTaskStates; import com.chinaztt.mes.production.vo.OperationTaskScreenVO; import com.chinaztt.mes.quality.entity.*; import com.chinaztt.mes.quality.mapper.*; import com.chinaztt.mes.quality.service.impl.ReportServiceImpl; import com.chinaztt.mes.technology.entity.Operation; import com.chinaztt.mes.technology.mapper.OperationMapper; import com.chinaztt.mes.warehouse.dto.PalletTransportsMaterialDTO; import com.chinaztt.mes.warehouse.entity.JoinStockOrder; import com.chinaztt.mes.warehouse.entity.Stock; import com.chinaztt.mes.warehouse.mapper.JoinStockOrderMapper; import com.chinaztt.mes.warehouse.mapper.StockMapper; import com.chinaztt.ztt.admin.api.feign.RemoteParamService; import com.chinaztt.ztt.common.core.constant.SecurityConstants; import com.chinaztt.ztt.common.core.util.R; import com.chinaztt.ztt.common.oss.OssProperties; import com.chinaztt.ztt.common.oss.service.OssTemplate; import com.chinaztt.ztt.common.sequence.sequence.Sequence; import com.google.gson.Gson; import lombok.AllArgsConstructor; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.springframework.core.env.Environment; import org.springframework.messaging.Message; import org.springframework.messaging.support.MessageBuilder; import org.springframework.statemachine.config.StateMachineFactory; import org.springframework.statemachine.persist.StateMachinePersister; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.Duration; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.Map.Entry; import java.util.stream.Collectors; /** * 工序任务 * * @author zhangxy * @date 2020-09-18 09:26:35 */ @Service @AllArgsConstructor @Transactional(rollbackFor = Exception.class) public class OperationTaskServiceImpl extends ServiceImpl implements OperationTaskService { private ApplyPartMapper applyPartMapper; private BasicParamTemplateMapper basicParamTemplateMapper; private CustomerOrderMapper customerOrderMapper; private CustomerOrderParamMapper customerOrderParamMapper; private JoinStockOrderMapper joinStockOrderMapper; private ManufacturingOrderMapper manufacturingOrderMapper; private ManufacturingOrderService manufacturingOrderService; private MoStructureComponentMapper moStructureComponentMapper; private MoRoutingOperationMapper moRoutingOperationMapper; private MoRoutingMapper moRoutingMapper; private ManufacturingOrderOperationTemplateMapper manufacturingOrderOperationTemplateMapper; private ManufacturingOrderOperationParamMapper manufacturingOrderOperationParamMapper; private MoTestStandardParamMapper moTestStandardParamMapper; private MoTestStandardMapper moTestStandardMapper; private NumberGenerator reportSampleNumberGenerator; private OperationTaskAttachmentMapper operationTaskAttachmentMapper; private OperationTaskSupplyMapper supplyMapper; private OperationTaskParamMapper operationTaskParamMapper; private OperationTaskProduceMapper operationTaskProduceMapper; private OperationTaskRecordMapper operationTaskRecordMapper; private OperationTaskMaterialMapper operationTaskMaterialMapper; private OperationTaskSupplyMapper operationTaskSupplyMapper; private OperationTaskMapper operationTaskMapper; private OperationMapper operationMapper; private ProductOutputMapper productOutputMapper; private PartMapper partMapper; private ReportSampleMapper reportSampleMapper; private ReportServiceImpl reportService; private ReportMeasuringToolMapper reportMeasuringToolMapper; private RemoteParamService remoteParamService; private ReportSampleItemMapper reportSampleItemMapper; private ReportMapper reportMapper; private StateMachineFactory operationTaskStateMachineFactory; private StateMachinePersister persister; private Sequence opTaskSequence; private WorkstationMapper workstationMapper; private StockMapper stockMapper; private SegmentationTaskRecordMapper segmentationTaskRecordMapper; private OperationTaskRecordService operationTaskRecordService; private OperationTaskParamService operationTaskParamService; private Environment environment; private final OssProperties ossProperties; private final OssTemplate minioTemplate; public static final String BUCKET_NAME = "mes"; @Override public IPage> getPage(Page page, QueryWrapper ew) { return baseMapper.queryPage(page, ew); } @Override public List getOperationTask(Long workstationId, String productSn, String salesOrder, String productName, String outBatchNo, String mpsNo) { List opreturn = new ArrayList<>(); if (workstationId == null) { return opreturn; } Workstation workstation = workstationMapper.selectById(workstationId); if (workstation == null) { return opreturn; } Boolean operationStockStatus = null; if (StringUtils.isNotBlank(outBatchNo)) { List stockList = stockMapper.selectList(Wrappers.lambdaQuery() .eq(Stock::getPartBatchNo, outBatchNo)); if (CollectionUtil.isNotEmpty(stockList)) { operationStockStatus = stockList.get(0).getOperationStockStatus(); } } //对应工作中心工单下面工作站位空的工单 和 对应的当前工作站的工单 QueryWrapper gen = Wrappers.query().eq("oot.work_center", workstation.getWorkCenter()); List operationTaskDTOS = baseMapper.getOperationTask(gen, true, productSn, salesOrder, productName, outBatchNo, mpsNo, operationStockStatus); operationTaskDTOS.forEach(operationTaskDTO -> { if (operationTaskDTO.getWorkstationId() == null) { opreturn.add(operationTaskDTO); } else { if (workstationId.equals(operationTaskDTO.getWorkstationId())) { opreturn.add(operationTaskDTO); } } }); return opreturn; } @Override public boolean changeState(List ids, String event) { if (CollectionUtil.isEmpty(ids)) { throw new RuntimeException("请选择至少一条工单"); } for (Long id : ids) { changeStateCommon(id, event); } return true; } @Override public boolean changeState(Long id, String event) { if (id == null) { throw new RuntimeException("请选择一条工单"); } changeStateCommon(id, event); return true; } public void changeStateCommon(Long id, String event) { OperationTask operationTask = baseMapper.selectById(id); // String moIfsNeedSync = remoteParamService.getByKey(Constant.MO_IFS_NEED_SYNC, SecurityConstants.FROM_IN).getData(); if (event.equals("UNSUBMIT")) { // String taskMoNo = baseMapper.getTaskMoNo(id); // ManufacturingOrder manufacturingOrder = manufacturingOrderMapper.selectOne(Wrappers.lambdaQuery() // .eq(ManufacturingOrder::getMoNo, taskMoNo)); // if (StringUtils.isBlank(manufacturingOrder.getIfsOrderNo()) && !org.apache.commons.lang3.StringUtils.equals(moIfsNeedSync, "false")) { // throw new RuntimeException("车间订单没有同步IFS"); // } // 调用 ERP派工单新增接口 ylErpJobOrderSave(id); operationTask.setState(OperationTaskStates.PENDING.getValue()); updateById(operationTask); } else if (event.equals("UNSUBMIT")) { operationTask.setState(OperationTaskStates.UNSUBMIT.getValue()); updateById(operationTask); } else { Message message = MessageBuilder.withPayload(OperationTaskEvents.valueOf(event)).setHeader("operationTask", operationTask).build(); StateMachineHandler handler = new StateMachineHandler(operationTaskStateMachineFactory, persister, OperationTaskStateMachineConfig.MACHINE_ID, operationTask); StateResult res = handler.sendEvent(message, operationTask.getId()); if (!res.isSuccess()) { throw new RuntimeException(res.getMsg()); } } //修改排程时间 changePlanTime(operationTask, event); } /** * 对接鹰联ERP派工 * * @param id 工单id */ private void ylErpJobOrderSave(Long id) { CustomerOrder customerOrder = customerOrderMapper.getCustomerOrderNoByOperationTaskId(id); if (null == customerOrder) { return; } if (null == customerOrder.getCustomerOrderNo()) { return; } //区分一下是不是鹰联的订单 鹰联订单开头是YL if (!customerOrder.getCustomerOrderNo().startsWith("YL")) { return; } List operationTaskMaterials = operationTaskMaterialMapper.selectList(new LambdaQueryWrapper().eq(OperationTaskMaterial::getOperationTaskId, id)); if (CollectionUtil.isEmpty(operationTaskMaterials)) { throw new RuntimeException("没有所需物料信息"); } List partIds = operationTaskMaterials.stream().map(OperationTaskMaterial::getPartId).collect(Collectors.toList()); List parts = partMapper.selectBatchIds(partIds); SaveWorkAssignsEntity saveWorkAssignsEntity = new SaveWorkAssignsEntity(); saveWorkAssignsEntity.setIsHasXLH(true); saveWorkAssignsEntity.setTitle("派工单" + id); saveWorkAssignsEntity.setCode(id + ""); saveWorkAssignsEntity.setHtid(customerOrder.getCustomerOrderNo()); List workAssignItems = new ArrayList<>(); List workAssignWFPs = new ArrayList<>(); BigDecimal num = new BigDecimal(0); for (OperationTaskMaterial operationTaskMaterial : operationTaskMaterials) { SaveWorkAssignsEntity.WorkAssignItems item = new SaveWorkAssignsEntity.WorkAssignItems(); item.setNeedNum(operationTaskMaterial.getQuantityRequired()); Long productID = parts.stream().filter(e -> e.getId().equals(operationTaskMaterial.getPartId())).findFirst().get().getPartFamilyId(); item.setProductID(productID); workAssignItems.add(item); num = num.add(operationTaskMaterial.getQuantityRequired()); SaveWorkAssignsEntity.WorkAssignWFPs wfPs = new SaveWorkAssignsEntity.WorkAssignWFPs(); wfPs.setNumMake(operationTaskMaterial.getQuantityRequired()); wfPs.setIsOut(0); wfPs.setUnitID(2); workAssignWFPs.add(wfPs); } saveWorkAssignsEntity.setWorkAssignItems(workAssignItems); saveWorkAssignsEntity.setWorkAssignWFPs(workAssignWFPs); saveWorkAssignsEntity.setNumMake(num); R r = addERPJobOrder(saveWorkAssignsEntity); if (r.getCode() != 0) { throw new RuntimeException(r.getMsg()); } } /** * @param saveWorkAssignsEntity * @return */ private R addERPJobOrder(SaveWorkAssignsEntity saveWorkAssignsEntity) { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); String syncErpUrl = environment.getProperty("addErpJobOrder"); HttpPost httpPost = new HttpPost(syncErpUrl); String jsonParams = new Gson().toJson(saveWorkAssignsEntity); // 设置请求体为JSON格式 StringEntity requestEntity = new StringEntity(jsonParams, ContentType.APPLICATION_JSON); httpPost.setEntity(requestEntity); String responseString = null; CloseableHttpResponse response = null; try { response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); responseString = EntityUtils.toString(entity, "UTF-8"); return new Gson().fromJson(responseString, R.class); } catch (IOException e) { e.printStackTrace(); } return R.failed(); } /** * 工单开始结束之后 修改计划开始结束时间 * * @param operationTask * @param event */ private void changePlanTime(OperationTask operationTask, String event) { LocalDateTime localDateTime = LocalDateTime.now(); //完成 if ("COMPLETE".equals(event)) { List operationTaskList = operationTaskMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(OperationTask::getPlannedFinishDate) .in(OperationTask::getState, Arrays.asList("07unsubmit", "01pending", "02inProgress", "03interrupted")) .eq(OperationTask::getWorkstationId, operationTask.getWorkstationId())); if (null != operationTask.getPlannedFinishDate()) { //获取时间的差值 分钟数 当前时间 - 计划完成时间 Duration dur = Duration.between(operationTask.getPlannedFinishDate(), localDateTime); Long mis = dur.toMinutes(); for (OperationTask taskChange : operationTaskList) { // 计划开始时间 = 计划开始时间 + 差值 if (null != taskChange.getPlannedStartDate()) { taskChange.setPlannedStartDate(taskChange.getPlannedStartDate().plusMinutes(mis)); } // 计划完成时间 = 计划完成时间 + 差值 if (null != taskChange.getPlannedFinishDate()) { taskChange.setPlannedFinishDate(taskChange.getPlannedFinishDate().plusMinutes(mis)); } baseMapper.updateById(taskChange); } } } } @Override public OperationTaskDTO getOperation(Long id) { OperationTaskDTO operationTaskDTO = baseMapper.getOperationTaskDTO(id); operationTaskDTO.setLocalDateTimes(Arrays.asList(operationTaskDTO.getPlannedStartDate(), operationTaskDTO.getPlannedFinishDate())); operationTaskDTO.setOutPutBatchList(operationTaskProduceMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getOperationTaskId, operationTaskDTO.getId()))); return operationTaskDTO; } /** * 新增工单 * * @param operationTaskDTO * @return */ private String saveSingle(OperationTaskDTO operationTaskDTO) { //如果前台没有指定工单类型默认是 M 制造 if (StringUtils.isBlank(operationTaskDTO.getOperationTaskType())) { operationTaskDTO.setOperationTaskType("M"); } //判断工单类型和符不符合当前工序 // 将IFS接口调用,放到最后一步,防止调用IFS接口成功,本地事务报错回滚,导致IFS接口数据无法回滚 ManufacturingOrder manufacturingOrder = manufacturingOrderMapper.selectById(operationTaskDTO.getMoId()); //if (manufacturingOrder.getState().equals(ManufacturingOrderStateStringValues.PLANNED)) { // manufacturingOrder.setState(ManufacturingOrderStateStringValues.ISSUED); // //调用ifs修改ifs车间订单状态 // R result = manufacturingOrderService.changeState(manufacturingOrder, "RELEASE"); // if (result.getCode() == 1) { // throw new RuntimeException(manufacturingOrder.getMoNo() + result.getMsg()); // } //} if (!checkTaskType(operationTaskDTO, manufacturingOrder)) { throw new RuntimeException("工序为:" + operationTaskDTO.getOperationName() + "的工单类型不符合"); } operationTaskDTO.setOptaskNo(opTaskSequence.nextNo()); operationTaskDTO.setState(OperationTaskStates.UNSUBMIT.getValue()); baseMapper.insert(operationTaskDTO); // 设置优先级 baseMapper.updateNextPriority(operationTaskDTO.getId()); OperationTask operationTask = baseMapper.selectOne(Wrappers.lambdaQuery().eq(OperationTask::getOptaskNo, operationTaskDTO.getOptaskNo())); OperationTaskSupply operationTaskSupply = new OperationTaskSupply(); operationTaskSupply.setMoId(operationTaskDTO.getMoId()); operationTaskSupply.setOperationTaskId(operationTask.getId()); operationTaskSupply.setQuantitySupply(operationTaskDTO.getPlannedQuantity()); operationTaskSupplyMapper.insert(operationTaskSupply); //添加工单所需物料 addMoStructureComponent(operationTaskDTO.getMoId(), operationTaskDTO.getPartId(), operationTask); // 更新制造订单主表的当前工序名称 //if (null != manufacturingOrder && !org.springframework.util.StringUtils.isEmpty(operationTaskDTO.getOperationName())) { // manufacturingOrder.setCurrentOperation(operationTaskDTO.getOperationName()); //} //manufacturingOrderMapper.updateById(manufacturingOrder); //修改段长关联关系 // List operationTaskProduceList = operationTaskDTO.getOutPutBatchList(); // if (CollectionUtil.isNotEmpty(operationTaskProduceList)) { // for (OperationTaskProduce operationTaskProduce : operationTaskProduceList) { // operationTaskProduce.setOperationTaskId(operationTaskDTO.getId()); // operationTaskProduceMapper.updateById(operationTaskProduce); // } // } return operationTaskDTO.getOptaskNo(); } /** * 单个工单新增 * * @param operationTaskDTO * @return */ @Override public String fullSave(OperationTaskDTO operationTaskDTO) { return batchFullSave(Collections.singletonList(operationTaskDTO)).get(0); } /** * 制造类型的车间订单的最后一道工序禁止创建【类型】为修理的工单 * 修理类型的车间订单则没有这个要求 * 判断当前工单是不是最后一道工序 * M :制造 * F :修理 * * @param operationTaskDTO * @return */ private boolean checkTaskType(OperationTaskDTO operationTaskDTO, ManufacturingOrder manufacturingOrder) { boolean isLast = true; //查询当前工序 MoRoutingOperation moRoutingOperation = moRoutingOperationMapper.selectById(operationTaskDTO.getMoRoutingOperationId()); //设置工艺路线id operationTaskDTO.setRoutingOperationId(moRoutingOperation.getTechnologyRoutingOperationId()); //如果车间订单类型是M 并且 工单是 F 类型 if ("M".equals(manufacturingOrder.getWorkshopTypeCode()) && "F".equals(operationTaskDTO.getOperationTaskType())) { //查询最后一道工序 MoRoutingOperation moRoutingOperationLast = moRoutingMapper.getLastMoRoutingOperation(operationTaskDTO.getMoId()); //如果两个工序的id 不一样 那就不是最后一道工序 if (moRoutingOperationLast.getId().equals(moRoutingOperation.getId())) { isLast = false; } } return isLast; } /** * 批量新增工单 * * @param operationTaskDTOList * @return */ @Override public List batchFullSave(List operationTaskDTOList) { List opTaskNoList = new ArrayList<>(); operationTaskDTOList.forEach(operationTaskDTO -> { opTaskNoList.add(saveSingle(operationTaskDTO)); }); releaseManufacturingOrder(operationTaskDTOList.get(0)); return opTaskNoList; } private void releaseManufacturingOrder(OperationTaskDTO operationTaskDTO) { //判断工单类型和符不符合当前工序 ManufacturingOrder manufacturingOrder = manufacturingOrderMapper.selectById(operationTaskDTO.getMoId()); if (manufacturingOrder.getState().equals(ManufacturingOrderStateStringValues.PLANNED)) { manufacturingOrder.setState(ManufacturingOrderStateStringValues.ISSUED); //调用ifs修改ifs车间订单状态 // R result = manufacturingOrderService.changeState(manufacturingOrder, "RELEASE"); // if (result.getCode() == 1) { // throw new RuntimeException(manufacturingOrder.getMoNo() + result.getMsg()); // } } //if (!checkTaskType(operationTaskDTO, manufacturingOrder)) { // throw new RuntimeException("工序为:" + operationTaskDTO.getOperationName() + "的工单类型不符合"); //} // 更新制造订单主表的当前工序名称 if (null != manufacturingOrder && !org.springframework.util.StringUtils.isEmpty(operationTaskDTO.getOperationName())) { manufacturingOrder.setCurrentOperation(operationTaskDTO.getOperationName()); } manufacturingOrderMapper.updateById(manufacturingOrder); } // public void addMoStructureComponent(Long moId, Long partId, OperationTask operationTask) { // ManufacturingOrder manufacturingOrder = manufacturingOrderMapper.selectById(moId); //// 计算出需要的根节点的数量 用计划数量 除以这个零件所有涉及到的qpa //// 先找到当前零件的所在节点 // List moStructureComponentList = moStructureComponentMapper.selectList(Wrappers.lambdaQuery() // .eq(MoStructureComponent::getPlanManufacturingOrderId, manufacturingOrder.getId()).eq(MoStructureComponent::getPartId, partId)); // if (CollectionUtil.isNotEmpty(moStructureComponentList)) { // BigDecimal sumUnitQpa = moStructureComponentList.stream().map(MoStructureComponent::getQpa).reduce(BigDecimal.ZERO, BigDecimal::add); // BigDecimal unitAcount = operationTask.getPlannedQuantity().divide(sumUnitQpa, 3, BigDecimal.ROUND_HALF_UP); // List materials = new ArrayList<>(); // for (MoStructureComponent moStructureComponent : moStructureComponentList) { // //找到当前零件的下级节点 // List newMoStructureComponentList = moStructureComponentMapper.selectList(Wrappers.lambdaQuery() // .eq(MoStructureComponent::getPlanManufacturingOrderId, manufacturingOrder.getId()) // .eq(MoStructureComponent::getParent, moStructureComponent.getId())); // if (CollectionUtil.isNotEmpty(newMoStructureComponentList)) { // for (MoStructureComponent newMoStructureComponent : newMoStructureComponentList) { // //工单所需物料保存 // OperationTaskMaterial material = new OperationTaskMaterial(); // material.setOperationTaskId(operationTask.getId()); // material.setPartId(newMoStructureComponent.getPartId()); // material.setQpa(newMoStructureComponent.getQpa().divide(moStructureComponent.getQpa(), 3, BigDecimal.ROUND_HALF_UP)); // material.setQuantityRequired((newMoStructureComponent.getQpa().multiply(unitAcount))); // materials.add(material); // } // } // } // Map> group = materials.stream().collect(Collectors.groupingBy(OperationTaskMaterial::getPartId)); // for (Map.Entry> map : group.entrySet()) { // OperationTaskMaterial material = new OperationTaskMaterial(); // BigDecimal quantityRequired = BigDecimal.ZERO; // for (OperationTaskMaterial operationTaskMaterial : map.getValue()) { // material.setOperationTaskId(operationTaskMaterial.getOperationTaskId()); // material.setPartId(operationTaskMaterial.getPartId()); // material.setQpa(operationTaskMaterial.getQpa()); // quantityRequired = quantityRequired.add(operationTaskMaterial.getQuantityRequired()); // } // material.setQuantityRequired(quantityRequired); // operationTaskMaterialMapper.insert(material); // } // } //} public void addMoStructureComponent(Long moId, Long partId, OperationTask operationTask) { MoRoutingOperation moRoutingOperation = moRoutingOperationMapper.selectById(operationTask.getMoRoutingOperationId()); Operation operation = operationMapper.selectById(moRoutingOperation.getOperationId()); if (operation == null) { throw new RuntimeException("工序丢失"); } // 根据零件id 和 车间订单id 查询产品结构半成品节点 List currentStrucList = moStructureComponentMapper.selectList(Wrappers.lambdaQuery() .eq(MoStructureComponent::getPlanManufacturingOrderId, moId) .eq(MoStructureComponent::getPartId, partId) .and(wrapper -> wrapper.ne(MoStructureComponent::getOperationId, moRoutingOperation.getOperationId()).or(w -> w.isNull(MoStructureComponent::getOperationId)))); // 零件id 的list if (CollectionUtil.isEmpty(currentStrucList)) { throw new RuntimeException("工序为:" + operation.getName() + "的工单生产的零件不存在车间订单bom中"); } //if (operationTask.getOperationTaskType().equals("M")) { List partIds = new ArrayList<>(); for (MoStructureComponent currentStruc : currentStrucList) { // 根据父节点id 和 消耗工序 车间订单id List childStrucList = moStructureComponentMapper.selectList(Wrappers.lambdaQuery() .eq(MoStructureComponent::getPlanManufacturingOrderId, moId) .eq(MoStructureComponent::getParent, currentStruc.getId()) .eq(MoStructureComponent::getOperationId, moRoutingOperation.getOperationId())); for (MoStructureComponent childStruc : childStrucList) { OperationTaskMaterial operationTaskMaterial = new OperationTaskMaterial(); operationTaskMaterial.setOperationTaskId(operationTask.getId()); operationTaskMaterial.setPartId(childStruc.getPartId()); operationTaskMaterial.setQpa(childStruc.getQpa().divide(currentStruc.getQpa(), 3, BigDecimal.ROUND_HALF_UP)); operationTaskMaterial.setQuantityRequired(operationTaskMaterial.getQpa().multiply(operationTask.getPlannedQuantity())); partIds.add(childStruc.getPartId()); operationTaskMaterialMapper.insert(operationTaskMaterial); } //查找当前工序的上一道工序的产出 MoRoutingOperation moRoutingOperationLast = getLastMoRoutingOperation(moId, operationTask.getMoRoutingOperationId()); if (null != moRoutingOperationLast.getPartId()) { if (!partIds.contains(moRoutingOperationLast.getPartId())) { OperationTaskMaterial operationTaskMaterial = new OperationTaskMaterial(); operationTaskMaterial.setOperationTaskId(operationTask.getId()); operationTaskMaterial.setPartId(moRoutingOperationLast.getPartId()); operationTaskMaterial.setQpa(BigDecimal.ONE); operationTaskMaterial.setQuantityRequired(operationTask.getPlannedQuantity()); partIds.add(moRoutingOperationLast.getPartId()); operationTaskMaterialMapper.insert(operationTaskMaterial); } } } //} //如果是修理就获取当前节点的零件 //if (operationTask.getOperationTaskType().equals("F")) { // OperationTaskMaterial operationTaskMaterial = new OperationTaskMaterial(); // operationTaskMaterial.setOperationTaskId(operationTask.getId()); // operationTaskMaterial.setPartId(partId); // operationTaskMaterial.setQpa(BigDecimal.ONE); // operationTaskMaterial.setQuantityRequired(operationTask.getPlannedQuantity()); // operationTaskMaterialMapper.insert(operationTaskMaterial); //} } /** * 根据工艺路线工序id 获取上一道工序 * * @param moId * @param id * @return */ private MoRoutingOperation getLastMoRoutingOperation(Long moId, Long id) { MoRoutingOperation moRoutingOperation = new MoRoutingOperation(); List moRoutingOperationList = moRoutingOperationMapper.selectList(Wrappers.lambdaQuery() .eq(MoRoutingOperation::getMoId, moId) .orderByAsc(MoRoutingOperation::getOperationOrder)); if (moRoutingOperationList.size() > 1) { for (int i = 1; i < moRoutingOperationList.size(); i++) { if (id.equals(moRoutingOperationList.get(i).getId())) { moRoutingOperation = moRoutingOperationList.get(i - 1); break; } } } return moRoutingOperation; } @Override public String fullUpdate(OperationTaskDTO operationTaskDTO) { OperationTask operationTask = baseMapper.selectById(operationTaskDTO.getId()); baseMapper.updateById(operationTaskDTO); OperationTask newOperationTask = baseMapper.selectById(operationTaskDTO.getId()); OperationTaskSupply operationTaskSupply = operationTaskSupplyMapper.selectOne(Wrappers.lambdaQuery() .eq(OperationTaskSupply::getOperationTaskId, operationTaskDTO.getId())); if (!operationTask.getRoutingOperationId().equals(newOperationTask.getRoutingOperationId())) { operationTaskMaterialMapper.delete(Wrappers.lambdaQuery().eq(OperationTaskMaterial::getOperationTaskId, operationTaskDTO.getId())); if (operationTaskSupply == null || operationTaskSupply.getMoId() == null) { throw new RuntimeException("工单不存在对应制造订单,添加对应的所需物料"); } //添加工单所需物料 addMoStructureComponent(operationTaskSupply.getMoId(), operationTaskDTO.getPartId(), newOperationTask); } if (operationTask.getPlannedQuantity().compareTo(newOperationTask.getPlannedQuantity()) != 0) { List operationTaskMaterialList = operationTaskMaterialMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskMaterial::getOperationTaskId, operationTaskDTO.getId())); for (OperationTaskMaterial operationTaskMaterial : operationTaskMaterialList) { operationTaskMaterial.setQuantityRequired(operationTaskMaterial.getQuantityRequired().subtract(operationTaskMaterial.getQuantityRequired()) .add(operationTaskMaterial.getQpa().multiply(newOperationTask.getPlannedQuantity()))); operationTaskMaterialMapper.updateById(operationTaskMaterial); } operationTaskSupply.setQuantitySupply(operationTaskDTO.getPlannedQuantity()); operationTaskSupplyMapper.updateById(operationTaskSupply); } return operationTask.getOptaskNo(); } @Override public boolean fullDelete(Long id) { baseMapper.deleteOperationById(id); return false; } @Override public List getOperationSupplyById(Long id) { List manufacturingOrderDTO = manufacturingOrderMapper.getOperationSupplyById(id); return manufacturingOrderDTO; } @Override public List getMaterial(QueryWrapper gen) { return operationTaskMaterialMapper.getMaterial(gen); } @Override public IPage> pdaPage(Page page, QueryWrapper gen) { return baseMapper.pdaPage(page, gen); } @Override public List pdaMaterial(QueryWrapper gen) { return operationTaskMaterialMapper.pdaMaterial(gen); } @Override public List getOperationMaterialById(Long id) { return operationTaskMaterialMapper.getOperationMaterialById(id); } @Override public OperationTaskMaterial getOperationMaterialByMaterialId(Long id) { return operationTaskMaterialMapper.getOperationMaterialByMaterialId(id); } @Override public R addOperationMaterial(OperationTaskMaterial operationTaskMaterial) { judgePartAndOperationTask(operationTaskMaterial.getPartId(), operationTaskMaterial.getOperationTaskId()); BigDecimal quantityRequired = calQuantityRequired(operationTaskMaterial.getOperationTaskId(), operationTaskMaterial.getQpa()); operationTaskMaterial.setQuantityRequired(quantityRequired); if (operationTaskMaterialMapper.insert(operationTaskMaterial) == 1) { return R.ok(); } else { return R.failed(); } } @Override public R updateOperationMaterial(OperationTaskMaterial operationTaskMaterial) { judgePartAndOperationTask(operationTaskMaterial.getPartId(), operationTaskMaterial.getOperationTaskId()); BigDecimal quantityRequired = calQuantityRequired(operationTaskMaterial.getOperationTaskId(), operationTaskMaterial.getQpa()); operationTaskMaterial.setQuantityRequired(quantityRequired); if (operationTaskMaterialMapper.updateById(operationTaskMaterial) == 1) { return R.ok(); } else { return R.failed(); } } /** * 判断零件和工序任务是否存在 * * @param partId * @param operationTaskId */ public void judgePartAndOperationTask(Long partId, Long operationTaskId) { Part part = partMapper.selectById(partId); OperationTask operationTask = operationTaskMapper.selectById(operationTaskId); if (part == null || operationTask == null) { throw new RuntimeException("没有此零件或者此工序任务!"); } } /** * 计算需求数量 * * @param operationTaskId * @param qpa */ public BigDecimal calQuantityRequired(Long operationTaskId, BigDecimal qpa) { OperationTask operationTask = operationTaskMapper.selectById(operationTaskId); BigDecimal quantityRequired = operationTask.getPlannedQuantity().multiply(qpa).setScale(6, RoundingMode.HALF_UP); return quantityRequired; } @Override public R deleteOperationMaterial(Long id) { if (operationTaskMaterialMapper.deleteById(id) == 1) { return R.ok(); } else { return R.failed(); } } @Override public List getTemplate(Long id) { List manufacturingOrderOperationTemplateDTOList = manufacturingOrderOperationTemplateMapper.getTemplate(id); if (CollectionUtil.isNotEmpty(manufacturingOrderOperationTemplateDTOList)) { for (ManufacturingOrderOperationTemplateDTO manufacturingOrderOperationTemplateDTO : manufacturingOrderOperationTemplateDTOList) { List manufacturingOrderOperationParamList = manufacturingOrderOperationParamMapper.selectList(Wrappers.lambdaQuery().eq(ManufacturingOrderOperationParam::getMoRoutingOperationId, manufacturingOrderOperationTemplateDTO.getMoRoutingOperationId()) .eq(ManufacturingOrderOperationParam::getOperationTemplateId, manufacturingOrderOperationTemplateDTO.getId())); if (CollectionUtil.isNotEmpty(manufacturingOrderOperationParamList)) { manufacturingOrderOperationTemplateDTO.setParamList(manufacturingOrderOperationParamList); } else { manufacturingOrderOperationTemplateDTO.setParamList(null); } } } return manufacturingOrderOperationTemplateDTOList; } @Override public IPage> getTemplateUpdate(Page page, Long id, Template template) { return basicParamTemplateMapper.getTemplateUpdate(page, id, template); } @Override public IPage> getTemplateByType(Page page, QueryWrapper