package com.chinaztt.mes.plan.service.impl; import cn.hutool.core.collection.CollectionUtil; 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.baomidou.mybatisplus.extension.toolkit.SqlHelper; 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.common.util.WxCpUtils; import com.chinaztt.mes.plan.dto.MpsRequirementsDTO; import com.chinaztt.mes.plan.entity.*; import com.chinaztt.mes.plan.mapper.*; import com.chinaztt.mes.plan.service.MpsRequirementsService; import com.chinaztt.mes.plan.state.requirement.MpsRequirementsStateMachineConfig; import com.chinaztt.mes.plan.state.requirement.constant.MpsRequirementsEvents; import com.chinaztt.mes.plan.state.requirement.constant.MpsRequirementsStates; import com.chinaztt.ztt.admin.api.feign.RemoteParamService; import com.chinaztt.ztt.common.core.constant.SecurityConstants; import lombok.AllArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @ClassName MpsRequirementsServiceImpl * @Description TODO * @Author luh * @Date 2020/8/27 16:51 * @Version 1.0 **/ @Service @Transactional(rollbackFor = Exception.class) @AllArgsConstructor public class MpsRequirementsServiceImpl extends ServiceImpl implements MpsRequirementsService { private static Logger logger = LoggerFactory.getLogger(MpsRequirementsServiceImpl.class); private PlanJoinOrderRequirementsMapper planJoinOrderRequirementsMapper; private MpsSourceMapper planMpsSourceMapper; private MasterProductionScheduleMapper masterProductionScheduleMapper; private NumberGenerator requirementsNumberGenerator; private NumberGenerator scheduleNumberGenerator; private StateMachineFactory mpsRequirementsStateMachineFactory; private StateMachinePersister persister; private CustomerOrderMapper customerOrderMapper; private RemoteParamService remoteParamService; @Override public IPage> getMpsRequirementsPage(Page page, QueryWrapper mpsRequirements, String type) { return baseMapper.getMpsRequirementsPage(page, mpsRequirements, type); } @Override public boolean deleteById(Long id) { // 判断一下是否已生成主计划,若生成无法删除 List mpsNos = baseMapper.selectScheduleByRequirementsId(id); if (CollectionUtil.isNotEmpty(mpsNos)) { throw new RuntimeException("已生成对应主计划无法删除:" + mpsNos.stream().collect(Collectors.joining(","))); } // 1.删除主生产计划需求 boolean result = SqlHelper.retBool(baseMapper.deleteById(id)); // 2.删除主生产计划需求和客户订单关联表 planJoinOrderRequirementsMapper.delete(Wrappers.query().lambda() .eq(PlanJoinOrderRequirements::getMpsRequirementsId, id)); return result; } @Override public boolean updateById(MpsRequirements mpsRequirements) { boolean result = SqlHelper.retBool(baseMapper.updateById(mpsRequirements)); // 更新来源对应的主生产计划的最新时间 masterProductionScheduleMapper.updateRequiredDateBySource(mpsRequirements); try { String staffStr = remoteParamService.getByKey("MPS_REQUIMENT_UPDATE_STAFF", SecurityConstants.FROM_IN).getData(); if (StringUtils.isNotBlank(staffStr)) { WxCpUtils.inform(staffStr, mpsRequirements.getUpdateUser() + "编辑了主需求:" + mpsRequirements.getIndeRequNo(), null); } } catch (Exception e) { logger.error(e.getMessage()); throw new RuntimeException("编辑主需求消息推送失败"); } return result; } @Override public boolean save(MpsRequirements mpsRequirements) { mpsRequirements.setSourceType("01"); mpsRequirements.setIndeRequNo(requirementsNumberGenerator.generateNumberWithPrefix(MpsRequirements.DIGIT, MpsRequirements.PREFIX, MpsRequirements::getIndeRequNo)); boolean result = SqlHelper.retBool(baseMapper.insert(mpsRequirements)); try { String staffStr = remoteParamService.getByKey("MPS_REQUIMENT_INSERT_STAFF", SecurityConstants.FROM_IN).getData(); if (StringUtils.isNotBlank(staffStr)) { WxCpUtils.inform(staffStr, mpsRequirements.getUpdateUser() + "创建了主需求:" + mpsRequirements.getIndeRequNo(), null); } } catch (Exception e) { logger.error(e.getMessage()); throw new RuntimeException("新增主需求消息推送失败"); } return result; } @Override public MpsRequirementsDTO selectById(Long id) { return baseMapper.selectDtoById(id); } @Override public void checkOverageOrder(MpsRequirements mpsRequirements) { BigDecimal qtyRequiredSum = baseMapper.getQtyRequiredSumById(mpsRequirements.getId()); if (BigDecimal.ZERO.compareTo(qtyRequiredSum) == 0) { // 1.不存在客户订单 return; } else { // 2.查询对应客户订单的数量 BigDecimal orderQuantity = baseMapper.getOrderQuantityById(mpsRequirements.getId()); qtyRequiredSum = qtyRequiredSum.add(mpsRequirements.getQtyRequired()); if (qtyRequiredSum.compareTo(orderQuantity) == 1) { // 超出数量 throw new RuntimeException("修改后的总计划需求数量超出订单数量:" + qtyRequiredSum.subtract(orderQuantity).stripTrailingZeros().toPlainString()); } } } @Override public boolean changeState(List ids, String event) { if (CollectionUtil.isEmpty(ids)) { throw new RuntimeException("请选择主生产计划需求"); } for (Long id : ids) { MpsRequirements mpsRequirements = baseMapper.selectById(id); Message message = MessageBuilder.withPayload(MpsRequirementsEvents.valueOf(event)).setHeader("mpsRequirements", mpsRequirements).build(); StateMachineHandler handler = new StateMachineHandler(mpsRequirementsStateMachineFactory, persister, MpsRequirementsStateMachineConfig.MACHINE_ID, mpsRequirements); StateResult res = handler.sendEvent(message, mpsRequirements.getId()); if (!res.isSuccess()) { throw new RuntimeException(res.getMsg()); } } return true; } @Override public boolean createMasterProductionSchedule(List mpsRequirementsDTOList) { if (CollectionUtil.isEmpty(mpsRequirementsDTOList)) { throw new RuntimeException("请选择主生产计划需求"); } List> partList = new ArrayList<>(); // 1.先按零件分组 List> groupList = new ArrayList<>(); mpsRequirementsDTOList.stream().collect(Collectors.groupingBy(MpsRequirementsDTO::getPartId, Collectors.toList())) .forEach((part, listByPart) -> { groupList.add(listByPart); }); try { for (List listByPart : groupList) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); Long id = listByPart.get(0).getPartId(); LocalDateTime requiredDate = listByPart.get(0).getRequiredDate(); String date = formatter.format(listByPart.get(0).getCreateTime()); MasterProductionSchedule newMasterProductionSchedule = masterProductionScheduleMapper.getPlanProduction(id, date); if (newMasterProductionSchedule != null) { if (newMasterProductionSchedule.getRequiredDate().isBefore(listByPart.get(0).getRequiredDate())) { requiredDate = newMasterProductionSchedule.getRequiredDate(); } newMasterProductionSchedule.setQtyRequired(newMasterProductionSchedule.getQtyRequired().add(listByPart.get(0).getQtyPlaned())); newMasterProductionSchedule.setRequiredDate(requiredDate); newMasterProductionSchedule.setSource("主需求"); masterProductionScheduleMapper.updateById(newMasterProductionSchedule); // 2.3.保存主生产计划来源 for (MpsRequirementsDTO mpsRequirementsDTO : listByPart) { save(mpsRequirementsDTO, newMasterProductionSchedule.getId()); } } else { partList.add(listByPart); } } } catch (Exception e) { log.error("创建主生产计划失败", e); throw new RuntimeException("创建主生产计划失败"); } // 2.再合并生成主计划 try { for (List listByPart : partList) { // 2.1合并计划数量,取最早的需求日期 BigDecimal totalQuantity = BigDecimal.ZERO; LocalDateTime requiredDate = listByPart.get(0).getRequiredDate(); for (MpsRequirementsDTO mpsRequirementsDTO : listByPart) { totalQuantity = totalQuantity.add(mpsRequirementsDTO.getQtyPlaned()); if (mpsRequirementsDTO.getRequiredDate().isBefore(requiredDate)) { requiredDate = mpsRequirementsDTO.getRequiredDate(); } } // 2.2.保存主生产计划 MasterProductionSchedule masterProductionSchedule = new MasterProductionSchedule(); masterProductionSchedule.setMpsNo(scheduleNumberGenerator.generateNumberWithPrefix(MasterProductionSchedule.DIGIT, MasterProductionSchedule.PREFIX, MasterProductionSchedule::getMpsNo)); masterProductionSchedule.setPartId(listByPart.get(0).getPartId()); masterProductionSchedule.setQtyRequired(totalQuantity); masterProductionSchedule.setRequiredDate(requiredDate); masterProductionSchedule.setSource("主需求"); masterProductionScheduleMapper.insert(masterProductionSchedule); // 2.3.保存主生产计划来源 for (MpsRequirementsDTO mpsRequirementsDTO : listByPart) { save(mpsRequirementsDTO, masterProductionSchedule.getId()); } } } catch (Exception e) { log.error("创建主生产计划失败", e); throw new RuntimeException("创建主生产计划失败"); } return true; } @Override public List getCustomer(Long id) { return customerOrderMapper.getCustomer(id); } private void save(MpsRequirementsDTO mpsRequirementsDTO, Long id) { try { MpsSource planMpsSource = new MpsSource(); planMpsSource.setMpsId(id); planMpsSource.setMpsRequId(mpsRequirementsDTO.getId()); planMpsSource.setQtyPlaned(mpsRequirementsDTO.getQtyPlaned()); planMpsSource.setRemark(mpsRequirementsDTO.getRemark()); planMpsSourceMapper.insert(planMpsSource); // 2.4.更新对应的主生产计划需求-已计划数量 baseMapper.updatePlanRequiredById(mpsRequirementsDTO); } catch (Exception e) { log.error("保存主生产计划来源失败", e); throw new RuntimeException("保存主生产计划来源失败"); } } }