feat(触发全检/抽检):增加 每N卷+N等级(自动切换频率)创建生产检验任务逻辑
This commit is contained in:
parent
cc195901f7
commit
6b9fe8d0d4
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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(",")));
|
||||
// 時間由小到大排序
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user