feat: 分切下卷

This commit is contained in:
2026-04-23 18:00:03 +08:00
parent 467f9aab12
commit 22939979d8
10 changed files with 855 additions and 6 deletions

View File

@@ -57,6 +57,12 @@ public interface IPdmBiSlittingproductionplanService extends IService<PdmBiSlitt
* @return 最多两个
*/
List<PdmBiSlittingproductionplan> getByQzzNo(String qzzNo);
/**
* 通过气涨轴编码获取分切计划(未删除)
* @param qzzNo 气胀轴尺寸
* @return 最多两个
*/
List<PdmBiSlittingproductionplan> getByQzzNoNotDeleted(String qzzNo);
/**
* 根据气胀轴数组获取分切计划

View File

@@ -25,6 +25,7 @@ import org.nl.modules.common.exception.BadRequestException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -98,6 +99,14 @@ public class PdmBiSlittingproductionplanServiceImpl extends ServiceImpl<PdmBiSli
return pdmBiSlittingproductionplanMapper.selectList(lam);
}
@Override
public List<PdmBiSlittingproductionplan> getByQzzNoNotDeleted(String qzzNo) {
LambdaQueryWrapper<PdmBiSlittingproductionplan> lam = new QueryWrapper<PdmBiSlittingproductionplan>().lambda();
lam.eq(PdmBiSlittingproductionplan::getQzzno, qzzNo)
.eq(PdmBiSlittingproductionplan::getIs_delete, "0");
return pdmBiSlittingproductionplanMapper.selectList(lam);
}
@Override
public List<PdmBiSlittingproductionplan> getByQzzNos(List<String> qzzNo, String status) {
LambdaQueryWrapper<PdmBiSlittingproductionplan> lam = new QueryWrapper<PdmBiSlittingproductionplan>().lambda();

View File

@@ -0,0 +1,411 @@
package org.nl.b_lms.sch.tasks;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.nl.b_lms.bst.ivt.cutpointivt.service.IBstIvtCutpointivtService;
import org.nl.b_lms.bst.ivt.cutpointivt.service.dao.BstIvtCutpointivt;
import org.nl.b_lms.pdm.bi.slittingproductionplan.service.IPdmBiSlittingproductionplanService;
import org.nl.b_lms.pdm.bi.slittingproductionplan.service.dao.PdmBiSlittingproductionplan;
import org.nl.b_lms.sch.point.dao.StIvtCutpointivt;
import org.nl.b_lms.sch.point.service.IstIvtCutpointivtService;
import org.nl.b_lms.sch.task.dao.SchBaseTask;
import org.nl.b_lms.sch.task.service.IschBaseTaskService;
import org.nl.b_lms.sch.tasks.slitter.constant.SlitterConstant;
import org.nl.b_lms.sch.tasks.slitter.util.SlitterTaskUtil;
import org.nl.b_lms.storage_manage.ios.enums.IOSEnum;
import org.nl.common.utils.IdUtil;
import org.nl.common.utils.SecurityUtils;
import org.nl.common.utils.TaskUtils;
import org.nl.modules.common.exception.BadRequestException;
import org.nl.modules.wql.WQL;
import org.nl.modules.wql.core.bean.WQLObject;
import org.nl.wms.pdm.ivt.deliverycache.service.IDeliverycachepointivtService;
import org.nl.wms.pdm.ivt.deliverycache.service.dao.Deliverycachepointivt;
import org.nl.wms.sch.AcsTaskDto;
import org.nl.wms.sch.manage.AbstractAcsTask;
import org.nl.wms.sch.manage.TaskStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 分切下料任务类(新改动)
* @Author: liyongde
* @Date: 2026/4/22 14:10
*/
@Slf4j
@Service
public class SlitterDownNewTrussTask extends AbstractAcsTask {
private final String THIS_CLASS = SlitterDownNewTrussTask.class.getName();
@Autowired
private IschBaseTaskService taskService;
@Autowired
private IPdmBiSlittingproductionplanService slittingproductionplanService;
@Autowired
private IBstIvtCutpointivtService bcutpointivtService;
@Autowired
private IstIvtCutpointivtService cutpointivtService;
@Autowired
private IDeliverycachepointivtService deliverycachepointivtService;
@Override
public List<AcsTaskDto> addTask() {
/*
* 下发给ACS时需要特殊处理
*/
List<SchBaseTask> taskList = taskService.getIssueTasks(THIS_CLASS);
ArrayList<AcsTaskDto> resultList = new ArrayList<>();
String agv_system_type = "2";
for (SchBaseTask task : taskList) {
String requestParam = task.getRequest_param();
JSONObject requestParamObj = JSONObject.parseObject(requestParam);
AcsTaskDto dto = AcsTaskDto.builder()
.ext_task_id(task.getTask_id())
.task_code(task.getTask_code())
.task_type(task.getAcs_task_type())
.start_device_code(task.getPoint_code1())
.next_device_code(task.getPoint_code2())
.start_device_code2(task.getPoint_code3())
.next_device_code2(task.getPoint_code4())
.vehicle_code(task.getVehicle_code())
.truss_type(requestParamObj.getString("truss_type"))
.empty_site(requestParamObj.getString("empty_site"))
.agv_system_type(agv_system_type)
.priority(task.getPriority())
.remark(task.getRemark())
.product_area(task.getProduct_area())
.build();
resultList.add(dto);
}
return resultList;
}
@Override
public List<AcsTaskDto> addTask(SchBaseTask task) {
ArrayList<AcsTaskDto> resultList = new ArrayList<>();
String agv_system_type = "2";
String requestParam = task.getRequest_param();
JSONObject requestParamObj = JSONObject.parseObject(requestParam);
AcsTaskDto dto = AcsTaskDto.builder()
.ext_task_id(task.getTask_id())
.task_code(task.getTask_code())
.task_type(task.getAcs_task_type())
.start_device_code(task.getPoint_code1())
.next_device_code(task.getPoint_code2())
.start_device_code2(task.getPoint_code3())
.next_device_code2(task.getPoint_code4())
.vehicle_code(task.getVehicle_code())
.truss_type(requestParamObj.getString("truss_type"))
.empty_site(requestParamObj.getString("empty_site"))
.agv_system_type(agv_system_type)
.priority(task.getPriority())
.remark(task.getRemark())
.product_area(task.getProduct_area())
.build();
resultList.add(dto);
return resultList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateTaskStatus(JSONObject taskObj, String status) {
SchBaseTask task = taskService.getById(taskObj.getString("task_id"));
if (TaskStatusEnum.EXECUTING.getCode().equals(status)) {
// 更新任务状态为执行中
task.setTask_status(TaskStatusEnum.EXECUTING.getCode());
}
if (StrUtil.equals(status, TaskStatusEnum.FINISHED.getCode())) {
task.setTask_status(TaskStatusEnum.FINISHED.getCode());
JSONObject requestParam = JSONObject.parseObject(task.getRequest_param());
String flag = requestParam.getString("flag");
switch (flag) {
case "1":
handleFinishFlag1(task, requestParam);
break;
case "2":
handleFinishFlag2(task, requestParam);
break;
case "3":
handleFinishFlag3(task, requestParam);
break;
default:
handleDefaultFlag(flag);
}
}
// 取消
if (status.equals(IOSEnum.IS_NOTANDYES.code(""))) {
task.setTask_status(TaskStatusEnum.FINISHED.getCode());
// 分切计划回退
// 下来06 -> 05 上去04 -> 03
String nextPlanQzzNo = task.getVehicle_code();
JSONObject requestParam = JSONObject.parseObject(task.getRequest_param());
// 下来的分切计划
JSONArray downContainers = requestParam.getJSONArray("down_roll");
List<String> downCons = downContainers.toJavaList(String.class);
if (!downCons.isEmpty()) {
PdmBiSlittingproductionplan p = new PdmBiSlittingproductionplan();
p.setStatus("05");
TaskUtils.updateOptMessageBySlitterPlan(p);
slittingproductionplanService.update(p, new LambdaQueryWrapper<PdmBiSlittingproductionplan>()
.in(PdmBiSlittingproductionplan::getContainer_name, downCons));
}
// 上去的分切计划状态04 -> 03
if (ObjectUtil.isNotEmpty(nextPlanQzzNo)) {
PdmBiSlittingproductionplan p = new PdmBiSlittingproductionplan();
p.setStatus("03");
TaskUtils.updateOptMessageBySlitterPlan(p);
slittingproductionplanService.update(p, new LambdaQueryWrapper<PdmBiSlittingproductionplan>()
.eq(PdmBiSlittingproductionplan::getQzzno, nextPlanQzzNo));
}
}
task.setUpdate_time(DateUtil.now());
task.setUpdate_optid(SecurityUtils.getCurrentUserId());
task.setUpdate_optname(SecurityUtils.getCurrentUsername());
taskService.updateById(task);
}
public void handleFinishFlag1(SchBaseTask task, JSONObject requestParam) {
// flag=1 业务逻辑
Deliverycachepointivt cachePoint = deliverycachepointivtService.getOneByPointCode(task.getPoint_code1(), false);
StIvtCutpointivt devicePoint = cutpointivtService.getPintByUpOrDownCode(task.getPoint_code2(), false);
BstIvtCutpointivt trussPoint = bcutpointivtService.getPintByTrussCode(task.getPoint_code4(), false);
// 获取计划
String nextPlanQzzNo = task.getVehicle_code();
String currentPlanQzzNo = task.getVehicle_code2();
List<PdmBiSlittingproductionplan> nextPlans = slittingproductionplanService.getByQzzNoNotDeleted(nextPlanQzzNo);
// List<PdmBiSlittingproductionplan> currentPlans = slittingproductionplanService.getByQzzNoNotDeleted(currentPlanQzzNo);
boolean same = task.getPoint_code2().equals(task.getPoint_code3());
// 更新设备点位数据
if (task.getPoint_code2().equals(devicePoint.getUp_point_code())) {
devicePoint.setUp_qzzno(nextPlanQzzNo);
if (!same) {
devicePoint.setDown_qzzno("");
}
} else {
devicePoint.setDown_qzzno(nextPlanQzzNo);
if (!same) {
devicePoint.setUp_qzzno("");
}
}
TaskUtils.updateOptMessageByStIvtCutPoint(devicePoint);
cutpointivtService.updateById(devicePoint);
// 清空更新架子点位
cachePoint.setQzzno("");
cachePoint.setPoint_status("01");
TaskUtils.updateOptMessageByCachePoint(cachePoint);
deliverycachepointivtService.updateById(cachePoint);
// 更新分切计划
List<PdmBiSlittingproductionplan> pdmBiSlittingproductionplans = updateDownRollPlan(requestParam);
updateUpRollPlan(nextPlans, nextPlanQzzNo);
// 赋值子卷
trussPoint.setPoint_status("3");
if (trussPoint.getTruss_point_code1().equals(task.getPoint_code4())) {
trussPoint.setQzz_no1(pdmBiSlittingproductionplans.get(0).getQzzno());
} else {
trussPoint.setQzz_no2(pdmBiSlittingproductionplans.get(0).getQzzno());
}
TaskUtils.updateOptMessageByBCutPoint(trussPoint);
bcutpointivtService.updateById(trussPoint);
}
public void updateUpRollPlan(List<PdmBiSlittingproductionplan> nextPlans, String nextPlanQzzNo) {
// 上去的分切计划状态04 -> 05
PdmBiSlittingproductionplan p = new PdmBiSlittingproductionplan();
p.setStatus("05");
p.setEnd_time("");
log.info("即将上卷的气胀轴编码数据:{}", nextPlans);
if (nextPlans.size() > 0) {
PdmBiSlittingproductionplan pp = nextPlans.get(0);
// 需要把重量记录到分切机上
// point1.setRemark(SlitterTaskUtil.getPaperWeightStr(nextPlans));
if (pp.getContainer_name().contains("虚拟")) {
// 如果是虚拟卷,需要执行删除标记,并且清空数据
// 将分切计划删除,设备禁用
nextPlans.forEach(p1 -> {
p1.setIs_delete("1");
p1.setQzzno("");
p1.setUpdate_time(DateUtil.now());
p1.setUpdate_optname(SecurityUtils.getCurrentNickName());
p1.setUpdate_optid(SecurityUtils.getCurrentUserId());
});
slittingproductionplanService.updateBatchById(nextPlans);
} else {
slittingproductionplanService.update(p, new LambdaQueryWrapper<PdmBiSlittingproductionplan>()
.eq(PdmBiSlittingproductionplan::getQzzno, nextPlanQzzNo));
}
}
}
public List<PdmBiSlittingproductionplan> updateDownRollPlan(JSONObject requestParam) {
// 下来的分切计划状态06 -> 09, 不在需要设置重量
JSONArray downContainers = requestParam.getJSONArray("down_roll");
List<String> downCons = downContainers.toJavaList(String.class);
log.info("即将下卷的上下轴的子卷号数据:{}", downCons);
List<PdmBiSlittingproductionplan> downPlans = slittingproductionplanService.getByContainerNames(downCons);
// 下来的卷的集合
List<PdmBiSlittingproductionplan> needUpdates = new ArrayList<>();
// 绑定气胀轴编码(可能没有气胀轴编码)
List<PdmBiSlittingproductionplan> deviceUpPlans = downPlans.stream().filter(p -> SlitterConstant.SLITTER_SHAFT_UP.equals(p.getUp_or_down())).collect(Collectors.toList());
List<PdmBiSlittingproductionplan> deviceDownPlans = downPlans.stream().filter(p -> SlitterConstant.SLITTER_SHAFT_DOWN.equals(p.getUp_or_down())).collect(Collectors.toList());
if (deviceUpPlans.size() > 0) {
PdmBiSlittingproductionplan upDemoPlan = deviceUpPlans.get(0);
String resourceName = upDemoPlan.getResource_name();
String qzzNO = resourceName.substring(0, 2)
+ resourceName.substring(resourceName.length() - 2)
+ upDemoPlan.getSplit_group()
+ TaskUtils.getDateTime("yyMMddHHmmss") + "-"
+ upDemoPlan.getUp_or_down();
for (PdmBiSlittingproductionplan deviceUpPlan : deviceUpPlans) {
deviceUpPlan.setQzzno(qzzNO);
deviceUpPlan.setStatus("09");
deviceUpPlan.setEnd_time(DateUtil.now());
TaskUtils.updateOptMessageBySlitterPlan(deviceUpPlan);
needUpdates.add(deviceUpPlan);
}
}
if (deviceDownPlans.size() > 0) {
PdmBiSlittingproductionplan downDemoPlan = deviceDownPlans.get(0);
String resourceName = downDemoPlan.getResource_name();
String qzzNO = resourceName.substring(0, 2)
+ resourceName.substring(resourceName.length() - 2)
+ downDemoPlan.getSplit_group()
+ TaskUtils.getDateTime("yyMMddHHmmss") + "-"
+ downDemoPlan.getUp_or_down();
for (PdmBiSlittingproductionplan deviceDownPlan : deviceDownPlans) {
deviceDownPlan.setQzzno(qzzNO);
deviceDownPlan.setStatus("09");
deviceDownPlan.setEnd_time(DateUtil.now());
TaskUtils.updateOptMessageBySlitterPlan(deviceDownPlan);
needUpdates.add(deviceDownPlan);
}
}
boolean b = slittingproductionplanService.updateBatchById(needUpdates);
log.info("{} - 即将下卷的上下轴的子卷号数据:{}", b, needUpdates);
return Stream.concat(deviceUpPlans.stream(), deviceDownPlans.stream()).collect(Collectors.toList());
}
public void handleFinishFlag2(SchBaseTask task, JSONObject requestParam) {
// flag=2 业务逻辑 (单下)
List<PdmBiSlittingproductionplan> pdmBiSlittingproductionplans = updateDownRollPlan(requestParam);
StIvtCutpointivt devicePoint = cutpointivtService.getPintByUpOrDownCode(task.getPoint_code1(), false);
BstIvtCutpointivt trussPoint = bcutpointivtService.getPintByTrussCode(task.getPoint_code2(), false);
// 设备清空
if (task.getPoint_code1().equals(devicePoint.getUp_point_code())) {
devicePoint.setUp_qzzno("");
} else {
devicePoint.setDown_qzzno("");
}
TaskUtils.updateOptMessageByStIvtCutPoint(devicePoint);
cutpointivtService.updateById(devicePoint);
// 站点赋值
trussPoint.setPoint_status("3");
if (trussPoint.getTruss_point_code1().equals(task.getPoint_code4())) {
trussPoint.setQzz_no1(pdmBiSlittingproductionplans.get(0).getQzzno());
} else {
trussPoint.setQzz_no2(pdmBiSlittingproductionplans.get(0).getQzzno());
}
TaskUtils.updateOptMessageByBCutPoint(trussPoint);
bcutpointivtService.updateById(trussPoint);
}
public void handleFinishFlag3(SchBaseTask task, JSONObject requestParam) {
// flag=3 业务逻辑 单上
Deliverycachepointivt cachePoint = deliverycachepointivtService.getOneByPointCode(task.getPoint_code1(), false);
StIvtCutpointivt devicePoint = cutpointivtService.getPintByUpOrDownCode(task.getPoint_code2(), false);
// 获取计划
String nextPlanQzzNo = task.getVehicle_code();
List<PdmBiSlittingproductionplan> nextPlans = slittingproductionplanService.getByQzzNoNotDeleted(nextPlanQzzNo);
// 起点清空
// 清空更新架子点位
cachePoint.setQzzno("");
cachePoint.setPoint_status("01");
TaskUtils.updateOptMessageByCachePoint(cachePoint);
deliverycachepointivtService.updateById(cachePoint);
// 终点赋值
if (task.getPoint_code2().equals(devicePoint.getUp_point_code())) {
devicePoint.setUp_qzzno(nextPlanQzzNo);
} else {
devicePoint.setDown_qzzno(nextPlanQzzNo);
}
TaskUtils.updateOptMessageByStIvtCutPoint(devicePoint);
cutpointivtService.updateById(devicePoint);
updateUpRollPlan(nextPlans, nextPlanQzzNo);
}
public void handleDefaultFlag(String flag) {
throw new BadRequestException("不支持的 flag" + flag);
}
@Override
public String createTask(JSONObject param) {
String currentUserId = SecurityUtils.getCurrentUserId();
String currentUsername = SecurityUtils.getCurrentUsername();
JSONArray tasks = param.getJSONArray("tasks");
for (int i = 0; i < tasks.size(); i++) {
JSONObject form = tasks.getJSONObject(i);
SchBaseTask task = new SchBaseTask();
task.setTask_id(IdUtil.getStringId());
task.setTask_code(IdUtil.getStringId());
task.setTask_status(TaskStatusEnum.START_AND_POINT.getCode());
task.setPoint_code1(form.getString("point_code1"));
task.setPoint_code2(form.getString("point_code2"));
task.setPoint_code3(form.getString("point_code3"));
task.setPoint_code4(form.getString("point_code4"));
task.setVehicle_code(form.getString("vehicle_code1"));
task.setVehicle_code2(form.getString("vehicle_code2"));
task.setAcs_task_type("6");
task.setIs_delete("0");
task.setTask_group_id(form.getString("groupId"));
task.setSort_seq(form.getBigDecimal("seq"));
task.setRequest_param(form.toJSONString());
task.setTask_type(form.getString("task_type"));
task.setProduct_area(form.getString("product_area"));
task.setCreate_id(currentUserId);
task.setCreate_name(currentUsername);
task.setCreate_time(DateUtil.now());
task.setHandle_class(THIS_CLASS);
//根据类型获取对应的任务优先级
JSONObject priority_jo = WQL.getWO("PDA_COOLIN").addParam("flag", "3").addParam("task_type", task.getTask_type()).process().uniqueResult(0);
if (ObjectUtil.isEmpty(priority_jo)) {
task.setPriority("1");
} else {
task.setPriority(priority_jo.getString("value"));
}
taskService.save(task);
this.immediateTaskNotifyAcs(task);
}
return "";
}
@Override
public void forceFinish(String task_id) {
JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0);
this.updateTaskStatus(taskObj, TaskStatusEnum.FINISHED.getCode());
}
@Override
public void cancel(String task_id) {
JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0);
this.updateTaskStatus(taskObj, "0");
}
}

