|
|
|
|
@ -3,23 +3,56 @@ package org.springblade.desk.order.service.impl; |
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
|
import org.springblade.common.constant.CommonConstant; |
|
|
|
|
import org.springblade.common.exception.BusinessException; |
|
|
|
|
import org.springblade.core.mp.base.BaseServiceImpl; |
|
|
|
|
import org.springblade.desk.order.pojo.entity.YieldOrderCraft; |
|
|
|
|
import org.springblade.core.tool.utils.Func; |
|
|
|
|
import org.springblade.desk.basic.pojo.entity.BsAssignEntity; |
|
|
|
|
import org.springblade.desk.basic.pojo.entity.Oem; |
|
|
|
|
import org.springblade.desk.basic.pojo.entity.OemCraftAbilityEntity; |
|
|
|
|
import org.springblade.desk.basic.service.IBsAssignService; |
|
|
|
|
import org.springblade.desk.basic.service.IOemCraftAbilityService; |
|
|
|
|
import org.springblade.desk.basic.service.IOemService; |
|
|
|
|
import org.springblade.desk.basic.service.IWorkCenterService; |
|
|
|
|
import org.springblade.desk.dashboard.pojo.entity.BsWorkCenterEntity; |
|
|
|
|
import org.springblade.desk.dashboard.service.IBsCraftAbilityService; |
|
|
|
|
import org.springblade.desk.order.mapper.YieldOrderCraftMapper; |
|
|
|
|
import org.springblade.desk.order.pojo.dto.YieldOrderAssignCount; |
|
|
|
|
import org.springblade.desk.order.pojo.entity.YieldOrder; |
|
|
|
|
import org.springblade.desk.order.pojo.entity.YieldOrderAssignDaily; |
|
|
|
|
import org.springblade.desk.order.pojo.entity.YieldOrderAssignSteer; |
|
|
|
|
import org.springblade.desk.order.pojo.entity.YieldOrderCraft; |
|
|
|
|
import org.springblade.desk.order.service.IYieldOrderAssignSteerService; |
|
|
|
|
import org.springblade.desk.order.service.IYieldOrderCraftService; |
|
|
|
|
import org.springblade.desk.order.service.IYieldOrderDailyAssignService; |
|
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
|
import java.math.BigDecimal; |
|
|
|
|
import java.util.*; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 服务实现类 |
|
|
|
|
* |
|
|
|
|
* @author BladeX |
|
|
|
|
*/ |
|
|
|
|
@Slf4j |
|
|
|
|
@RequiredArgsConstructor |
|
|
|
|
@Service |
|
|
|
|
public class YieldOrderCraftServiceImpl extends BaseServiceImpl<YieldOrderCraftMapper, YieldOrderCraft> 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; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public IPage<YieldOrderCraft> selectPage(IPage<YieldOrderCraft> page, YieldOrderCraft entity) { |
|
|
|
|
List<YieldOrderCraft> dataList = baseMapper.selectPage(page, entity); |
|
|
|
|
@ -37,14 +70,606 @@ public class YieldOrderCraftServiceImpl extends BaseServiceImpl<YieldOrderCraftM |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public int deleteByYoId(Long yoId) { |
|
|
|
|
LambdaQueryWrapper<YieldOrderCraft> deleteWrapper = Wrappers.lambdaQuery(YieldOrderCraft.class) |
|
|
|
|
.eq(YieldOrderCraft::getYoId, yoId) |
|
|
|
|
.eq(YieldOrderCraft::getIsDeleted, CommonConstant.DELETE_FALSE); |
|
|
|
|
LambdaQueryWrapper<YieldOrderCraft> deleteWrapper = Wrappers.lambdaQuery(YieldOrderCraft.class).eq(YieldOrderCraft::getYoId, yoId).eq(YieldOrderCraft::getIsDeleted, CommonConstant.DELETE_FALSE); |
|
|
|
|
return baseMapper.delete(deleteWrapper); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void syncYieldOrderCraftData() { |
|
|
|
|
public void automaticDispatch(List<YieldOrderCraft> yieldOrderCraftList, YieldOrder yieldOrder, Boolean factor, Boolean rxlSpace) throws BusinessException { |
|
|
|
|
// 组装key为工艺能力的作业计划map
|
|
|
|
|
Map<Long, List<YieldOrderCraft>> craftAbilityMap = yieldOrderCraftList.stream().collect(Collectors.groupingBy(YieldOrderCraft::getCaId)); |
|
|
|
|
//作业计划map工艺能力key集合
|
|
|
|
|
Set<Long> craftKeys = craftAbilityMap.keySet(); |
|
|
|
|
//获取到认定的主工艺能力(默认第一个工艺能力为主工艺能力)
|
|
|
|
|
Long hostAbilityId = craftKeys.iterator().next(); |
|
|
|
|
//获取可以做此主工艺能力的作业中心集合
|
|
|
|
|
Map<Long, BsWorkCenterEntity> workCenterMap = workCenterService.selectByAbility(hostAbilityId, yieldOrder.getYpQty(), yieldOrder.getYpArea(), yieldOrder.getPartCode(), yieldOrder.getPrimaryCraft(), yieldOrder.getYieldType(), rxlSpace); |
|
|
|
|
//获取可以做此主工艺能力的外协商集合
|
|
|
|
|
List<Long> 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<BsAssignEntity> 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("未找到合适的作业中心或者供应商!请排查工艺能力、作业中心等因素!"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//获取到可以做主工艺能力的最合适的作业中心,并且标记必须、优先、正常
|
|
|
|
|
BsWorkCenterEntity workCenter = null; |
|
|
|
|
//获取到可以做主工艺能力的最合适的外协商,并且标记必须、优先、正常
|
|
|
|
|
Oem oemCustomer = null; |
|
|
|
|
//自动分派后的结果集
|
|
|
|
|
List<YieldOrderCraft> dispatchCraftList = null; |
|
|
|
|
|
|
|
|
|
// 根据车间订单是否厂内标识判定是否强制厂内(单工序时不进行标识验证)
|
|
|
|
|
if (yieldOrder.getSiteWork() && factor == null) { |
|
|
|
|
//订单强制分派厂内,若未找到工艺能力对应的作业中心,则提示异常
|
|
|
|
|
if (workCenterMap == null || workCenterMap.size() == 0) { |
|
|
|
|
throw new BusinessException("此订单需强制分派厂内,未找到满足条件得作业中心,自动分派失败!"); |
|
|
|
|
} |
|
|
|
|
//寻找最合适的作业中心
|
|
|
|
|
workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); |
|
|
|
|
if (workCenter == null) { |
|
|
|
|
throw new BusinessException("此订单需强制分派厂内,未找到满足条件得作业中心,自动分派失败!"); |
|
|
|
|
} |
|
|
|
|
} 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) { |
|
|
|
|
// 指定厂内作业中心生产
|
|
|
|
|
workCenter = workCenterService.getWorkCenter(partAssign.getCenterId()); |
|
|
|
|
} else if (partAssign != null && partAssign.getOemId() != null) { |
|
|
|
|
// 指定外协商生产
|
|
|
|
|
oemCustomer = oemService.getById(partAssign.getOemId()); |
|
|
|
|
} else if (partAssign != null && partAssign.getLimitType().equals(BsAssignEntity.MUST)) { |
|
|
|
|
if (partAssign.getPointType().equals(BsAssignEntity.IN_FACTORY)) { |
|
|
|
|
// 必须厂内生产
|
|
|
|
|
workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); |
|
|
|
|
} else { |
|
|
|
|
//必须外协生产
|
|
|
|
|
oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_MUST); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// 寻找最合适的作业中心
|
|
|
|
|
workCenter = this.inPlantDistribution(hostAbilityId, workCenterMap, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_NORMAL); |
|
|
|
|
oemCustomer = this.offsiteDistribution(hostAbilityId, oemList, yieldOrder, BsWorkCenterEntity.LIMIT_TYPE_NORMAL); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// factor等于null代表是整体,有值时代表是单工序,true转厂内,false转厂外
|
|
|
|
|
if (factor == null) { |
|
|
|
|
if (workCenter != null && oemCustomer == null) { |
|
|
|
|
//只有厂内有工艺能力
|
|
|
|
|
dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); |
|
|
|
|
} else if (oemCustomer != null && workCenter == null) { |
|
|
|
|
//只有厂外有工艺能力
|
|
|
|
|
dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); |
|
|
|
|
} else if (workCenter != null && oemCustomer != null) { |
|
|
|
|
//场内外共有工艺能力
|
|
|
|
|
if (workCenter.getLimitType().equals(BsWorkCenterEntity.LIMIT_TYPE_MUST)) { |
|
|
|
|
dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); |
|
|
|
|
} else if (oemCustomer.getLimitType().equals(BsWorkCenterEntity.LIMIT_TYPE_MUST)) { |
|
|
|
|
dispatchCraftList = this.bindOem(oemCustomer, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//如果匹配到了作业单位,则直接停止
|
|
|
|
|
if (dispatchCraftList != null && dispatchCraftList.size() > 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 厂内优先
|
|
|
|
|
if (workCenter.getLimitType().equals(BsWorkCenterEntity.LIMIT_TYPE_PRIOR)) { |
|
|
|
|
dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//如果匹配到了作业单位,则直接停止
|
|
|
|
|
if (dispatchCraftList != null && dispatchCraftList.size() > 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//外协优先
|
|
|
|
|
if (oemCustomer.getLimitType().equals(BsWorkCenterEntity.LIMIT_TYPE_PRIOR)) { |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO 根据工艺能力编码获取厂内应分比例
|
|
|
|
|
// BsDispatch dispatch = bsDispatchService.findByType(hostAbilityId, BsDispatch.D_TYPE_CLASS);
|
|
|
|
|
// if (dispatch == null) {
|
|
|
|
|
// // 获取厂内通用应分比列
|
|
|
|
|
// dispatch = bsDispatchService.findByType(null, BsDispatch.D_TYPE_FACTORY);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// //如果厂内占比大于已经设置的比列,则直接分派外协
|
|
|
|
|
// if (rate <= Double.valueOf(dispatch.getdValue())) {
|
|
|
|
|
// log.info("{}自动分派按照比例分派给厂内:{},分派比例:{} 应分比例:{}", yieldOrder.getCardNo(),
|
|
|
|
|
// workCenter.getWcName(), rate, dispatch.getdValue());
|
|
|
|
|
// dispatchCraftList = this.bindWorkCenter(workCenter.getId(), workCenterMap, hostAbilityId, craftAbilityMap, craftKeys, yieldOrder, null);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
//如果匹配到了作业单位,则直接停止
|
|
|
|
|
if (dispatchCraftList != null && dispatchCraftList.size() > 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//外协
|
|
|
|
|
// log.info("{}自动分派按照比例分派给外协:{},分派比例:{} 应分比例:{}", yieldOrder.getCardNo(),
|
|
|
|
|
// oemCustomer.getOcName(), rate, dispatch.getdValue());
|
|
|
|
|
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 BusinessException("自动分派失败,未找到合适的班组或者供应商!"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 分派成功,保存分派结果
|
|
|
|
|
this.saveBatch(dispatchCraftList); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @param hostCaId 主工艺能力 |
|
|
|
|
* @param wcMap 拥有主工艺能力的作业中心 |
|
|
|
|
* @param yieldOrder 生产订单 |
|
|
|
|
* @param limitType 0: 正常,1:优先,2:必须 |
|
|
|
|
* @return BsWorkCenter |
|
|
|
|
* @Description: 寻找满足条件的作业中心 |
|
|
|
|
* @Author dxl |
|
|
|
|
* @CreateTime 2023/3/7 18:30 |
|
|
|
|
*/ |
|
|
|
|
private BsWorkCenterEntity inPlantDistribution(Long hostCaId, Map<Long, BsWorkCenterEntity> wcMap, YieldOrder yieldOrder, Integer limitType) { |
|
|
|
|
//没有工艺能力的对应作业中心,直接分派厂外
|
|
|
|
|
if (wcMap == null || wcMap.size() == 0) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//组装wcList集合
|
|
|
|
|
List<Long> wcList = new ArrayList<>(); |
|
|
|
|
wcList.addAll(wcMap.keySet()); |
|
|
|
|
|
|
|
|
|
//作业中心
|
|
|
|
|
BsWorkCenterEntity 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 BsWorkCenterEntity priorityInPlantDistribution(Long hostCaId, List<Long> wcList, YieldOrder yieldOrder, Integer limitType) { |
|
|
|
|
//没有工艺能力的对应作业中心,直接分派厂外
|
|
|
|
|
if (wcList == null || wcList.size() == 0) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//作业中心
|
|
|
|
|
BsWorkCenterEntity workCenter = null; |
|
|
|
|
//如果找到合适的作业中心直接分派,反之如果未找到合适的作业中心(bool 是true的情况下强制厂内,bool是false是优先厂内,不满足的情况下直接返回空)
|
|
|
|
|
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<YieldOrderCraft> |
|
|
|
|
* @Description: 分配到班组 |
|
|
|
|
* @Author dxl |
|
|
|
|
* @CreateTime 2023/3/8 15:30 |
|
|
|
|
*/ |
|
|
|
|
private List<YieldOrderCraft> bindWorkCenter(Long workCenterId, Map<Long, BsWorkCenterEntity> workCenterMap, Long craftAbilityId, |
|
|
|
|
Map<Long, List<YieldOrderCraft>> craftAbilityMap, Set<Long> craftKeys, |
|
|
|
|
YieldOrder yieldOrder, Boolean factor) { |
|
|
|
|
List<YieldOrderCraft> orderCrafts = new ArrayList<>(); |
|
|
|
|
// 开始循环生产订单中组合的工艺能力key集合, 主工艺能力之前的全部分配到此作业中心
|
|
|
|
|
for (Long craftId : craftKeys) { |
|
|
|
|
//验证工艺能力
|
|
|
|
|
BsWorkCenterEntity workCenter = workCenterMap.get(craftId); |
|
|
|
|
if (workCenter == null) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
orderCrafts.addAll(craftAbilityMap.get(craftId)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 开始分派到作业中心
|
|
|
|
|
for (YieldOrderCraft orderCraft : orderCrafts) { |
|
|
|
|
BsWorkCenterEntity workCenter = workCenterMap.get(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<Long> 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)) { |
|
|
|
|
//如果指定了外协商,则强制分派到此外协商;反之则分派至厂外有同种工艺能力的外协商
|
|
|
|
|
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<Long> 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<Long> 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 != null && ocList.size() > 0) { |
|
|
|
|
List<YieldOrderAssignSteer> bsPlanAssignSteerList = assignSteerService.sortDataByFactor(ocList, 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 (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<YieldOrderCraft> |
|
|
|
|
* @Description: 绑定外协商到生成计划 |
|
|
|
|
* @Author dxl |
|
|
|
|
* @CreateTime 2023/2/17 16:28 |
|
|
|
|
*/ |
|
|
|
|
private List<YieldOrderCraft> bindOem(Oem oemCustomer, Long craftAbilityId, Map<Long, |
|
|
|
|
List<YieldOrderCraft>> craftAbilityMap, Set<Long> keys, YieldOrder yieldOrder, Boolean factor) { |
|
|
|
|
|
|
|
|
|
List<YieldOrderCraft> 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)); |
|
|
|
|
} |
|
|
|
|
// 开始分派到外协商
|
|
|
|
|
for (YieldOrderCraft orderCraft : rtnList) { |
|
|
|
|
orderCraft.setOcId(oemCustomer.getId()); |
|
|
|
|
orderCraft.setIsOutsource(Boolean.TRUE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 更新主工序工艺能力日产能信息
|
|
|
|
|
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<BsAssignEntity> 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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|