add:自动送子卷任务,自动套轴任务,自动拔轴未提交的代码
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package cn.code.nl.module.lms.api;
|
||||
|
||||
import cn.code.nl.framework.common.pojo.CommonResult;
|
||||
import cn.code.nl.module.lms.enums.ApiConstants;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
/**
|
||||
* 自动子卷搬运 RPC API
|
||||
*/
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
public interface AutoCallAirShaftApi {
|
||||
|
||||
/**
|
||||
* 执行自动子卷搬运调度
|
||||
*
|
||||
* @return 是否执行成功
|
||||
*/
|
||||
@PostMapping(ApiConstants.PREFIX + "/autoCallAirShaft/execute")
|
||||
CommonResult<Boolean> executeAutoCallAirShaft();
|
||||
|
||||
/**
|
||||
* 执行 C、D 到 E 自动搬运调度
|
||||
*
|
||||
* @return 是否执行成功
|
||||
*/
|
||||
@PostMapping(ApiConstants.PREFIX + "/autoCallAirShaft/executeToDevice")
|
||||
CommonResult<Boolean> executeAutoCallAirShaftToDevice();
|
||||
|
||||
/**
|
||||
* 执行自动套轴调度
|
||||
*
|
||||
* @return 是否执行成功
|
||||
*/
|
||||
@PostMapping(ApiConstants.PREFIX + "/autoCallAirShaft/executeSleeve")
|
||||
CommonResult<Boolean> executeAutoSleeve();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.code.nl.module.lms.api;
|
||||
|
||||
import cn.code.nl.framework.common.pojo.CommonResult;
|
||||
import cn.code.nl.module.lms.service.autocall.AutoCallAirShaftService;
|
||||
import cn.code.nl.module.lms.service.autosleeve.AutoSleeveService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static cn.code.nl.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* 自动子卷搬运 RPC API 实现类
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
public class AutoCallAirShaftApiImpl implements AutoCallAirShaftApi {
|
||||
|
||||
/** 自动子卷搬运 Service */
|
||||
@Resource
|
||||
private AutoCallAirShaftService autoCallAirShaftService;
|
||||
|
||||
@Resource
|
||||
private AutoSleeveService autoSleeveService;
|
||||
|
||||
/**
|
||||
* 执行自动子卷搬运调度
|
||||
*
|
||||
* @return 是否执行成功
|
||||
*/
|
||||
@Override
|
||||
public CommonResult<Boolean> executeAutoCallAirShaft() {
|
||||
autoCallAirShaftService.execute();
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行 C、D 到 E 自动搬运调度
|
||||
*
|
||||
* @return 是否执行成功
|
||||
*/
|
||||
@Override
|
||||
public CommonResult<Boolean> executeAutoCallAirShaftToDevice() {
|
||||
autoCallAirShaftService.executeWaitingRollToDevice();
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> executeAutoSleeve() {
|
||||
autoSleeveService.execute();
|
||||
return success(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.code.nl.module.lms.controller.admin.btcutpointivt.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 分切区缓存点位下拉选项 Response VO")
|
||||
@Data
|
||||
public class BtIvtCutpointivtOptionsRespVO {
|
||||
|
||||
@Schema(description = "是否启用选项")
|
||||
private List<OptionVO> isUsedOptions;
|
||||
|
||||
@Schema(description = "点位类型选项")
|
||||
private List<OptionVO> pointTypeOptions;
|
||||
|
||||
@Schema(description = "生产区域选项")
|
||||
private List<OptionVO> productAreaOptions;
|
||||
|
||||
@Schema(description = "点位状态选项")
|
||||
private List<OptionVO> pointStatusOptions;
|
||||
|
||||
@Schema(description = "下拉选项")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class OptionVO {
|
||||
|
||||
@Schema(description = "选项名称")
|
||||
private String label;
|
||||
|
||||
@Schema(description = "选项值")
|
||||
private String value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.code.nl.module.lms.controller.admin.ivtshafttubeivt.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 穿拔轴区点位库存下拉选项 Response VO")
|
||||
@Data
|
||||
public class IvtShafttubeivtOptionsRespVO {
|
||||
|
||||
@Schema(description = "点位类型选项")
|
||||
private List<OptionVO> pointTypeOptions;
|
||||
|
||||
@Schema(description = "规划区域选项")
|
||||
private List<OptionVO> planOptions;
|
||||
|
||||
@Schema(description = "下拉选项")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class OptionVO {
|
||||
|
||||
@Schema(description = "选项名称")
|
||||
private String label;
|
||||
|
||||
@Schema(description = "选项值")
|
||||
private String value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.code.nl.module.lms.controller.pda.slittingproduction.eum;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 分切区缓存点位启用状态枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum CutpointivtIsUsedEnum {
|
||||
|
||||
DISABLED("0", "关闭"),
|
||||
ENABLED("1", "启用");
|
||||
|
||||
/**
|
||||
* 状态编码
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* 状态名称
|
||||
*/
|
||||
private final String name;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cn.code.nl.module.lms.controller.pda.slittingproduction.eum;
|
||||
|
||||
/**
|
||||
* 分切区缓存点位生产区域枚举
|
||||
*/
|
||||
public enum CutpointivtProductAreaEnum {
|
||||
|
||||
A1,
|
||||
A2,
|
||||
A
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.code.nl.module.lms.controller.pda.slittingproduction.eum;
|
||||
|
||||
/**
|
||||
* 穿拔轴区规划区域。
|
||||
*/
|
||||
public enum ShafttubeivtPlanEnum {
|
||||
|
||||
WEST("1", "西区"),
|
||||
EAST("2", "东区");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
ShafttubeivtPlanEnum(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.code.nl.module.lms.controller.pda.slittingproduction.eum;
|
||||
|
||||
/**
|
||||
* 穿拔轴区点位类型。
|
||||
*/
|
||||
public enum ShafttubeivtPointTypeEnum {
|
||||
|
||||
PULL_AXIS_SUB_ROLL("1", "拔轴子卷位"),
|
||||
SLEEVE_TUBE_CORE("2", "套管管芯位"),
|
||||
AIR_SHAFT_CACHE("3", "气涨轴缓存位"),
|
||||
TUBE_CORE_CACHE("4", "管芯缓存位"),
|
||||
AIR_SHAFT_LINE_SIDE_WAREHOUSE("5", "气涨轴线边库"),
|
||||
PULL_AXIS_AIR_SHAFT("6", "拔轴气涨轴位"),
|
||||
SLEEVE_AIR_SHAFT("7", "套管气涨轴位");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
ShafttubeivtPointTypeEnum(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package cn.code.nl.module.lms.service.autocall;
|
||||
|
||||
/**
|
||||
* 自动子卷搬运阶段
|
||||
*/
|
||||
public enum AutoAirShaftStageEnum {
|
||||
|
||||
A_TO_B,
|
||||
B_TO_C,
|
||||
C_TO_D,
|
||||
C_TO_E,
|
||||
D_TO_E
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.code.nl.module.lms.service.autocall;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 自动子卷搬运任务上下文
|
||||
*/
|
||||
@Data
|
||||
public class AutoAirShaftTaskContext {
|
||||
|
||||
/** 搬运阶段 */
|
||||
private AutoAirShaftStageEnum stage;
|
||||
/** 来源点 */
|
||||
private String sourcePointCode;
|
||||
/** 目标点 */
|
||||
private String targetPointCode;
|
||||
/** A 到 B 阶段预留的 C 点 */
|
||||
private String reservedPointCode;
|
||||
/** 生产区域 */
|
||||
private String productArea;
|
||||
/** 气胀轴编码 */
|
||||
private String qzzNo;
|
||||
/** 管芯编码 */
|
||||
private String gxNo;
|
||||
/** 子卷号 */
|
||||
private String subContainer;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.code.nl.module.lms.service.autocall;
|
||||
|
||||
/**
|
||||
* 自动子卷搬运 Service
|
||||
*/
|
||||
public interface AutoCallAirShaftService {
|
||||
|
||||
/**
|
||||
* 执行自动搬运调度
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* 执行 C、D 到 E 自动搬运调度,优先处理 C 点子卷
|
||||
*/
|
||||
void executeWaitingRollToDevice();
|
||||
|
||||
/** 校验并调度 B 到 C 任务 */
|
||||
void dispatchBToC(AutoAirShaftTaskContext context);
|
||||
|
||||
/** 校验并调度 C 的下一段任务 */
|
||||
void dispatchAfterBToC(AutoAirShaftTaskContext context);
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package cn.code.nl.module.lms.service.autocall;
|
||||
|
||||
import cn.code.nl.module.lms.controller.pda.slittingproduction.eum.CutpointivtPointStatusEnum;
|
||||
import cn.code.nl.module.lms.controller.pda.slittingproduction.eum.CutpointivtTypeEnum;
|
||||
import cn.code.nl.module.lms.dal.dataobject.btivtcutpointivt.BtIvtCutpointivtDO;
|
||||
import cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO;
|
||||
import cn.code.nl.module.lms.dal.mysql.btivtcutpointivt.BtIvtCutpointivtMapper;
|
||||
import cn.code.nl.module.lms.dal.mysql.ivtshafttubeivt.IvtShafttubeivtMapper;
|
||||
import cn.code.nl.module.lms.task.AutoAirShaftTask;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 自动子卷搬运点位校验及调度 Service
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AutoCallAirShaftServiceImpl implements AutoCallAirShaftService {
|
||||
|
||||
private static final String PRODUCT_AREA_A1 = "A1";
|
||||
private static final String PRODUCT_AREA_A2 = "A2";
|
||||
|
||||
@Resource
|
||||
private BtIvtCutpointivtMapper btIvtCutpointivtMapper;
|
||||
@Resource
|
||||
private IvtShafttubeivtMapper ivtShafttubeivtMapper;
|
||||
/** 延迟注入用于解除状态回调的循环依赖 */
|
||||
@Lazy
|
||||
@Resource
|
||||
private AutoAirShaftTask autoAirShaftTask;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
createInitialTasks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeWaitingRollToDevice() {
|
||||
dispatchWaitingRollToDevice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchBToC(AutoAirShaftTaskContext context) {
|
||||
BtIvtCutpointivtDO reservedPoint = btIvtCutpointivtMapper.selectByPointCode(context.getReservedPointCode());
|
||||
if (reservedPoint == null) {
|
||||
throw new IllegalStateException("B 到 C 预留点不存在");
|
||||
}
|
||||
AutoAirShaftTaskContext nextContext = copyContext(context, AutoAirShaftStageEnum.B_TO_C,
|
||||
context.getTargetPointCode(), context.getReservedPointCode());
|
||||
autoAirShaftTask.createTransportTask(nextContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchAfterBToC(AutoAirShaftTaskContext context) {
|
||||
IvtShafttubeivtDO device = lockIdleDevice();
|
||||
if (device != null) {
|
||||
autoAirShaftTask.createTransportTask(copyContext(context, AutoAirShaftStageEnum.C_TO_E,
|
||||
context.getTargetPointCode(), device.getPointCode()));
|
||||
return;
|
||||
}
|
||||
BtIvtCutpointivtDO cache = lockCutPoint(CutpointivtTypeEnum.PULL_AXIS_SUB_CACHE.getCode(),
|
||||
CutpointivtPointStatusEnum.NO_STOCK.getCode(), context.getProductArea());
|
||||
if (cache != null) {
|
||||
autoAirShaftTask.createTransportTask(copyContext(context, AutoAirShaftStageEnum.C_TO_D,
|
||||
context.getTargetPointCode(), cache.getPointCode()));
|
||||
return;
|
||||
}
|
||||
autoAirShaftTask.releasePointLock(context.getTargetPointCode());
|
||||
}
|
||||
|
||||
/** 遍历 A1、A2 的下料缓存位并创建 A 到 B 首段任务 */
|
||||
private void createInitialTasks() {
|
||||
List<BtIvtCutpointivtDO> sources = btIvtCutpointivtMapper.selectAvailablePoints(
|
||||
CutpointivtTypeEnum.CUTTING_BLANKING_CACHE.getCode(),
|
||||
CutpointivtPointStatusEnum.HAS_SUB_ROLL.getCode(), null);
|
||||
List<BtIvtCutpointivtDO> targets = btIvtCutpointivtMapper.selectAvailablePoints(
|
||||
CutpointivtTypeEnum.CUTTING_BLANKING_AGV.getCode(),
|
||||
CutpointivtPointStatusEnum.NO_STOCK.getCode(), null);
|
||||
List<BtIvtCutpointivtDO> reservedPoints = btIvtCutpointivtMapper.selectAvailablePoints(
|
||||
CutpointivtTypeEnum.PULL_AXIS_SUB_DOCK.getCode(),
|
||||
CutpointivtPointStatusEnum.NO_STOCK.getCode(), null);
|
||||
|
||||
for (BtIvtCutpointivtDO source : sources) {
|
||||
if (!PRODUCT_AREA_A1.equals(source.getProductArea())
|
||||
&& !PRODUCT_AREA_A2.equals(source.getProductArea())) {
|
||||
continue;
|
||||
}
|
||||
BtIvtCutpointivtDO target = findTargetPoint(targets, source.getProductArea());
|
||||
if (target == null || CollectionUtils.isEmpty(reservedPoints)) {
|
||||
continue;
|
||||
}
|
||||
BtIvtCutpointivtDO reserved = reservedPoints.get(0);
|
||||
int lockedRows = btIvtCutpointivtMapper.lockPointsIfAvailable(List.of(
|
||||
source.getIvtId(), target.getIvtId(), reserved.getIvtId()));
|
||||
if (lockedRows != 3) {
|
||||
releaseInitialLocks(source, target, reserved);
|
||||
continue;
|
||||
}
|
||||
targets.remove(target);
|
||||
reservedPoints.remove(reserved);
|
||||
AutoAirShaftTaskContext context = buildContext(AutoAirShaftStageEnum.A_TO_B,
|
||||
source, target.getPointCode(), reserved.getPointCode());
|
||||
try {
|
||||
autoAirShaftTask.createTransportTask(context);
|
||||
} catch (Exception ex) {
|
||||
releaseInitialLocks(source, target, reserved);
|
||||
log.error("创建 A 到 B 自动搬运任务失败,来源点={},目标点={},预留点={}",
|
||||
source.getPointCode(), target.getPointCode(), reserved.getPointCode(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 将 C 或 D 中等待的子卷优先搬入空闲 E */
|
||||
private void dispatchWaitingRollToDevice() {
|
||||
BtIvtCutpointivtDO source = lockCutPoint(CutpointivtTypeEnum.PULL_AXIS_SUB_DOCK.getCode(),
|
||||
CutpointivtPointStatusEnum.HAS_SUB_ROLL.getCode(), null);
|
||||
AutoAirShaftStageEnum stage = AutoAirShaftStageEnum.C_TO_E;
|
||||
if (source == null) {
|
||||
source = lockCutPoint(CutpointivtTypeEnum.PULL_AXIS_SUB_CACHE.getCode(),
|
||||
CutpointivtPointStatusEnum.HAS_SUB_ROLL.getCode(), null);
|
||||
stage = AutoAirShaftStageEnum.D_TO_E;
|
||||
}
|
||||
if (source == null) {
|
||||
return;
|
||||
}
|
||||
IvtShafttubeivtDO device = lockIdleDevice();
|
||||
if (device == null) {
|
||||
autoAirShaftTask.releasePointLock(source.getPointCode());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
autoAirShaftTask.createTransportTask(buildContext(stage, source, device.getPointCode(), null));
|
||||
} catch (Exception ex) {
|
||||
autoAirShaftTask.releasePointLock(source.getPointCode());
|
||||
autoAirShaftTask.releaseDeviceLock(device.getPointCode());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/** 释放首段任务占用的点位 */
|
||||
private void releaseInitialLocks(BtIvtCutpointivtDO source, BtIvtCutpointivtDO target,
|
||||
BtIvtCutpointivtDO reserved) {
|
||||
autoAirShaftTask.releasePointLock(source.getPointCode());
|
||||
autoAirShaftTask.releasePointLock(target.getPointCode());
|
||||
autoAirShaftTask.releasePointLock(reserved.getPointCode());
|
||||
}
|
||||
|
||||
/** 查询同生产区域的目标点 */
|
||||
private BtIvtCutpointivtDO findTargetPoint(List<BtIvtCutpointivtDO> targets, String productArea) {
|
||||
for (BtIvtCutpointivtDO point : targets) {
|
||||
if (Objects.equals(point.getProductArea(), productArea)) {
|
||||
return point;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 查询并 CAS 占用首个符合条件的 A 至 D 点位 */
|
||||
private BtIvtCutpointivtDO lockCutPoint(String pointType, String pointStatus, String productArea) {
|
||||
List<BtIvtCutpointivtDO> points = btIvtCutpointivtMapper.selectAvailablePoints(
|
||||
pointType, pointStatus, productArea);
|
||||
for (BtIvtCutpointivtDO point : points) {
|
||||
if (btIvtCutpointivtMapper.lockPointIfAvailable(point.getIvtId(), pointStatus) > 0) {
|
||||
return point;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 查询并 CAS 占用首个空闲 E 设备 */
|
||||
private IvtShafttubeivtDO lockIdleDevice() {
|
||||
List<IvtShafttubeivtDO> devices = ivtShafttubeivtMapper.selectIdleDevices();
|
||||
for (IvtShafttubeivtDO device : devices) {
|
||||
if (ivtShafttubeivtMapper.lockIdleDevice(device.getIvtId()) > 0) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 根据来源点库存构造任务上下文 */
|
||||
private AutoAirShaftTaskContext buildContext(AutoAirShaftStageEnum stage, BtIvtCutpointivtDO source,
|
||||
String targetPointCode, String reservedPointCode) {
|
||||
AutoAirShaftTaskContext context = new AutoAirShaftTaskContext();
|
||||
context.setStage(stage);
|
||||
context.setSourcePointCode(source.getPointCode());
|
||||
context.setTargetPointCode(targetPointCode);
|
||||
context.setReservedPointCode(reservedPointCode);
|
||||
context.setProductArea(source.getProductArea());
|
||||
context.setQzzNo(source.getQzzNo());
|
||||
context.setGxNo(source.getGxNo());
|
||||
context.setSubContainer(source.getSubContainer());
|
||||
return context;
|
||||
}
|
||||
|
||||
/** 复制物料信息并构造下一阶段任务上下文 */
|
||||
private AutoAirShaftTaskContext copyContext(AutoAirShaftTaskContext source, AutoAirShaftStageEnum stage,
|
||||
String sourcePointCode, String targetPointCode) {
|
||||
AutoAirShaftTaskContext context = new AutoAirShaftTaskContext();
|
||||
context.setStage(stage);
|
||||
context.setSourcePointCode(sourcePointCode);
|
||||
context.setTargetPointCode(targetPointCode);
|
||||
context.setProductArea(source.getProductArea());
|
||||
context.setQzzNo(source.getQzzNo());
|
||||
context.setGxNo(source.getGxNo());
|
||||
context.setSubContainer(source.getSubContainer());
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.code.nl.module.lms.service.autosleeve;
|
||||
|
||||
/**
|
||||
* 自动套轴调度 Service。
|
||||
*/
|
||||
public interface AutoSleeveService {
|
||||
|
||||
/** 轮询管芯缓存位并创建配套搬运任务。 */
|
||||
void execute();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package cn.code.nl.module.lms.service.autosleeve;
|
||||
|
||||
import cn.code.nl.module.lms.controller.pda.slittingproduction.eum.ShafttubeivtPointTypeEnum;
|
||||
import cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO;
|
||||
import cn.code.nl.module.lms.dal.mysql.ivtshafttubeivt.IvtShafttubeivtMapper;
|
||||
import cn.code.nl.module.lms.task.AutoSleeveTask;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自动套轴点位校验和任务调度。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AutoSleeveServiceImpl implements AutoSleeveService {
|
||||
|
||||
@Resource
|
||||
private IvtShafttubeivtMapper ivtShafttubeivtMapper;
|
||||
@Resource
|
||||
private AutoSleeveTask autoSleeveTask;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<IvtShafttubeivtDO> tubeCoreCaches = ivtShafttubeivtMapper.selectTubeCoreCaches(
|
||||
ShafttubeivtPointTypeEnum.TUBE_CORE_CACHE.getCode());
|
||||
for (IvtShafttubeivtDO tubeCoreCache : tubeCoreCaches) {
|
||||
dispatch(tubeCoreCache);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按管芯缓存位的规划区域分配两个套管目的点,并匹配指定气涨轴。
|
||||
*/
|
||||
private void dispatch(IvtShafttubeivtDO tubeCoreCache) {
|
||||
if (tubeCoreCache.getPlan() == null || tubeCoreCache.getPlan().isBlank()) {
|
||||
log.warn("管芯缓存位未配置规划区域,跳过自动套轴,pointCode={}", tubeCoreCache.getPointCode());
|
||||
return;
|
||||
}
|
||||
List<IvtShafttubeivtDO> tubeTargets = ivtShafttubeivtMapper.selectEmptyPoints(
|
||||
ShafttubeivtPointTypeEnum.SLEEVE_TUBE_CORE.getCode(), tubeCoreCache.getPlan());
|
||||
List<IvtShafttubeivtDO> shaftTargets = ivtShafttubeivtMapper.selectEmptyPoints(
|
||||
ShafttubeivtPointTypeEnum.SLEEVE_AIR_SHAFT.getCode(), tubeCoreCache.getPlan());
|
||||
if (CollectionUtils.isEmpty(tubeTargets) || CollectionUtils.isEmpty(shaftTargets)) {
|
||||
return;
|
||||
}
|
||||
IvtShafttubeivtDO airShaftCache = ivtShafttubeivtMapper.selectAirShaftCache(
|
||||
ShafttubeivtPointTypeEnum.AIR_SHAFT_CACHE.getCode(), tubeCoreCache.getQzzGeneration());
|
||||
if (airShaftCache == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IvtShafttubeivtDO tubeTarget = tubeTargets.get(0);
|
||||
IvtShafttubeivtDO shaftTarget = shaftTargets.get(0);
|
||||
List<IvtShafttubeivtDO> lockedPoints = new ArrayList<>();
|
||||
if (!lockPoint(tubeCoreCache, lockedPoints)
|
||||
|| !lockPoint(tubeTarget, lockedPoints)
|
||||
|| !lockPoint(airShaftCache, lockedPoints)
|
||||
|| !lockPoint(shaftTarget, lockedPoints)) {
|
||||
releaseLocks(lockedPoints);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean tubeTaskCreated = false;
|
||||
boolean shaftTaskCreated = false;
|
||||
try {
|
||||
autoSleeveTask.createTransportTask(buildTubeContext(tubeCoreCache, tubeTarget));
|
||||
tubeTaskCreated = true;
|
||||
autoSleeveTask.createTransportTask(buildShaftContext(tubeCoreCache, airShaftCache, shaftTarget));
|
||||
shaftTaskCreated = true;
|
||||
} catch (Exception ex) {
|
||||
if (!tubeTaskCreated) {
|
||||
releaseLocks(List.of(tubeCoreCache, tubeTarget));
|
||||
}
|
||||
if (!shaftTaskCreated) {
|
||||
releaseLocks(List.of(airShaftCache, shaftTarget));
|
||||
}
|
||||
log.error("创建自动套轴任务失败,管芯点={},气涨轴点={},规划区域={}",
|
||||
tubeCoreCache.getPointCode(), airShaftCache.getPointCode(), tubeCoreCache.getPlan(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean lockPoint(IvtShafttubeivtDO point, List<IvtShafttubeivtDO> lockedPoints) {
|
||||
if (ivtShafttubeivtMapper.lockInventoryPoint(point.getIvtId()) == 0) {
|
||||
return false;
|
||||
}
|
||||
lockedPoints.add(point);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void releaseLocks(List<IvtShafttubeivtDO> points) {
|
||||
for (IvtShafttubeivtDO point : points) {
|
||||
ivtShafttubeivtMapper.releaseDeviceLock(point.getPointCode());
|
||||
}
|
||||
}
|
||||
|
||||
private AutoSleeveTaskContext buildTubeContext(IvtShafttubeivtDO source, IvtShafttubeivtDO target) {
|
||||
AutoSleeveTaskContext context = new AutoSleeveTaskContext();
|
||||
context.setStage(AutoSleeveStageEnum.TUBE_CORE_TO_SLEEVE);
|
||||
context.setSourcePointCode(source.getPointCode());
|
||||
context.setTargetPointCode(target.getPointCode());
|
||||
context.setPlan(source.getPlan());
|
||||
context.setTubeCode(source.getTubeCode());
|
||||
context.setAirShaftCode(source.getQzzGeneration());
|
||||
return context;
|
||||
}
|
||||
|
||||
private AutoSleeveTaskContext buildShaftContext(IvtShafttubeivtDO tubeCoreCache,
|
||||
IvtShafttubeivtDO source,
|
||||
IvtShafttubeivtDO target) {
|
||||
AutoSleeveTaskContext context = new AutoSleeveTaskContext();
|
||||
context.setStage(AutoSleeveStageEnum.AIR_SHAFT_TO_SLEEVE);
|
||||
context.setSourcePointCode(source.getPointCode());
|
||||
context.setTargetPointCode(target.getPointCode());
|
||||
context.setPlan(tubeCoreCache.getPlan());
|
||||
context.setTubeCode(tubeCoreCache.getTubeCode());
|
||||
context.setAirShaftCode(source.getQzzGeneration());
|
||||
context.setAirShaftSize(source.getQzzSize());
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.code.nl.module.lms.service.autosleeve;
|
||||
|
||||
/**
|
||||
* 自动套轴搬运阶段。
|
||||
*/
|
||||
public enum AutoSleeveStageEnum {
|
||||
TUBE_CORE_TO_SLEEVE,
|
||||
AIR_SHAFT_TO_SLEEVE
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.code.nl.module.lms.service.autosleeve;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 自动套轴任务上下文。
|
||||
*/
|
||||
@Data
|
||||
public class AutoSleeveTaskContext {
|
||||
|
||||
private AutoSleeveStageEnum stage;
|
||||
private String sourcePointCode;
|
||||
private String targetPointCode;
|
||||
/** 1-西区,2-东区 */
|
||||
private String plan;
|
||||
private String tubeCode;
|
||||
/** 当前库存表使用 qzzGeneration 保存气涨轴编码 */
|
||||
private String airShaftCode;
|
||||
private String airShaftSize;
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package cn.code.nl.module.lms.task;
|
||||
|
||||
import cn.code.nl.framework.common.pojo.CommonResult;
|
||||
import cn.code.nl.framework.common.util.json.JsonUtils;
|
||||
import cn.code.nl.framework.execute.core.AbstractTask;
|
||||
import cn.code.nl.framework.execute.core.dto.TaskExecuteDTO;
|
||||
import cn.code.nl.module.lms.controller.pda.slittingproduction.eum.CutpointivtPointStatusEnum;
|
||||
import cn.code.nl.module.lms.dal.dataobject.btivtcutpointivt.BtIvtCutpointivtDO;
|
||||
import cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO;
|
||||
import cn.code.nl.module.lms.dal.mysql.btivtcutpointivt.BtIvtCutpointivtMapper;
|
||||
import cn.code.nl.module.lms.dal.mysql.ivtshafttubeivt.IvtShafttubeivtMapper;
|
||||
import cn.code.nl.module.lms.enums.LockStatusEnum;
|
||||
import cn.code.nl.module.lms.enums.slittingproduction.SlittingproductionHandleCodeConstants;
|
||||
import cn.code.nl.module.lms.service.autocall.AutoAirShaftStageEnum;
|
||||
import cn.code.nl.module.lms.service.autocall.AutoAirShaftTaskContext;
|
||||
import cn.code.nl.module.lms.service.autocall.AutoCallAirShaftService;
|
||||
import cn.code.nl.module.task.api.TransportTaskApi;
|
||||
import cn.code.nl.module.task.dto.TaskInfoDTO;
|
||||
import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
|
||||
import cn.code.nl.module.task.enums.AcsTaskTypeEnum;
|
||||
import cn.code.nl.module.task.enums.TaskOwnerServiceEnum;
|
||||
import cn.code.nl.module.task.enums.TaskTypeEnum;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CUT_FOIL_TRANSPORT_TASK_CREATE_FAIL;
|
||||
|
||||
/**
|
||||
* 自动子卷桁架搬运任务操作器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component(SlittingproductionHandleCodeConstants.AUTO_AIR_SHAFT_TASK)
|
||||
public class AutoAirShaftTask extends AbstractTask {
|
||||
|
||||
@Resource
|
||||
private TransportTaskApi transportTaskApi;
|
||||
@Resource
|
||||
private AutoCallAirShaftService autoCallAirShaftService;
|
||||
@Resource
|
||||
private BtIvtCutpointivtMapper btIvtCutpointivtMapper;
|
||||
@Resource
|
||||
private IvtShafttubeivtMapper ivtShafttubeivtMapper;
|
||||
|
||||
/**
|
||||
* 处理任务进入运行中后的逻辑
|
||||
*/
|
||||
@Override
|
||||
public void doHandleExecuting(TaskExecuteDTO taskExecuteDTO) {
|
||||
TaskInfoDTO task = getTaskInfo(taskExecuteDTO.getTaskId());
|
||||
AutoAirShaftTaskContext context = parseContext(task);
|
||||
log.info("自动子卷搬运任务进入运行中,taskId={},stage={}", task.getTaskId(), context.getStage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任务完成后的逻辑
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void doHandleFinish(TaskExecuteDTO taskExecuteDTO) {
|
||||
TaskInfoDTO task = getTaskInfo(taskExecuteDTO.getTaskId());
|
||||
handleFinish(parseContext(task));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任务取消后的逻辑
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void doHandleCancel(TaskExecuteDTO taskExecuteDTO) {
|
||||
TaskInfoDTO task = getTaskInfo(taskExecuteDTO.getTaskId());
|
||||
handleCancel(parseContext(task));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建桁架搬运任务
|
||||
*/
|
||||
public void createTransportTask(AutoAirShaftTaskContext context) {
|
||||
TransportTaskCreateReqDTO reqDTO = new TransportTaskCreateReqDTO();
|
||||
reqDTO.setTaskName(UUID.randomUUID().toString());
|
||||
reqDTO.setOwnerService(TaskOwnerServiceEnum.LMS.getCode());
|
||||
reqDTO.setBizType(TaskTypeEnum.AUTO_AIR_SHAFT_TASK.getCode());
|
||||
reqDTO.setBizId(context.getSubContainer());
|
||||
reqDTO.setHandleCode(SlittingproductionHandleCodeConstants.AUTO_AIR_SHAFT_TASK);
|
||||
reqDTO.setAcsTaskType(AcsTaskTypeEnum.AGV_TASK.getCode());
|
||||
reqDTO.setAgvSystemType("1");
|
||||
reqDTO.setPointCode1(context.getSourcePointCode());
|
||||
reqDTO.setPointCode2(context.getTargetPointCode());
|
||||
reqDTO.setMaterialCode(context.getSubContainer());
|
||||
reqDTO.setPriority("1");
|
||||
reqDTO.setProductArea(context.getProductArea());
|
||||
reqDTO.setIsAutoIssue("1");
|
||||
reqDTO.setIsCreateFinish(true);
|
||||
reqDTO.setTaskType(TaskTypeEnum.AUTO_AIR_SHAFT_TASK.getCode());
|
||||
reqDTO.setRequestParam(JsonUtils.toJsonString(context));
|
||||
|
||||
CommonResult<Long> result = transportTaskApi.createTransportTask(reqDTO);
|
||||
if (result == null || result.isError()) {
|
||||
log.error("创建自动子卷搬运任务失败,请求参数={},返回={}", JsonUtils.toJsonString(reqDTO), result);
|
||||
throw exception(CUT_FOIL_TRANSPORT_TASK_CREATE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行任务完成后的点位操作
|
||||
*/
|
||||
private void handleFinish(AutoAirShaftTaskContext context) {
|
||||
switch (context.getStage()) {
|
||||
case A_TO_B -> handleAToBFinish(context);
|
||||
case B_TO_C -> handleBToCFinish(context);
|
||||
case C_TO_D -> handleCToDFinish(context);
|
||||
case C_TO_E, D_TO_E -> handleToEFinish(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行任务取消后的点位操作
|
||||
*/
|
||||
private void handleCancel(AutoAirShaftTaskContext context) {
|
||||
releasePointLock(context.getSourcePointCode());
|
||||
if (context.getStage() == AutoAirShaftStageEnum.C_TO_E
|
||||
|| context.getStage() == AutoAirShaftStageEnum.D_TO_E) {
|
||||
releaseDeviceLock(context.getTargetPointCode());
|
||||
} else {
|
||||
releasePointLock(context.getTargetPointCode());
|
||||
}
|
||||
if (context.getStage() == AutoAirShaftStageEnum.A_TO_B) {
|
||||
releasePointLock(context.getReservedPointCode());
|
||||
}
|
||||
}
|
||||
|
||||
/** 释放点位锁 */
|
||||
public void releasePointLock(String pointCode) {
|
||||
btIvtCutpointivtMapper.releasePointLock(pointCode);
|
||||
}
|
||||
|
||||
/** 释放设备锁 */
|
||||
public void releaseDeviceLock(String pointCode) {
|
||||
ivtShafttubeivtMapper.releaseDeviceLock(pointCode);
|
||||
}
|
||||
|
||||
/** 完成 A 到 B,并进入 B 到 C 调度 */
|
||||
private void handleAToBFinish(AutoAirShaftTaskContext context) {
|
||||
moveToCutPoint(context, LockStatusEnum.OCCUPIED.getCode(), "A 到 B");
|
||||
autoCallAirShaftService.dispatchBToC(context);
|
||||
}
|
||||
|
||||
/** 完成 B 到 C,并校验下一段路径 */
|
||||
private void handleBToCFinish(AutoAirShaftTaskContext context) {
|
||||
moveToCutPoint(context, LockStatusEnum.OCCUPIED.getCode(), "B 到 C");
|
||||
autoCallAirShaftService.dispatchAfterBToC(context);
|
||||
}
|
||||
|
||||
/** 完成 C 到 D 的点位流转 */
|
||||
private void handleCToDFinish(AutoAirShaftTaskContext context) {
|
||||
moveToCutPoint(context, LockStatusEnum.IDLE.getCode(), "C 到 D");
|
||||
}
|
||||
|
||||
/** 完成 C 或 D 到 E 的点位流转 */
|
||||
private void handleToEFinish(AutoAirShaftTaskContext context) {
|
||||
int sourceRows = btIvtCutpointivtMapper.clearPoint(
|
||||
context.getSourcePointCode(), context.getSubContainer());
|
||||
if (sourceRows == 0) {
|
||||
IvtShafttubeivtDO device = ivtShafttubeivtMapper.selectByPointCode(context.getTargetPointCode());
|
||||
if (device != null && Objects.equals(device.getContainerName(), context.getSubContainer())) {
|
||||
log.info("到 E 任务已完成点位处理,跳过重复回调,子卷号={}", context.getSubContainer());
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("到 E 来源点库存状态不一致");
|
||||
}
|
||||
int rows = ivtShafttubeivtMapper.fillDevice(context.getTargetPointCode(),
|
||||
context.getSubContainer(), context.getGxNo());
|
||||
if (rows == 0) {
|
||||
throw new IllegalStateException("E 设备库存状态不一致");
|
||||
}
|
||||
}
|
||||
|
||||
/** 将子卷从来源点移动到 A 至 D 目标点 */
|
||||
private void moveToCutPoint(AutoAirShaftTaskContext context, String targetLockStatus, String stageName) {
|
||||
int sourceRows = btIvtCutpointivtMapper.clearPoint(
|
||||
context.getSourcePointCode(), context.getSubContainer());
|
||||
if (sourceRows == 0) {
|
||||
if (isTargetFilled(context)) {
|
||||
log.info("{} 任务已完成点位处理,跳过重复回调,子卷号={}", stageName, context.getSubContainer());
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException(stageName + " 来源点库存状态不一致");
|
||||
}
|
||||
int targetRows = btIvtCutpointivtMapper.fillPoint(
|
||||
context.getTargetPointCode(), context.getQzzNo(), context.getGxNo(),
|
||||
context.getSubContainer(), CutpointivtPointStatusEnum.HAS_SUB_ROLL.getCode(), targetLockStatus);
|
||||
if (targetRows == 0) {
|
||||
throw new IllegalStateException(stageName + " 目标点库存状态不一致");
|
||||
}
|
||||
}
|
||||
|
||||
/** 判断目标点是否已经写入当前子卷 */
|
||||
private boolean isTargetFilled(AutoAirShaftTaskContext context) {
|
||||
BtIvtCutpointivtDO point = btIvtCutpointivtMapper.selectByPointCode(context.getTargetPointCode());
|
||||
return point != null
|
||||
&& Objects.equals(point.getPointStatus(), CutpointivtPointStatusEnum.HAS_SUB_ROLL.getCode())
|
||||
&& Objects.equals(point.getSubContainer(), context.getSubContainer());
|
||||
}
|
||||
|
||||
/** 查询任务全量信息 */
|
||||
private TaskInfoDTO getTaskInfo(Long taskId) {
|
||||
CommonResult<TaskInfoDTO> result = transportTaskApi.getTaskById(taskId);
|
||||
if (result == null || result.isError() || result.getData() == null) {
|
||||
log.error("查询自动子卷搬运任务失败,taskId={},返回={}", taskId, result);
|
||||
throw new IllegalStateException("自动子卷搬运任务不存在");
|
||||
}
|
||||
return result.getData();
|
||||
}
|
||||
|
||||
/** 解析任务上下文 */
|
||||
private AutoAirShaftTaskContext parseContext(TaskInfoDTO task) {
|
||||
AutoAirShaftTaskContext context = JsonUtils.parseObject(task.getRequestParam(), AutoAirShaftTaskContext.class);
|
||||
if (context == null || context.getStage() == null || context.getSourcePointCode() == null
|
||||
|| context.getTargetPointCode() == null || context.getSubContainer() == null) {
|
||||
throw new IllegalStateException("自动子卷搬运任务点位参数不完整");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package cn.code.nl.module.lms.task;
|
||||
|
||||
import cn.code.nl.framework.common.pojo.CommonResult;
|
||||
import cn.code.nl.framework.common.util.json.JsonUtils;
|
||||
import cn.code.nl.framework.execute.core.AbstractTask;
|
||||
import cn.code.nl.framework.execute.core.dto.TaskExecuteDTO;
|
||||
import cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO;
|
||||
import cn.code.nl.module.lms.dal.mysql.ivtshafttubeivt.IvtShafttubeivtMapper;
|
||||
import cn.code.nl.module.lms.enums.slittingproduction.SlittingproductionHandleCodeConstants;
|
||||
import cn.code.nl.module.lms.service.autosleeve.AutoSleeveStageEnum;
|
||||
import cn.code.nl.module.lms.service.autosleeve.AutoSleeveTaskContext;
|
||||
import cn.code.nl.module.task.api.TransportTaskApi;
|
||||
import cn.code.nl.module.task.dto.TaskInfoDTO;
|
||||
import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
|
||||
import cn.code.nl.module.task.enums.AcsTaskTypeEnum;
|
||||
import cn.code.nl.module.task.enums.TaskOwnerServiceEnum;
|
||||
import cn.code.nl.module.task.enums.TaskTypeEnum;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CUT_FOIL_TRANSPORT_TASK_CREATE_FAIL;
|
||||
|
||||
/**
|
||||
* 自动套轴桁架任务状态处理器。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component(SlittingproductionHandleCodeConstants.AUTO_SLEEVE_TASK)
|
||||
public class AutoSleeveTask extends AbstractTask {
|
||||
|
||||
@Resource
|
||||
private TransportTaskApi transportTaskApi;
|
||||
@Resource
|
||||
private IvtShafttubeivtMapper ivtShafttubeivtMapper;
|
||||
|
||||
@Override
|
||||
public void doHandleExecuting(TaskExecuteDTO taskExecuteDTO) {
|
||||
AutoSleeveTaskContext context = getContext(taskExecuteDTO.getTaskId());
|
||||
log.info("自动套轴任务进入运行中,taskId={},stage={}", taskExecuteDTO.getTaskId(), context.getStage());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void doHandleFinish(TaskExecuteDTO taskExecuteDTO) {
|
||||
AutoSleeveTaskContext context = getContext(taskExecuteDTO.getTaskId());
|
||||
if (context.getStage() == AutoSleeveStageEnum.TUBE_CORE_TO_SLEEVE) {
|
||||
finishTubeCoreTask(context);
|
||||
} else {
|
||||
finishAirShaftTask(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHandleCancel(TaskExecuteDTO taskExecuteDTO) {
|
||||
AutoSleeveTaskContext context = getContext(taskExecuteDTO.getTaskId());
|
||||
ivtShafttubeivtMapper.releaseDeviceLock(context.getSourcePointCode());
|
||||
ivtShafttubeivtMapper.releaseDeviceLock(context.getTargetPointCode());
|
||||
}
|
||||
|
||||
/** 创建单条桁架搬运任务。 */
|
||||
public void createTransportTask(AutoSleeveTaskContext context) {
|
||||
String materialCode = context.getStage() == AutoSleeveStageEnum.TUBE_CORE_TO_SLEEVE
|
||||
? context.getTubeCode() : context.getAirShaftCode();
|
||||
TransportTaskCreateReqDTO reqDTO = new TransportTaskCreateReqDTO();
|
||||
reqDTO.setTaskName(UUID.randomUUID().toString());
|
||||
reqDTO.setOwnerService(TaskOwnerServiceEnum.LMS.getCode());
|
||||
reqDTO.setBizType(TaskTypeEnum.AUTO_SLEEVE_TASK.getCode());
|
||||
reqDTO.setBizId(materialCode);
|
||||
reqDTO.setHandleCode(SlittingproductionHandleCodeConstants.AUTO_SLEEVE_TASK);
|
||||
reqDTO.setAcsTaskType(AcsTaskTypeEnum.TRUSS_TASK.getCode());
|
||||
reqDTO.setAgvSystemType("1");
|
||||
reqDTO.setPointCode1(context.getSourcePointCode());
|
||||
reqDTO.setPointCode2(context.getTargetPointCode());
|
||||
reqDTO.setMaterialCode(materialCode);
|
||||
reqDTO.setPriority("1");
|
||||
reqDTO.setProductArea(context.getPlan());
|
||||
reqDTO.setIsAutoIssue("1");
|
||||
reqDTO.setIsCreateFinish(true);
|
||||
reqDTO.setTaskType(TaskTypeEnum.AUTO_SLEEVE_TASK.getCode());
|
||||
reqDTO.setRequestParam(JsonUtils.toJsonString(context));
|
||||
CommonResult<Long> result = transportTaskApi.createTransportTask(reqDTO);
|
||||
if (result == null || result.isError()) {
|
||||
log.error("创建自动套轴任务失败,请求参数={},返回={}", JsonUtils.toJsonString(reqDTO), result);
|
||||
throw exception(CUT_FOIL_TRANSPORT_TASK_CREATE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
private void finishTubeCoreTask(AutoSleeveTaskContext context) {
|
||||
int sourceRows = ivtShafttubeivtMapper.clearTubeCore(
|
||||
context.getSourcePointCode(), context.getTubeCode());
|
||||
if (sourceRows == 0 && isTubeTargetFilled(context)) {
|
||||
return;
|
||||
}
|
||||
if (sourceRows == 0 || ivtShafttubeivtMapper.fillSleeveTubeCore(
|
||||
context.getTargetPointCode(), context.getTubeCode()) == 0) {
|
||||
throw new IllegalStateException("自动套轴管芯点位库存状态不一致");
|
||||
}
|
||||
}
|
||||
|
||||
private void finishAirShaftTask(AutoSleeveTaskContext context) {
|
||||
int sourceRows = ivtShafttubeivtMapper.clearAirShaft(
|
||||
context.getSourcePointCode(), context.getAirShaftCode());
|
||||
if (sourceRows == 0 && isShaftTargetFilled(context)) {
|
||||
return;
|
||||
}
|
||||
if (sourceRows == 0 || ivtShafttubeivtMapper.fillSleeveAirShaft(
|
||||
context.getTargetPointCode(), context.getAirShaftCode(), context.getAirShaftSize()) == 0) {
|
||||
throw new IllegalStateException("自动套轴气涨轴点位库存状态不一致");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isTubeTargetFilled(AutoSleeveTaskContext context) {
|
||||
IvtShafttubeivtDO target = ivtShafttubeivtMapper.selectByPointCode(context.getTargetPointCode());
|
||||
return target != null && Objects.equals(target.getTubeCode(), context.getTubeCode());
|
||||
}
|
||||
|
||||
private boolean isShaftTargetFilled(AutoSleeveTaskContext context) {
|
||||
IvtShafttubeivtDO target = ivtShafttubeivtMapper.selectByPointCode(context.getTargetPointCode());
|
||||
return target != null && Objects.equals(target.getQzzGeneration(), context.getAirShaftCode());
|
||||
}
|
||||
|
||||
private AutoSleeveTaskContext getContext(Long taskId) {
|
||||
CommonResult<TaskInfoDTO> result = transportTaskApi.getTaskById(taskId);
|
||||
if (result == null || result.isError() || result.getData() == null) {
|
||||
throw new IllegalStateException("自动套轴任务不存在");
|
||||
}
|
||||
AutoSleeveTaskContext context = JsonUtils.parseObject(
|
||||
result.getData().getRequestParam(), AutoSleeveTaskContext.class);
|
||||
if (context == null || context.getStage() == null || context.getSourcePointCode() == null
|
||||
|| context.getTargetPointCode() == null) {
|
||||
throw new IllegalStateException("自动套轴任务点位参数不完整");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.code.nl.module.lms.dal.mysql.btivtcutpointivt.BtIvtCutpointivtMapper">
|
||||
|
||||
<select id="selectByPointCode"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.btivtcutpointivt.BtIvtCutpointivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_cutpointivt
|
||||
WHERE point_code = #{pointCode}
|
||||
AND deleted = 0
|
||||
</select>
|
||||
|
||||
<select id="selectAvailablePoints"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.btivtcutpointivt.BtIvtCutpointivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_cutpointivt
|
||||
WHERE point_type = #{pointType}
|
||||
AND point_status = #{pointStatus}
|
||||
<if test="productArea != null and productArea != ''">
|
||||
AND product_area = #{productArea}
|
||||
</if>
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
ORDER BY ivt_id DESC
|
||||
</select>
|
||||
|
||||
<update id="lockPointIfAvailable">
|
||||
UPDATE bst_ivt_cutpointivt
|
||||
SET lock_status = '1'
|
||||
WHERE ivt_id = #{ivtId}
|
||||
AND point_status = #{pointStatus}
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="lockPointsIfAvailable">
|
||||
UPDATE bst_ivt_cutpointivt
|
||||
SET lock_status = '1'
|
||||
WHERE ivt_id IN
|
||||
<foreach collection="ivtIds" item="ivtId" open="(" separator="," close=")">
|
||||
#{ivtId}
|
||||
</foreach>
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="releasePointLock">
|
||||
UPDATE bst_ivt_cutpointivt
|
||||
SET lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="clearPoint">
|
||||
UPDATE bst_ivt_cutpointivt
|
||||
SET qzz_no = NULL,
|
||||
gx_no = NULL,
|
||||
sub_container = NULL,
|
||||
point_status = '0',
|
||||
lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND sub_container = #{subContainer}
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="fillPoint">
|
||||
UPDATE bst_ivt_cutpointivt
|
||||
SET qzz_no = #{qzzNo},
|
||||
gx_no = #{gxNo},
|
||||
sub_container = #{subContainer},
|
||||
point_status = #{pointStatus},
|
||||
lock_status = #{lockStatus}
|
||||
WHERE point_code = #{pointCode}
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.code.nl.module.lms.dal.mysql.ivtshafttubeivt.IvtShafttubeivtMapper">
|
||||
|
||||
<select id="selectByPointCode"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_shafttubeivt
|
||||
WHERE point_code = #{pointCode}
|
||||
AND deleted = 0
|
||||
</select>
|
||||
|
||||
<select id="selectIdleDevices"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_shafttubeivt
|
||||
WHERE (container_name IS NULL OR container_name = '')
|
||||
AND have_qzz = '0'
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
ORDER BY ivt_id DESC
|
||||
</select>
|
||||
|
||||
<update id="lockIdleDevice">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET lock_status = '1'
|
||||
WHERE ivt_id = #{ivtId}
|
||||
AND (container_name IS NULL OR container_name = '')
|
||||
AND have_qzz = '0'
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="releaseDeviceLock">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="fillDevice">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET container_name = #{containerName},
|
||||
tube_code = #{tubeCode},
|
||||
have_qzz = '1',
|
||||
lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<select id="selectTubeCoreCaches"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_shafttubeivt
|
||||
WHERE point_type = #{pointType}
|
||||
AND tube_code IS NOT NULL
|
||||
AND tube_code != ''
|
||||
AND qzz_generation IS NOT NULL
|
||||
AND qzz_generation != ''
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
ORDER BY sort_seq, ivt_id
|
||||
</select>
|
||||
|
||||
<select id="selectEmptyPoints"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_shafttubeivt
|
||||
WHERE point_type = #{pointType}
|
||||
AND plan = #{plan}
|
||||
AND (tube_code IS NULL OR tube_code = '')
|
||||
AND (qzz_generation IS NULL OR qzz_generation = '')
|
||||
AND (container_name IS NULL OR container_name = '')
|
||||
AND (have_qzz IS NULL OR have_qzz = '' OR have_qzz = '0')
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
ORDER BY sort_seq, ivt_id
|
||||
</select>
|
||||
|
||||
<select id="selectAirShaftCache"
|
||||
resultType="cn.code.nl.module.lms.dal.dataobject.ivtshafttubeivt.IvtShafttubeivtDO">
|
||||
SELECT *
|
||||
FROM bst_ivt_shafttubeivt
|
||||
WHERE point_type = #{pointType}
|
||||
AND qzz_generation = #{airShaftCode}
|
||||
AND have_qzz = '1'
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
ORDER BY sort_seq, ivt_id
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<update id="lockInventoryPoint">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET lock_status = '1'
|
||||
WHERE ivt_id = #{ivtId}
|
||||
AND lock_status = '0'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="clearTubeCore">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET tube_code = NULL,
|
||||
tube_name = NULL,
|
||||
qzz_generation = NULL,
|
||||
lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND tube_code = #{tubeCode}
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="fillSleeveTubeCore">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET tube_code = #{tubeCode},
|
||||
lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND (tube_code IS NULL OR tube_code = '')
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="clearAirShaft">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET qzz_size = NULL,
|
||||
qzz_generation = NULL,
|
||||
have_qzz = '0',
|
||||
lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND qzz_generation = #{airShaftCode}
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="fillSleeveAirShaft">
|
||||
UPDATE bst_ivt_shafttubeivt
|
||||
SET qzz_size = #{airShaftSize},
|
||||
qzz_generation = #{airShaftCode},
|
||||
have_qzz = '1',
|
||||
lock_status = '0'
|
||||
WHERE point_code = #{pointCode}
|
||||
AND (qzz_generation IS NULL OR qzz_generation = '')
|
||||
AND lock_status = '1'
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.code.nl.module.system.job.slitter;
|
||||
|
||||
import cn.code.nl.framework.tenant.core.job.TenantJob;
|
||||
import cn.code.nl.module.lms.api.AutoCallAirShaftApi;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* C、D 点子卷自动搬运至 E 点任务
|
||||
*/
|
||||
@Component
|
||||
public class AutoCallAirShaftToDeviceTask {
|
||||
|
||||
/** 自动子卷搬运 RPC */
|
||||
@Resource
|
||||
private AutoCallAirShaftApi autoCallAirShaftApi;
|
||||
|
||||
/**
|
||||
* 执行 C、D 到 E 自动搬运调度,优先处理 C 点子卷
|
||||
*/
|
||||
@XxlJob("autoCallAirShaftToDeviceTask")
|
||||
@TenantJob
|
||||
public void execute() {
|
||||
autoCallAirShaftApi.executeAutoCallAirShaftToDevice().getCheckedData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.code.nl.module.system.job.slitter;
|
||||
|
||||
import cn.code.nl.framework.tenant.core.job.TenantJob;
|
||||
import cn.code.nl.module.lms.api.AutoCallAirShaftApi;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 自动套轴定时任务。
|
||||
*/
|
||||
@Component
|
||||
public class AutoSleeveScheduledTask {
|
||||
|
||||
@Resource
|
||||
private AutoCallAirShaftApi autoCallAirShaftApi;
|
||||
|
||||
/**
|
||||
* 轮询管芯缓存位并创建管芯、气涨轴配套搬运任务。
|
||||
*/
|
||||
@XxlJob("autoSleeveScheduledTask")
|
||||
@TenantJob
|
||||
public void execute() {
|
||||
autoCallAirShaftApi.executeAutoSleeve().getCheckedData();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
78
sql/mysql/lms_slitting_management_menu.sql
Normal file
78
sql/mysql/lms_slitting_management_menu.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
-- 将四个分切业务菜单归并到“分切管理”目录。脚本可重复执行。
|
||||
START TRANSACTION;
|
||||
|
||||
SET @lms_menu_id = (
|
||||
SELECT id
|
||||
FROM system_menu
|
||||
WHERE name = 'LMS管理'
|
||||
AND type = 1
|
||||
AND deleted = b'0'
|
||||
LIMIT 1
|
||||
);
|
||||
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component,
|
||||
component_name, status, visible, keep_alive, always_show,
|
||||
creator, create_time, updater, update_time, deleted)
|
||||
SELECT 6863, '分切管理', '', 1, 5, @lms_menu_id, 'slitting-management',
|
||||
'carbon:category', NULL, NULL, 0, b'1', b'1', b'1',
|
||||
'1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @lms_menu_id IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM system_menu
|
||||
WHERE parent_id = @lms_menu_id
|
||||
AND path = 'slitting-management'
|
||||
AND type = 1
|
||||
AND deleted = b'0'
|
||||
);
|
||||
|
||||
SET @slitting_menu_id = (
|
||||
SELECT id
|
||||
FROM system_menu
|
||||
WHERE parent_id = @lms_menu_id
|
||||
AND path = 'slitting-management'
|
||||
AND type = 1
|
||||
AND deleted = b'0'
|
||||
LIMIT 1
|
||||
);
|
||||
|
||||
-- 为原本拥有任一子菜单的角色补充分切管理父目录权限。
|
||||
INSERT INTO system_role_menu
|
||||
(role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
SELECT DISTINCT role_menu.role_id, @slitting_menu_id, '1', NOW(), '1', NOW(), b'0', role_menu.tenant_id
|
||||
FROM system_role_menu role_menu
|
||||
WHERE role_menu.menu_id IN (6826, 6839, 6845, 6851)
|
||||
AND role_menu.deleted = b'0'
|
||||
AND @slitting_menu_id IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM system_role_menu parent_role_menu
|
||||
WHERE parent_role_menu.role_id = role_menu.role_id
|
||||
AND parent_role_menu.menu_id = @slitting_menu_id
|
||||
AND parent_role_menu.tenant_id = role_menu.tenant_id
|
||||
AND parent_role_menu.deleted = b'0'
|
||||
);
|
||||
|
||||
UPDATE system_menu
|
||||
SET parent_id = @slitting_menu_id,
|
||||
sort = CASE name
|
||||
WHEN '分切区点位库存管理' THEN 1
|
||||
WHEN '穿拔轴区点位库存管理' THEN 2
|
||||
WHEN '分切区缓存点位库存管理' THEN 3
|
||||
WHEN '分切生产计划管理' THEN 4
|
||||
END,
|
||||
updater = '1',
|
||||
update_time = NOW()
|
||||
WHERE type = 2
|
||||
AND deleted = b'0'
|
||||
AND name IN (
|
||||
'分切区点位库存管理',
|
||||
'穿拔轴区点位库存管理',
|
||||
'分切区缓存点位库存管理',
|
||||
'分切生产计划管理'
|
||||
)
|
||||
AND parent_id IN (@lms_menu_id, @slitting_menu_id)
|
||||
AND @slitting_menu_id IS NOT NULL;
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user