View File

@@ -2,8 +2,11 @@ package org.nl.b_lms.sch.tasks.slitter.mapper;
import org.nl.b_lms.bst.ivt.cutpointivt.service.dao.BstIvtCutpointivt;
import org.nl.b_lms.pdm.bi.slittingproductionplan.service.dao.PdmBiSlittingproductionplan;
import org.nl.b_lms.sch.point.dao.StIvtCutpointivt;
import org.nl.b_lms.sch.tasks.slitter.mapper.dto.CallPlanViewVO;
import org.nl.b_lms.sch.tasks.slitter.mapper.dto.CombinedOrderDto;
import org.nl.b_lms.sch.tasks.slitter.mapper.dto.SlitterDownNewDto;
import org.nl.wms.pdm.ivt.deliverycache.service.dao.Deliverycachepointivt;
import java.math.BigDecimal;
import java.util.List;
@@ -77,4 +80,8 @@ public interface SlitterMapper {
List<BstIvtCutpointivt> getCombinedOrders(CombinedOrderDto cod);
List<BstIvtCutpointivt> getEmptyAirShaftAgvPointNotTask(String area, String location, String plan);
List<Deliverycachepointivt> getReadyShaftCachePoint(StIvtCutpointivt actualDevice);
List<SlitterDownNewDto> getCanDownPoints(StIvtCutpointivt actualDevice);
}

