package com.chinaztt.mes.plan.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; 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.ifs.api.feign.IfsFeignClient; import com.chinaztt.mes.basic.entity.Part; import com.chinaztt.mes.basic.mapper.PartMapper; import com.chinaztt.mes.common.handler.StateMachineHandler; import com.chinaztt.mes.common.numgen.NumberGenerator; import com.chinaztt.mes.common.oa.OAProcess; import com.chinaztt.mes.common.oa.OAProperty; import com.chinaztt.mes.common.oa.OAResult; import com.chinaztt.mes.common.util.StateResult; import com.chinaztt.mes.plan.dto.*; import com.chinaztt.mes.plan.entity.*; import com.chinaztt.mes.plan.mapper.*; import com.chinaztt.mes.plan.service.CustomerOrderService; import com.chinaztt.mes.plan.service.MasterProductionScheduleService; import com.chinaztt.mes.plan.state.auditstate.constant.AuditStateStringValues; import com.chinaztt.mes.plan.state.masterproductionschedule.MasterProductionScheduleStateMachineConfig; import com.chinaztt.mes.plan.state.masterproductionschedule.constant.MasterProductionScheduleEvents; import com.chinaztt.mes.plan.state.masterproductionschedule.constant.MasterProductionScheduleStates; import com.chinaztt.mes.technology.entity.Document; import com.chinaztt.mes.technology.entity.Routing; import com.chinaztt.mes.technology.entity.Structure; import com.chinaztt.mes.technology.mapper.DocumentMapper; import com.chinaztt.mes.technology.mapper.RoutingMapper; import com.chinaztt.mes.technology.mapper.StructureMapper; import com.chinaztt.mes.technology.service.DocumentService; import com.chinaztt.mes.technology.state.document.constant.DocumentStates; import com.chinaztt.ztt.admin.api.vo.TreeUtil; import com.chinaztt.ztt.common.core.util.R; import com.chinaztt.ztt.common.security.util.SecurityUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; 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.util.CollectionUtils; import java.math.BigDecimal; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 计划 * * @author cxf * @date 2020-09-21 14:42:39 */ @Slf4j @Service @AllArgsConstructor @Transactional(rollbackFor = Exception.class) public class MasterProductionScheduleServiceImpl extends ServiceImpl implements MasterProductionScheduleService { private CustomerOrderMapper customerOrderMapper; private CustomerOrderService customerOrderService; private DocumentMapper documentMapper; private DocumentService documentService; private IfsFeignClient ifsFeignClient; private MasterProductionScheduleMapper masterProductionScheduleMapper; private MasterProductionScheduleTheoryQuantityMapper masterProductionScheduleTheoryQuantityMapper; private MpsSourceMapper planMpsSourceMapper; private MpsStructureComponentMapper mpsStructureComponentMapper; private NumberGenerator scheduleNumberGenerator; private OAProperty oaProperty; private OutsourcingOrderMapper outsourcingOrderMapper; private OperationTaskProduceMapper operationTaskProduceMapper; private PartMapper partMapper; private RoutingMapper routingMapper; private StructureMapper structureMapper; private StateMachineFactory masterproductionscheduleStateMachineFactory; private StateMachinePersister persister; private MoStructureComponentMapper moStructureComponentMapper; @Override public IPage> getMasterProductionSchedulePage(Page page, QueryWrapper masterProductionScheduleDTO) { return baseMapper.getMasterProductionSchedulePage(page, masterProductionScheduleDTO); } @Override public MasterProductionScheduleDTO getByIdExt(Long id) { if (null == id) { return null; } return baseMapper.getByIdExt(id); } @Override public List loadMasterPlanSourceById(Long id) { return planMpsSourceMapper.loadMasterPlanSourceById(id); } @Override public boolean updateQtyPlaned(CustomerOrderDTO customerOrderDTO) { MasterProductionSchedule masterProductionSchedule = baseMapper.selectById(customerOrderDTO.getMpsId()); // 1.检查对应需求数量是否超出:客户订单的销售数量require - 客户订单的已下发数量original >= 主计划的修改数量updatePlan - 主计划的下发数量plan(有需要可以简化,当前方便阅读) //主计划的修改数量 BigDecimal updatePlan = customerOrderDTO.getQtyPlaned(); // 2.3 保存计划 masterProductionSchedule.setQtyRequired(updatePlan); baseMapper.updateById(masterProductionSchedule); // 删除原先的理论用量重 masterProductionScheduleTheoryQuantityMapper.delete(Wrappers.lambdaQuery() .eq(MasterProductionScheduleTheoryQuantity::getMid, masterProductionSchedule.getId())); // 重新计算理论用量 customerOrderService.calPlanTheory(masterProductionSchedule); return true; } @Override public List saveMpsStructureComponent(List list, Long mpsId) { MpsStructureComponentDTO mpsStructureComponentDTO = list.get(0); // 1.先把对应的主计划产品结构全部删除 mpsStructureComponentMapper.delete(Wrappers.query().lambda().eq(MpsStructureComponent::getMpsId, mpsId)); // 2.保存结构 if (mpsStructureComponentDTO.getParentId() == null) { mpsStructureComponentDTO.setParentId(0L); } saveOrUpdateComponent(mpsStructureComponentDTO, mpsId); return list; } public void saveOrUpdateComponent(MpsStructureComponentDTO mpsStructureComponentDTO, Long mpsId) { // 如果存在id就更新回来,其他就新增 if (mpsStructureComponentDTO.getId() != null) { mpsStructureComponentMapper.updateActiveById(mpsStructureComponentDTO.getId()); } else { mpsStructureComponentDTO.setMpsId(mpsId); mpsStructureComponentDTO.setManufacturingOrderQuantity(BigDecimal.ZERO); mpsStructureComponentMapper.insert(mpsStructureComponentDTO); } List children = mpsStructureComponentDTO.getChildren(); if (CollectionUtil.isNotEmpty(children)) { for (MpsStructureComponentDTO component : children) { if (component.getParentId() == null) { component.setParentId(mpsStructureComponentDTO.getId()); } saveOrUpdateComponent(component, mpsId); } } } @Override public boolean deleteMpsStructureComponentById(Long id) { // 递归删除结构节点 recursiveDeleteMpsStructureComponent(id); return true; } public void recursiveDeleteMpsStructureComponent(Long id) { mpsStructureComponentMapper.delete(Wrappers.query().lambda().eq(MpsStructureComponent::getId, id).ne(MpsStructureComponent::getParentId, 0)); List children = mpsStructureComponentMapper.selectList(Wrappers.query().lambda().eq(MpsStructureComponent::getParentId, id)); if (CollectionUtil.isNotEmpty(children)) { for (MpsStructureComponent child : children) { recursiveDeleteMpsStructureComponent(child.getId()); } } } @Override public List getMpsStructureComponentByMpsId(Long id) { List collect = mpsStructureComponentMapper.selectDtoListByMpsId(id) .stream().sorted(Comparator.comparing(MpsStructureComponent::getId)).map(mpsStructureComponentDTO -> { MpsStructureComponentTreeNode node = new MpsStructureComponentTreeNode(); node.setId(mpsStructureComponentDTO.getId().intValue()); node.setPartId(mpsStructureComponentDTO.getPartId()); node.setPartNo(mpsStructureComponentDTO.getPartNo()); node.setDrawingNumber(mpsStructureComponentDTO.getDrawingNumber()); node.setUnit(mpsStructureComponentDTO.getUnit()); node.setParentId(mpsStructureComponentDTO.getParentId().intValue()); node.setLabel(mpsStructureComponentDTO.getLabel()); node.setManufacturingOrderQuantity(mpsStructureComponentDTO.getManufacturingOrderQuantity()); node.setMpsId(mpsStructureComponentDTO.getMpsId()); node.setQpa(mpsStructureComponentDTO.getQpa()); return node; }).collect(Collectors.toList()); return TreeUtil.build(collect, 0); } @Override public MpsStructureComponentDTO insertMpsStructureComponent(MpsStructureComponentDTO mpsStructureComponentDTO, Long mpsId) { try { saveOrUpdateComponent(mpsStructureComponentDTO, mpsId); } catch (Exception e) { throw new RuntimeException("新增节点失败"); } return mpsStructureComponentDTO; } @Override public boolean updateMpsStructureComponent(MpsStructureComponentDTO mpsStructureComponentDTO) { return SqlHelper.retBool(mpsStructureComponentMapper.updateById(mpsStructureComponentDTO)); } @Override public boolean changeState(List ids, String event) { for (Long id : ids) { MasterProductionSchedule masterProductionSchedule = baseMapper.selectById(id); Message message = MessageBuilder.withPayload(MasterProductionScheduleEvents.valueOf(event)).setHeader("masterProductionSchedule", masterProductionSchedule).build(); StateMachineHandler handler = new StateMachineHandler(masterproductionscheduleStateMachineFactory, persister, MasterProductionScheduleStateMachineConfig.MACHINE_ID, masterProductionSchedule); StateResult res = handler.sendEvent(message, masterProductionSchedule.getId()); if (!res.isSuccess()) { throw new RuntimeException(res.getMsg()); } } return true; } @Override public List loadOrder(Long id) { return outsourcingOrderMapper.loadOrderByMpsId(id); } @Override public List loadMasterPlanSourceByCustomer(Long id) { return customerOrderMapper.loadMasterPlanSourceByCustomer(id); } @Override public R handleDocument(List ids, Long docId) { Integer count = baseMapper.selectCount(Wrappers.lambdaQuery() .isNotNull(MasterProductionSchedule::getTechnologyDocumentId) .in(MasterProductionSchedule::getId, ids)); if (count > 0) { return R.failed("存在关联的生产计划"); } else { List masterProductionScheduleList = baseMapper.selectBatchIds(ids); Document document = documentMapper.selectById(docId); if (document == null) { return R.failed("工艺文件缺失"); } else { masterProductionScheduleList.forEach(MasterProductionSchedule -> { MasterProductionSchedule.setTechnologyDocumentId(document.getId()); MasterProductionSchedule.setDocNumber(document.getNumber()); baseMapper.updateById(MasterProductionSchedule); customerOrderService.calPlanTheory(MasterProductionSchedule); }); return R.ok(); } } } /** * 取消关联 * * @param ids * @return */ @Override public R rejectHandleDocument(List ids) { for (Long id : ids) { MasterProductionSchedule masterProductionSchedule = baseMapper.selectById(id); // if (masterProductionSchedule.getIsAudit() != null) { // if (masterProductionSchedule.getIsAudit().equals(AuditStateStringValues.ACCEPTED) || masterProductionSchedule.getIsAudit().equals(AuditStateStringValues.PENDING)) { // return R.failed("生产计划号为" + masterProductionSchedule.getMpsNo() + ",已在流程中不可取消关联"); // } // } baseMapper.rejectHandleDocument(id); masterProductionScheduleTheoryQuantityMapper.delete(Wrappers.lambdaQuery() .eq(MasterProductionScheduleTheoryQuantity::getMid, id)); } return R.ok(); } /** * oa对接 * * @param id * @return */ @Override public R oa(Long id) { try { MasterProductionSchedule masterProductionSchedule = baseMapper.selectById(id); if (masterProductionSchedule.getTechnologyDocumentId() == null) { return R.failed("请先关联工艺文件"); } Map fields = new HashMap<>(); Document document = documentMapper.selectById(masterProductionSchedule.getTechnologyDocumentId()); Part part = partMapper.selectById(document.getPartId()); //零件编号 fields.put("part_no", part.getPartNo()); //零件名称 fields.put("part_desc", part.getPartName()); //产品名称 fields.put("product_name", part.getPartName()); //规格型号 fields.put("product_style", part.getSpecs()); //订单来源 fields.put("source", "masterProductionSchedule"); //工艺文件展示连接 fields.put("technology_document_id", "工艺审批流程,点击阅览"); OAResult oaResult = OAProcess.start(fields, "工艺审批流程", oaProperty.getCustomerOrderOaId(), SecurityUtils.getUser().getUsername()); if (oaResult.success()) { //OA流程发起成功,状态变成待审批 ,订单和工艺文件同步进行 masterProductionSchedule.setOaWorkflowId(oaResult.getAddWorkflowResult()); masterProductionSchedule.setIsAudit(AuditStateStringValues.PENDING); baseMapper.updateById(masterProductionSchedule); document.setOaWorkflowId(oaResult.getAddWorkflowResult()); document.setState(DocumentStates.PENDING.getValue()); documentMapper.updateById(document); return R.ok().setMsg("发起成功"); } else { return R.failed(oaResult.getErrorMsg()); } } catch (Exception e) { return R.failed("发起失败"); } } @Override public R changeAudit(Long id, String status) { MasterProductionSchedule masterProductionSchedule = baseMapper.selectById(id); Document document = documentMapper.selectById(masterProductionSchedule.getTechnologyDocumentId()); if (document == null) { return R.failed("缺少工艺文件"); } masterProductionSchedule.setIsAudit(status); baseMapper.updateById(masterProductionSchedule); if (status.equals(AuditStateStringValues.ACCEPTED)) { document.setState(status); documentService.saveOrUpdate(document); } return R.ok().setMsg("操作成功"); } @Override public R queryInventUseablePlanStd(String partNo) { if (StringUtils.isBlank(partNo)) { return R.failed("无零件号"); } R result = ifsFeignClient.queryInventUseablePlanStd(new JSONObject().fluentPut("PART_NO", partNo), true); if (result.getCode() == 0) { JSONObject data = (JSONObject) JSON.toJSON(result.getData()); return R.ok(data.getJSONArray("LIST_INFO"), "OK"); } else { return R.failed("IFS错误——" + result.getMsg()); } } /** * 工艺文件对接IFS * * @param id * @return */ @Override public R checkIfsSync(Long id) { MasterProductionSchedule masterProductionSchedule = masterProductionScheduleMapper.selectById(id); if (masterProductionSchedule.getTechnologyDocumentId() != null) { Document document = documentMapper.selectById(masterProductionSchedule.getId()); if (document == null) { return R.failed("工艺文件丢失"); } List routingList = routingMapper.selectUnIfsSyncByDocId(document.getId()); if (!CollectionUtils.isEmpty(routingList)) { return R.failed("工艺路线未同步"); } List structureList = structureMapper.getUnIfsedStructureDtoByDocId(document.getId()); if (!CollectionUtils.isEmpty(structureList)) { return R.failed("产品结构未同步"); } } return R.ok(); } /** * 查询半成品理论用量 * * @param id * @return */ @Override public R getTheoryQuantity(Long id, List operationTaskProduceList) { List masterProductionScheduleTheoryQuantityDTOList = masterProductionScheduleTheoryQuantityMapper.getTheoryQuantity(id); // changeQty(id, masterProductionScheduleTheoryQuantityDTOList, operationTaskProduceList); return R.ok(masterProductionScheduleTheoryQuantityDTOList); } /** * 成品订单需求数量改为段长长度和 * * @param id * @param masterProductionScheduleTheoryQuantityDTOList * @param operationTaskProduceList */ private void changeQty(Long id, List masterProductionScheduleTheoryQuantityDTOList, List operationTaskProduceList) { if (CollectionUtil.isNotEmpty(operationTaskProduceList)) { //查询成品的用量 List list = masterProductionScheduleTheoryQuantityMapper.selectList( Wrappers.lambdaQuery() .eq(MasterProductionScheduleTheoryQuantity::getMid, id) .eq(MasterProductionScheduleTheoryQuantity::getIsMaster, true) ); if (list.size() != 1) { throw new RuntimeException("成品工序的理论用量丢失,或存在多个成品理论用量"); } //段长长度总和 BigDecimal totalQuantity = operationTaskProduceList.stream().map(OperationTaskProduce::getQty).reduce(BigDecimal.ZERO, BigDecimal::add); masterProductionScheduleTheoryQuantityDTOList.forEach(e -> { //成品理论数量 BigDecimal rtq = list.get(0).getQuantity(); //成品段长长度总和 BigDecimal tq = totalQuantity; //当前产出的理论用量 BigDecimal thq = e.getQuantity(); //实际数量 BigDecimal acq = thq.multiply(tq).divide(rtq).setScale(3, BigDecimal.ROUND_UP); e.setOrderQuantity(acq); }); } } /** * 手动新增生产计划 * * @param masterProductionSchedule * @return */ @Override public R doAdd(MasterProductionSchedule masterProductionSchedule) { if (StringUtils.isBlank(masterProductionSchedule.getManufactureAttr())) { masterProductionSchedule.setManufactureAttr("N"); } masterProductionSchedule.setMpsNo(scheduleNumberGenerator.generateNumberWithPrefix(MasterProductionSchedule.DIGIT, MasterProductionSchedule.PREFIX, MasterProductionSchedule::getMpsNo)); masterProductionSchedule.setIsAudit(AuditStateStringValues.DRAFT); return R.ok(save(masterProductionSchedule)); } /** * 根据id查询 * * @param id * @return */ @Override public MasterProductionScheduleDTO getById(Long id) { MasterProductionScheduleDTO masterProductionScheduleDTO = baseMapper.getDtoById(id); List operationTaskProduceList = operationTaskProduceMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getMpsId, id)); masterProductionScheduleDTO.setOutPutBatchList(operationTaskProduceList); return masterProductionScheduleDTO; } /** * 添加采购计划 * @param masterProductionSchedules * @return */ @Override public boolean addPlanPurchasing(ListmasterProductionSchedules) { masterProductionSchedules.forEach(p->{ Long technologyDocumentId = p.getTechnologyDocumentId(); Document document = documentMapper.selectById(technologyDocumentId); Long firstPart = document.getPartId(); List moStructureComponents = moStructureComponentMapper.selectList(new QueryWrapper().lambda().eq(MoStructureComponent::getPlanManufacturingOrderId, p.getId())); moStructureComponents.forEach(m->{ Part part = partMapper.selectById(m.getPartId()); String url="http://192.168.20.47:8008/PurchService.ashx?contract=ZTKJ&contractKey=4ttDeLKNsZuhstjtROMcRE1USNFXKdFYE7lQ2p1m5Bo=&procedureName=QUERY_INVENTORY_INFO_STD&userId=7632&inAttr={\"LOCATION_NO\": \"1019\",\"PART_NO\":"+part.getPartNo()+"}"; String body = HttpRequest.get(url).execute().body(); JSONObject partInfo = JSONObject.parseObject(body); log.info("库存零件==================================>"+partInfo); }); }); return false; } }