package com.chinaztt.mes.aps.service.impl; import cn.hutool.core.collection.CollectionUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.chinaztt.mes.aps.core.domain.OperationBo; import com.chinaztt.mes.aps.core.domain.Order; import com.chinaztt.mes.aps.entity.Resource; import com.chinaztt.mes.aps.entity.ResourceDuration; import com.chinaztt.mes.aps.entity.SceneTask; import com.chinaztt.mes.aps.mapper.ApsCoreMapper; import com.chinaztt.mes.aps.mapper.ResourceDurationMapper; import com.chinaztt.mes.aps.mapper.ResourceMapper; import com.chinaztt.mes.aps.mapper.SceneTaskMapper; import com.chinaztt.mes.aps.service.ApsCoreService; import com.chinaztt.mes.aps.vo.GanttTaskVo; import com.chinaztt.mes.aps.vo.ResourceVo; import com.chinaztt.mes.basic.entity.Workstation; import com.chinaztt.mes.basic.mapper.WorkstationMapper; import com.chinaztt.mes.plan.entity.MoStructureComponent; import com.chinaztt.mes.plan.mapper.MoStructureComponentMapper; import com.chinaztt.mes.production.dto.OperationTaskDTO; import com.chinaztt.mes.production.entity.OperationTask; import com.chinaztt.mes.production.entity.OperationTaskMaterial; import com.chinaztt.mes.production.entity.OperationTaskSupply; import com.chinaztt.mes.production.mapper.OperationTaskMapper; import com.chinaztt.mes.production.mapper.OperationTaskMaterialMapper; import com.chinaztt.mes.production.mapper.OperationTaskSupplyMapper; import com.chinaztt.mes.production.state.operationtask.constant.OperationTaskStateStringValues; import com.chinaztt.ztt.common.core.util.R; import com.chinaztt.ztt.common.sequence.sequence.Sequence; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * @Author: zhangxy * @Date: 2020-10-09 10:35 */ @Service @AllArgsConstructor public class ApsCoreServiceImpl implements ApsCoreService { private Sequence opTaskSequence; private ApsCoreMapper apsCoreMapper; private ResourceMapper resourceMapper; private ResourceDurationMapper resourceDurationMapper; private SceneTaskMapper sceneTaskMapper; private OperationTaskMapper operationTaskMapper; private OperationTaskSupplyMapper operationTaskSupplyMapper; private MoStructureComponentMapper moStructureComponentMapper; private OperationTaskMaterialMapper operationTaskMaterialMapper; private WorkstationMapper workstationMapper; @Override public void saveSceneTask(SceneTask task) { sceneTaskMapper.insert(task); } @Override public OperationBo queryOperation(Long operationId) { return apsCoreMapper.queryOperation(operationId); } @Override public JSONObject query(Long sceneId, Long groupId, LocalDate start, LocalDate end) { List resources; if (groupId == null || groupId == 0) { resources = apsCoreMapper.getAllResourceVo(); } else { resources = apsCoreMapper.queryResourceByGroupId(groupId); } Set resourceIds = resources.stream().map(r -> r.getId()).collect(Collectors.toSet()); JSONObject obj = new JSONObject(); obj.put("resources", resources); if (sceneId != null && sceneId > 0) { obj.put("sceneTasks", apsCoreMapper.querySceneTaskByTimeRange(sceneId, start, end, resourceIds)); } obj.put("operationTasks", apsCoreMapper.queryOperationTaskByTimeRange(start, end, resourceIds)); return obj; } @Override public JSONObject loadGantt(Long sceneId, List workStationList, String workCenter, LocalDate start, LocalDate end, List stateList) { List resources = apsCoreMapper.queryResourceByGroupIdGantt(workStationList, workCenter); Set workstationIds = resources.stream().map(r -> r.getId()).collect(Collectors.toSet()); JSONObject obj = new JSONObject(); obj.put("resources", resources); if (sceneId != null && sceneId > 0) { obj.put("sceneTasks", apsCoreMapper.querySceneTaskByTimeRange(sceneId, start, end, workstationIds)); } obj.put("operationTasks", apsCoreMapper.queryOperationTaskByTimeRangeGantt(start, end, workstationIds, stateList)); return obj; } /** * 根据工作站零件数量计算机台时间 * * @param workstationId * @param partId * @param qty * @return */ @Override public OperationTaskDTO calOperationTaskTime(Long workstationId, Long partId, BigDecimal qty) { OperationTaskDTO operationTask = new OperationTaskDTO(); //根据工作站查询资源 Resource resource = resourceMapper.selectOne(Wrappers.lambdaQuery() .eq(Resource::getWorkstationId, workstationId)); if (resource != null) { //根据资源id和零件id 查询资源产能 List resourceDurationList = resourceDurationMapper.selectList(Wrappers.lambdaQuery() .orderByDesc(ResourceDuration::getId) .eq(ResourceDuration::getPartId, partId) .eq(ResourceDuration::getResourceId, resource.getId())); if (CollectionUtil.isNotEmpty(resourceDurationList)) { ResourceDuration resourceDuration = resourceDurationList.get(0); //工单时间 = (计划数量 / 机台速率) + 前置时间 + 后置时间 单位是分钟 BigDecimal machnieTime = qty.divide(resourceDuration.getProductionRate(), 0, BigDecimal.ROUND_UP) .add(resourceDuration.getPostProcessing()) .add(resourceDuration.getSetupTime()); //查询未完成的工单的最大的计划完成时间 如果没有就获取当前时间 LocalDateTime localDateTime = apsCoreMapper.getOperatioTaskMaxPlanEndTime(workstationId); if (localDateTime == null) { localDateTime = LocalDateTime.now(); } operationTask.setTaskTheoreticalTime(machnieTime); operationTask.setPlannedStartDate(localDateTime.plusMinutes(1)); operationTask.setPlannedFinishDate(operationTask.getPlannedStartDate().plusMinutes(machnieTime.longValue())); } } return operationTask; } /** * 根据零件数量 自动选择机台 * * @param partId * @param qty * @return */ @Override public OperationTaskDTO autoSetTime(String workCenter, Long partId, BigDecimal qty) { OperationTaskDTO returnOp = new OperationTaskDTO(); //查询当前工作中心下面配置了 资源能力的 工作站 List workstationIds = apsCoreMapper.getWorkstationIdByWorkcenter(workCenter, partId); if (CollectionUtil.isNotEmpty(workstationIds)) { // 在这些工作站 中查找 未完成的工单 并且根据 计划完成时间 正序排序 List operationTaskList = operationTaskMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(OperationTask::getPlannedFinishDate) .isNotNull(OperationTask::getPlannedFinishDate) .in(OperationTask::getState, Arrays.asList("07unsubmit", "01pending", "02inProgress", "03interrupted")) .in(OperationTask::getWorkstationId, workstationIds)); //设置默认时间为当前 LocalDateTime planStartDate = LocalDateTime.now(); //如果工单存 就先看看有没有不存在工单的机台 如果都有工单机台就选取第一个 工单的机台 时间根据最早时间计算 如果不存在工单就 工作站 选取第一个 时间获取当前 if (CollectionUtil.isNotEmpty(operationTaskList)) { //将工单根据工作站进行分组 Map> mapWorkstationIdOps = operationTaskList.stream().collect(Collectors.groupingBy(OperationTask::getWorkstationId)); //过滤出在产工作台 List optaskStationIdList = new ArrayList<>(mapWorkstationIdOps.keySet()); //过滤出空闲工作台 List noOptaskStationIdList = workstationIds.stream().filter(item -> optaskStationIdList.stream().allMatch(each -> !item.equals(each))).collect(Collectors.toList()); //如果 空闲工作台 是空的 if (CollectionUtil.isEmpty(noOptaskStationIdList)) { OperationTask firstFirstFinished = operationTaskList.get(0); returnOp.setWorkstationId(firstFirstFinished.getWorkstationId()); //如果最早的结束时间在当前时间之后 开始时间就是当前时间 + 1min if (firstFirstFinished.getPlannedFinishDate().isAfter(LocalDateTime.now())) { planStartDate = firstFirstFinished.getPlannedFinishDate().plusMinutes(1); } } else { returnOp.setWorkstationId(noOptaskStationIdList.get(0)); } } else { returnOp.setWorkstationId(workstationIds.get(0)); } returnOp.setPlannedStartDate(planStartDate); //查询资源 Resource resource = resourceMapper.selectOne(Wrappers.lambdaQuery() .eq(Resource::getWorkstationId, returnOp.getWorkstationId())); //查询能力 ResourceDuration resourceDuration = resourceDurationMapper.selectOne(Wrappers.lambdaQuery() .orderByDesc(ResourceDuration::getId) .eq(ResourceDuration::getPartId, partId) .eq(ResourceDuration::getResourceId, resource.getId()) .last("limit 1")); //计算工单需要完成时间 BigDecimal machnieTime = qty.divide(resourceDuration.getProductionRate(), 0, BigDecimal.ROUND_UP) .add(resourceDuration.getPostProcessing()) .add(resourceDuration.getSetupTime()); //结束时间 + 完成时间 returnOp.setPlannedFinishDate(returnOp.getPlannedStartDate().plusMinutes(machnieTime.longValue())); returnOp.setTaskTheoreticalTime(machnieTime); Workstation workstation = workstationMapper.selectById(returnOp.getWorkstationId()); returnOp.setWorkstationNo(workstation.getWorkstationNo()); returnOp.setWorkstationName(workstation.getName()); } return returnOp; } @Override public Boolean updateTaskById(GanttTaskVo taskVo) { SceneTask task = sceneTaskMapper.selectById(Long.valueOf(taskVo.getId())); task.setStartTime(taskVo.getStartDate()); task.setEndTime(taskVo.getEndDate()); task.setResourceId(Long.valueOf(taskVo.getParent())); sceneTaskMapper.updateById(task); return Boolean.TRUE; } @Override public Boolean removeSceneTask(Long id) { sceneTaskMapper.deleteById(id); return Boolean.TRUE; } @Transactional(rollbackFor = Exception.class) @Override public synchronized R applyToReality(Long sceneId) { List taskList = sceneTaskMapper.selectList(Wrappers.lambdaQuery().eq(SceneTask::getSceneId, sceneId).eq(SceneTask::getApplied, false)); if (CollectionUtil.isEmpty(taskList)) { return R.failed("该场景下没有未应用的内容"); } for (SceneTask sceneTask : taskList) { OperationTask optask = new OperationTask(); String number = opTaskSequence.nextNo(); optask.setOptaskNo(number); optask.setRoutingId(sceneTask.getRoutingId()); optask.setRoutingOperationId(sceneTask.getRoutingOperationId()); optask.setState(OperationTaskStateStringValues.PENDING); optask.setPlannedQuantity(sceneTask.getQuantity()); optask.setPlannedStartDate(sceneTask.getStartTime()); optask.setPlannedFinishDate(sceneTask.getEndTime()); optask.setPartId(sceneTask.getPartId()); Resource resource = resourceMapper.selectById(sceneTask.getResourceId()); optask.setWorkstationId(resource.getWorkstationId()); optask.setResourceId(resource.getId()); operationTaskMapper.insert(optask); createMaterial(optask); createSupply(optask, sceneTask); sceneTask.setApplied(true); sceneTaskMapper.updateById(sceneTask); } return R.ok(); } /** * 工单供应表 暂定1:1 * todo 拆分或者合并订单 * * @param optask * @param sceneTask */ private void createSupply(OperationTask optask, SceneTask sceneTask) { OperationTaskSupply supply = new OperationTaskSupply(); supply.setMoId(sceneTask.getOrderId()); supply.setOperationTaskId(optask.getId()); supply.setQuantitySupply(sceneTask.getQuantity()); operationTaskSupplyMapper.insert(supply); } private void createMaterial(OperationTask optask) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery().eq(MoStructureComponent::getRoutingOperationId, optask.getRoutingOperationId()); List list = moStructureComponentMapper.selectList(wrapper); if (CollectionUtil.isNotEmpty(list)) { for (MoStructureComponent s : list) { OperationTaskMaterial material = new OperationTaskMaterial(); material.setOperationTaskId(optask.getId()); material.setPartId(s.getPartId()); material.setQpa(s.getQpa()); material.setQuantityRequired(s.getQpa().multiply(optask.getPlannedQuantity())); operationTaskMaterialMapper.insert(material); } } } }