diff --git a/qms-api/src/main/java/com/foreverwin/iep/qms/constant/Freq.java b/qms-api/src/main/java/com/foreverwin/iep/qms/constant/Freq.java index d376951..366d6e5 100644 --- a/qms-api/src/main/java/com/foreverwin/iep/qms/constant/Freq.java +++ b/qms-api/src/main/java/com/foreverwin/iep/qms/constant/Freq.java @@ -26,6 +26,8 @@ public class Freq { public static final String CHK_DAILY_FIXED_TIME = "CHK_DAILY_FIXED_TIME"; // 每日固定N点 public static final String MANUAL = "MANUAL"; // 手动 + + public static final String CHK_INTERVAL_SFC_INSPEC_LEVEL = "CHK_INTERVAL_SFC_INSPEC_LEVEL"; // 每N卷+N等级(自动切换频率) public static List getFreq() { List freqList = new ArrayList<>(); @@ -38,6 +40,8 @@ public class Freq { freqList.add(CHK_SEVERAL_SFC); freqList.add(CHK_INTERVAL_HOUR2); freqList.add(CHK_DAILY_FIXED_TIME); + freqList.add(CHK_SEVERAL_SFC2); + freqList.add(CHK_INTERVAL_SFC_INSPEC_LEVEL); return freqList; } } diff --git a/qms-api/src/main/java/com/foreverwin/iep/qms/entity/QmsQcPlan.java b/qms-api/src/main/java/com/foreverwin/iep/qms/entity/QmsQcPlan.java index 230857d..4b9c070 100644 --- a/qms-api/src/main/java/com/foreverwin/iep/qms/entity/QmsQcPlan.java +++ b/qms-api/src/main/java/com/foreverwin/iep/qms/entity/QmsQcPlan.java @@ -166,6 +166,12 @@ public class QmsQcPlan extends Model { @ApiModelProperty(value = "复核人员群组") private String checkUserGroup; + /** + * 新检验频率主键 + */ + @ApiModelProperty(value = "新检验频率主键") + private String newInspecFreqBo; + @TableField(exist = false) private String itemBo; diff --git a/qms-core/src/main/java/com/foreverwin/iep/qms/service/impl/AutoCreateJobServiceImpl.java b/qms-core/src/main/java/com/foreverwin/iep/qms/service/impl/AutoCreateJobServiceImpl.java index d08675f..c8ef96c 100644 --- a/qms-core/src/main/java/com/foreverwin/iep/qms/service/impl/AutoCreateJobServiceImpl.java +++ b/qms-core/src/main/java/com/foreverwin/iep/qms/service/impl/AutoCreateJobServiceImpl.java @@ -85,8 +85,10 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { private static final String ADMIN = "admin"; private static final String REPAIR_FIRST_LOT = "REPAIR_FIRST_LOT"; - + // 检验批数(N卷-工单+机台) private static final String QC_INTERVAL_LOT = "QC_INTERVAL_LOT"; + // 检验批数(N卷+N等级) + private static final String QC_INTERVAL_LOT_12 = "QC_INTERVAL_LOT_12"; private static final String TRUE = "true"; @@ -103,25 +105,35 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { @Transactional(rollbackFor = Exception.class) @Override public void invoke(AutoCreateJobRequest autoCreateJobRequest) { + // 获取 站点 $site = TenantContextHolder.getTenantId(); + // 获取 用户 $user = autoCreateJobRequest.getUser(); + // 获取 批次基础信息列表 List objects = autoCreateJobRequest.getLotBasisList(); + // 获取 设备 $resource = autoCreateJobRequest.getResource(); + // 获取 工序 $operation = autoCreateJobRequest.getOperation(); - + + // 如果批次基础信息列表为空且设备为空,则直接返回 if (ListUtils.isEmpty(objects) && StrUtil.isBlank($resource)) { return; } - + + // 将批次基础信息列表转换为LotBasis对象列表 List lotBasisList = toLotBasis(objects); + // 根据LotBasis对象列表获取itemBo String itemBo = getItemBo(lotBasisList); - + // 根据itemBo获取检验计划使用对象(即获取物料上挂的检验计划) List qcPlanTargets = getQcPlanTargets(itemBo); + // 如果检验计划使用对象列表为空,则直接返回 if (ListUtils.isEmpty(qcPlanTargets)) { return; } - + // 获取检验计划 List qcPlans = getQcPlans($site, qcPlanTargets); + // 如果检验计划列表为空,则直接返回 if (ListUtils.isEmpty(qcPlans)) { return; } @@ -132,33 +144,96 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { Map> shopOrderBoMap = groupByShopOrder(lotBasisList); qcPlans.forEach(qcPlan -> { + // 获取当前qcPlan的检验计划编号 $qcPlan = qcPlan.getQcPlan(); + // 根据检验计划上的检验频率主键查询检验频率表 QmsInspecFreq inspecFreq = qmsInspecFreqService.getById(qcPlan.getInspecFreqBo()); - - String chkFirstSfc = inspecFreq.getChkFirstSfc(); - String chkDailyFirstSfc = inspecFreq.getChkDailyFirstSfc(); - String dailyFirstSfc = inspecFreq.getDailyFirstSfc(); - String chkChangeProduct = inspecFreq.getChkChangeProduct(); - String chkChangeMould = inspecFreq.getChkChangeMould(); - String chkMaintenFirstSfc = inspecFreq.getChkMaintenFirstSfc(); - String chkStopAfterSfc = inspecFreq.getChkStopAfterSfc(); - BigDecimal stopAfterSfc = inspecFreq.getStopAfterSfc(); - String chkSeveralSfc = inspecFreq.getChkSeveralSfc(); - Integer severalSfc = inspecFreq.getSeveralSfc(); - String chkIntervalHour2 = inspecFreq.getChkIntervalHour2(); + // 获取检验计划的新检验频率主键 + String newInspecFreqBo = qcPlan.getNewInspecFreqBo(); + + // 获取各种检验频率配置项 + // 工单第一个生产的生产批 + String chkFirstSfc = inspecFreq.getChkFirstSfc(); + // 每日第一个生产的生产批 + String chkDailyFirstSfc = inspecFreq.getChkDailyFirstSfc(); + // 每日起始時間 + String dailyFirstSfc = inspecFreq.getDailyFirstSfc(); + // 更换产品后第一个生产的生产批 + String chkChangeProduct = inspecFreq.getChkChangeProduct(); + // 设备维修后第一个生产的生产批 + String chkChangeMould = inspecFreq.getChkChangeMould(); + // 设备维修后第一个生产的生产批 + String chkMaintenFirstSfc = inspecFreq.getChkMaintenFirstSfc(); + // 设备停机N小时以上, 生產的第一个生产批 + String chkStopAfterSfc = inspecFreq.getChkStopAfterSfc(); + // 停机小时数 + BigDecimal stopAfterSfc = inspecFreq.getStopAfterSfc(); + // 每N个生产批(以机台计算) + String chkSeveralSfc = inspecFreq.getChkSeveralSfc(); + // 生产批批数 + Integer severalSfc = inspecFreq.getSeveralSfc(); + // 机台生产每N小时 + String chkIntervalHour2 = inspecFreq.getChkIntervalHour2(); // 每N个生产批(以机台+工单计算) String chkSeveralSfc2 = inspecFreq.getChkSeveralSfc2(); // 每N个生产批(以机台+工单计算) Integer severalSfc2 = inspecFreq.getSeveralSfc2(); + // 每N卷+N等级(自动切换频率) + String chkIntervalSfcInspecLevel = inspecFreq.getChkIntervalSfcInspecLevel(); + // 间隔N卷(自动切换频率) + Integer intervalSfcInspecLevel = inspecFreq.getIntervalSfcInspecLevel(); + + // 如果 每N卷+N等级(自动切换频率) 为 true ,且 新检验频率主键 不为空时,则切换新的检验频率 + if ("true".equals(chkIntervalSfcInspecLevel) && StrUtil.isNotBlank(newInspecFreqBo)) { + // 新检验频率 + inspecFreq = qmsInspecFreqService.getById(newInspecFreqBo); + + // 获取各种检验频率配置项 + // 工单第一个生产的生产批 + chkFirstSfc = inspecFreq.getChkFirstSfc(); + // 每日第一个生产的生产批 + chkDailyFirstSfc = inspecFreq.getChkDailyFirstSfc(); + // 每日起始時間 + dailyFirstSfc = inspecFreq.getDailyFirstSfc(); + // 更换产品后第一个生产的生产批 + chkChangeProduct = inspecFreq.getChkChangeProduct(); + // 设备维修后第一个生产的生产批 + chkChangeMould = inspecFreq.getChkChangeMould(); + // 设备维修后第一个生产的生产批 + chkMaintenFirstSfc = inspecFreq.getChkMaintenFirstSfc(); + // 设备停机N小时以上, 生產的第一个生产批 + chkStopAfterSfc = inspecFreq.getChkStopAfterSfc(); + // 停机小时数 + stopAfterSfc = inspecFreq.getStopAfterSfc(); + // 每N个生产批(以机台计算) + chkSeveralSfc = inspecFreq.getChkSeveralSfc(); + // 生产批批数 + severalSfc = inspecFreq.getSeveralSfc(); + // 机台生产每N小时 + chkIntervalHour2 = inspecFreq.getChkIntervalHour2(); + // 每N个生产批(以机台+工单计算) + chkSeveralSfc2 = inspecFreq.getChkSeveralSfc2(); + // 每N个生产批(以机台+工单计算) + severalSfc2 = inspecFreq.getSeveralSfc2(); + // 每N卷+N等级(自动切换频率) + chkIntervalSfcInspecLevel = inspecFreq.getChkIntervalSfcInspecLevel(); + // 间隔N卷(自动切换频率) + intervalSfcInspecLevel = inspecFreq.getIntervalSfcInspecLevel(); + } + + // 初始化标志位 String flag = null; + // 遍历频率列表,根据不同的频率执行相应的检查方法 for (String freq : freqList) { if (StrUtil.isNotBlank(flag)) { + // 如果标志位已设置,则跳出循环 break; } switch (freq) { + // 工单第一个生产的生产批 case Freq.CHK_FIRST_SFC: if (execute(flag, chkFirstSfc)) { flag = chkFirstSfc(shopOrderBoMap); @@ -194,6 +269,7 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { flag = chkSeveralSfc(lotBasisList, severalSfc); } break; + // 每N个生产批(以机台+工单计算) case Freq.CHK_SEVERAL_SFC2: if (execute(flag, chkSeveralSfc2)) { flag = chkSeveralSfc2(lotBasisList, severalSfc2); @@ -204,6 +280,13 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { flag = chkIntervalHour2(); } break; + // 每N卷+N等级(自动切换频率) + case Freq.CHK_INTERVAL_SFC_INSPEC_LEVEL: + // 如果 开启频率切换 为 true + if (execute(flag, chkIntervalSfcInspecLevel)) { + flag = chkIntervalSfcInspecLevel(lotBasisList, intervalSfcInspecLevel); + } + break; } } }); @@ -478,32 +561,19 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { return null; } + // 每N个生产批(以机台+工单计算) ,自动创建检验任务 public String chkSeveralSfc2(List lotBasisList, Integer severalSfc2) { String resourceBo = Resrce.genHandle($site, $resource); - - // 获取设备 上一个进站的 LotNo上的工单 + // 获取设备 上一个进站的 LotNo上的工单主键 String preLotNoShopOrderBo = autoCreateJobMapper.getPreLotNoShopOrder(resourceBo); - // 获取设备 当前进站的 LotNo上的工单 + // 获取设备 当前进站的 LotNo上的工单主键 String currentLotNoShopOrderBo = lotBasisList.get(0).getShopOrderBo(); -// // 如果 上一个进站的 LotNo上的工单 为空,则说明设备上没有工单进过站 -// if (StrUtil.isBlank(preLotNoShopOrderBo)) { -// // 更新设备自定义字段为 severalSfc2 -// updateOrInsertCustomFields(QC_INTERVAL_LOT, String.valueOf(severalSfc2)); -// } else { -// // 获取设备上一个进站的LotNo上的工单 -// // 判断 如果 设备上一个进站的LotNo上的工单 和 设备当前进站的LotNo上的工单 不一致,说明切换工单了,则需更新设备自定义字段为 severalSfc2 -// if (!preLotNoShopOrderBo.equals(currentLotNoShopOrderBo)) { -// // 更新设备自定义字段为 severalSfc2 -// updateOrInsertCustomFields(QC_INTERVAL_LOT, String.valueOf(severalSfc2)); -// } -// } - // 获取设备自定义字段 String value = autoCreateJobMapper.getIntervalLot($site, $resource); if (StrUtil.isBlank(value) || StrUtil.isBlank(preLotNoShopOrderBo) || !preLotNoShopOrderBo.equals(currentLotNoShopOrderBo)) { - // 设置默认值为 severalSfc2 + // 设置默认值为 severalSfc2-1 value = String.valueOf(severalSfc2-1); } @@ -536,24 +606,86 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { return null; } + // 每N卷+N等级(自动切换频率),自动创建检验任务 + public String chkIntervalSfcInspecLevel(List lotBasisList, Integer intervalSfcInspecLevel) { + String resourceBo = Resrce.genHandle($site, $resource); + // 获取设备 上一个进站的 LotNo上的工单主键 + String preLotNoShopOrderBo = autoCreateJobMapper.getPreLotNoShopOrder(resourceBo); + // 获取设备 当前进站的 LotNo上的工单主键 + String currentLotNoShopOrderBo = lotBasisList.get(0).getShopOrderBo(); + + // 获取设备自定义字段 + String value = autoCreateJobMapper.getIntervalLotValue($site, $resource); + + if (StrUtil.isBlank(value) || StrUtil.isBlank(preLotNoShopOrderBo) || !preLotNoShopOrderBo.equals(currentLotNoShopOrderBo)) { + // 设置默认值为 intervalSfcInspecLevel-1 + value = String.valueOf(intervalSfcInspecLevel-1); + } + + List sort = lotBasisList.stream().sorted(Comparator.comparing(LotBasis::getLotNo)) + .collect(Collectors.toList()); + + int size = lotBasisList.size(); + int interval = Integer.parseInt(value); + int sum = size + interval; + int quotient = sum / intervalSfcInspecLevel; + int remainder = sum % intervalSfcInspecLevel; + + boolean flag = false; + for (int i = 1; i <= quotient; i++) { + int target = (i * intervalSfcInspecLevel) - interval; + int index = target - 1; + if (index >= 0 && index < size) { + // prevent out of list range + String lotNo = sort.get(index).getLotNo(); + createJob(lotNo, Freq.CHK_INTERVAL_SFC_INSPEC_LEVEL); + + flag = true; + } + } + updateOrInsertCustomFields(QC_INTERVAL_LOT_12, String.valueOf(remainder)); + + if (flag) { + return Freq.CHK_INTERVAL_SFC_INSPEC_LEVEL; + } + return null; + } + public String chkIntervalHour2() { return null; } - + + /** + * 根据 itemBo 获取 检验计划使用对象 + * + * @param itemBo 物料主键 + * @return 检验计划使用对象 + */ private List getQcPlanTargets(String itemBo) { + // 生成 工序主键 String operationBo = Operation.genHandle($site, $operation, BaseConstants.CURRENT_REVISION); - + + // 生成 产品配置作业-工序主键 String productOpBo = ProductOp.genHandle(ProductConfig.genHandle(itemBo), operationBo); + + // 根据 productOpBo 查询 检验计划使用对象 return qmsQcPlanTargetService.list( - Wrappers.lambdaQuery(QmsQcPlanTarget.class).eq(QmsQcPlanTarget::getTargetBo, productOpBo)); + Wrappers.lambdaQuery(QmsQcPlanTarget.class) + .eq(QmsQcPlanTarget::getTargetBo, productOpBo)); } - + /** + * 根据站点和检验计划使用对象列表获取有效的检验计划列表 + * + * @param site 站点 + * @param qcPlanTargets 检验计划使用对象 + * @return 符合条件的有效检验计划使用对象列表 + */ private List getQcPlans(String site, List qcPlanTargets) { return qmsQcPlanService.list(Wrappers.lambdaQuery(QmsQcPlan.class).eq(QmsQcPlan::getSite, site) - .in(QmsQcPlan::getQcPlan, - qcPlanTargets.stream().map(QmsQcPlanTarget::getQcPlan) - .collect(Collectors.toList())) - .eq(QmsQcPlan::getCurrentRevision, BaseConstants.Y)); + .in(QmsQcPlan::getQcPlan, + qcPlanTargets.stream().map(QmsQcPlanTarget::getQcPlan) + .collect(Collectors.toList())) + .eq(QmsQcPlan::getCurrentRevision, BaseConstants.Y)); } private Map> groupByShopOrder(List lotBasisList) { @@ -639,19 +771,38 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService { customFields.setCreator($user); customFieldsMapper.insert(customFields); } - + + /** + * 将 AutoCreateJobRequest.BasisInfo 对象列表转换为 LotBasis 对象列表。 + * + * @param objects AutoCreateJobRequest.BasisInfo 对象列表 + * @return 转换后的 LotBasis 对象列表 + */ private List toLotBasis(List objects) { - return objects.stream().map(object -> { - LotBasis lotBasis = new LotBasis(); - BeanUtils.copyProperties(object, lotBasis); - return lotBasis; - }).collect(Collectors.toList()); + // 使用流操作将每个 AutoCreateJobRequest.BasisInfo 对象转换为 LotBasis 对象 + return objects.stream() + .map(object -> { + LotBasis lotBasis = new LotBasis(); // 创建一个新的 LotBasis 对象 + BeanUtils.copyProperties(object, lotBasis); // 复制属性到 LotBasis 对象 + return lotBasis; // 返回转换后的 LotBasis 对象 + }) + .collect(Collectors.toList()); // 收集结果为 List } - + /** + * 从 LotBasis 对象列表中获取第一个元素的 itemBo 值。 + * 如果列表为空,则返回一个新创建的 LotBasis 对象的 itemBo 值。 + * + * @param lotBasisList LotBasis 对象列表 + * @return 第一个 LotBasis 对象的 itemBo 值,或新创建的 LotBasis 对象的 itemBo 值(如果列表为空) + */ private String getItemBo(List lotBasisList) { - return lotBasisList.stream().findFirst().orElse(new LotBasis()).getItemBo(); + // 使用流操作获取列表中的第一个元素 + // 如果列表为空,则使用 orElse 提供一个默认的 LotBasis 对象 + return lotBasisList.stream() + .findFirst() + .orElse(new LotBasis()) + .getItemBo(); } - private String getSpecifiedTime(String dailyFixedTime, String localTime) { List dailyFixedTimes = new ArrayList<>(Arrays.asList(dailyFixedTime.split(","))); // 時間由小到大排序 diff --git a/qms-db/src/main/java/com/foreverwin/iep/qms/mapper/AutoCreateJobMapper.java b/qms-db/src/main/java/com/foreverwin/iep/qms/mapper/AutoCreateJobMapper.java index 1173d3f..244ee12 100644 --- a/qms-db/src/main/java/com/foreverwin/iep/qms/mapper/AutoCreateJobMapper.java +++ b/qms-db/src/main/java/com/foreverwin/iep/qms/mapper/AutoCreateJobMapper.java @@ -34,15 +34,19 @@ public interface AutoCreateJobMapper { List getStopTime(@Param("site") String site, @Param("resource") String resource, @Param("afterTime") LocalDateTime afterTime); - + + // 获取设备自定义字段 QC_INTERVAL_LOT 的值 String getIntervalLot(@Param("site") String site, @Param("resource") String resource); List getProductionResrce(@Param("site") String site); List getProductionLot(@Param("site") String site, @Param("resource") String resource); - // // 获取设备上一个进站的LotNo上的工单, + // 获取设备上一个进站的LotNo上的工单 String getPreLotNoShopOrder( @Param("resourceBo") String resourceBo); + + // 获取设备自定义字段 QC_INTERVAL_LOT_12 的值 + String getIntervalLotValue(@Param("site") String site, @Param("resource") String resource); } diff --git a/qms-db/src/main/resources/qms/mapper/AutoCreateJobMapper.xml b/qms-db/src/main/resources/qms/mapper/AutoCreateJobMapper.xml index 8c9494b..41329ab 100644 --- a/qms-db/src/main/resources/qms/mapper/AutoCreateJobMapper.xml +++ b/qms-db/src/main/resources/qms/mapper/AutoCreateJobMapper.xml @@ -161,6 +161,14 @@ where a.SITE = #{site} and a.RESRCE = #{resource} + +