View File

@@ -378,4 +378,97 @@
OR t.point_code4 = bcp.truss_point_code1 OR t.point_code2 = bcp.truss_point_code2 OR t.point_code4 = bcp.truss_point_code2)
)
</select>
<select id="getReadyShaftCachePoint"
resultType="org.nl.wms.pdm.ivt.deliverycache.service.dao.Deliverycachepointivt">
SELECT sd.*
FROM st_ivt_deliverycachepointivt sd
INNER JOIN pdm_bi_slittingproductionplan p
ON p.is_delete = '0'
AND p.status = '03'
AND p.resource_name = #{point_code}
AND (p.qzzno = sd.qzz_no1 OR p.qzzno = sd.qzz_no2)
WHERE sd.product_area = #{area}
AND sd.point_location = #{location}
AND sd.point_status = '02'
AND sd.point_type = '02'
AND sd.is_used = '1'
AND NOT EXISTS (SELECT 1
FROM sch_base_task task
WHERE (
task.point_code1 = sd.point_code
OR task.point_code2 = sd.point_code
OR task.point_code3 = sd.point_code
OR task.point_code4 = sd.point_code
)
AND task.task_status <![CDATA[ < ]]> '07'
AND task.is_delete = '0')
</select>
<select id="getCanDownPoints" resultType="org.nl.b_lms.sch.tasks.slitter.mapper.dto.SlitterDownNewDto">
SELECT truss_code,
qzz_no,
point_type,
product_area,
point_location
FROM (SELECT t1.truss_point_code1 AS truss_code,
t1.qzz_no1 AS qzz_no,
t1.point_type,
t1.product_area,
t1.point_location,
t1.ivt_id AS base_id
FROM bst_ivt_cutpointivt t1
WHERE (t1.qzz_no1 IS NULL OR t1.qzz_no1 = '')
AND (t1.qzz_no2 IS NULL OR t1.qzz_no2 = '')
AND (t1.point_status <![CDATA[ <> ]]> '2' OR t1.point_status IS NULL)
AND t1.point_type = '3'
AND t1.is_used = '1'
AND t1.product_area = #{product_area}
AND t1.point_location = #{point_location}
AND t1.plan = #{plan}
AND NOT EXISTS (SELECT 1
FROM sch_base_task task
WHERE (
task.point_code1 = t1.truss_point_code1
OR task.point_code2 = t1.truss_point_code1
OR task.point_code3 = t1.truss_point_code1
OR task.point_code4 = t1.truss_point_code1
)
AND task.task_status <![CDATA[ < ]]> '07'
AND task.is_delete = '0')
UNION ALL
SELECT t2.truss_point_code2 AS truss_code,
t2.qzz_no2 AS qzz_no,
t2.point_type,
t2.product_area,
t2.point_location,
t2.ivt_id AS base_id
FROM bst_ivt_cutpointivt t2
WHERE (t2.qzz_no2 IS NULL OR t2.qzz_no2 = '')
AND (t2.point_status <![CDATA[ <> ]]> '2' OR t2.point_status IS NULL)
AND t2.point_type = '3'
AND t2.is_used = '1'
AND t2.product_area = #{product_area}
AND t2.point_location = #{point_location}
AND t2.plan = #{plan}
AND NOT EXISTS (SELECT 1
FROM sch_base_task task
WHERE (
task.point_code1 = t2.truss_point_code2
OR task.point_code2 = t2.truss_point_code2
OR task.point_code3 = t2.truss_point_code2
OR task.point_code4 = t2.truss_point_code2
)
AND task.task_status <![CDATA[ < ]]> '07'
AND task.is_delete = '0')) AS tmp
ORDER BY base_id,
truss_code
</select>
</mapper>

