diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/IYieldOrderCraftService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/IYieldOrderCraftService.java index 1fbf812d3..21a88162e 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/IYieldOrderCraftService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/IYieldOrderCraftService.java @@ -15,39 +15,41 @@ import java.util.List; */ public interface IYieldOrderCraftService extends BaseService { - /** - * 自定义分页 - * - * @param page - * @param entity - * @return - */ - IPage selectPage(IPage page, YieldOrderCraft entity); - - /** - * 根据生产订单ID查询工艺列表 - * - * @param yoId - * @return - */ - List listByYoId(Long yoId); - - /** - * 根据生产订单ID删除工艺列表 - * - * @param yoId - * @return - */ - int deleteByYoId(Long yoId); - - /** - * 查找订单各工序的加工单位 - * - * @param yieldOrderCraftList 订单工艺列表 - * @param yieldOrder 生产订单 - * @param factor null 整体 ,true : 转厂内 ,false:转厂外 - * @param rxlSpace 需要特殊分派,true:需要, false:不需要,null:不需要 - * @throws BusinessException - */ - void automaticDispatch(List yieldOrderCraftList, YieldOrder yieldOrder, Boolean factor, Boolean rxlSpace) throws Exception; + /** + * 自定义分页 + * + * @param page + * @param entity + * @return + */ + IPage selectPage(IPage page, YieldOrderCraft entity); + + /** + * 根据生产订单ID查询工艺列表 + * + * @param yoId + * @return + */ + List listByYoId(Long yoId); + + /** + * 根据生产订单ID删除工艺列表 + * + * @param yoId + * @return + */ + int deleteByYoId(Long yoId); + + /** + * 查找订单各工序的加工单位 + * + * @param yieldOrderCraftList 订单工艺列表 + * @param yieldOrder 生产订单 + * @param factor null 整体 ,true : 转厂内 ,false:转厂外 + * @param rxlSpace 需要特殊分派,true:需要, false:不需要,null:不需要 + * @throws BusinessException + */ + void automaticDispatch(List yieldOrderCraftList, YieldOrder yieldOrder, Boolean factor, Boolean rxlSpace) throws Exception; + + List listByYoIdAndNo(Long id, String orders); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/impl/YieldOrderCraftServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/impl/YieldOrderCraftServiceImpl.java index 58a7ed950..49e8593cc 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/impl/YieldOrderCraftServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/impl/YieldOrderCraftServiceImpl.java @@ -51,714 +51,743 @@ import java.util.stream.Collectors; @Service public class YieldOrderCraftServiceImpl extends BaseServiceImpl implements IYieldOrderCraftService { - private final IWorkCenterService workCenterService; - private final IOemService oemService; - private final IOemCraftAbilityService oemCraftAbilityService; - private final IBsCraftAbilityService craftAbilityService; - private final IBsAssignService assignService; - private final IYieldOrderDailyAssignService dailyAssignService; - - private final IYieldOrderAssignSteerService assignSteerService; - private final IBsProcessSetService processSetService; - private final IBsTeamSetService teamSetService; - private final YieldOrderMapper yieldOrderMapper; - private final ICraftAbilityService iCraftAbilityService; - - @Override - public IPage selectPage(IPage page, YieldOrderCraft entity) { - List dataList = baseMapper.selectPage(page, entity); - return page.setRecords(dataList); - } - - @Override - public List listByYoId(Long yoId) { - LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(YieldOrderCraft.class) - .eq(YieldOrderCraft::getYoId, yoId) - .eq(YieldOrderCraft::getIsDeleted, CommonConstant.DELETE_FALSE).orderByAsc(YieldOrderCraft::getProcessNo); - List craftList = baseMapper.selectList(queryWrapper); - craftList.stream().forEach(item ->{ - BsProcessSetEntity processSet = processSetService.getById(item.getPpsId()); - if(processSet != null){ - item.setProcessCode(processSet.getCode()); - item.setProcessName(processSet.getName()); - } - if(item.getIsOutsource()){ - if(null != item.getOcId()){ - Oem oem = oemService.getById(item.getOcId()); - if(null != oem){ - item.setWorkCenterName(oem.getOcName()); - } - } - }else { - if(null != item.getWorkCenterId()){ - WorkCenter workCenter = workCenterService.getById(item.getWorkCenterId()); - if(null != workCenter){ - item.setWorkCenterName(workCenter.getWcName()); - } - } - } - }); - return craftList; - } - - @Override - public int deleteByYoId(Long yoId) { - LambdaQueryWrapper deleteWrapper = Wrappers.lambdaQuery(YieldOrderCraft.class).eq(YieldOrderCraft::getYoId, yoId).eq(YieldOrderCraft::getIsDeleted, CommonConstant.DELETE_FALSE); - return baseMapper.delete(deleteWrapper); - } - - @Override - public void automaticDispatch(List yieldOrderCraftList, YieldOrder yieldOrder, Boolean factor, Boolean rxlSpace) throws Exception { - // 组装key为工艺能力的作业计划map - Map> craftAbilityMap = yieldOrderCraftList.stream() - .collect(Collectors.groupingBy(YieldOrderCraft::getCaId,LinkedHashMap::new,Collectors.toList())); - //作业计划map工艺能力key集合 - Set craftKeys = craftAbilityMap.keySet(); - //获取到认定的主工艺能力(默认第一个工艺能力为主工艺能力) - Long hostAbilityId = craftKeys.iterator().next(); - BsCraftAbilityEntity craftAbility = craftAbilityService.getById(hostAbilityId); - //获取可以做此主工艺能力的作业中心集合 - Map workCenterMap = workCenterService.selectByAbility(hostAbilityId, yieldOrder.getYpQty(), yieldOrder.getYpArea(), yieldOrder.getPartCode(), yieldOrder.getPrimaryCraft(), yieldOrder.getYieldType(), rxlSpace); - //获取可以做此主工艺能力的外协商集合 - List oemList = oemService.selectByAbility(hostAbilityId, yieldOrder.getYpQty(), yieldOrder.getYpArea(), yieldOrder.getPartCode(), yieldOrder.getPrimaryCraft(), yieldOrder.getYieldType(), yieldOrder.getPlate(), rxlSpace); - - // 如果未找到适合的班组或者供应商,提示排查方向 - if ((workCenterMap == null || workCenterMap.size() == 0) && (oemList == null || oemList.size() == 0)) { - throw new BusinessException("未找到合适的作业中心或者供应商!请排查工艺能力、作业中心等因素!"); - } - - // 查询是否存在必须厂内且等级要求的规则,如果是则需要验证作业中心必须有值 - List mustAssignList = assignService.listMustAssign(hostAbilityId, BsAssignEntity.IN_FACTORY); - if (mustAssignList != null && mustAssignList.size() > 0) { - // 遍历强制规则,查找跟订单匹配的质量等级规则,若规则不为空,判定厂内作业中心列表是否为空 - for (BsAssignEntity mustAssign : mustAssignList) { - if (StringUtils.isNotBlank(mustAssign.getProdMark())) { - if (mustAssign.getProdMark().contains("\"" + yieldOrder.getProductIdent() + "\"")) { - if (workCenterMap == null || workCenterMap.size() == 0) { - throw new BusinessException("未找到合适的作业中心或者供应商!请排查工艺能力、作业中心等因素!"); - } - } - } - } - } - - //获取到可以做主工艺能力的最合适的作业中心,并且标记必须、优先、正常 - WorkCenter workCenter = null; - //获取到可以做主工艺能力的最合适的外协商,并且标记必须、优先、正常 - Oem oemCustomer = null; - //自动分派后的结果集 - List dispatchCraftList = null; - - // 根据车间订单是否厂内标识判定是否强制厂内(单工序时不进行标识验证) - if (yieldOrder.getSiteWork() && factor == null) { - log.info("自动分派,流程卡号:{},标注厂内生产", yieldOrder.getCardNo()); - //订单强制分派厂内,若未找到工艺能力对应的作业中心,则提示异常 - if (workCenterMap == null || workCenterMap.isEmpty()) { - throw new BusinessException("此订单需强制分派厂内,未找到满足条件得作业中心,自动分派失败!1"); - } - //寻找最合适的作业中心 - workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); - if (workCenter == null) { - throw new BusinessException("此订单需强制分派厂内,未找到满足条件得作业中心,自动分派失败!2"); - } - } else if (factor != null) { - if (factor) { - workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); - } else if (!factor) { - oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); - } - } else { - // 先判定规则是否存在零件级强制匹配 - BsAssignEntity partAssign = assignService.getByPartCode(hostAbilityId, yieldOrder.getPartCode()); - if (partAssign != null && partAssign.getCenterId() != null) { - log.info("自动分派,流程卡号:{},指定厂内作业中心生产", yieldOrder.getCardNo()); - // 指定厂内作业中心生产 - workCenter = workCenterService.getWorkCenter(partAssign.getCenterId()); - } else if (partAssign != null && partAssign.getOemId() != null) { - // 指定外协商生产 - log.info("自动分派,流程卡号:{},指定外协商生产", yieldOrder.getCardNo()); - oemCustomer = oemService.getById(partAssign.getOemId()); - } else if (partAssign != null && partAssign.getLimitType().equals(BsAssignEntity.MUST.toString())) { - if (partAssign.getPointType().equals(BsAssignEntity.IN_FACTORY.toString())) { - // 必须厂内生产 - log.info("自动分派,流程卡号:{},必须厂内生产", yieldOrder.getCardNo()); - workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); - } else { - //必须外协生产 - log.info("自动分派,流程卡号:{},必须外协生产", yieldOrder.getCardNo()); - oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); - } - } else { - // 寻找最合适的作业中心 - log.info("自动分派,流程卡号:{},寻找最合适的作业中心或班组", yieldOrder.getCardNo()); - workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_NORMAL); - oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_NORMAL); - } - } - log.info("自动分派,流程卡号:{},作业中心:{},外协商:{}", yieldOrder.getCardNo(), workCenter, oemCustomer); - // factor等于null代表是整体,有值时代表是单工序,true转厂内,false转厂外 - if (factor == null) { - if (workCenter != null && oemCustomer == null) { - log.info("自动分派,流程卡号:{},分派到厂内", yieldOrder.getCardNo()); - //只有厂内有工艺能力 - dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } else if (oemCustomer != null && workCenter == null) { - log.info("自动分派,流程卡号:{},分派到外协", yieldOrder.getCardNo()); - //只有厂外有工艺能力 - dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } else if (workCenter != null && oemCustomer != null) { - log.info("自动分派,流程卡号:{},分派到厂内或外协", yieldOrder.getCardNo()); - //场内外共有工艺能力 - if (workCenter.getLimitType().equals(WorkCenter.LIMIT_TYPE_MUST)) { - log.info("自动分派,流程卡号:{},必须厂内2", yieldOrder.getCardNo()); - dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } else if (oemCustomer.getLimitType().equals(WorkCenter.LIMIT_TYPE_MUST)) { - log.info("自动分派,流程卡号:{},必须外协2", yieldOrder.getCardNo()); - dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } - - //如果匹配到了作业单位,则直接停止 - if (dispatchCraftList != null && dispatchCraftList.size() > 0) { - return; - } - - // 厂内优先 - if (workCenter.getLimitType().equals(WorkCenter.LIMIT_TYPE_PRIOR)) { - log.info("自动分派,流程卡号:{},优先厂内", yieldOrder.getCardNo()); - dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } - - //如果匹配到了作业单位,则直接停止 - if (dispatchCraftList != null && dispatchCraftList.size() > 0) { - return; - } - - //外协优先 - if (oemCustomer.getLimitType().equals(WorkCenter.LIMIT_TYPE_PRIOR)) { - log.info("自动分派,流程卡号:{},优先外协", yieldOrder.getCardNo()); - dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } - - //如果匹配到了作业单位,则直接停止 - if (dispatchCraftList != null && dispatchCraftList.size() > 0) { - return; - } - - // 开始根据分派比例分派 - Long facTotalNum = 0L; - YieldOrderAssignCount facCapacity = dailyAssignService.queryCount(hostAbilityId, BsAssignEntity.IN_FACTORY); - if (facCapacity != null) { - facTotalNum = facCapacity.getTotalNum(); - } - // 获取厂外已经分派的总量 - Long oemTotalNum = 0L; - YieldOrderAssignCount oemCapacity = dailyAssignService.queryCount(hostAbilityId, BsAssignEntity.OUTSOURCE); - if (oemCapacity != null) { - oemTotalNum = oemCapacity.getTotalNum(); - } - - //日分派总量 - Long totalNum = facTotalNum + oemTotalNum; - // 厂内分派比列 - Double rate = 0D; - if (totalNum > 0) { - rate = Double.valueOf(facTotalNum) / Double.valueOf(totalNum) * 100; - } - log.info("自动分派,流程卡号:{},分派总量:{},厂内分派比列:{}", yieldOrder.getCardNo(), totalNum, rate); - - // 如果厂内占比大于已经设置的比列,则直接分派外协 - if (rate <= Double.parseDouble(craftAbility.getInRate())) { - log.info("{}自动分派按照比例分派给厂内:{},分派比例:{} 应分比例:{}", yieldOrder.getCardNo(), workCenter.getWcName(), rate, craftAbility.getInRate()); - dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } - - //如果匹配到了作业单位,则直接停止 - if (dispatchCraftList != null && !dispatchCraftList.isEmpty()) { - return; - } - - // 外协 - log.info("{}自动分派按照比例分派给外协:{},分派比例:{} 应分比例:{}", yieldOrder.getCardNo(), oemCustomer.getOcName(), rate, craftAbility.getInRate()); - dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); - } - } else { - if (Boolean.TRUE.equals(factor)) { - if (workCenter == null) { - throw new BusinessException("未找到合适的班组或者供应商!请排查工艺能力、班组日分派时间、相似零件、键位零件等因素!"); - } - dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, true); - } else { - if (oemCustomer == null) { - throw new BusinessException("未找到合适的班组或者供应商!请排查工艺能力、班组日分派时间、相似零件、键位零件等因素!"); - } - dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, false); - } - } - - if (dispatchCraftList == null || dispatchCraftList.size() == 0) { - throw new ServiceException("自动分派失败,未找到合适的班组或者供应商!"); - } - - if(workCenter != null){ - yieldOrder.setWorkCenterId(workCenter.getId()); - yieldOrderMapper.updateById(yieldOrder); - } - // 分派成功,保存分派结果 - this.saveOrUpdateBatch(dispatchCraftList); - } - - /** - * @param hostCaId 主工艺能力 - * @param wcMap 拥有主工艺能力的作业中心 - * @param yieldOrder 生产订单 - * @param limitType 0: 正常,1:优先,2:必须 - * @return BsWorkCenter - * @Description: 寻找满足条件的作业中心 - * @Author dxl - * @CreateTime 2023/3/7 18:30 - */ - private WorkCenter inPlantDistribution(Long hostCaId, Map wcMap, YieldOrder yieldOrder, Integer limitType) { - //没有工艺能力的对应作业中心,直接分派厂外 - if (wcMap == null || wcMap.size() == 0) { - return null; - } - - //组装wcList集合 - List wcList = new ArrayList<>(); - wcList.addAll(wcMap.keySet()); - - //作业中心 - WorkCenter workCenter = null; - //在规则表中匹配是否存在匹配的条件(查厂内) - BsAssignEntity assign = this.getRules(yieldOrder, hostCaId, BsAssignEntity.IN_FACTORY); - if (assign != null) { - //限制类型是必须(强制运用此规则),反之则优先分派厂内 - if (assign.getLimitType().equals(BsAssignEntity.MUST)) { - if (assign.getCenterId() != null) { - //判断规则中配置的工作中心是否满足当前工艺能力要求,如果不满足,则此条规则作废 - if (wcMap.get(assign.getCenterId()) != null) { - workCenter = workCenterService.getWorkCenter(assign.getCenterId()); - workCenter.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_MUST); - return workCenter; - } - } - //挑选一个最合适的作业中心 - return this.priorityInPlantDistribution(hostCaId, wcList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); - } else { - //优先规则配置的作业中心,若无则,规则 - if (assign.getCenterId() != null) { - //判断规则中配置的工作中心是否满足当前工艺能力要求,如果不满足,则此条规则作废 - if (wcMap.get(assign.getCenterId()) != null) { - //查询当前作业中心是否满足生产当前这批活的条件,若不满足,则考虑其他满足的作业中心 - YieldOrderAssignDaily dayAbilityAssignment = dailyAssignService.findMinNum(hostCaId, wcList); - if (dayAbilityAssignment != null) { - workCenter = workCenterService.getWorkCenter(assign.getCenterId()); - //外部如果限制类型不是必须,则直接考虑规则限制类型 - if (limitType.equals(BsWorkCenterEntity.LIMIT_TYPE_MUST)) { - workCenter.setLimitType(limitType); - } else { - workCenter.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_PRIOR); - } - return workCenter; - } - } - } - } - } - //挑选一个最合适的作业中心 - return this.priorityInPlantDistribution(hostCaId, wcList, yieldOrder, limitType); - } - - /** - * @param hostCaId 主工艺能力 - * @param wcList 作业中心集合 - * @param yieldOrder 生产订单 - * @param limitType 正常,1:优先,2:必须 - * @return BsWorkCenter - * @Description: 多作业中心挑选合适的作业中心 - * @Author dxl - * @CreateTime 2023/3/7 18:31 - */ - private WorkCenter priorityInPlantDistribution(Long hostCaId, List wcList, YieldOrder yieldOrder, Integer limitType) { - //没有工艺能力的对应作业中心,直接分派厂外 - if (wcList == null || wcList.size() == 0) { - return null; - } - - //作业中心 - WorkCenter workCenter = null; - //如果找到合适的作业中心直接分派,反之如果未找到合适的作业中心(bool 是true的情况下强制厂内,bool是false是优先厂内,不满足的情况下直接返回空) - // todo 待完善 - YieldOrderAssignDaily dayAbilityAssignment = dailyAssignService.findMinNum(hostCaId, wcList); - if (Func.isEmpty(dayAbilityAssignment)) { - return null; - } - workCenter = workCenterService.getWorkCenter(dayAbilityAssignment.getWorkCenterId()); - workCenter.setLimitType(limitType); - return workCenter; - } - - /** - * 为每个工序绑定作业中心 - * - * @param workCenterId 作业中心 - * @param workCenterMap 作业中心和班组集合 - * @param craftAbilityId 工艺能力 - * @param craftAbilityMap 工艺能力组装的生产计划map - * @param craftKeys 当前生产订单下的工艺能力集合 - * @return List - * @Description: 分配到班组 - * @Author dxl - * @CreateTime 2023/3/8 15:30 - */ - private List bindWorkCenter(Long workCenterId, Map workCenterMap, Long craftAbilityId, - Map> craftAbilityMap, Set craftKeys, - YieldOrder yieldOrder, Boolean factor) throws Exception { - log.info("自动分派,流程卡号:{},分给厂内,作业中心为:{}", yieldOrder.getCardNo(), workCenterId); - List orderCrafts = new ArrayList<>(); - // 开始循环生产订单中组合的工艺能力key集合, 主工艺能力之前的全部分配到此作业中心 - for (Long craftId : craftKeys) { - //验证工艺能力 + private final IWorkCenterService workCenterService; + private final IOemService oemService; + private final IOemCraftAbilityService oemCraftAbilityService; + private final IBsCraftAbilityService craftAbilityService; + private final IBsAssignService assignService; + private final IYieldOrderDailyAssignService dailyAssignService; + + private final IYieldOrderAssignSteerService assignSteerService; + private final IBsProcessSetService processSetService; + private final IBsTeamSetService teamSetService; + private final YieldOrderMapper yieldOrderMapper; + private final ICraftAbilityService iCraftAbilityService; + + @Override + public IPage selectPage(IPage page, YieldOrderCraft entity) { + List dataList = baseMapper.selectPage(page, entity); + return page.setRecords(dataList); + } + + @Override + public List listByYoId(Long yoId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(YieldOrderCraft.class) + .eq(YieldOrderCraft::getYoId, yoId) + .eq(YieldOrderCraft::getIsDeleted, CommonConstant.DELETE_FALSE).orderByAsc(YieldOrderCraft::getProcessNo); + List craftList = baseMapper.selectList(queryWrapper); + craftList.stream().forEach(item -> { + BsProcessSetEntity processSet = processSetService.getById(item.getPpsId()); + if (processSet != null) { + item.setProcessCode(processSet.getCode()); + item.setProcessName(processSet.getName()); + } + if (item.getIsOutsource()) { + if (null != item.getOcId()) { + Oem oem = oemService.getById(item.getOcId()); + if (null != oem) { + item.setWorkCenterName(oem.getOcName()); + } + } + } else { + if (null != item.getWorkCenterId()) { + WorkCenter workCenter = workCenterService.getById(item.getWorkCenterId()); + if (null != workCenter) { + item.setWorkCenterName(workCenter.getWcName()); + } + } + } + }); + return craftList; + } + + @Override + public int deleteByYoId(Long yoId) { + LambdaQueryWrapper deleteWrapper = Wrappers.lambdaQuery(YieldOrderCraft.class).eq(YieldOrderCraft::getYoId, yoId).eq(YieldOrderCraft::getIsDeleted, CommonConstant.DELETE_FALSE); + return baseMapper.delete(deleteWrapper); + } + + @Override + public void automaticDispatch(List yieldOrderCraftList, YieldOrder yieldOrder, Boolean factor, Boolean rxlSpace) throws Exception { + // 组装key为工艺能力的作业计划map + Map> craftAbilityMap = yieldOrderCraftList.stream() + .collect(Collectors.groupingBy(YieldOrderCraft::getCaId, LinkedHashMap::new, Collectors.toList())); + //作业计划map工艺能力key集合 + Set craftKeys = craftAbilityMap.keySet(); + //获取到认定的主工艺能力(默认第一个工艺能力为主工艺能力) + Long hostAbilityId = craftKeys.iterator().next(); + BsCraftAbilityEntity craftAbility = craftAbilityService.getById(hostAbilityId); + //获取可以做此主工艺能力的作业中心集合 + Map workCenterMap = workCenterService.selectByAbility(hostAbilityId, yieldOrder.getYpQty(), yieldOrder.getYpArea(), yieldOrder.getPartCode(), yieldOrder.getPrimaryCraft(), yieldOrder.getYieldType(), rxlSpace); + //获取可以做此主工艺能力的外协商集合 + List oemList = oemService.selectByAbility(hostAbilityId, yieldOrder.getYpQty(), yieldOrder.getYpArea(), yieldOrder.getPartCode(), yieldOrder.getPrimaryCraft(), yieldOrder.getYieldType(), yieldOrder.getPlate(), rxlSpace); + + // 如果未找到适合的班组或者供应商,提示排查方向 + if ((workCenterMap == null || workCenterMap.size() == 0) && (oemList == null || oemList.size() == 0)) { + throw new BusinessException("未找到合适的作业中心或者供应商!请排查工艺能力、作业中心等因素!"); + } + + // 查询是否存在必须厂内且等级要求的规则,如果是则需要验证作业中心必须有值 + List mustAssignList = assignService.listMustAssign(hostAbilityId, BsAssignEntity.IN_FACTORY); + if (mustAssignList != null && mustAssignList.size() > 0) { + // 遍历强制规则,查找跟订单匹配的质量等级规则,若规则不为空,判定厂内作业中心列表是否为空 + for (BsAssignEntity mustAssign : mustAssignList) { + if (StringUtils.isNotBlank(mustAssign.getProdMark())) { + if (mustAssign.getProdMark().contains("\"" + yieldOrder.getProductIdent() + "\"")) { + if (workCenterMap == null || workCenterMap.size() == 0) { + throw new BusinessException("未找到合适的作业中心或者供应商!请排查工艺能力、作业中心等因素!"); + } + } + } + } + } + + //获取到可以做主工艺能力的最合适的作业中心,并且标记必须、优先、正常 + WorkCenter workCenter = null; + //获取到可以做主工艺能力的最合适的外协商,并且标记必须、优先、正常 + Oem oemCustomer = null; + //自动分派后的结果集 + List dispatchCraftList = null; + + // 根据车间订单是否厂内标识判定是否强制厂内(单工序时不进行标识验证) + if (yieldOrder.getSiteWork() && factor == null) { + log.info("自动分派,流程卡号:{},标注厂内生产", yieldOrder.getCardNo()); + //订单强制分派厂内,若未找到工艺能力对应的作业中心,则提示异常 + if (workCenterMap == null || workCenterMap.isEmpty()) { + throw new BusinessException("此订单需强制分派厂内,未找到满足条件得作业中心,自动分派失败!1"); + } + //寻找最合适的作业中心 + workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); + if (workCenter == null) { + throw new BusinessException("此订单需强制分派厂内,未找到满足条件得作业中心,自动分派失败!2"); + } + } else if (factor != null) { + if (factor) { + workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); + } else if (!factor) { + oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); + } + } else { + // 先判定规则是否存在零件级强制匹配 + BsAssignEntity partAssign = assignService.getByPartCode(hostAbilityId, yieldOrder.getPartCode()); + if (partAssign != null && partAssign.getCenterId() != null) { + log.info("自动分派,流程卡号:{},指定厂内作业中心生产", yieldOrder.getCardNo()); + // 指定厂内作业中心生产 + workCenter = workCenterService.getWorkCenter(partAssign.getCenterId()); + } else if (partAssign != null && partAssign.getOemId() != null) { + // 指定外协商生产 + log.info("自动分派,流程卡号:{},指定外协商生产", yieldOrder.getCardNo()); + oemCustomer = oemService.getById(partAssign.getOemId()); + } else if (partAssign != null && partAssign.getLimitType().equals(BsAssignEntity.MUST.toString())) { + if (partAssign.getPointType().equals(BsAssignEntity.IN_FACTORY.toString())) { + // 必须厂内生产 + log.info("自动分派,流程卡号:{},必须厂内生产", yieldOrder.getCardNo()); + workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); + } else { + //必须外协生产 + log.info("自动分派,流程卡号:{},必须外协生产", yieldOrder.getCardNo()); + oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); + } + } else { + // 寻找最合适的作业中心 + log.info("自动分派,流程卡号:{},寻找最合适的作业中心或班组", yieldOrder.getCardNo()); + workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_NORMAL); + oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_NORMAL); + } + } + log.info("自动分派,流程卡号:{},作业中心:{},外协商:{}", yieldOrder.getCardNo(), workCenter, oemCustomer); + // factor等于null代表是整体,有值时代表是单工序,true转厂内,false转厂外 + if (factor == null) { + if (workCenter != null && oemCustomer == null) { + log.info("自动分派,流程卡号:{},分派到厂内", yieldOrder.getCardNo()); + //只有厂内有工艺能力 + dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } else if (oemCustomer != null && workCenter == null) { + log.info("自动分派,流程卡号:{},分派到外协", yieldOrder.getCardNo()); + //只有厂外有工艺能力 + dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } else if (workCenter != null && oemCustomer != null) { + log.info("自动分派,流程卡号:{},分派到厂内或外协", yieldOrder.getCardNo()); + //场内外共有工艺能力 + if (workCenter.getLimitType().equals(WorkCenter.LIMIT_TYPE_MUST)) { + log.info("自动分派,流程卡号:{},必须厂内2", yieldOrder.getCardNo()); + dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } else if (oemCustomer.getLimitType().equals(WorkCenter.LIMIT_TYPE_MUST)) { + log.info("自动分派,流程卡号:{},必须外协2", yieldOrder.getCardNo()); + dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } + + //如果匹配到了作业单位,则直接停止 + if (dispatchCraftList != null && dispatchCraftList.size() > 0) { + return; + } + + // 厂内优先 + if (workCenter.getLimitType().equals(WorkCenter.LIMIT_TYPE_PRIOR)) { + log.info("自动分派,流程卡号:{},优先厂内", yieldOrder.getCardNo()); + dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } + + //如果匹配到了作业单位,则直接停止 + if (dispatchCraftList != null && dispatchCraftList.size() > 0) { + return; + } + + //外协优先 + if (oemCustomer.getLimitType().equals(WorkCenter.LIMIT_TYPE_PRIOR)) { + log.info("自动分派,流程卡号:{},优先外协", yieldOrder.getCardNo()); + dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } + + //如果匹配到了作业单位,则直接停止 + if (dispatchCraftList != null && dispatchCraftList.size() > 0) { + return; + } + + // 开始根据分派比例分派 + Long facTotalNum = 0L; + YieldOrderAssignCount facCapacity = dailyAssignService.queryCount(hostAbilityId, BsAssignEntity.IN_FACTORY); + if (facCapacity != null) { + facTotalNum = facCapacity.getTotalNum(); + } + // 获取厂外已经分派的总量 + Long oemTotalNum = 0L; + YieldOrderAssignCount oemCapacity = dailyAssignService.queryCount(hostAbilityId, BsAssignEntity.OUTSOURCE); + if (oemCapacity != null) { + oemTotalNum = oemCapacity.getTotalNum(); + } + + //日分派总量 + Long totalNum = facTotalNum + oemTotalNum; + // 厂内分派比列 + Double rate = 0D; + if (totalNum > 0) { + rate = Double.valueOf(facTotalNum) / Double.valueOf(totalNum) * 100; + } + log.info("自动分派,流程卡号:{},分派总量:{},厂内分派比列:{}", yieldOrder.getCardNo(), totalNum, rate); + + // 如果厂内占比大于已经设置的比列,则直接分派外协 + if (rate <= Double.parseDouble(craftAbility.getInRate())) { + log.info("{}自动分派按照比例分派给厂内:{},分派比例:{} 应分比例:{}", yieldOrder.getCardNo(), workCenter.getWcName(), rate, craftAbility.getInRate()); + dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } + + //如果匹配到了作业单位,则直接停止 + if (dispatchCraftList != null && !dispatchCraftList.isEmpty()) { + return; + } + + // 外协 + log.info("{}自动分派按照比例分派给外协:{},分派比例:{} 应分比例:{}", yieldOrder.getCardNo(), oemCustomer.getOcName(), rate, craftAbility.getInRate()); + dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); + } + } else { + if (Boolean.TRUE.equals(factor)) { + if (workCenter == null) { + throw new BusinessException("未找到合适的班组或者供应商!请排查工艺能力、班组日分派时间、相似零件、键位零件等因素!"); + } + dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, true); + } else { + if (oemCustomer == null) { + throw new BusinessException("未找到合适的班组或者供应商!请排查工艺能力、班组日分派时间、相似零件、键位零件等因素!"); + } + dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, false); + } + } + + if (dispatchCraftList == null || dispatchCraftList.size() == 0) { + throw new ServiceException("自动分派失败,未找到合适的班组或者供应商!"); + } + + if (workCenter != null) { + yieldOrder.setWorkCenterId(workCenter.getId()); + yieldOrderMapper.updateById(yieldOrder); + } + // 分派成功,保存分派结果 + this.saveOrUpdateBatch(dispatchCraftList); + } + + @Override + public List listByYoIdAndNo(Long id, String orders) { + List craftList = this.list(Wrappers.lambdaQuery(YieldOrderCraft.class).eq(YieldOrderCraft::getYoId, id) + .gt(YieldOrderCraft::getProcessNo, orders).orderByAsc(YieldOrderCraft::getProcessNo)); + craftList.forEach(item -> { + BsProcessSetEntity processSet = processSetService.getById(item.getPpsId()); + if (processSet != null) { + item.setProcessCode(processSet.getCode()); + item.setProcessName(processSet.getName()); + } + if (item.getIsOutsource()) { + if (null != item.getOcId()) { + Oem oem = oemService.getById(item.getOcId()); + if (null != oem) { + item.setWorkCenterName(oem.getOcName()); + } + } + } else { + if (null != item.getWorkCenterId()) { + WorkCenter workCenter = workCenterService.getById(item.getWorkCenterId()); + if (null != workCenter) { + item.setWorkCenterName(workCenter.getWcName()); + } + } + } + }); + return craftList; + } + + /** + * @param hostCaId 主工艺能力 + * @param wcMap 拥有主工艺能力的作业中心 + * @param yieldOrder 生产订单 + * @param limitType 0: 正常,1:优先,2:必须 + * @return BsWorkCenter + * @Description: 寻找满足条件的作业中心 + * @Author dxl + * @CreateTime 2023/3/7 18:30 + */ + private WorkCenter inPlantDistribution(Long hostCaId, Map wcMap, YieldOrder yieldOrder, Integer limitType) { + //没有工艺能力的对应作业中心,直接分派厂外 + if (wcMap == null || wcMap.size() == 0) { + return null; + } + + //组装wcList集合 + List wcList = new ArrayList<>(); + wcList.addAll(wcMap.keySet()); + + //作业中心 + WorkCenter workCenter = null; + //在规则表中匹配是否存在匹配的条件(查厂内) + BsAssignEntity assign = this.getRules(yieldOrder, hostCaId, BsAssignEntity.IN_FACTORY); + if (assign != null) { + //限制类型是必须(强制运用此规则),反之则优先分派厂内 + if (assign.getLimitType().equals(BsAssignEntity.MUST)) { + if (assign.getCenterId() != null) { + //判断规则中配置的工作中心是否满足当前工艺能力要求,如果不满足,则此条规则作废 + if (wcMap.get(assign.getCenterId()) != null) { + workCenter = workCenterService.getWorkCenter(assign.getCenterId()); + workCenter.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_MUST); + return workCenter; + } + } + //挑选一个最合适的作业中心 + return this.priorityInPlantDistribution(hostCaId, wcList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); + } else { + //优先规则配置的作业中心,若无则,规则 + if (assign.getCenterId() != null) { + //判断规则中配置的工作中心是否满足当前工艺能力要求,如果不满足,则此条规则作废 + if (wcMap.get(assign.getCenterId()) != null) { + //查询当前作业中心是否满足生产当前这批活的条件,若不满足,则考虑其他满足的作业中心 + YieldOrderAssignDaily dayAbilityAssignment = dailyAssignService.findMinNum(hostCaId, wcList); + if (dayAbilityAssignment != null) { + workCenter = workCenterService.getWorkCenter(assign.getCenterId()); + //外部如果限制类型不是必须,则直接考虑规则限制类型 + if (limitType.equals(BsWorkCenterEntity.LIMIT_TYPE_MUST)) { + workCenter.setLimitType(limitType); + } else { + workCenter.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_PRIOR); + } + return workCenter; + } + } + } + } + } + //挑选一个最合适的作业中心 + return this.priorityInPlantDistribution(hostCaId, wcList, yieldOrder, limitType); + } + + /** + * @param hostCaId 主工艺能力 + * @param wcList 作业中心集合 + * @param yieldOrder 生产订单 + * @param limitType 正常,1:优先,2:必须 + * @return BsWorkCenter + * @Description: 多作业中心挑选合适的作业中心 + * @Author dxl + * @CreateTime 2023/3/7 18:31 + */ + private WorkCenter priorityInPlantDistribution(Long hostCaId, List wcList, YieldOrder yieldOrder, Integer limitType) { + //没有工艺能力的对应作业中心,直接分派厂外 + if (wcList == null || wcList.size() == 0) { + return null; + } + + //作业中心 + WorkCenter workCenter = null; + //如果找到合适的作业中心直接分派,反之如果未找到合适的作业中心(bool 是true的情况下强制厂内,bool是false是优先厂内,不满足的情况下直接返回空) + // todo 待完善 + YieldOrderAssignDaily dayAbilityAssignment = dailyAssignService.findMinNum(hostCaId, wcList); + if (Func.isEmpty(dayAbilityAssignment)) { + return null; + } + workCenter = workCenterService.getWorkCenter(dayAbilityAssignment.getWorkCenterId()); + workCenter.setLimitType(limitType); + return workCenter; + } + + /** + * 为每个工序绑定作业中心 + * + * @param workCenterId 作业中心 + * @param workCenterMap 作业中心和班组集合 + * @param craftAbilityId 工艺能力 + * @param craftAbilityMap 工艺能力组装的生产计划map + * @param craftKeys 当前生产订单下的工艺能力集合 + * @return List + * @Description: 分配到班组 + * @Author dxl + * @CreateTime 2023/3/8 15:30 + */ + private List bindWorkCenter(Long workCenterId, Map workCenterMap, Long craftAbilityId, + Map> craftAbilityMap, Set craftKeys, + YieldOrder yieldOrder, Boolean factor) throws Exception { + log.info("自动分派,流程卡号:{},分给厂内,作业中心为:{}", yieldOrder.getCardNo(), workCenterId); + List orderCrafts = new ArrayList<>(); + // 开始循环生产订单中组合的工艺能力key集合, 主工艺能力之前的全部分配到此作业中心 + for (Long craftId : craftKeys) { + //验证工艺能力 /*WorkCenter workCenter = workCenterService.getOne(Wrappers.lambdaQuery().eq(BaseEntity::getId,workCenterId).like(WorkCenter::getCraftAbilityId,craftId)); if (workCenter == null) { break; }*/ - orderCrafts.addAll(craftAbilityMap.get(craftId)); - } - - // 开始分派到作业中心 - for (YieldOrderCraft orderCraft : orderCrafts) { - Long centerId = orderCraft.getWorkCenterId(); - // 判定是否是特殊工序 - BsProcessSetEntity processSet = processSetService.getById(orderCraft.getPpsId()); - if (Func.isNotEmpty(processSet) && Func.isNotBlank(processSet.getTeam())) { - BsTeamSetEntity teamSetEntity = teamSetService.selectByTeamName(processSet.getTeam()); - if (Func.isNotEmpty(teamSetEntity)) { - centerId = teamSetEntity.getWcId(); - } - } - WorkCenter workCenter = null; - if(orderCraft.getCaId().equals(craftAbilityId)){ - workCenter = workCenterMap.get(workCenterId); - }else{ - workCenter = workCenterService.getOne(Wrappers.lambdaQuery().apply("INSTR(',' || CRAFT_ABILITY_ID || ',', ',' || {0} || ',') > 0", orderCraft.getCaId())); - } - - if(centerId != null){ - orderCraft.setWorkCenterId(centerId); - }else{ - if(workCenter == null){ - throw new ServiceException("工艺" + orderCraft.getCaId() + "未查询到对应作业中心"); - } - orderCraft.setWorkCenterId(workCenter.getId()); - } - orderCraft.setIsOutsource(Boolean.FALSE); - } - //factor等于null代表是整体,有值时代表是单工序 - if (factor == null) { - // 更新主工序工艺能力日产能信息 - dailyAssignService.saveOrEdit(workCenterId, null, craftAbilityId, yieldOrder.getYpArea(), yieldOrder.getYpQty()); - } - return orderCrafts; - } - - /** - * @param hostCaId 主工艺能力 - * @param ocList 拥有主工艺能力的外协商 - * @param yieldOrder 生产订单 - * @param limitType 0: 正常,1:优先,2:必须 - * @return Oem - * @Description: 寻找满足条件的外协商 - * @Author dxl - * @CreateTime 2023/3/8 13:49 - */ - private Oem offsiteDistribution(Long hostCaId, List ocList, YieldOrder yieldOrder, Integer limitType) { - //没有工艺能力直接跳过 - if (ocList == null || ocList.size() == 0) { - return null; - } - //作业中心 - Oem oemCustomer = null; - //在规则表中匹配是否存在匹配的条件(查厂外) - BsAssignEntity assign = this.getRules(yieldOrder, hostCaId, BsAssignEntity.OUTSOURCE); - if (assign != null) { - //限制类型是必须(强制按此规则分派) - if (assign.getLimitType().equals(BsAssignEntity.MUST.toString())) { - //如果指定了外协商,则强制分派到此外协商;反之则分派至厂外有同种工艺能力的外协商 - if (assign.getOemId() != null) { - //判断规则中配置的外协商是否满足当前工艺能力要求,如果不满足,则此条规则作废 - if (ocList.contains(assign.getOemId())) { - //直接安排给主工艺能力对应的外协商 - oemCustomer = oemService.getById(assign.getOemId()); - oemCustomer.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_MUST); - return oemCustomer; - } - } - //挑选一个最合适的外协商 - return this.priorityOffsiteDistribution(hostCaId, ocList, BsWorkCenterEntity.LIMIT_TYPE_MUST, yieldOrder); - } else { - //如果指定了外协商,则优先判定此外协商是否满足条件,满足则分给当前外协商;反之则分派至厂外有同种工艺能力的外协商 - if (assign.getOemId() != null) { - //指定了外协商(判断规则中配置的供应商是否满足当前工艺能力要求,如果不满足,则此条规则作废) - if (ocList.contains(assign.getOemId())) { - //验证此外协商是否满足分派条件,若不满足,则在现有规则中挑选一个满足条件的供应商 - List thisLst = new ArrayList<>(); - thisLst.add(assign.getOemId()); - //查询当前外协商是否满足生产当前这批活的条件,若不满足,则考虑其他满足的供应商 - YieldOrderAssignSteer planAssignSteer = assignSteerService.findByOcIdLstAndCaId(thisLst, null, yieldOrder.getPartCode()); - //用于标识匹配规则是按零件还是工艺能力 - boolean bool = true; - if (planAssignSteer == null) { - bool = false; - planAssignSteer = assignSteerService.findByOcIdLstAndCaId(thisLst, hostCaId, null); - } - - if (planAssignSteer != null) { - oemCustomer = oemService.getById(assign.getOemId()); - oemCustomer.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_PRIOR); - oemCustomer.setPartCodeYesOrNo(bool); - return oemCustomer; - } - } - } - } - } - //挑选一个最合适的外协商 - return this.priorityOffsiteDistribution(hostCaId, ocList, limitType, yieldOrder); - } - - /** - * @param hostCaId 主工艺能力 - * @param ocList 外协商集合 - * @param limitType 正常,1:优先,2:必须 - * @return Oem - * @Description: 多外协商挑选合适的作业中心 - * @Author dxl - * @CreateTime 2023/3/8 14:03 - */ - private Oem priorityOffsiteDistribution(Long hostCaId, List ocList, Integer limitType, YieldOrder yieldOrder) { - // 没有工艺能力的对应作业中心,直接分派厂外 - if (ocList == null || ocList.size() == 0) { - return null; - } - - // 外协商 - Oem oemCustomer = null; - // 首先根据零件号查询是否存在零件级的分派规则 - YieldOrderAssignSteer planAssignSteer = assignSteerService.findByOcIdLstAndCaId(ocList, null, yieldOrder.getPartCode()); - //用于标识匹配规则是按零件还是工艺能力 - boolean bool = true; - if (planAssignSteer == null) { - bool = false; - - // 获取到满足条件的供应商 - // 对有能力做这个单子厂家按照偏差因子排序 - if (!ocList.isEmpty()) { - List bsPlanAssignSteerList = assignSteerService.sortDataByFactor(ocList, hostCaId); - CraftAbilityEntity craftAbility = iCraftAbilityService.getById(hostCaId); - for (YieldOrderAssignSteer bsPlanAssignSteer : bsPlanAssignSteerList) { - oemCustomer = oemService.getById(bsPlanAssignSteer.getOemId()); - String oemCode = oemCustomer.getCode(); - - // 改伊川喷砂工艺能力不限制厂家等级资质 - // 使用工艺能力表中加工类型字段控制工艺能力是否需要进行外协等级资质判断 - boolean aBoolean = false; - aBoolean = assignSteerService.queryOemAndCaid(oemCode, yieldOrder.getProductIdent()); - //zxh 20251015 工作订单备注中包含zdzx时,单独校验厂家是否有JI以及JHT资质,若不存在相关等级资质,不允许派此厂家 - if (yieldOrder.getYpMemo() != null && yieldOrder.getYpMemo().toLowerCase(Locale.ROOT).contains("zdzx")) { - boolean aBooleanJI = assignSteerService.queryOemAndCaid(oemCode, "JI"); - boolean aBooleanJHT = assignSteerService.queryOemAndCaid(oemCode, "JHT"); - if (!aBooleanJI || !aBooleanJHT) { - aBoolean = false; - } - } - - if ("0".equals(craftAbility.getWtId())) { - aBoolean = true; - } - - if (aBoolean) { - oemCustomer.setLimitType(limitType); - oemCustomer.setPartCodeYesOrNo(bool); - return oemCustomer; - } - } - } - } - // 如果找到合适的外协商直接分派,反之如果未找到合适的外协商 - if (planAssignSteer != null) { - oemCustomer = oemService.getById(planAssignSteer.getOemId()); - oemCustomer.setLimitType(limitType); - oemCustomer.setPartCodeYesOrNo(bool); - return oemCustomer; - } - return null; - } - - /** - * @param oemCustomer 外协商 - * @param craftAbilityMap 工艺能力组装的生产计划map - * @param keys 当前生产订单下的工艺能力集合 - * @return List - * @Description: 绑定外协商到生成计划 - * @Author dxl - * @CreateTime 2023/2/17 16:28 - */ - private List bindOem(Oem oemCustomer, Long craftAbilityId, Map> craftAbilityMap, Set keys, YieldOrder yieldOrder, Boolean factor) throws Exception { - log.info("自动分派,流程卡号:{},分给外协,外协商为:{}", yieldOrder.getCardNo(), JSONObject.toJSONString(oemCustomer)); - List rtnList = new ArrayList<>(); - - OemCraftAbilityEntity oemAbility = null; - //开始循环生产订单中组合的工艺能力key集合,主工艺能力之前的全部分配到此外协商 - for (Long key : keys) { - //验证工艺能力 + orderCrafts.addAll(craftAbilityMap.get(craftId)); + } + + // 开始分派到作业中心 + for (YieldOrderCraft orderCraft : orderCrafts) { + Long centerId = orderCraft.getWorkCenterId(); + // 判定是否是特殊工序 + BsProcessSetEntity processSet = processSetService.getById(orderCraft.getPpsId()); + if (Func.isNotEmpty(processSet) && Func.isNotBlank(processSet.getTeam())) { + BsTeamSetEntity teamSetEntity = teamSetService.selectByTeamName(processSet.getTeam()); + if (Func.isNotEmpty(teamSetEntity)) { + centerId = teamSetEntity.getWcId(); + } + } + WorkCenter workCenter = null; + if (orderCraft.getCaId().equals(craftAbilityId)) { + workCenter = workCenterMap.get(workCenterId); + } else { + workCenter = workCenterService.getOne(Wrappers.lambdaQuery().apply("INSTR(',' || CRAFT_ABILITY_ID || ',', ',' || {0} || ',') > 0", orderCraft.getCaId())); + } + + if (centerId != null) { + orderCraft.setWorkCenterId(centerId); + } else { + if (workCenter == null) { + throw new ServiceException("工艺" + orderCraft.getCaId() + "未查询到对应作业中心"); + } + orderCraft.setWorkCenterId(workCenter.getId()); + } + orderCraft.setIsOutsource(Boolean.FALSE); + } + //factor等于null代表是整体,有值时代表是单工序 + if (factor == null) { + // 更新主工序工艺能力日产能信息 + dailyAssignService.saveOrEdit(workCenterId, null, craftAbilityId, yieldOrder.getYpArea(), yieldOrder.getYpQty()); + } + return orderCrafts; + } + + /** + * @param hostCaId 主工艺能力 + * @param ocList 拥有主工艺能力的外协商 + * @param yieldOrder 生产订单 + * @param limitType 0: 正常,1:优先,2:必须 + * @return Oem + * @Description: 寻找满足条件的外协商 + * @Author dxl + * @CreateTime 2023/3/8 13:49 + */ + private Oem offsiteDistribution(Long hostCaId, List ocList, YieldOrder yieldOrder, Integer limitType) { + //没有工艺能力直接跳过 + if (ocList == null || ocList.size() == 0) { + return null; + } + //作业中心 + Oem oemCustomer = null; + //在规则表中匹配是否存在匹配的条件(查厂外) + BsAssignEntity assign = this.getRules(yieldOrder, hostCaId, BsAssignEntity.OUTSOURCE); + if (assign != null) { + //限制类型是必须(强制按此规则分派) + if (assign.getLimitType().equals(BsAssignEntity.MUST.toString())) { + //如果指定了外协商,则强制分派到此外协商;反之则分派至厂外有同种工艺能力的外协商 + if (assign.getOemId() != null) { + //判断规则中配置的外协商是否满足当前工艺能力要求,如果不满足,则此条规则作废 + if (ocList.contains(assign.getOemId())) { + //直接安排给主工艺能力对应的外协商 + oemCustomer = oemService.getById(assign.getOemId()); + oemCustomer.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_MUST); + return oemCustomer; + } + } + //挑选一个最合适的外协商 + return this.priorityOffsiteDistribution(hostCaId, ocList, BsWorkCenterEntity.LIMIT_TYPE_MUST, yieldOrder); + } else { + //如果指定了外协商,则优先判定此外协商是否满足条件,满足则分给当前外协商;反之则分派至厂外有同种工艺能力的外协商 + if (assign.getOemId() != null) { + //指定了外协商(判断规则中配置的供应商是否满足当前工艺能力要求,如果不满足,则此条规则作废) + if (ocList.contains(assign.getOemId())) { + //验证此外协商是否满足分派条件,若不满足,则在现有规则中挑选一个满足条件的供应商 + List thisLst = new ArrayList<>(); + thisLst.add(assign.getOemId()); + //查询当前外协商是否满足生产当前这批活的条件,若不满足,则考虑其他满足的供应商 + YieldOrderAssignSteer planAssignSteer = assignSteerService.findByOcIdLstAndCaId(thisLst, null, yieldOrder.getPartCode()); + //用于标识匹配规则是按零件还是工艺能力 + boolean bool = true; + if (planAssignSteer == null) { + bool = false; + planAssignSteer = assignSteerService.findByOcIdLstAndCaId(thisLst, hostCaId, null); + } + + if (planAssignSteer != null) { + oemCustomer = oemService.getById(assign.getOemId()); + oemCustomer.setLimitType(BsWorkCenterEntity.LIMIT_TYPE_PRIOR); + oemCustomer.setPartCodeYesOrNo(bool); + return oemCustomer; + } + } + } + } + } + //挑选一个最合适的外协商 + return this.priorityOffsiteDistribution(hostCaId, ocList, limitType, yieldOrder); + } + + /** + * @param hostCaId 主工艺能力 + * @param ocList 外协商集合 + * @param limitType 正常,1:优先,2:必须 + * @return Oem + * @Description: 多外协商挑选合适的作业中心 + * @Author dxl + * @CreateTime 2023/3/8 14:03 + */ + private Oem priorityOffsiteDistribution(Long hostCaId, List ocList, Integer limitType, YieldOrder yieldOrder) { + // 没有工艺能力的对应作业中心,直接分派厂外 + if (ocList == null || ocList.size() == 0) { + return null; + } + + // 外协商 + Oem oemCustomer = null; + // 首先根据零件号查询是否存在零件级的分派规则 + YieldOrderAssignSteer planAssignSteer = assignSteerService.findByOcIdLstAndCaId(ocList, null, yieldOrder.getPartCode()); + //用于标识匹配规则是按零件还是工艺能力 + boolean bool = true; + if (planAssignSteer == null) { + bool = false; + + // 获取到满足条件的供应商 + // 对有能力做这个单子厂家按照偏差因子排序 + if (!ocList.isEmpty()) { + List bsPlanAssignSteerList = assignSteerService.sortDataByFactor(ocList, hostCaId); + CraftAbilityEntity craftAbility = iCraftAbilityService.getById(hostCaId); + for (YieldOrderAssignSteer bsPlanAssignSteer : bsPlanAssignSteerList) { + oemCustomer = oemService.getById(bsPlanAssignSteer.getOemId()); + String oemCode = oemCustomer.getCode(); + + // 改伊川喷砂工艺能力不限制厂家等级资质 + // 使用工艺能力表中加工类型字段控制工艺能力是否需要进行外协等级资质判断 + boolean aBoolean = false; + aBoolean = assignSteerService.queryOemAndCaid(oemCode, yieldOrder.getProductIdent()); + //zxh 20251015 工作订单备注中包含zdzx时,单独校验厂家是否有JI以及JHT资质,若不存在相关等级资质,不允许派此厂家 + if (yieldOrder.getYpMemo() != null && yieldOrder.getYpMemo().toLowerCase(Locale.ROOT).contains("zdzx")) { + boolean aBooleanJI = assignSteerService.queryOemAndCaid(oemCode, "JI"); + boolean aBooleanJHT = assignSteerService.queryOemAndCaid(oemCode, "JHT"); + if (!aBooleanJI || !aBooleanJHT) { + aBoolean = false; + } + } + + if ("0".equals(craftAbility.getWtId())) { + aBoolean = true; + } + + if (aBoolean) { + oemCustomer.setLimitType(limitType); + oemCustomer.setPartCodeYesOrNo(bool); + return oemCustomer; + } + } + } + } + // 如果找到合适的外协商直接分派,反之如果未找到合适的外协商 + if (planAssignSteer != null) { + oemCustomer = oemService.getById(planAssignSteer.getOemId()); + oemCustomer.setLimitType(limitType); + oemCustomer.setPartCodeYesOrNo(bool); + return oemCustomer; + } + return null; + } + + /** + * @param oemCustomer 外协商 + * @param craftAbilityMap 工艺能力组装的生产计划map + * @param keys 当前生产订单下的工艺能力集合 + * @return List + * @Description: 绑定外协商到生成计划 + * @Author dxl + * @CreateTime 2023/2/17 16:28 + */ + private List bindOem(Oem oemCustomer, Long craftAbilityId, Map> craftAbilityMap, Set keys, YieldOrder yieldOrder, Boolean factor) throws Exception { + log.info("自动分派,流程卡号:{},分给外协,外协商为:{}", yieldOrder.getCardNo(), JSONObject.toJSONString(oemCustomer)); + List rtnList = new ArrayList<>(); + + OemCraftAbilityEntity oemAbility = null; + //开始循环生产订单中组合的工艺能力key集合,主工艺能力之前的全部分配到此外协商 + for (Long key : keys) { + //验证工艺能力 // oemAbility = oemCraftAbilityService.findBsOemAbility(oemCustomer.getId(), key); // if (oemAbility == null) { // break; // } - rtnList.addAll(craftAbilityMap.get(key)); - } - // 开始分派到外协商 - WorkCenter workCenter = null; - for (YieldOrderCraft orderCraft : rtnList) { - BsProcessSetEntity processSet = processSetService.getById(orderCraft.getPpsId()); - if (processSet != null && "1".equals(processSet.getIsDispatch())) { - workCenter = workCenterService.getOne(Wrappers.lambdaQuery().apply("INSTR(',' || CRAFT_ABILITY_ID || ',', ',' || {0} || ',') > 0", orderCraft.getCaId())); - if (workCenter == null) { - throw new ServiceException("工艺" + orderCraft.getCaId() + "未查询到对应作业中心"); - } - orderCraft.setWorkCenterId(workCenter.getId()); - orderCraft.setIsOutsource(Boolean.FALSE); - } else { - orderCraft.setOcId(oemCustomer.getId()); - orderCraft.setIsOutsource(Boolean.TRUE); - } - } - - if (workCenter != null) { - yieldOrder.setWorkCenterId(workCenter.getId()); - yieldOrderMapper.updateById(yieldOrder); - } - - // 更新主工序工艺能力日产能信息 - dailyAssignService.saveOrEdit(null, oemCustomer.getId(), craftAbilityId, yieldOrder.getYpArea(), yieldOrder.getYpQty()); - return rtnList; - } - - /** - * 获取一个优先级最高的规则 - * - * @param yieldOrder 生产订单 - * @param caId 工艺能力 - * @return PjRules - * @Description: 匹配规则条件 - * @Author dxl - * @CreateTime 2023/2/16 17:30 - */ - private BsAssignEntity getRules(YieldOrder yieldOrder, Long caId, int appointType) { - List rulesList = assignService.listByPointType(appointType); - BsAssignEntity rtnRule = null; - int num = 0, rtn = 0; - for (BsAssignEntity rules : rulesList) { - rtn = this.analysesRule(rules, yieldOrder, caId); - if (rtn > num) { - // 判定规则优先级,如果本次匹配到的规则的RulesOrder如果大于上次匹配规则的RulesOrder,则跳过 - if (rtnRule != null && rtnRule.getSort() < rules.getSort()) { - continue; - } - num = rtn; - rtnRule = rules; - } - } - // 质量等级规则监控 - if (rtnRule != null && StringUtils.isNotBlank(rtnRule.getProdMark())) { - log.error("生产订单id: " + yieldOrder.getId() + "等级:" + yieldOrder.getProductIdent() + "规则id:" + (rtnRule == null ? "" : rtnRule.getId())); - } - return rtnRule; - } - - /** - * 根据规则的匹配项, 计算使用能力的优先级 - * - * @param rules 规则记录 - * @param yieldOrder 生产订单 - * @param caId 工艺能力 - * @return int - * @Description: 匹配条件 - * @Author dxl - * @CreateTime 2023/2/16 17:26 - */ - private int analysesRule(BsAssignEntity rules, YieldOrder yieldOrder, Long caId) { - //条件匹配根据占比累计 - int sum = 0; - - //工艺能力 - if (rules.getCraftAbilityId() != null) { - if (caId.equals(rules.getCraftAbilityId())) { - sum = sum + 51; - } else { - return 0; - } - } - - //零件号 - if (StringUtils.isNotBlank(rules.getPartCode())) { - if (yieldOrder.getPartCode().equals(rules.getPartCode())) { - sum = sum + 25; - } else { - return 0; - } - } - - // 质量等级 - if (StringUtils.isNotBlank(rules.getProdMark())) { - if (rules.getProdMark().contains("\"" + yieldOrder.getProductIdent() + "\"")) { - sum = sum + 13; - } else { - return 0; - } - } - - Double totalArea = yieldOrder.getYpArea() * yieldOrder.getYpQty(); - BigDecimal areaVal = new BigDecimal(totalArea); - - //单批面积规则和单位面积规则取其一,如果单批面积存在则按照单批面积规则 - if ((rules.getSingleUpArea() != null && rules.getSingleUpArea().compareTo(BigDecimal.ZERO) > 0) || (rules.getSingleDownArea() != null && rules.getSingleDownArea().compareTo(BigDecimal.ZERO) > 0)) { - //单批面积下限 - if (rules.getSingleDownArea() != null && rules.getSingleDownArea().compareTo(BigDecimal.ZERO) > 0) { - if (areaVal.compareTo(rules.getSingleDownArea()) >= 0) { - sum = sum + 7; - } else { - return 0; - } - } - //单批面积上限 - if (rules.getSingleUpArea() != null && rules.getSingleUpArea().compareTo(BigDecimal.ZERO) > 0) { - if (areaVal.compareTo(rules.getSingleUpArea()) <= 0) { - sum = sum + 4; - } else { - return 0; - } - } - } else { - //单位面积下限 - if (rules.getLowArea() != null && rules.getLowArea().compareTo(BigDecimal.ZERO) > 0) { - if (areaVal.compareTo(rules.getLowArea()) >= 0) { - sum = sum + 7; - } else { - return 0; - } - } - //单位面积上限 - if (rules.getUpArea() != null && rules.getUpArea().compareTo(BigDecimal.ZERO) > 0) { - if (areaVal.compareTo(rules.getUpArea()) <= 0) { - sum = sum + 4; - } else { - return 0; - } - } - } - return sum; - } + rtnList.addAll(craftAbilityMap.get(key)); + } + // 开始分派到外协商 + WorkCenter workCenter = null; + for (YieldOrderCraft orderCraft : rtnList) { + BsProcessSetEntity processSet = processSetService.getById(orderCraft.getPpsId()); + if (processSet != null && "1".equals(processSet.getIsDispatch())) { + workCenter = workCenterService.getOne(Wrappers.lambdaQuery().apply("INSTR(',' || CRAFT_ABILITY_ID || ',', ',' || {0} || ',') > 0", orderCraft.getCaId())); + if (workCenter == null) { + throw new ServiceException("工艺" + orderCraft.getCaId() + "未查询到对应作业中心"); + } + orderCraft.setWorkCenterId(workCenter.getId()); + orderCraft.setIsOutsource(Boolean.FALSE); + } else { + orderCraft.setOcId(oemCustomer.getId()); + orderCraft.setIsOutsource(Boolean.TRUE); + } + } + + if (workCenter != null) { + yieldOrder.setWorkCenterId(workCenter.getId()); + yieldOrderMapper.updateById(yieldOrder); + } + + // 更新主工序工艺能力日产能信息 + dailyAssignService.saveOrEdit(null, oemCustomer.getId(), craftAbilityId, yieldOrder.getYpArea(), yieldOrder.getYpQty()); + return rtnList; + } + + /** + * 获取一个优先级最高的规则 + * + * @param yieldOrder 生产订单 + * @param caId 工艺能力 + * @return PjRules + * @Description: 匹配规则条件 + * @Author dxl + * @CreateTime 2023/2/16 17:30 + */ + private BsAssignEntity getRules(YieldOrder yieldOrder, Long caId, int appointType) { + List rulesList = assignService.listByPointType(appointType); + BsAssignEntity rtnRule = null; + int num = 0, rtn = 0; + for (BsAssignEntity rules : rulesList) { + rtn = this.analysesRule(rules, yieldOrder, caId); + if (rtn > num) { + // 判定规则优先级,如果本次匹配到的规则的RulesOrder如果大于上次匹配规则的RulesOrder,则跳过 + if (rtnRule != null && rtnRule.getSort() < rules.getSort()) { + continue; + } + num = rtn; + rtnRule = rules; + } + } + // 质量等级规则监控 + if (rtnRule != null && StringUtils.isNotBlank(rtnRule.getProdMark())) { + log.error("生产订单id: " + yieldOrder.getId() + "等级:" + yieldOrder.getProductIdent() + "规则id:" + (rtnRule == null ? "" : rtnRule.getId())); + } + return rtnRule; + } + + /** + * 根据规则的匹配项, 计算使用能力的优先级 + * + * @param rules 规则记录 + * @param yieldOrder 生产订单 + * @param caId 工艺能力 + * @return int + * @Description: 匹配条件 + * @Author dxl + * @CreateTime 2023/2/16 17:26 + */ + private int analysesRule(BsAssignEntity rules, YieldOrder yieldOrder, Long caId) { + //条件匹配根据占比累计 + int sum = 0; + + //工艺能力 + if (rules.getCraftAbilityId() != null) { + if (caId.equals(rules.getCraftAbilityId())) { + sum = sum + 51; + } else { + return 0; + } + } + + //零件号 + if (StringUtils.isNotBlank(rules.getPartCode())) { + if (yieldOrder.getPartCode().equals(rules.getPartCode())) { + sum = sum + 25; + } else { + return 0; + } + } + + // 质量等级 + if (StringUtils.isNotBlank(rules.getProdMark())) { + if (rules.getProdMark().contains("\"" + yieldOrder.getProductIdent() + "\"")) { + sum = sum + 13; + } else { + return 0; + } + } + + Double totalArea = yieldOrder.getYpArea() * yieldOrder.getYpQty(); + BigDecimal areaVal = new BigDecimal(totalArea); + + //单批面积规则和单位面积规则取其一,如果单批面积存在则按照单批面积规则 + if ((rules.getSingleUpArea() != null && rules.getSingleUpArea().compareTo(BigDecimal.ZERO) > 0) || (rules.getSingleDownArea() != null && rules.getSingleDownArea().compareTo(BigDecimal.ZERO) > 0)) { + //单批面积下限 + if (rules.getSingleDownArea() != null && rules.getSingleDownArea().compareTo(BigDecimal.ZERO) > 0) { + if (areaVal.compareTo(rules.getSingleDownArea()) >= 0) { + sum = sum + 7; + } else { + return 0; + } + } + //单批面积上限 + if (rules.getSingleUpArea() != null && rules.getSingleUpArea().compareTo(BigDecimal.ZERO) > 0) { + if (areaVal.compareTo(rules.getSingleUpArea()) <= 0) { + sum = sum + 4; + } else { + return 0; + } + } + } else { + //单位面积下限 + if (rules.getLowArea() != null && rules.getLowArea().compareTo(BigDecimal.ZERO) > 0) { + if (areaVal.compareTo(rules.getLowArea()) >= 0) { + sum = sum + 7; + } else { + return 0; + } + } + //单位面积上限 + if (rules.getUpArea() != null && rules.getUpArea().compareTo(BigDecimal.ZERO) > 0) { + if (areaVal.compareTo(rules.getUpArea()) <= 0) { + sum = sum + 4; + } else { + return 0; + } + } + } + return sum; + } } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderRunServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderRunServiceImpl.java index 714b24a4a..8bbe0f81a 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderRunServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderRunServiceImpl.java @@ -25,6 +25,7 @@ import org.springblade.desk.basic.mapper.TeamSetMapper; import org.springblade.desk.basic.pojo.entity.Oem; import org.springblade.desk.basic.pojo.entity.OemCraftAbilityEntity; import org.springblade.desk.basic.pojo.entity.TeamSet; +import org.springblade.desk.basic.pojo.entity.WorkCenter; import org.springblade.desk.dashboard.mapper.BsProcessSetMapper; import org.springblade.desk.dashboard.pojo.entity.BsProcessSetEntity; import org.springblade.desk.oem.pojo.request.*; @@ -171,8 +172,9 @@ public class WorkOrderRunServiceImpl extends BaseServiceImpl yieldOrderCrafts = yieldOrderCraftService.listByYoId(yieldOrder.getId()); + // 调用转厂内自动分派逻辑,只查询外协工序之后的工序 + List yieldOrderCrafts = yieldOrderCraftService.listByYoIdAndNo(yieldOrder.getId(), deliverablePlan.getOrders()); +// List yieldOrderCrafts = yieldOrderCraftService.listByYoId(yieldOrder.getId(), deliverablePlan.getOrders()); try { yieldOrderCraftService.automaticDispatch(yieldOrderCrafts, yieldOrder, Boolean.TRUE, null); } catch (Exception e) {