opt: 拆解套轴完成

This commit is contained in:
2026-04-21 11:11:11 +08:00
parent 0ddf7f8989
commit 982c71d2c8
7 changed files with 497 additions and 268 deletions

View File

@@ -43,6 +43,7 @@ import org.nl.system.service.notice.ISysNoticeService;
import org.nl.system.service.param.ISysParamService;
import org.nl.system.service.param.dao.Param;
import org.nl.wms.ext.acs.service.WmsToAcsService;
import org.nl.wms.pdm.ivt.deliverycache.service.IDeliverycachepointivtService;
import org.nl.wms.sch.manage.TaskStatusEnum;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
@@ -103,12 +104,16 @@ public class AutoCallAirShaftTask extends Prun {
private RedisUtils redisUtils;
@Autowired
private IMdPbPapervehicleService papervehicleService;
@Autowired
private IDeliverycachepointivtService iDeliverycachepointivtService;
public final static String PARAM_CODE_PLAN_AREA = "PARAM_CODE_PLAN_AREA";
public final static String IS_ONLY_PULLING = "IS_ONLY_PULLING";
public final static String TZ_DAY = "TZ_DAY";
public final static String USE_XN = "USE_XN";
public final static String BZ_CHECK_EMPTY = "BZ_CHECK_EMPTY";
/** 合单配送 */
public final static String IS_COMBINED_ORDER = "IS_COMBINED_ORDER";
public List<String> stepErrorInfo = new ArrayList<>();
@Autowired
private RedissonClient redissonClient;
@@ -1244,6 +1249,19 @@ public class AutoCallAirShaftTask extends Prun {
}
List<String> stringList = cuts2.stream().map(BstIvtCutpointivt::getPoint_code).collect(Collectors.toList());
stepErrorInfo.add("设备" + dto.getResource_name() + "检测到暂存架" + stringList + "有套好的管芯,不会进行套轴。");
// 检测是否存在气胀轴缓存架子上
Param codParam = paramService.findByCode(IS_COMBINED_ORDER);
// 不允许拼单(不拼单代表不使用拼单逻辑,无需检测)
if (ObjectUtil.isEmpty(codParam) || !"1".equals(codParam.getValue())) {
return true;
}
// 检测 todo: 可以优化考虑任务,但似乎没太大作用
Integer num = iDeliverycachepointivtService.countPendingUseByDevice(dto.getResource_name());
if (num == 0) {
return true;
}
}
log.info("检查有同母卷不允许套轴:{}", dto);
// 有就返回true

View File