View File

@@ -0,0 +1,19 @@
package org.nl.b_lms.sch.tasks.slitter.mapper.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
* @Author: liyongde
* @Date: 2026/4/22 14:32
*/
@Data
public class SlitterDownNewDto implements Serializable {
private String truss_code;
private String qzz_no;
private String point_type;
private String product_area;
private String point_location;
}

View File

@@ -5,7 +5,9 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.nl.b_lms.sch.point.dao.mapper.StIvtCutpointivtMapper;
import org.nl.b_lms.sch.tasks.SlitterDownNewTrussTask;
import org.nl.b_lms.sch.tasks.slitter.mapper.dto.CombinedOrderDto;
import org.nl.b_lms.sch.tasks.slitter.mapper.dto.SlitterDownNewDto;
import org.nl.b_lms.storage_manage.ios.enums.IOSEnum;
import org.nl.common.utils.IdUtil;
import cn.hutool.core.util.NumberUtil;
@@ -58,6 +60,8 @@ import org.nl.system.service.param.dao.Param;
import org.nl.wms.basedata.master.service.ClassstandardService;
import org.nl.wms.basedata.master.service.dto.ClassstandardDto;
import org.nl.wms.ext.acs.service.WmsToAcsService;
import org.nl.wms.pdm.ivt.deliverycache.service.IDeliverycachepointivtService;
import org.nl.wms.pdm.ivt.deliverycache.service.dao.Deliverycachepointivt;
import org.nl.wms.sch.manage.TaskStatusEnum;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
@@ -68,10 +72,7 @@ import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.regex.Pattern;
@@ -165,6 +166,10 @@ public class SlitterServiceImpl implements SlitterService {
private StockAreaInOutTask stockAreaInOutTask;
@Autowired
private IBstIvtShafttubeivtService bstIvtShafttubeivtService;
@Autowired
private IDeliverycachepointivtService deliverycachepointivtService;
@Autowired
private SlitterDownNewTrussTask slitterDownNewTrussTask;
// 预编译正则表达式,提升性能
private static final Pattern GX_PATTERN = Pattern.compile("^GX(0[1-9]|[1-9]\\d)$");
@@ -602,16 +607,23 @@ public class SlitterServiceImpl implements SlitterService {
log.error("当前子卷已经出卷或者不存在!");
throw new BadRequestException("当前子卷已经出卷或者不存在!");
}
// 获取上轴分切计划和下轴分切计划,各一条
// 获取当前子卷上轴分切计划和下轴分切计划,各一条
PdmBiSlittingproductionplan currentUpPlan = currentPlans.stream()
.filter(p -> "1".equals(p.getUp_or_down())).findFirst().orElse(null);
PdmBiSlittingproductionplan currentDownPlan = currentPlans.stream()
.filter(p -> "2".equals(p.getUp_or_down())).findFirst().orElse(null);
// hint: 获取分切机台子卷的所有计划数据(为了更新时候气胀轴编码发送丢失,直接用卷号)
List<PdmBiSlittingproductionplan> currentUpPlans = currentPlans.stream()
.filter(p -> "1".equals(p.getUp_or_down())).collect(Collectors.toList());
List<PdmBiSlittingproductionplan> currentDownPlans = currentPlans.stream()
.filter(p -> "2".equals(p.getUp_or_down())).collect(Collectors.toList());
// 获取其中一条分切计划
PdmBiSlittingproductionplan demoPlan = currentPlans.get(0);
// 获得设备
StIvtCutpointivt device = cutpointivtService.getOne(new LambdaQueryWrapper<StIvtCutpointivt>()
.eq(StIvtCutpointivt::getExt_code, demoPlan.getResource_name()));
// 实际设备
StIvtCutpointivt actualDevice = device;
if (!actualDeviceCode.equals(demoPlan.getResource_name())) {
// 如果设备与指定的设备不同
@@ -622,10 +634,15 @@ public class SlitterServiceImpl implements SlitterService {
// 获取当前分切机的下一组分切计划(最多四条分切计划)
// 寻找备好轴的对接点位
List<BstIvtCutpointivt> cutPointList = slitterMapper.getReadyShaftPoint(actualDeviceCode);
// 有可能在缓存架
List<Deliverycachepointivt> cutCachePointList = slitterMapper.getReadyShaftCachePoint(actualDevice);
// todo: 也有可能在空轴的AGV对接位, 此时不能直接上到分切机(如果确保一台设备只有一趟气胀轴,那就可以考虑送到对接位)
// List<BstIvtCutpointivt> cutAgvPointList = slitterMapper.getReadyShaftPoint(actualDeviceCode);
// 任务参数
JSONObject taskParam = new JSONObject();
JSONObject taskParam2 = new JSONObject();
taskParam.put("containers", containers);
if (cutPointList.size() == 0) {
if (cutPointList.isEmpty() && cutCachePointList.isEmpty()) {
// 如果没有下一组的分切计划,就只做下卷任务(判断下单/下双)
// 获取分切对接位没任务的空位置
List<BstIvtCutpointivt> emptyPoints = slitterMapper.getEmptyCutPointNotTask(area,
@@ -680,6 +697,270 @@ public class SlitterServiceImpl implements SlitterService {
}
}
}
if (cutCachePointList.size() > 0) {
// 如果在架子上 - 创建的是多条任务toCreateGroupDownRollTask
List<String> qzzNos = cutCachePointList.stream().map(Deliverycachepointivt::getQzzno)
.filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
// 获取所有分切计划
List<PdmBiSlittingproductionplan> allReadyPlans = slittingproductionplanService.getByQzzNos(qzzNos, "03");
// 过滤这些计划,获取时间排序,同组,同母卷的计划数据
if (allReadyPlans.isEmpty()) {
throw new BadRequestException("未找到对应的分切计划数据!");
}
// 按 call_time 升序排序(时间早的在前)
allReadyPlans.sort(Comparator.comparing(PdmBiSlittingproductionplan::getCall_time));
// 以排完序的第一条计划为基准进行过滤
PdmBiSlittingproductionplan firstPlan = allReadyPlans.get(0);
String targetGroup = firstPlan.getSplit_group();
String targetParentContainer = firstPlan.getParent_container_name();
String targetRestructContainer = firstPlan.getRestruct_container_name();
List<PdmBiSlittingproductionplan> filterNextPlans = allReadyPlans.stream()
.filter(plan ->
Objects.equals(targetGroup, plan.getSplit_group())
&& Objects.equals(targetParentContainer, plan.getParent_container_name())
&& Objects.equals(targetRestructContainer, plan.getRestruct_container_name())
).collect(Collectors.toList());
log.info("获取下一趟分切计划数据:{}", filterNextPlans);
// 查找分切对接位空位根据原理分切机先放优先放区域、location、plan进行过滤
List<SlitterDownNewDto> slitterDownNewDtoList = slitterMapper.getCanDownPoints(actualDevice);
String groupId = IdUtil.getStringId();
// 筛选上下轴各一条
PdmBiSlittingproductionplan nextUpPlan = filterNextPlans.stream().filter(p -> "1".equals(p.getUp_or_down())).findFirst().orElse(null);
PdmBiSlittingproductionplan nextDownPlan = filterNextPlans.stream().filter(p -> "2".equals(p.getUp_or_down())).findFirst().orElse(null);
List<PdmBiSlittingproductionplan> nextUpPlans = filterNextPlans.stream().filter(p -> "1".equals(p.getUp_or_down())).collect(Collectors.toList());
List<PdmBiSlittingproductionplan> nextDownPlans = filterNextPlans.stream().filter(p -> "2".equals(p.getUp_or_down())).collect(Collectors.toList());
String binaryExpress = TaskUtils.binaryConvertExpress(currentUpPlan, currentDownPlan, nextUpPlan, nextDownPlan);
switch (binaryExpress) {
case "00":
// 下单上单(一条四点任务)
SlitterDownNewDto slitterDownNewDto = slitterDownNewDtoList.get(0);
PdmBiSlittingproductionplan demo = nextUpPlan != null ? nextUpPlan : nextDownPlan;
PdmBiSlittingproductionplan demo2 = currentUpPlan != null ? currentUpPlan : currentDownPlan;
// 获取该气胀轴对应的站点
Deliverycachepointivt ivt = deliverycachepointivtService.getDeliveryByQzzNo(demo.getQzzno());
if (ObjectUtil.isEmpty(ivt)) {
throw new BadRequestException("没找到气胀轴为" + demo.getQzzno() + "的空气胀轴暂存点!");
}
taskParam.put("point_code1", ivt.getPoint_code());
taskParam.put("point_code2", nextUpPlan != null
? actualDevice.getUp_point_code() : actualDevice.getDown_point_code());
taskParam.put("point_code3", currentUpPlan != null
? actualDevice.getUp_point_code() : actualDevice.getDown_point_code());
taskParam.put("point_code4", slitterDownNewDto.getTruss_code());
taskParam.put("truss_type", "10");
taskParam.put("empty_site", "0");
taskParam.put("groupId", groupId);
taskParam.put("flag", "1"); // 标记是上单下单的
// 上去的气胀轴编码
taskParam.put("vehicle_code", demo.getQzzno());
// 下来的子卷的气胀轴编码
taskParam.put("vehicle_code2", demo2.getQzzno());
// 上去的子卷号
taskParam.put("up_roll", nextUpPlan != null ? nextUpPlans : nextDownPlans);
// 下来的子卷好
taskParam.put("down_roll", currentUpPlan != null ? currentUpPlans : currentDownPlans);
break;
case "01":
// 下单上双(下单上单 + 单上 任务)
SlitterDownNewDto slitterDownNewADto = slitterDownNewDtoList.get(0);
// 获取该气胀轴对应的站点
Deliverycachepointivt ivt1 = deliverycachepointivtService.getDeliveryByQzzNo(nextUpPlan.getQzzno());
Deliverycachepointivt ivt2 = deliverycachepointivtService.getDeliveryByQzzNo(nextDownPlan.getQzzno());
if (ObjectUtil.isEmpty(ivt1) || ObjectUtil.isEmpty(ivt2)) {
throw new BadRequestException("没找到完整的气胀轴为空气胀轴暂存点!");
}
taskParam.put("point_code1", ivt1.getPoint_code());
taskParam.put("point_code2", actualDevice.getUp_point_code());
taskParam.put("point_code3", actualDevice.getUp_point_code());
taskParam.put("point_code4", slitterDownNewADto.getTruss_code());
taskParam.put("truss_type", "13");
taskParam.put("empty_site", "0");
taskParam.put("groupId", groupId);
// 上去的气胀轴编码
taskParam.put("vehicle_code", nextUpPlan.getQzzno());
// 下来的子卷的气胀轴编码
taskParam.put("vehicle_code2", currentUpPlan.getQzzno());
// 上去的子卷号
taskParam.put("up_roll", nextUpPlans);
// 下来的子卷好
taskParam.put("down_roll", currentUpPlans);
taskParam.put("flag", "1"); // 标记是上单下单的
taskParam2.put("point_code1", ivt2.getPoint_code());
taskParam2.put("point_code2", actualDevice.getDown_point_code());
taskParam2.put("truss_type", "13");
taskParam2.put("empty_site", "0");
taskParam2.put("groupId", groupId);
// 上去的气胀轴编码
taskParam2.put("vehicle_code", nextDownPlan.getQzzno());
taskParam2.put("up_roll", nextDownPlans);
taskParam2.put("flag", "3");
break;
case "10":
// 下双上单(下单上单 + 单下 任务) : 先下上面的卷
if (slitterDownNewDtoList.size() < 2) {
throw new BadRequestException("位置不够...");
}
SlitterDownNewDto slitterDownNewA1Dto = slitterDownNewDtoList.get(0);
SlitterDownNewDto slitterDownNewB1Dto = slitterDownNewDtoList.get(1);
// 获取该气胀轴对应的站点
PdmBiSlittingproductionplan slittingproductionplan = nextUpPlan != null ? nextUpPlan : nextDownPlan;
Deliverycachepointivt ivt3 = deliverycachepointivtService.getDeliveryByQzzNo(slittingproductionplan.getQzzno());
if (ObjectUtil.isEmpty(ivt3)) {
throw new BadRequestException("没找到完整的气胀轴为空气胀轴暂存点!");
}
if (nextUpPlan != null) {
// 下一个是分切机上面的轴(第一个任务就是四点任务)
taskParam.put("point_code1", ivt3.getPoint_code());
taskParam.put("point_code2", actualDevice.getUp_point_code());
taskParam.put("point_code3", actualDevice.getUp_point_code());
taskParam.put("point_code4", slitterDownNewA1Dto.getTruss_code());
taskParam.put("truss_type", "14");
taskParam.put("empty_site", "0");
taskParam.put("groupId", groupId);
taskParam.put("seq", 1);
// 上去的气胀轴编码
taskParam.put("vehicle_code", nextUpPlan.getQzzno());
// 下来的子卷的气胀轴编码
taskParam.put("vehicle_code2", currentUpPlan.getQzzno());
// 上去的子卷号
taskParam.put("up_roll", nextUpPlans);
// 下来的子卷好
taskParam.put("down_roll", currentUpPlans);
taskParam.put("flag", "1"); // 标记是上单下单的
// 单下
taskParam2.put("point_code1", actualDevice.getDown_point_code());
taskParam2.put("point_code2", slitterDownNewB1Dto.getTruss_code());
taskParam2.put("truss_type", "14");
taskParam2.put("empty_site", "0");
taskParam2.put("groupId", groupId);
taskParam2.put("seq", 2);
// 下来的子卷的气胀轴编码
taskParam2.put("vehicle_code2", currentDownPlan.getQzzno());
// 下来的子卷好
taskParam2.put("down_roll", currentDownPlans);
taskParam2.put("flag", "2");
} else {
// 下一个是分切机下面的轴第一个任务就是2点任务
taskParam.put("point_code1", actualDevice.getUp_point_code());
taskParam.put("point_code2", slitterDownNewA1Dto.getTruss_code());
taskParam.put("truss_type", "14");
taskParam.put("empty_site", "0");
taskParam.put("groupId", groupId);
taskParam.put("seq", 1);
// 下来的子卷的气胀轴编码
taskParam.put("vehicle_code2", currentUpPlan.getQzzno());
// 下来的子卷好
taskParam.put("down_roll", currentUpPlans);
taskParam.put("flag", "2");
// 上单下单
taskParam2.put("point_code1", ivt3.getPoint_code());
taskParam2.put("point_code2", actualDevice.getDown_point_code());
taskParam2.put("point_code3", actualDevice.getDown_point_code());
taskParam2.put("point_code4", slitterDownNewB1Dto.getTruss_code());
taskParam2.put("truss_type", "14");
taskParam2.put("empty_site", "0");
taskParam2.put("groupId", groupId);
taskParam2.put("seq", 2);
// 上去的气胀轴编码
taskParam2.put("vehicle_code", nextDownPlan.getQzzno());
// 下来的子卷的气胀轴编码
taskParam2.put("vehicle_code2", currentDownPlan.getQzzno());
// 上去的子卷号
taskParam2.put("up_roll", nextDownPlans);
// 下来的子卷好
taskParam2.put("down_roll", currentDownPlans);
taskParam2.put("flag", "1"); // 标记是上单下单的
}
break;
case "11":
// 下双上双(两条 下单上单 任务)
if (slitterDownNewDtoList.size() < 2) {
throw new BadRequestException("位置不够...");
}
SlitterDownNewDto slitterDownNewA2Dto = slitterDownNewDtoList.get(0);
SlitterDownNewDto slitterDownNewB2Dto = slitterDownNewDtoList.get(1);
// 获取该气胀轴对应的站点
Deliverycachepointivt ivtUp = deliverycachepointivtService.getDeliveryByQzzNo(nextUpPlan.getQzzno());
Deliverycachepointivt ivtDown = deliverycachepointivtService.getDeliveryByQzzNo(nextDownPlan.getQzzno());
if (ObjectUtil.isEmpty(ivtUp) || ObjectUtil.isEmpty(ivtDown)) {
throw new BadRequestException("没找到完整的气胀轴为空气胀轴暂存点!");
}
taskParam.put("point_code1", ivtUp.getPoint_code());
taskParam.put("point_code2", actualDevice.getUp_point_code());
taskParam.put("point_code3", actualDevice.getUp_point_code());
taskParam.put("point_code4", slitterDownNewA2Dto.getTruss_code());
taskParam.put("truss_type", "11");
taskParam.put("empty_site", "0");
taskParam.put("groupId", groupId);
taskParam.put("seq", 1);
taskParam.put("flag", "1"); // 标记是上单下单的
// 上去的气胀轴编码
taskParam.put("vehicle_code", nextUpPlan.getQzzno());
// 下来的子卷的气胀轴编码
taskParam.put("vehicle_code2", currentUpPlan.getQzzno());
// 上去的子卷号
taskParam.put("up_roll", nextUpPlans);
// 下来的子卷好
taskParam.put("down_roll", currentUpPlans);
taskParam2.put("point_code1", ivtDown.getPoint_code());
taskParam2.put("point_code2", actualDevice.getDown_point_code());
taskParam2.put("point_code3", actualDevice.getDown_point_code());
taskParam2.put("point_code4", slitterDownNewB2Dto.getTruss_code());
taskParam2.put("truss_type", "11");
taskParam2.put("empty_site", "0");
taskParam2.put("groupId", groupId);
taskParam2.put("seq", 2);
taskParam2.put("flag", "1"); // 标记是上单下单的
// 上去的气胀轴编码
taskParam2.put("vehicle_code", nextDownPlan.getQzzno());
// 下来的子卷的气胀轴编码
taskParam2.put("vehicle_code2", currentDownPlan.getQzzno());
// 上去的子卷号
taskParam2.put("up_roll", nextDownPlans);
// 下来的子卷好
taskParam2.put("down_roll", currentDownPlans);
break;
default:
throw new BadRequestException("错误表达式");
}
// 创建任务
taskParam.put("task_type", SlitterEnum.TASK_TYPE.code("分切机下料桁架任务"));
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
// taskParam.put("d_containers", currentPlans.stream().map(PdmBiSlittingproductionplan::getContainer_name).collect(Collectors.toList()));
// taskParam.put("u_containers", filterNextPlans.stream().map(PdmBiSlittingproductionplan::getContainer_name).collect(Collectors.toList()));
JSONArray array = new JSONArray();
array.add(taskParam);
if (ObjectUtil.isNotEmpty(taskParam2)) {
taskParam2.put("task_type", SlitterEnum.TASK_TYPE.code("分切机下料桁架任务"));
taskParam2.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
// taskParam2.put("d_containers", currentPlans.stream().map(PdmBiSlittingproductionplan::getContainer_name).collect(Collectors.toList()));
// taskParam2.put("u_containers", filterNextPlans.stream().map(PdmBiSlittingproductionplan::getContainer_name).collect(Collectors.toList()));
array.add(taskParam2);
}
JSONObject p = new JSONObject();
p.put("tasks", array);
slitterDownNewTrussTask.createTask(p);
// 下来的分切计划修改状态05 -> 06
currentPlans.forEach(plan -> {
plan.setStatus("06");
TaskUtils.updateOptMessageBySlitterPlan(plan);
});
// 上去的分切计划修改状态03 -> 04
filterNextPlans.forEach(plan -> {
plan.setStatus("04");
TaskUtils.updateOptMessageBySlitterPlan(plan);
});
// hint: 为了减少IO次数将两个数组放在一起批量插入
List<PdmBiSlittingproductionplan> mergedList = new ArrayList<>();
mergedList.addAll(currentPlans);
mergedList.addAll(filterNextPlans);
slittingproductionplanService.updateBatchById(mergedList);
res.put("status", HttpStatus.HTTP_OK);
res.put("message", "子卷出站任务生成成功!");
return res;
}
// 找到该分切计划的点位
BstIvtCutpointivt newCutPoint = cutPointList.get(0);
List<String> qzznos = Stream.of(newCutPoint.getQzz_no1(), newCutPoint.getQzz_no2()).filter(ObjectUtil::isNotEmpty)

View File

@@ -8,6 +8,7 @@ import org.nl.b_lms.bst.ivt.cutpointivt.service.dao.BstIvtCutpointivt;
import org.nl.b_lms.bst.ivt.shafttubeivt.service.dao.BstIvtShafttubeivt;
import org.nl.b_lms.bst.ivt.stockingivt.service.dao.BstIvtStockingivt;
import org.nl.b_lms.pdm.bi.slittingproductionplan.service.dao.PdmBiSlittingproductionplan;
import org.nl.b_lms.sch.point.dao.StIvtCutpointivt;
import org.nl.b_lms.sch.task.dao.SchBaseTask;
import org.nl.modules.common.exception.BadRequestException;
import org.nl.modules.wql.util.SpringContextHolder;
@@ -164,6 +165,15 @@ public class TaskUtils {
point.setUpdate_optname(SecurityUtils.getCurrentUsername());
point.setUpdate_time(DateUtil.now());
}
/**
* 赋值分切设备的修改时间、人等信息
* @param point 分切设备点
*/
public static void updateOptMessageByStIvtCutPoint(StIvtCutpointivt point) {
point.setUpdate_optid(Long.valueOf(SecurityUtils.getCurrentUserId()));
point.setUpdate_optname(SecurityUtils.getCurrentUsername());
point.setUpdate_time(DateUtil.now());
}
/**
* 获取指定格式的日期时间

View File

@@ -101,4 +101,6 @@ public interface IDeliverycachepointivtService extends IService<Deliverycachepoi
List<Deliverycachepointivt> getAreaBCacheByConditionsAndNoTask(AreaBCachePointDto build);
Deliverycachepointivt getPintByCode(String pointCode, boolean flag);
Deliverycachepointivt getDeliveryByQzzNo(String qzzno);
}

View File

@@ -141,4 +141,15 @@ public class DeliverycachepointivtServiceImpl extends ServiceImpl<Deliverycachep
return deliverycachepointivtMapper.selectOne(lam);
}
@Override
public Deliverycachepointivt getDeliveryByQzzNo(String qzzno) {
if (ObjectUtil.isEmpty(qzzno)) {
return null;
}
LambdaQueryWrapper<Deliverycachepointivt> lam = new QueryWrapper<Deliverycachepointivt>().lambda();
lam.eq(Deliverycachepointivt::getIs_used, "1")
.eq(Deliverycachepointivt::getQzzno, qzzno);
return deliverycachepointivtMapper.selectOne(lam);
}
}