feat(触发全检/抽检):增加 每N卷+N等级(自动切换频率)创建生产检验任务逻辑

This commit is contained in:
leiqiaozhen 2024-12-06 18:12:24 +08:00
parent cc195901f7
commit 6b9fe8d0d4
5 changed files with 226 additions and 53 deletions

View File

@ -27,6 +27,8 @@ public class Freq {
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<String> getFreq() {
List<String> freqList = new ArrayList<>();
freqList.add(CHK_FIRST_SFC);
@ -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;
}
}

View File

@ -166,6 +166,12 @@ public class QmsQcPlan extends Model<QmsQcPlan> {
@ApiModelProperty(value = "复核人员群组")
private String checkUserGroup;
/**
* 新检验频率主键
*/
@ApiModelProperty(value = "新检验频率主键")
private String newInspecFreqBo;
@TableField(exist = false)
private String itemBo;

View File

@ -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<AutoCreateJobRequest.BasisInfo> objects = autoCreateJobRequest.getLotBasisList();
// 获取 设备
$resource = autoCreateJobRequest.getResource();
// 获取 工序
$operation = autoCreateJobRequest.getOperation();
// 如果批次基础信息列表为空且设备为空,则直接返回
if (ListUtils.isEmpty(objects) && StrUtil.isBlank($resource)) {
return;
}
// 将批次基础信息列表转换为LotBasis对象列表
List<LotBasis> lotBasisList = toLotBasis(objects);
// 根据LotBasis对象列表获取itemBo
String itemBo = getItemBo(lotBasisList);
// 根据itemBo获取检验计划使用对象(即获取物料上挂的检验计划)
List<QmsQcPlanTarget> qcPlanTargets = getQcPlanTargets(itemBo);
// 如果检验计划使用对象列表为空,则直接返回
if (ListUtils.isEmpty(qcPlanTargets)) {
return;
}
// 获取检验计划
List<QmsQcPlan> qcPlans = getQcPlans($site, qcPlanTargets);
// 如果检验计划列表为空,则直接返回
if (ListUtils.isEmpty(qcPlans)) {
return;
}
@ -132,33 +144,96 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService {
Map<String, List<LotBasis>> shopOrderBoMap = groupByShopOrder(lotBasisList);
qcPlans.forEach(qcPlan -> {
// 获取当前qcPlan的检验计划编号
$qcPlan = qcPlan.getQcPlan();
// 根据检验计划上的检验频率主键查询检验频率表
QmsInspecFreq inspecFreq = qmsInspecFreqService.getById(qcPlan.getInspecFreqBo());
// 获取检验计划的新检验频率主键
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<LotBasis> 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,18 +606,80 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService {
return null;
}
// 每N卷+N等级(自动切换频率),自动创建检验任务
public String chkIntervalSfcInspecLevel(List<LotBasis> 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<LotBasis> 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<QmsQcPlanTarget> getQcPlanTargets(String itemBo) {
// 生成 工序主键
String operationBo = Operation.genHandle($site, $operation, BaseConstants.CURRENT_REVISION);
// 生成 产品配置作业-工序主键
String productOpBo = ProductOp.genHandle(ProductConfig.genHandle(itemBo), operationBo);
return qmsQcPlanTargetService.list(
Wrappers.lambdaQuery(QmsQcPlanTarget.class).eq(QmsQcPlanTarget::getTargetBo, productOpBo));
}
// 根据 productOpBo 查询 检验计划使用对象
return qmsQcPlanTargetService.list(
Wrappers.lambdaQuery(QmsQcPlanTarget.class)
.eq(QmsQcPlanTarget::getTargetBo, productOpBo));
}
/**
* 根据站点和检验计划使用对象列表获取有效的检验计划列表
*
* @param site 站点
* @param qcPlanTargets 检验计划使用对象
* @return 符合条件的有效检验计划使用对象列表
*/
private List<QmsQcPlan> getQcPlans(String site, List<QmsQcPlanTarget> qcPlanTargets) {
return qmsQcPlanService.list(Wrappers.lambdaQuery(QmsQcPlan.class).eq(QmsQcPlan::getSite, site)
.in(QmsQcPlan::getQcPlan,
@ -640,18 +772,37 @@ public class AutoCreateJobServiceImpl implements AutoCreateJobService {
customFieldsMapper.insert(customFields);
}
/**
* 将 AutoCreateJobRequest.BasisInfo 对象列表转换为 LotBasis 对象列表。
*
* @param objects AutoCreateJobRequest.BasisInfo 对象列表
* @return 转换后的 LotBasis 对象列表
*/
private List<LotBasis> toLotBasis(List<AutoCreateJobRequest.BasisInfo> 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>
}
/**
* 从 LotBasis 对象列表中获取第一个元素的 itemBo 值。
* 如果列表为空,则返回一个新创建的 LotBasis 对象的 itemBo 值。
*
* @param lotBasisList LotBasis 对象列表
* @return 第一个 LotBasis 对象的 itemBo 值,或新创建的 LotBasis 对象的 itemBo 值(如果列表为空)
*/
private String getItemBo(List<LotBasis> 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<String> dailyFixedTimes = new ArrayList<>(Arrays.asList(dailyFixedTime.split(",")));
// 時間由小到大排序

View File

@ -35,14 +35,18 @@ public interface AutoCreateJobMapper {
List<ChkInfo> 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<String> getProductionResrce(@Param("site") String site);
List<ChkInfo> 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);
}

View File

@ -162,6 +162,14 @@
and a.RESRCE = #{resource}
</select>
<select id="getIntervalLotValue" resultType="java.lang.String">
select b.FIELD_VALUE
from resrce a
join custom_fields b on b.HANDLE = a.HANDLE and b.FIELD_NAME = 'QC_INTERVAL_LOT_12'
where a.SITE = #{site}
and a.RESRCE = #{resource}
</select>
<select id="getProductionResrce" resultType="java.lang.String">
select distinct b.RESRCE
from lot_state a