add:自动送子卷任务,自动套轴任务,自动拔轴未提交的代码

This commit is contained in:
ls
2026-08-25 14:50:25 +08:00
parent 73b5a86cc0
commit 6d20b34023
24 changed files with 1418 additions and 0 deletions

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,11 @@
package cn.code.nl.module.lms.controller.pda.slittingproduction.eum;
/**
* 分切区缓存点位生产区域枚举
*/
public enum CutpointivtProductAreaEnum {
A1,
A2,
A
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,10 @@
package cn.code.nl.module.lms.service.autosleeve;
/**
* 自动套轴调度 Service。
*/
public interface AutoSleeveService {
/** 轮询管芯缓存位并创建配套搬运任务。 */
void execute();
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,9 @@
package cn.code.nl.module.lms.service.autosleeve;
/**
* 自动套轴搬运阶段。
*/
public enum AutoSleeveStageEnum {
TUBE_CORE_TO_SLEEVE,
AIR_SHAFT_TO_SLEEVE
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View 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;