@@ -64,6 +64,8 @@ import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -370,6 +372,13 @@ public class SlitterServiceImpl implements SlitterService {
/**
* 拼单规则:双轴不拼,单轴拼,同区域拼
* validateAndGetPlans() - 验证并获取分切计划
* handleExceptionCase() - 处理异常情况
* updatePlanWeights() - 更新分切计划重量
* generateQzzNo() - 生成气胀轴编码
* completeShaftLoading() - 完成套轴
* tryCombineOrder() - 尝试拼单逻辑
* handleNormalProcess() - 处理正常业务流程
* @param param
* @return
*/
@@ -377,286 +386,86 @@ public class SlitterServiceImpl implements SlitterService {
@Override
@Transactional(rollbackFor = Exception.class)
public JSONObject acsFinishLoadShaft(JSONObject param) {
String msg = "";
JSONObject res = new JSONObject();
// 穿拔轴位
String deviceCode = param.getString("device_code");
List<String> stepTipLogs = getRedisListValue("ERROR" + deviceCode);
// 枷锁
RLock lock = redissonClient.getLock("doAcsFinishLoadShaft");
boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS);
try {
if (tryLock) {
log.info("ACS申请套管完成参数: {}", param);
// 纸管
BigDecimal weight1 = param.getBigDecimal("weight1");
String material1 = param.getString("material1");
BigDecimal weight2 = param.getBigDecimal("weight2");
String material2 = param.getString("material2");
BstIvtShafttubeivt startPoint = shafttubeivtService.getOne(new LambdaQueryWrapper<BstIvtShafttubeivt>()
.eq(BstIvtShafttubeivt::getPoint_code, deviceCode));
// 获取分切计划
List<String> collect = Stream.of(startPoint.getContainer_name1(), startPoint.getContainer_name2())
.filter(value -> value != null && !value.isEmpty()).collect(Collectors.toList());
if (collect.size() == 0) {
log.error("找不到[{}]对应的分切计划!", deviceCode);
stepTipLogs.add("套轴完成->找不到[" + deviceCode + "]点位记录的分切计划!分切计划可能被删除或者拼接!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
throw new BadRequestException("找不到[" + deviceCode + "]对应的分切计划!");
}
List<PdmBiSlittingproductionplan> plans = slittingproductionplanService.list(
new LambdaQueryWrapper<PdmBiSlittingproductionplan>()
.in(PdmBiSlittingproductionplan::getContainer_name, collect)
.eq(PdmBiSlittingproductionplan::getStatus, "01")
.eq(PdmBiSlittingproductionplan::getIs_delete, "0"));
// 判断是否有未完成的任务
List<SchBaseTask> list = taskService.list(new LambdaQueryWrapper<SchBaseTask>()
.eq(SchBaseTask::getPoint_code1, deviceCode)
.like(SchBaseTask::getRequest_param, collect.get(0))
.lt(SchBaseTask::getTask_status, "07"));
if (list.size() > 0) {
log.error("点位[{}]存在未完成得任务!", deviceCode);
stepTipLogs.add("套轴完成->点位[" + deviceCode + "]存在未完成得任务!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
throw new BadRequestException("点位[" + deviceCode + "]存在未完成得任务!");
}
// 去异常位
if (plans.size() == 0) {
log.error("找不到[{}]对应的分切计划,分切计划可能被删除或者拼接!", collect);
// 移动到异常处理位随机一个点位在送到B2对面的位置
List<String> exceptionPointCodes = bcutpointivtService.getCanUseMinPointByShelf("4", "0");
if (exceptionPointCodes.size() > 0) {
String exceptionPoint = exceptionPointCodes.get(0);
JSONObject exParam = new JSONObject();
exParam.put("point_code1", startPoint.getPoint_code());
exParam.put("point_code2", exceptionPoint);
if (exceptionPoint.endsWith("A")) {
exParam.put("vehicle_code1", collect);
} else {
exParam.put("vehicle_code2", collect);
}
exParam.put("task_type", SlitterEnum.TASK_TYPE.code("套轴异常处理桁架任务"));
exParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
exParam.put("acs_task_type", "6");
exParam.put("containers", collect);
exParam.put("qzz_size", startPoint.getQzz_size());
sendNBJExceptionPointTask.createTask(exParam);
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "创建送至异常处理位!");
return res;
}
// 半条任务等待补齐
stepTipLogs.add("套轴完成->[" + collect + "]对应的分切计划状态已更改,无暂存位置,创建任务失败!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
JSONObject exParam = new JSONObject();
exParam.put("point_code1", startPoint.getPoint_code());
exParam.put("point_code2", "-");
exParam.put("vehicle_code1", collect);
exParam.put("task_type", SlitterEnum.TASK_TYPE.code("套轴异常处理桁架任务"));
exParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
exParam.put("task_status", TaskStatusEnum.SURE_START.getCode());
exParam.put("acs_task_type", "6");
exParam.put("containers", collect);
exParam.put("qzz_size", startPoint.getQzz_size());
sendNBJExceptionPointTask.createTask(exParam);
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "请求成功");
res.put("msg", msg);
return res;
}
// 分切计划设置纸卷重量
for (PdmBiSlittingproductionplan plan : plans) {
if (SlitterConstant.SLITTER_SUB_VOLUME_LEFT.equals(plan.getLeft_or_right())) {
plan.setPaper_weight(String.valueOf(NumberUtil.round(weight1, 2)));
msg = msg + "子卷号:" + plan.getContainer_name() + "的纸管重量: " + weight1 + " | ";
} else {
plan.setPaper_weight(String.valueOf(NumberUtil.round(weight2, 2)));
msg = msg + "子卷号:" + plan.getContainer_name() + "的纸管重量: " + weight2 + " | ";
}
TaskUtils.updateOptMessageBySlitterPlan(plan);
}
slittingproductionplanService.updateBatchById(plans);
// 当前套轴的分切计划
PdmBiSlittingproductionplan demoPlan = plans.get(0);
// 分切计划设置套轴完成
String resourceName = demoPlan.getResource_name();
String qzzNo = resourceName.substring(0, 2)
+ resourceName.substring(resourceName.length() - 2)
+ demoPlan.getSplit_group()
+ TaskUtils.getDateTime("yyMMddHHmmss") + "-"
+ demoPlan.getUp_or_down();
plans.forEach(plan -> {
plan.setIs_child_tz_ok(SlitterConstant.SLITTER_YES);
plan.setQzzno(qzzNo);
TaskUtils.updateOptMessageBySlitterPlan(plan);
});
slittingproductionplanService.updateBatchById(plans);
// 搬运的点
BstIvtCutpointivt cutPoint;
//============================= 拼单业务 ==============================
// 标记是否是通过拼单的
String flag = "0";
// 标记气胀轴编码是存到任务的载具号1还是2
String vehicleLocation = "1";
// 指定点位
String specialPoint = "";
// 合单开关
Param codParam = paramService.findByCode(IS_COMBINED_ORDER);
// 总判断是否有同组(判断自己能不能拼单)
Integer sameNumber = slittingproductionplanService.getSameTripParentContainerPlanCount(demoPlan);
// 允许拼单
if (sameNumber == 0 && ObjectUtil.isNotEmpty(codParam) && "1".equals(codParam.getValue())) {
StIvtCutpointivt deviceInfo = cutpointivtService.getPintByExtCode(resourceName, false);
List<BstIvtCutpointivt> emptyNotTaskPoint;
// 查找能够拼单(没任务)的点位
emptyNotTaskPoint = slitterMapper.getCombinedOrders(CombinedOrderDto
.builder()
.pointStatus("2")
.pointType("1")
.pointLocation(deviceInfo.getPoint_location())
.plan(deviceInfo.getPlan())
.device(resourceName).build());
flag = "1";
// 如果为空,看看路上的那根轴能不能拼单
if (emptyNotTaskPoint.size() == 0) {
SchBaseTask runningTask = taskService.getOne(new LambdaQueryWrapper<SchBaseTask>()
.eq(SchBaseTask::getHandle_class, "org.nl.b_lms.sch.tasks.slitter.TrussSendAirShaftTask")
.lt(SchBaseTask::getTask_status, "07")
.eq(SchBaseTask::getIs_delete, "0")
.ne(SchBaseTask::getPoint_code1, deviceCode));
if (ObjectUtil.isNotEmpty(runningTask) && ObjectUtil.isNotEmpty(runningTask.getPoint_code2())) {
List<PdmBiSlittingproductionplan> runningShafts = slittingproductionplanService.getByQzzNos(Arrays.asList(runningTask.getVehicle_code(), runningTask.getVehicle_code2()));
if (runningShafts.size() > 0) {
PdmBiSlittingproductionplan runningShaft = runningShafts.get(0);
// 判断有没有同组同母卷同设备不同轴的卷号,没有则判断和当前计划是不是允许拼单的
Integer otherPlans =
slittingproductionplanService.getSameTripParentContainerPlanCount(runningShaft);
if (otherPlans == 0) {
StIvtCutpointivt runDeviceInfo = cutpointivtService.getPintByExtCode(runningShaft.getResource_name(), false);
// 判断对应设备与当前计划设是否能够拼在一起
if (runDeviceInfo.getPlan().equals(deviceInfo.getPlan())) {
// 可以拼单
BstIvtCutpointivt one = bcutpointivtService.getOne(new LambdaQueryWrapper<BstIvtCutpointivt>()
.eq(BstIvtCutpointivt::getTruss_point_code1, runningTask.getPoint_code2()).or()
.eq(BstIvtCutpointivt::getTruss_point_code2, runningTask.getPoint_code2()));
// 判断目标点是否为空
specialPoint = one.getTruss_point_code1().equals(runningTask.getPoint_code2())
? one.getTruss_point_code2() : one.getTruss_point_code1();
vehicleLocation = one.getTruss_point_code1().equals(runningTask.getPoint_code2())
? "2" : "1";
if ((specialPoint.equals(one.getTruss_point_code1())
&& ObjectUtil.isNotEmpty(one.getQzz_no1()))
|| (specialPoint.equals(one.getTruss_point_code2())
&& ObjectUtil.isNotEmpty(one.getQzz_no2()))) {
emptyNotTaskPoint.add(one);
flag = "2";
}
}
}
}
}
}
if (emptyNotTaskPoint.size() > 0) {
cutPoint = emptyNotTaskPoint.get(0);
// 创建任务
JSONObject taskParam = new JSONObject();
taskParam.put("point_code1", startPoint.getPoint_code());
taskParam.put("point_code2",
"2".equals(flag) ? specialPoint
: "1".equals(flag) ? ObjectUtil.isEmpty(cutPoint.getQzz_no1())
? cutPoint.getTruss_point_code1() : cutPoint.getTruss_point_code2()
: SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down())
? cutPoint.getTruss_point_code1() : cutPoint.getTruss_point_code2());
taskParam.put("vehicle_code1",
"2".equals(flag) ? "1".equals(vehicleLocation) ? qzzNo : ""
: "1".equals(flag) ? ObjectUtil.isEmpty(cutPoint.getQzz_no1())
? qzzNo : ""
: SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("vehicle_code2",
"2".equals(flag) ? "2".equals(vehicleLocation) ? qzzNo : ""
: "1".equals(flag) ? ObjectUtil.isEmpty(cutPoint.getQzz_no2())
? qzzNo : ""
: SlitterConstant.SLITTER_SHAFT_DOWN.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("task_type", "010814");
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("immediateNotifyAcs", "1");
trussSendAirShaftTask.createTask(taskParam);
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "请求成功");
res.put("msg", msg);
return res;
}
}
flag = "0";
//============================= 不进行拼单的正常业务 ==============================
// 查找是否有同组的气胀轴位置
cutPoint = slitterMapper.getSameGroupPoint(demoPlan);
if (ObjectUtil.isEmpty(cutPoint)) {
// 也有可能在路上, 获取任务的终点
String endPoint = slitterMapper.getSameGroupTaskPoint(demoPlan);
if (ObjectUtil.isNotEmpty(endPoint)) {
cutPoint = bcutpointivtService.getOne(new LambdaQueryWrapper<BstIvtCutpointivt>()
.eq(BstIvtCutpointivt::getTruss_point_code1, endPoint).or()
.eq(BstIvtCutpointivt::getTruss_point_code2, endPoint));
}
}
if (ObjectUtil.isEmpty(cutPoint)) {
// 获取一个空位 (上下区域)
List<BstIvtCutpointivt> emptyNotTaskPoint = bcutpointivtService.getNBJAreaNotTaskPointByStatus(
"1", "1", startPoint.getPoint_location(), "1");
if (emptyNotTaskPoint.size() > 0) {
cutPoint = emptyNotTaskPoint.get(0);
} else {
stepTipLogs.add("提示:套轴完成->找不到可用套轴对接位创建半条任务等待AGV取货完成触发!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
// 创建任务
JSONObject taskParam = new JSONObject();
taskParam.put("point_code1", startPoint.getPoint_code());
taskParam.put("point_code2", "-");
taskParam.put("needPosition", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down())
? "A" : "B");
taskParam.put("vehicle_code1", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("vehicle_code2", SlitterConstant.SLITTER_SHAFT_DOWN.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("task_type", "010814");
taskParam.put("containers", collect);
taskParam.put("qzz_size", demoPlan.getQzz_size());
taskParam.put("task_status", TaskStatusEnum.SURE_START.getCode());
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("immediateNotifyAcs", "0");
trussSendAirShaftTask.createTask(taskParam);
}
}
if (ObjectUtil.isNotEmpty(cutPoint)) {
// 创建任务
JSONObject taskParam = new JSONObject();
taskParam.put("point_code1", startPoint.getPoint_code());
taskParam.put("point_code2", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down())
? cutPoint.getTruss_point_code1() : cutPoint.getTruss_point_code2());
taskParam.put("vehicle_code1", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("vehicle_code2", SlitterConstant.SLITTER_SHAFT_DOWN.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("task_type", "010814");
taskParam.put("containers", collect);
taskParam.put("qzz_size", demoPlan.getQzz_size());
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("immediateNotifyAcs", "1");
trussSendAirShaftTask.createTask(taskParam);
}
} else {
if (!tryLock) {
stepTipLogs.add("套轴完成->系统繁忙,稍后在试!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
throw new BadRequestException("系统繁忙,稍后在试!");
}
log.info("ACS申请套管完成参数: {}", param);
// 1. 获取起点和分切计划
BstIvtShafttubeivt startPoint = shafttubeivtService.getOne(
new LambdaQueryWrapper<BstIvtShafttubeivt>()
.eq(BstIvtShafttubeivt::getPoint_code, deviceCode));
List<PdmBiSlittingproductionplan> plans = validateAndGetPlans(deviceCode, startPoint, stepTipLogs);
// 2. 处理异常情况 - 分切计划不存在
if (plans.isEmpty()) {
List<String> containerNames = Stream.of(startPoint.getContainer_name1(), startPoint.getContainer_name2())
.filter(ObjectUtil::isNotEmpty)
.collect(Collectors.toList());
return handleExceptionCase(deviceCode, startPoint, containerNames, stepTipLogs);
}
// 3. 更新分切计划重量
BigDecimal weight1 = param.getBigDecimal("weight1");
BigDecimal weight2 = param.getBigDecimal("weight2");
String msg = updatePlanWeights(plans, weight1, weight2);
// 4. 生成气胀轴编码并完成套轴
PdmBiSlittingproductionplan demoPlan = plans.get(0);
String qzzNo = generateQzzNo(demoPlan);
completeShaftLoading(plans, qzzNo);
// 5. 获取子卷名称列表
List<String> containerNames = Stream.of(startPoint.getContainer_name1(), startPoint.getContainer_name2())
.filter(ObjectUtil::isNotEmpty)
.collect(Collectors.toList());
// 6. 尝试拼单
BstIvtCutpointivt combinedPoint = tryCombineOrder(demoPlan, deviceCode, startPoint, qzzNo);
if (combinedPoint == null) {
// 7. 正常业务流程(不拼单)
handleNormalProcess(demoPlan, startPoint, qzzNo, containerNames, deviceCode, stepTipLogs);
}
JSONObject res = new JSONObject();
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "请求成功");
res.put("msg", msg);
return res;
} finally {
if (tryLock) {
lock.unlock();
// 使用 TransactionSynchronization 在事务提交后释放锁
// 避免锁释放但事务未提交导致的并发问题
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCompletion(int status) {
try {
lock.unlock();
log.debug("分布式锁已在事务完成后释放: doAcsFinishLoadShaft, 事务状态: {}",
status == STATUS_COMMITTED ? "已提交" : "已回滚");
} catch (Exception e) {
log.error("释放分布式锁失败", e);
}
}
});
} else {
// 如果没有事务,直接释放锁
lock.unlock();
}
}
}
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "请求成功");
res.put("msg", msg);
return res;
}
@SneakyThrows
@@ -3506,4 +3315,377 @@ public class SlitterServiceImpl implements SlitterService {
}
return stepTipLogs;
}
/**
* 验证并获取分切计划
*/
private List<PdmBiSlittingproductionplan> validateAndGetPlans(String deviceCode, BstIvtShafttubeivt startPoint, List<String> stepTipLogs) {
List<String> containerNames = Stream.of(startPoint.getContainer_name1(), startPoint.getContainer_name2())
.filter(value -> value != null && !value.isEmpty())
.collect(Collectors.toList());
if (containerNames.isEmpty()) {
log.error("找不到[{}]对应的分切计划!", deviceCode);
stepTipLogs.add("套轴完成->找不到[" + deviceCode + "]点位记录的分切计划!分切计划可能被删除或者拼接!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
throw new BadRequestException("找不到[" + deviceCode + "]对应的分切计划!");
}
// 判断是否有未完成的任务
List<SchBaseTask> existingTasks = taskService.list(new LambdaQueryWrapper<SchBaseTask>()
.eq(SchBaseTask::getPoint_code1, deviceCode)
.like(SchBaseTask::getRequest_param, containerNames.get(0))
.lt(SchBaseTask::getTask_status, "07"));
if (!existingTasks.isEmpty()) {
log.error("点位[{}]存在未完成得任务!", deviceCode);
stepTipLogs.add("套轴完成->点位[" + deviceCode + "]存在未完成得任务!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
throw new BadRequestException("点位[" + deviceCode + "]存在未完成得任务!");
}
return slittingproductionplanService.list(
new LambdaQueryWrapper<PdmBiSlittingproductionplan>()
.in(PdmBiSlittingproductionplan::getContainer_name, containerNames)
.eq(PdmBiSlittingproductionplan::getStatus, "01")
.eq(PdmBiSlittingproductionplan::getIs_delete, "0"));
}
/**
* 处理异常情况 - 分切计划不存在
*/
private JSONObject handleExceptionCase(String deviceCode, BstIvtShafttubeivt startPoint,
List<String> containerNames, List<String> stepTipLogs) {
log.error("找不到[{}]对应的分切计划,分切计划可能被删除或者拼接!", containerNames);
// 尝试移动到异常处理位
List<String> exceptionPointCodes = bcutpointivtService.getCanUseMinPointByShelf("4", "0");
if (!exceptionPointCodes.isEmpty()) {
String exceptionPoint = exceptionPointCodes.get(0);
JSONObject exParam = buildExceptionTaskParam(startPoint, exceptionPoint, containerNames);
sendNBJExceptionPointTask.createTask(exParam);
JSONObject res = new JSONObject();
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "创建送至异常处理位!");
return res;
}
// 创建半条任务等待补齐
stepTipLogs.add("套轴完成->[" + containerNames + "]对应的分切计划状态已更改,无暂存位置,创建任务失败!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
JSONObject exParam = buildWaitingTaskParam(startPoint, containerNames);
sendNBJExceptionPointTask.createTask(exParam);
JSONObject res = new JSONObject();
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "请求成功");
return res;
}
/**
* 构建异常任务参数
*/
private JSONObject buildExceptionTaskParam(BstIvtShafttubeivt startPoint, String exceptionPoint, List<String> containerNames) {
JSONObject exParam = new JSONObject();
exParam.put("point_code1", startPoint.getPoint_code());
exParam.put("point_code2", exceptionPoint);
if (exceptionPoint.endsWith("A")) {
exParam.put("vehicle_code1", containerNames);
} else {
exParam.put("vehicle_code2", containerNames);
}
exParam.put("task_type", SlitterEnum.TASK_TYPE.code("套轴异常处理桁架任务"));
exParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
exParam.put("acs_task_type", "6");
exParam.put("containers", containerNames);
exParam.put("qzz_size", startPoint.getQzz_size());
return exParam;
}
/**
* 构建等待任务参数
*/
private JSONObject buildWaitingTaskParam(BstIvtShafttubeivt startPoint, List<String> containerNames) {
JSONObject exParam = new JSONObject();
exParam.put("point_code1", startPoint.getPoint_code());
exParam.put("point_code2", "-");
exParam.put("vehicle_code1", containerNames);
exParam.put("task_type", SlitterEnum.TASK_TYPE.code("套轴异常处理桁架任务"));
exParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
exParam.put("task_status", TaskStatusEnum.SURE_START.getCode());
exParam.put("acs_task_type", "6");
exParam.put("containers", containerNames);
exParam.put("qzz_size", startPoint.getQzz_size());
return exParam;
}
/**
* 更新分切计划重量
*/
private String updatePlanWeights(List<PdmBiSlittingproductionplan> plans, BigDecimal weight1, BigDecimal weight2) {
StringBuilder msg = new StringBuilder();
for (PdmBiSlittingproductionplan plan : plans) {
if (SlitterConstant.SLITTER_SUB_VOLUME_LEFT.equals(plan.getLeft_or_right())) {
plan.setPaper_weight(String.valueOf(NumberUtil.round(weight1, 2)));
msg.append("子卷号:").append(plan.getContainer_name()).append("的纸管重量: ").append(weight1).append(" | ");
} else {
plan.setPaper_weight(String.valueOf(NumberUtil.round(weight2, 2)));
msg.append("子卷号:").append(plan.getContainer_name()).append("的纸管重量: ").append(weight2).append(" | ");
}
TaskUtils.updateOptMessageBySlitterPlan(plan);
}
slittingproductionplanService.updateBatchById(plans);
return msg.toString();
}
/**
* 生成气胀轴编码
*/
private String generateQzzNo(PdmBiSlittingproductionplan demoPlan) {
String resourceName = demoPlan.getResource_name();
return resourceName.substring(0, 2)
+ resourceName.substring(resourceName.length() - 2)
+ demoPlan.getSplit_group()
+ TaskUtils.getDateTime("yyMMddHHmmss") + "-"
+ demoPlan.getUp_or_down();
}
/**
* 完成套轴并更新计划
*/
private void completeShaftLoading(List<PdmBiSlittingproductionplan> plans, String qzzNo) {
plans.forEach(plan -> {
plan.setIs_child_tz_ok(SlitterConstant.SLITTER_YES);
plan.setQzzno(qzzNo);
TaskUtils.updateOptMessageBySlitterPlan(plan);
});
slittingproductionplanService.updateBatchById(plans);
}
/**
* 尝试拼单逻辑
*/
private BstIvtCutpointivt tryCombineOrder(PdmBiSlittingproductionplan demoPlan, String deviceCode,
BstIvtShafttubeivt startPoint, String qzzNo) {
Param codParam = paramService.findByCode(IS_COMBINED_ORDER);
// 判断是否有同组(判断自己能不能拼单)
Integer sameNumber = slittingproductionplanService.getSameTripParentContainerPlanCount(demoPlan);
// 不允许拼单(未开启拼单逻辑)
if (sameNumber != 0 || ObjectUtil.isEmpty(codParam) || !"1".equals(codParam.getValue())) {
log.info("本身不允许拼单或者拼单配置未设置或者设置不拼单...");
return null;
}
String resourceName = demoPlan.getResource_name();
StIvtCutpointivt deviceInfo = cutpointivtService.getPintByExtCode(resourceName, false);
// 查找能够拼单的点位(查找套轴对接位)
List<BstIvtCutpointivt> emptyNotTaskPoint = slitterMapper.getCombinedOrders(
CombinedOrderDto.builder()
.pointStatus("2")
.pointType("1")
.pointLocation(deviceInfo.getPoint_location())
.plan(deviceInfo.getPlan())
.device(resourceName)
.build());
// 如果没有空点位,尝试与路上的轴拼单
if (emptyNotTaskPoint.isEmpty()) {
emptyNotTaskPoint = tryMatchRunningTask(demoPlan, deviceCode, deviceInfo);
}
// 如果找到可拼单点位,创建任务
if (!emptyNotTaskPoint.isEmpty()) {
BstIvtCutpointivt cutPoint = emptyNotTaskPoint.get(0);
createCombinedOrderTask(cutPoint, startPoint, demoPlan, qzzNo);
return cutPoint;
}
return null;
}
/**
* 尝试与运行中的任务拼单
*/
private List<BstIvtCutpointivt> tryMatchRunningTask(PdmBiSlittingproductionplan demoPlan,
String deviceCode, StIvtCutpointivt deviceInfo) {
List<BstIvtCutpointivt> result = new ArrayList<>();
SchBaseTask runningTask = taskService.getOne(new LambdaQueryWrapper<SchBaseTask>()
.eq(SchBaseTask::getHandle_class, "org.nl.b_lms.sch.tasks.slitter.TrussSendAirShaftTask")
.lt(SchBaseTask::getTask_status, "07")
.eq(SchBaseTask::getIs_delete, "0")
.ne(SchBaseTask::getPoint_code1, deviceCode));
if (ObjectUtil.isEmpty(runningTask) || ObjectUtil.isEmpty(runningTask.getPoint_code2())) {
return result;
}
List<PdmBiSlittingproductionplan> runningShafts = slittingproductionplanService.getByQzzNos(
Arrays.asList(runningTask.getVehicle_code(), runningTask.getVehicle_code2()));
if (runningShafts.isEmpty()) {
return result;
}
PdmBiSlittingproductionplan runningShaft = runningShafts.get(0);
// 判断路上的轴能不能拼
Integer otherPlans = slittingproductionplanService.getSameTripParentContainerPlanCount(runningShaft);
if (otherPlans == 0) {
StIvtCutpointivt runDeviceInfo = cutpointivtService.getPintByExtCode(runningShaft.getResource_name(), false);
// 同个子区域
if (runDeviceInfo.getPlan().equals(deviceInfo.getPlan())) {
BstIvtCutpointivt one = bcutpointivtService.getOne(new LambdaQueryWrapper<BstIvtCutpointivt>()
.eq(BstIvtCutpointivt::getTruss_point_code1, runningTask.getPoint_code2()).or()
.eq(BstIvtCutpointivt::getTruss_point_code2, runningTask.getPoint_code2()));
if (one != null && canCombineWithRunningTask(one, runningTask)) {
result.add(one);
}
}
}
return result;
}
/**
* 判断是否可以与运行中的任务拼单
*/
private boolean canCombineWithRunningTask(BstIvtCutpointivt one, SchBaseTask runningTask) {
String specialPoint = one.getTruss_point_code1().equals(runningTask.getPoint_code2())
? one.getTruss_point_code2() : one.getTruss_point_code1();
return (specialPoint.equals(one.getTruss_point_code1()) && ObjectUtil.isNotEmpty(one.getQzz_no1()))
|| (specialPoint.equals(one.getTruss_point_code2()) && ObjectUtil.isNotEmpty(one.getQzz_no2()));
}
/**
* 创建拼单任务
* @param cutPoint 分切点位
* @param startPoint 穿拔轴点位
* @param demoPlan 分切计划
* @param qzzNo 气胀轴编码
*/
private void createCombinedOrderTask(BstIvtCutpointivt cutPoint, BstIvtShafttubeivt startPoint,
PdmBiSlittingproductionplan demoPlan, String qzzNo) {
JSONObject taskParam = new JSONObject();
taskParam.put("point_code1", startPoint.getPoint_code());
String pointCode2 = ObjectUtil.isEmpty(cutPoint.getQzz_no1())
? cutPoint.getTruss_point_code1() : cutPoint.getTruss_point_code2();
taskParam.put("point_code2", pointCode2);
String vehicleCode1 = ObjectUtil.isEmpty(cutPoint.getQzz_no1()) ? qzzNo : "";
String vehicleCode2 = ObjectUtil.isEmpty(cutPoint.getQzz_no2()) ? qzzNo : "";
taskParam.put("vehicle_code1", vehicleCode1);
taskParam.put("vehicle_code2", vehicleCode2);
taskParam.put("flag", "1");
taskParam.put("task_type", "010814");
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("immediateNotifyAcs", "1");
trussSendAirShaftTask.createTask(taskParam);
}
/**
* 处理正常业务流程(不拼单)
*/
private void handleNormalProcess(PdmBiSlittingproductionplan demoPlan, BstIvtShafttubeivt startPoint,
String qzzNo, List<String> containerNames, String deviceCode,
List<String> stepTipLogs) {
// 查找是否有同组的气胀轴位置
BstIvtCutpointivt cutPoint = findSameGroupPoint(demoPlan);
if (ObjectUtil.isEmpty(cutPoint)) {
// 获取一个空位
List<BstIvtCutpointivt> emptyNotTaskPoint = bcutpointivtService.getNBJAreaNotTaskPointByStatus(
"1", "1", startPoint.getPoint_location(), "1");
if (!emptyNotTaskPoint.isEmpty()) {
cutPoint = emptyNotTaskPoint.get(0);
} else {
// 创建半条任务
createHalfTask(startPoint, demoPlan, qzzNo, containerNames, deviceCode, stepTipLogs);
return;
}
}
// 创建完整任务
createNormalTask(cutPoint, startPoint, demoPlan, qzzNo, containerNames);
}
/**
* 查找同组点位
*/
private BstIvtCutpointivt findSameGroupPoint(PdmBiSlittingproductionplan demoPlan) {
BstIvtCutpointivt cutPoint = slitterMapper.getSameGroupPoint(demoPlan);
if (ObjectUtil.isEmpty(cutPoint)) {
String endPoint = slitterMapper.getSameGroupTaskPoint(demoPlan);
if (ObjectUtil.isNotEmpty(endPoint)) {
cutPoint = bcutpointivtService.getOne(new LambdaQueryWrapper<BstIvtCutpointivt>()
.eq(BstIvtCutpointivt::getTruss_point_code1, endPoint).or()
.eq(BstIvtCutpointivt::getTruss_point_code2, endPoint));
}
}
return cutPoint;
}
/**
* 创建半条任务
*/
private void createHalfTask(BstIvtShafttubeivt startPoint, PdmBiSlittingproductionplan demoPlan,
String qzzNo, List<String> containerNames, String deviceCode,
List<String> stepTipLogs) {
stepTipLogs.add("提示:套轴完成->找不到可用套轴对接位创建半条任务等待AGV取货完成触发!");
redisUtils.set("ERROR" + deviceCode, stepTipLogs);
JSONObject taskParam = new JSONObject();
taskParam.put("point_code1", startPoint.getPoint_code());
taskParam.put("point_code2", "-");
taskParam.put("needPosition", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down()) ? "A" : "B");
taskParam.put("vehicle_code1", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("vehicle_code2", SlitterConstant.SLITTER_SHAFT_DOWN.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("task_type", "010814");
taskParam.put("containers", containerNames);
taskParam.put("qzz_size", demoPlan.getQzz_size());
taskParam.put("task_status", TaskStatusEnum.SURE_START.getCode());
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("immediateNotifyAcs", "0");
trussSendAirShaftTask.createTask(taskParam);
}
/**
* 创建正常任务
*/
private void createNormalTask(BstIvtCutpointivt cutPoint, BstIvtShafttubeivt startPoint,
PdmBiSlittingproductionplan demoPlan, String qzzNo,
List<String> containerNames) {
JSONObject taskParam = new JSONObject();
taskParam.put("point_code1", startPoint.getPoint_code());
taskParam.put("point_code2", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down())
? cutPoint.getTruss_point_code1() : cutPoint.getTruss_point_code2());
taskParam.put("vehicle_code1", SlitterConstant.SLITTER_SHAFT_UP.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("vehicle_code2", SlitterConstant.SLITTER_SHAFT_DOWN.equals(demoPlan.getUp_or_down()) ? qzzNo : "");
taskParam.put("task_type", "010814");
taskParam.put("containers", containerNames);
taskParam.put("flag", "0");
taskParam.put("qzz_size", demoPlan.getQzz_size());
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("immediateNotifyAcs", "1");
trussSendAirShaftTask.createTask(taskParam);
}
}

View File

@@ -84,4 +84,11 @@ public interface IDeliverycachepointivtService extends IService<Deliverycachepoi
* @return
*/
List<Deliverycachepointivt> getMoreConformShaft(String gxCode1, String gcCode2, String area, String location);
/**
* 获取待使用的点位
* @param resourceName
* @return
*/
Integer countPendingUseByDevice(String resourceName);
}

View File

@@ -24,4 +24,6 @@ public interface DeliverycachepointivtMapper extends BaseMapper<Deliverycachepoi
List<Deliverycachepointivt> getMoreConformShaft(String gxCode1, String gcCode2, String area, String location);
IPage<Deliverycachepointivt> selectPageLeftJoin(IPage<Deliverycachepointivt> pages, DeliverycachepointivtQuery param);
Integer countPendingUseByDevice(String resourceName);
}

View File

@@ -136,4 +136,16 @@
</if>
</where>
</select>
<select id="countPendingUseByDevice" resultType="java.lang.Integer">
SELECT COUNT(*)
FROM `st_ivt_deliverycachepointivt` sc
WHERE sc.point_status = '02'
AND sc.product_area LIKE 'B%'
AND sc.qzzno IS NOT NULL
AND sc.qzzno <![CDATA[ <> ]]> ''
AND NOT EXISTS (SELECT 1
FROM pdm_bi_slittingproductionplan p
WHERE p.qzzno = sc.qzzno
AND p.resource_name = #{resourceName});
</select>
</mapper>

View File

@@ -116,4 +116,9 @@ public class DeliverycachepointivtServiceImpl extends ServiceImpl<Deliverycachep
return deliverycachepointivtMapper.getMoreConformShaft(gxCode1, gcCode2, area, location);
}
@Override
public Integer countPendingUseByDevice(String resourceName) {
return deliverycachepointivtMapper.countPendingUseByDevice(resourceName);
}
}

View File

@@ -129,5 +129,8 @@
"browserslist": [
"> 1%",
"last 2 versions"
]
],
"volta": {
"node": "14.21.3"
}
}