开发移库任务
This commit is contained in:
parent
e2f46b2978
commit
7ed63a7388
@ -195,6 +195,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode TASK_CHECK_TASK_PRIORITY = new ErrorCode(1-002-035-007, "非新单据不能修改优先级");
|
||||
ErrorCode TASK_CHECK_TASK_STATUS = new ErrorCode(1-002-035-100, "订单已完成");
|
||||
ErrorCode TASK_CHECK_UPDATE_STATUS = new ErrorCode(1-002-035-101, "订单更新失败");
|
||||
ErrorCode TASK_CHECK_EXIST_NO = new ErrorCode(1-002-035-102, "订单号已存在");
|
||||
|
||||
// ========== 机器人任务明细 1-002-036-000 ==========
|
||||
ErrorCode TASK_DETAIL_NOT_EXISTS = new ErrorCode(1-002-036-001, "机器人任务明细不存在");
|
||||
@ -213,4 +214,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_LINE_WAREHOUSES = new ErrorCode(1_002_038_007, "已有库位在其他线库内");
|
||||
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_STORAGE_AREAS = new ErrorCode(1_002_038_008, "已有库位在其他库区内");
|
||||
|
||||
// ========== 机器人自动移库 1-002-039-000 ==========
|
||||
ErrorCode TASK_AUTO_MOVE_NOT_EXISTS = new ErrorCode(1_002_039_001, "机器人自动移库不存在");
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMovePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMoveRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMoveSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskAutoMoveDO;
|
||||
import cn.iocoder.yudao.module.system.service.robot.job.RobotTaskAutoMoveService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
|
||||
@Tag(name = "管理后台 - 机器人自动移库")
|
||||
@RestController
|
||||
@RequestMapping("/robot/task-auto-move")
|
||||
@Validated
|
||||
public class RobotTaskAutoMoveController {
|
||||
|
||||
@Resource
|
||||
private RobotTaskAutoMoveService taskAutoMoveService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建机器人自动移库")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-auto-move:create')")
|
||||
public CommonResult<Long> createTaskAutoMove(@Valid @RequestBody RobotTaskAutoMoveSaveReqVO createReqVO) {
|
||||
return success(taskAutoMoveService.createTaskAutoMove(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新机器人自动移库")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-auto-move:update')")
|
||||
public CommonResult<Boolean> updateTaskAutoMove(@Valid @RequestBody RobotTaskAutoMoveSaveReqVO updateReqVO) {
|
||||
taskAutoMoveService.updateTaskAutoMove(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除机器人自动移库")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-auto-move:delete')")
|
||||
public CommonResult<Boolean> deleteTaskAutoMove(@RequestParam("id") Long id) {
|
||||
taskAutoMoveService.deleteTaskAutoMove(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得机器人自动移库")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-auto-move:query')")
|
||||
public CommonResult<RobotTaskAutoMoveRespVO> getTaskAutoMove(@RequestParam("id") Long id) {
|
||||
RobotTaskAutoMoveDO taskAutoMove = taskAutoMoveService.getTaskAutoMove(id);
|
||||
return success(BeanUtils.toBean(taskAutoMove, RobotTaskAutoMoveRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得机器人自动移库分页")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-auto-move:query')")
|
||||
public CommonResult<PageResult<RobotTaskAutoMoveRespVO>> getTaskAutoMovePage(@Valid RobotTaskAutoMovePageReqVO pageReqVO) {
|
||||
PageResult<RobotTaskAutoMoveDO> pageResult = taskAutoMoveService.getTaskAutoMovePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, RobotTaskAutoMoveRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出机器人自动移库 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-auto-move:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportTaskAutoMoveExcel(@Valid RobotTaskAutoMovePageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<RobotTaskAutoMoveDO> list = taskAutoMoveService.getTaskAutoMovePage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "机器人自动移库.xls", "数据", RobotTaskAutoMoveRespVO.class,
|
||||
BeanUtils.toBean(list, RobotTaskAutoMoveRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 机器人自动移库分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class RobotTaskAutoMovePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "机器人任务主表id", example = "24553")
|
||||
private Long robotTaskId;
|
||||
|
||||
@Schema(description = "机器人任务明细表id", example = "11392")
|
||||
private Long robotTaskDetailId;
|
||||
|
||||
@Schema(description = "原库位编号")
|
||||
private String fromLocationNo;
|
||||
|
||||
@Schema(description = "原库位id", example = "8838")
|
||||
private Long fromLocationId;
|
||||
|
||||
@Schema(description = "搬去的目标库位编号")
|
||||
private String toLocationNo;
|
||||
|
||||
@Schema(description = "搬去的目标库位id/停车点/充电点/移动终点", example = "19168")
|
||||
private Long toLocationId;
|
||||
|
||||
@Schema(description = "任务状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)", example = "1")
|
||||
private Integer taskStatus;
|
||||
|
||||
@Schema(description = "取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id(目前设计不会用到此字段)")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "优先级")
|
||||
private Long priority;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
private String robotNo;
|
||||
|
||||
@Schema(description = "任务类型(1:自动移库、 )", example = "2")
|
||||
private Integer taskType;
|
||||
|
||||
@Schema(description = "移动类型(1:去、 2:回)", example = "2")
|
||||
private Integer moveType;
|
||||
|
||||
@Schema(description = "开始时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] startTime;
|
||||
|
||||
@Schema(description = "结束时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] endTime;
|
||||
|
||||
@Schema(description = "robot_task_auto_move表id,来回搬运需要记录上一次搬运的源库位", example = "32231")
|
||||
private Long taskAutoMoveId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 机器人自动移库 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class RobotTaskAutoMoveRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30110")
|
||||
@ExcelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "机器人任务主表id", example = "24553")
|
||||
@ExcelProperty("机器人任务主表id")
|
||||
private Long robotTaskId;
|
||||
|
||||
@Schema(description = "机器人任务明细表id", example = "11392")
|
||||
@ExcelProperty("机器人任务明细表id")
|
||||
private Long robotTaskDetailId;
|
||||
|
||||
@Schema(description = "原库位编号")
|
||||
@ExcelProperty("原库位编号")
|
||||
private String fromLocationNo;
|
||||
|
||||
@Schema(description = "原库位id", example = "8838")
|
||||
@ExcelProperty("原库位id")
|
||||
private Long fromLocationId;
|
||||
|
||||
@Schema(description = "搬去的目标库位编号")
|
||||
@ExcelProperty("搬去的目标库位编号")
|
||||
private String toLocationNo;
|
||||
|
||||
@Schema(description = "搬去的目标库位id/停车点/充电点/移动终点", example = "19168")
|
||||
@ExcelProperty("搬去的目标库位id/停车点/充电点/移动终点")
|
||||
private Long toLocationId;
|
||||
|
||||
@Schema(description = "取货线库id")
|
||||
@ExcelProperty("取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id(目前设计不会用到此字段)")
|
||||
@ExcelProperty("放货线库id(目前设计不会用到此字段)")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "任务状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)", example = "1")
|
||||
@ExcelProperty("任务状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)")
|
||||
private Integer taskStatus;
|
||||
|
||||
@Schema(description = "优先级")
|
||||
@ExcelProperty("优先级")
|
||||
private Long priority;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
@ExcelProperty("AGV编号")
|
||||
private String robotNo;
|
||||
|
||||
@Schema(description = "任务类型(1:自动移库、 )", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("任务类型(1:自动移库、 )")
|
||||
private Integer taskType;
|
||||
|
||||
@Schema(description = "移动类型(1:去、 2:回)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("移动类型(1:去、 2:回)")
|
||||
private Integer moveType;
|
||||
|
||||
@Schema(description = "开始时间")
|
||||
@ExcelProperty("开始时间")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "结束时间")
|
||||
@ExcelProperty("结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "robot_task_auto_move表id,来回搬运需要记录上一次搬运的源库位", example = "32231")
|
||||
@ExcelProperty("robot_task_auto_move表id,来回搬运需要记录上一次搬运的源库位")
|
||||
private Long taskAutoMoveId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 机器人自动移库新增/修改 Request VO")
|
||||
@Data
|
||||
public class RobotTaskAutoMoveSaveReqVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30110")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "机器人任务主表id", example = "24553")
|
||||
private Long robotTaskId;
|
||||
|
||||
@Schema(description = "机器人任务明细表id", example = "11392")
|
||||
private Long robotTaskDetailId;
|
||||
|
||||
@Schema(description = "原库位编号")
|
||||
private String fromLocationNo;
|
||||
|
||||
@Schema(description = "原库位id", example = "8838")
|
||||
private Long fromLocationId;
|
||||
|
||||
@Schema(description = "搬去的目标库位编号")
|
||||
private String toLocationNo;
|
||||
|
||||
@Schema(description = "取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id(目前设计不会用到此字段)")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "搬去的目标库位id/停车点/充电点/移动终点", example = "19168")
|
||||
private Long toLocationId;
|
||||
|
||||
@Schema(description = "任务状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)", example = "1")
|
||||
private Integer taskStatus;
|
||||
|
||||
@Schema(description = "优先级")
|
||||
private Long priority;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
private String robotNo;
|
||||
|
||||
@Schema(description = "任务类型(1:自动移库、 )", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "任务类型(1:自动移库、 )不能为空")
|
||||
private Integer taskType;
|
||||
|
||||
@Schema(description = "移动类型(1:去、 2:回)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "移动类型(1:去、 2:回)不能为空")
|
||||
private Integer moveType;
|
||||
|
||||
@Schema(description = "开始时间")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "robot_task_auto_move表id,来回搬运需要记录上一次搬运的源库位", example = "32231")
|
||||
private Long taskAutoMoveId;
|
||||
|
||||
}
|
@ -37,6 +37,15 @@ public class RobotTaskDetailAddVO {
|
||||
@Schema(description = "所选车辆电量(充电模式)")
|
||||
private Integer electricity;
|
||||
|
||||
@Schema(description = "取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "取货库位的排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "计算后的来源库位编号(前端不用传此字段)")
|
||||
private String fromLocationNo;
|
||||
@Schema(description = "计算后的来源库位id(前端不用传此字段)")
|
||||
|
@ -46,6 +46,14 @@ public class RobotTaskDetailPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "AGV动作")
|
||||
private String robotAction;
|
||||
@Schema(description = "取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "取货库位的排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "任务状态(0:未开始、1:执行中、2:已完成、3:已取消)", example = "1")
|
||||
private Integer taskStatus;
|
||||
|
@ -78,6 +78,18 @@ public class RobotTaskDetailRespVO {
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "取货线库id")
|
||||
@ExcelProperty("取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id")
|
||||
@ExcelProperty("放货线库id")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "取货库位的排序的位置,越大越优先堆放")
|
||||
@ExcelProperty("取货库位的排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "取货层数")
|
||||
@ExcelProperty("取货层数")
|
||||
private Integer fromLocationStorey;
|
||||
|
@ -38,6 +38,15 @@ public class RobotTaskDetailSaveReqVO {
|
||||
@NotNull(message = "取货库位/线库/区域不能为空")
|
||||
private Long takeId;
|
||||
|
||||
@Schema(description = "取货线库id")
|
||||
private Long fromLaneId;
|
||||
|
||||
@Schema(description = "放货线库id")
|
||||
private Long toLaneId;
|
||||
|
||||
@Schema(description = "取货库位的排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "计算后的来源库位编号")
|
||||
private String fromLocationNo;
|
||||
@Schema(description = "计算后的来源库位id")
|
||||
|
@ -0,0 +1,98 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.robot;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 机器人自动移库 DO
|
||||
*
|
||||
* @author 陈宾顺
|
||||
*/
|
||||
@TableName("robot_task_auto_move")
|
||||
@KeySequence("robot_task_auto_move_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RobotTaskAutoMoveDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/**
|
||||
* 机器人任务主表id
|
||||
*/
|
||||
private Long robotTaskId;
|
||||
/**
|
||||
* 机器人任务明细表id
|
||||
*/
|
||||
private Long robotTaskDetailId;
|
||||
/**
|
||||
* 原库位编号
|
||||
*/
|
||||
private String fromLocationNo;
|
||||
/**
|
||||
* 原库位id
|
||||
*/
|
||||
private Long fromLocationId;
|
||||
/**
|
||||
* 搬去的目标库位编号
|
||||
*/
|
||||
private String toLocationNo;
|
||||
/**
|
||||
* 搬去的目标库位id/停车点/充电点/移动终点
|
||||
*/
|
||||
private Long toLocationId;
|
||||
/**
|
||||
* 取货线库id
|
||||
*/
|
||||
private Long fromLaneId;
|
||||
/**
|
||||
* 放货线库id (目前设计不会用到此字段)
|
||||
*/
|
||||
private Long toLaneId;
|
||||
/**
|
||||
* 任务状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)
|
||||
*/
|
||||
private Integer taskStatus;
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
private Long priority;
|
||||
/**
|
||||
* AGV编号
|
||||
*/
|
||||
private String robotNo;
|
||||
/**
|
||||
* 任务类型(1:自动移库、 )
|
||||
*/
|
||||
private Integer taskType;
|
||||
/**
|
||||
* 移动类型(1:去、 2:回)
|
||||
*/
|
||||
private Integer moveType;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
/**
|
||||
* robot_task_auto_move表id,来回搬运需要记录上一次搬运的源库位
|
||||
*/
|
||||
private Long taskAutoMoveId;
|
||||
|
||||
}
|
@ -59,6 +59,18 @@ public class RobotTaskDetailDO extends BaseDO {
|
||||
* 计算后的来源库位id
|
||||
*/
|
||||
private Long fromLocationId;
|
||||
/**
|
||||
* 取货线库id
|
||||
*/
|
||||
private Long fromLaneId;
|
||||
/**
|
||||
* 放货线库id
|
||||
*/
|
||||
private Long toLaneId;
|
||||
/**
|
||||
* 取货库位的排序的位置,越大越优先堆放
|
||||
*/
|
||||
private Long locationNumber;
|
||||
/**
|
||||
* 计算后的目标库位编号
|
||||
*/
|
||||
|
@ -73,14 +73,6 @@ public interface WareHouseLocationMapper extends BaseMapperX<WareHouseLocationDO
|
||||
*/
|
||||
WareHouseLocationDO queryAllByLimit(WareHouseLocationDO wareHouseLocationDO);
|
||||
|
||||
/**
|
||||
* 更新库位锁定状态
|
||||
* @param id
|
||||
* @param locationLock
|
||||
*/
|
||||
void updateLocationLockStatus(@Param("id") Long id,
|
||||
@Param("locationLock") int locationLock,
|
||||
@Param("taskId") Long taskId);
|
||||
|
||||
/**
|
||||
* 查询库位
|
||||
@ -102,4 +94,18 @@ public interface WareHouseLocationMapper extends BaseMapperX<WareHouseLocationDO
|
||||
* @return
|
||||
*/
|
||||
List<WareHouseLocationRespVO> getLocationByName(WareHouseLocationVO requestVO);
|
||||
|
||||
/**
|
||||
* 查询相通的线库 且 有货的 排序的位置较小的库位
|
||||
* @param locations
|
||||
* @return
|
||||
*/
|
||||
List<WareHouseLocationDO> selectLocationByList(@Param("locations") List<WareHouseLocationDO> locations);
|
||||
|
||||
/**
|
||||
* 查询需要移库的库位
|
||||
* @param locationIds
|
||||
* @return
|
||||
*/
|
||||
List<WareHouseLocationDO> selectNeedMoveLocation(@Param("locationIds") Set<Long> locationIds);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.robot;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMovePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskAutoMoveDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 机器人自动移库 Mapper
|
||||
*
|
||||
* @author 陈宾顺
|
||||
*/
|
||||
@Mapper
|
||||
public interface RobotTaskAutoMoveMapper extends BaseMapperX<RobotTaskAutoMoveDO> {
|
||||
|
||||
default PageResult<RobotTaskAutoMoveDO> selectPage(RobotTaskAutoMovePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<RobotTaskAutoMoveDO>()
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getRobotTaskId, reqVO.getRobotTaskId())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getRobotTaskDetailId, reqVO.getRobotTaskDetailId())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getFromLocationNo, reqVO.getFromLocationNo())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getFromLocationId, reqVO.getFromLocationId())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getToLocationNo, reqVO.getToLocationNo())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getToLocationId, reqVO.getToLocationId())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getTaskStatus, reqVO.getTaskStatus())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getPriority, reqVO.getPriority())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getRobotNo, reqVO.getRobotNo())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getTaskType, reqVO.getTaskType())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getMoveType, reqVO.getMoveType())
|
||||
.betweenIfPresent(RobotTaskAutoMoveDO::getStartTime, reqVO.getStartTime())
|
||||
.betweenIfPresent(RobotTaskAutoMoveDO::getEndTime, reqVO.getEndTime())
|
||||
.eqIfPresent(RobotTaskAutoMoveDO::getTaskAutoMoveId, reqVO.getTaskAutoMoveId())
|
||||
.betweenIfPresent(RobotTaskAutoMoveDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(RobotTaskAutoMoveDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.system.enums.robot;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task_auto_move的task_status
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AutoMoveTaskStatusEnum {
|
||||
NEW(0),//未开始
|
||||
DOING(1),//执行中
|
||||
DONE(2),//已完成
|
||||
CLOSE(3), //已取消
|
||||
Exc(4); //异常
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.system.enums.robot;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task_auto_move的task_type
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AutoMoveTaskTypeEnum {
|
||||
|
||||
AUTO_MOVE(1); //自动移库
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.system.enums.robot;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task_auto_move的move_type
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AutoMoveTypeEnum {
|
||||
|
||||
GO(1), //去
|
||||
BACK(1); //回
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
|
||||
}
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 下发给车机的类型
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum CommandTypeEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task的do_cycle
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DoCycleEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* ware_house_location的location_enable
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LocationEnableEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* ware_house_location的location_lock
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LocationLockEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* ware_house_location的location_use_status
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LocationUseStatusEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task的montage_task
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MontageTaskEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task的do_move_all
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MoveAllEnum {
|
||||
|
@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 放货类型
|
||||
* 放货类型robot_task_detail的release_type
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.system.enums.robot;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task_auto_move表的task_status状态
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RobotMoveStatusEnum {
|
||||
NEW(0),//未开始
|
||||
DOING(1),//执行中
|
||||
DONE(2),//已完成
|
||||
CLOSE(3), //已取消
|
||||
Exc(4); //异常
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
}
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task_detail的task_status
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RobotTaskDetailStatusEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_information的robot_task_model
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RobotTaskModelEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task表的task_status
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RobotTaskStatusEnum {
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* robot_task_detail的task_type
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RobotTaskTypeEnum {
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.job.robot;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum;
|
||||
import cn.iocoder.yudao.module.system.service.robot.job.DistributeTasksService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.job.RobotTaskAutoMoveService;
|
||||
import cn.iocoder.yudao.module.system.util.redis.RedissonUtils;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -12,6 +13,12 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REDISSON_NOT_OBTAIN_LOCK;
|
||||
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@ -23,6 +30,9 @@ public class RobotJob {
|
||||
@Autowired
|
||||
private DistributeTasksService distributeTasksService;
|
||||
|
||||
@Autowired
|
||||
private RobotTaskAutoMoveService robotTaskAutoMoveService;
|
||||
|
||||
//下发任务给车机
|
||||
@XxlJob("DistributeTasksJob")
|
||||
@TenantJob
|
||||
@ -37,6 +47,32 @@ public class RobotJob {
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}else {
|
||||
log.info("下发任务未获取到锁");
|
||||
throw exception(REDISSON_NOT_OBTAIN_LOCK);
|
||||
}
|
||||
}
|
||||
|
||||
//下发自动移库任务
|
||||
@XxlJob("DistributeAutoMoveJob")
|
||||
@TenantJob
|
||||
public void distributeAutoMoveJob() throws InterruptedException {
|
||||
log.info("----下发自动移库任务----");
|
||||
Set<String> locks = new HashSet<>();
|
||||
locks.add(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
|
||||
locks.add(RobotCacheLockEnum.ROBOT_TASK_ADD_LOCK.getKey());
|
||||
RLock lock = redissonUtils.getLocks(locks);
|
||||
if (lock.tryLock()){
|
||||
try {
|
||||
robotTaskAutoMoveService.distributeAutoMoveJob();
|
||||
} catch (Exception e) {
|
||||
log.error("下发自动移库任务出现异常 :{}",e.getMessage());
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}else {
|
||||
log.info("下发自动移库任务未获取到锁");
|
||||
throw exception(REDISSON_NOT_OBTAIN_LOCK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.robot;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
|
||||
@ -93,7 +94,7 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_ADD_LOCK.getKey());
|
||||
|
||||
String addResult = "";
|
||||
if (lock.tryLock(30l,TimeUnit.MINUTES)){
|
||||
if (lock.tryLock(60l,TimeUnit.MINUTES)){
|
||||
try {
|
||||
addResult = addTask(createReqVO);
|
||||
} catch (Exception e) {
|
||||
@ -155,6 +156,14 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
throw exception0(TASK_CHECK_EXCEPTION.getCode(), "以下机器人已被禁用 ",robotNo);
|
||||
}
|
||||
}
|
||||
//校验任务号是否重复
|
||||
if (ObjectUtil.isNotEmpty(createReqVO.getTaskNo())) {
|
||||
List<RobotTaskDO> taskDOS = taskMapper.selectList(new LambdaQueryWrapperX<RobotTaskDO>()
|
||||
.eq(RobotTaskDO::getTaskNo, createReqVO.getTaskNo()));
|
||||
if (ObjectUtil.isNotEmpty(taskDOS)) {
|
||||
throw exception(TASK_CHECK_EXIST_NO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -306,6 +315,9 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
robotTaskDetailAddVo.setFromLocationId(stockList.get(i).getId());
|
||||
robotTaskDetailAddVo.setToLocationNo(releaseStockList.get(i).getLocationNo());
|
||||
robotTaskDetailAddVo.setToLocationId(releaseStockList.get(i).getId());
|
||||
robotTaskDetailAddVo.setFromLaneId(stockList.get(i).getLaneId());
|
||||
robotTaskDetailAddVo.setToLaneId(releaseStockList.get(i).getLaneId());
|
||||
robotTaskDetailAddVo.setLocationNumber(stockList.get(i).getLocationNumber());
|
||||
robotTaskDetailAddVo.setRobotTaskId(taskId);
|
||||
robotTaskDetailAddVo.setPriority(robotTaskVo.getPriority());
|
||||
robotTaskDetailAddVo.setFromLocationStorey(stockList.get(i).getLocationStorey());
|
||||
@ -399,7 +411,11 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void doTake(RobotTaskDetailAddVO robotTaskVo, List<Long> locationIds) {
|
||||
locationMapper.updateLocationLockStatus(robotTaskVo.getFromLocationId(),0,robotTaskVo.getRobotTaskId());
|
||||
Set<Long> mapIds = new HashSet<>();
|
||||
if (ObjectUtil.isNotEmpty(robotTaskVo.getRobotNo())) {
|
||||
mapIds = getMapIdsByRobotNo(robotTaskVo.getRobotNo());
|
||||
}
|
||||
setFromLocation(robotTaskVo,mapIds,locationIds);
|
||||
locationIds.add(robotTaskVo.getFromLocationId());
|
||||
}
|
||||
|
||||
@ -461,6 +477,7 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
robotTaskVo.setToLocationNo(locationDO.getLocationNo());
|
||||
robotTaskVo.setToLocationId(robotTaskVo.getReleaseId());
|
||||
robotTaskVo.setToLocationStorey(locationDO.getLocationStorey());
|
||||
robotTaskVo.setToLaneId(locationDO.getLaneId());
|
||||
if (ObjectUtil.isNotEmpty(mapIds) && !mapIds.contains(locationDO.getMapId())) {
|
||||
log.error("机器人不能在此放货库位放货 :{}, 机器人编号 :{}", locationDO.getLocationNo(),robotTaskVo.getRobotNo());
|
||||
throw new RuntimeException("机器人不能在此放货库位放货 "+ robotTaskVo.getReleaseId());
|
||||
@ -476,6 +493,7 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
robotTaskVo.setToLocationNo(wareHouseLocationDO.getLocationNo());
|
||||
robotTaskVo.setToLocationId(wareHouseLocationDO.getId());
|
||||
robotTaskVo.setToLocationStorey(wareHouseLocationDO.getLocationStorey());
|
||||
robotTaskVo.setToLaneId(wareHouseLocationDO.getLaneId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,6 +511,8 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
robotTaskVo.setFromLocationNo(locationDO.getLocationNo());
|
||||
robotTaskVo.setFromLocationId(robotTaskVo.getTakeId());
|
||||
robotTaskVo.setFromLocationStorey(locationDO.getLocationStorey());
|
||||
robotTaskVo.setFromLaneId(locationDO.getLaneId());
|
||||
robotTaskVo.setLocationNumber(locationDO.getLocationNumber());
|
||||
if (ObjectUtil.isNotEmpty(mapIds) && !mapIds.contains(locationDO.getMapId())) {
|
||||
log.error("机器人不能在此取货库位取货 :{}, 机器人编号 :{}", locationDO.getLocationNo(),robotTaskVo.getRobotNo());
|
||||
throw new RuntimeException("机器人不能在此取货库位取货 "+ robotTaskVo.getTakeId());
|
||||
@ -508,6 +528,8 @@ public class RobotTaskServiceImpl implements RobotTaskService {
|
||||
robotTaskVo.setFromLocationNo(wareHouseLocationDO.getLocationNo());
|
||||
robotTaskVo.setFromLocationId(wareHouseLocationDO.getId());
|
||||
robotTaskVo.setFromLocationStorey(wareHouseLocationDO.getLocationStorey());
|
||||
robotTaskVo.setFromLaneId(wareHouseLocationDO.getLaneId());
|
||||
robotTaskVo.setLocationNumber(wareHouseLocationDO.getLocationNumber());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,19 @@
|
||||
package cn.iocoder.yudao.module.system.service.robot.job;
|
||||
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DistributeTasksService {
|
||||
/**
|
||||
* 下发搬运任务
|
||||
*/
|
||||
void distributeTasks();
|
||||
|
||||
/**
|
||||
* 获取待执行的机器人和任务
|
||||
*/
|
||||
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> getRobotAndTaskDetails();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.*;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.ImmutableTriple;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -75,6 +76,29 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void distributeTasks() {
|
||||
|
||||
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> robotAndTaskDetails = getRobotAndTaskDetails();
|
||||
List<RobotInformationDO> robots = robotAndTaskDetails.getLeft();
|
||||
if (ObjectUtil.isEmpty(robots)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<RobotTaskDetailDO> taskDetailDOS = robotAndTaskDetails.getRight();
|
||||
if (ObjectUtil.isEmpty(taskDetailDOS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//任务下发给机器人
|
||||
distributeTasks(robots,taskDetailDOS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待执行的机器人和任务
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> getRobotAndTaskDetails() {
|
||||
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> pair = Pair.of(new ArrayList<>(), new ArrayList<>());;
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
List<RobotInformationDO> robots = robotInformationMapper.selectList(new LambdaQueryWrapperX<RobotInformationDO>()
|
||||
.eq(RobotInformationDO::getRobotStatus, (RobotStatusEnum.STAND_BY.getType()))
|
||||
@ -83,9 +107,11 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
|
||||
|
||||
if (robots.isEmpty()) {
|
||||
log.info("暂无空闲的机器人");
|
||||
return;
|
||||
return pair;
|
||||
}
|
||||
|
||||
//todo 还需要根据车机上报的信息,过滤掉不能用的机器人
|
||||
|
||||
//拼接任务id
|
||||
List<Long> detailDongIds = robotTaskDetailMapper.getDoingTaskIds();
|
||||
List<Long> montageTaskIds = robotTaskMapper.getUnDoAndDoingTaskIds(MontageTaskEnum.YES.getType(),detailDongIds);
|
||||
@ -94,24 +120,16 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
|
||||
|
||||
if (ObjectUtil.isEmpty(montageTaskIds) && ObjectUtil.isEmpty(singleTaskIds)) {
|
||||
log.info("暂无需要处理的主任务");
|
||||
return;
|
||||
return pair;
|
||||
}
|
||||
|
||||
List<RobotTaskDetailDO> taskDetailDOS = getTaskDetail(montageTaskIds,singleTaskIds);
|
||||
|
||||
if (taskDetailDOS.isEmpty()) {
|
||||
log.info("暂无需要处理的明细任务");
|
||||
return;
|
||||
return pair;
|
||||
}
|
||||
|
||||
//如果系统暂停 则不下发任务
|
||||
|
||||
//todo 更新数据库顺序 后续改为和创建订单一致
|
||||
|
||||
// todo 更新数据库 改为批量修改
|
||||
|
||||
//任务下发给机器人
|
||||
distributeTasks(robots,taskDetailDOS);
|
||||
return ImmutablePair.of(robots, taskDetailDOS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -395,6 +413,8 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
|
||||
return;
|
||||
}
|
||||
|
||||
// todo 需要校验取放线库, 都没有移库的任务
|
||||
|
||||
RobotAcceptTaskDTO robotTaskDO = new RobotAcceptTaskDTO();
|
||||
robotTaskDO.setOrder_id(taskDetailDO.getId().toString());
|
||||
robotTaskDO.setOrder_type("出库");//未定
|
||||
@ -583,7 +603,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
|
||||
taskIdSet.add(taskDetailDO.getRobotTaskId());
|
||||
}
|
||||
|
||||
private Pair<String, String> getMadAddressRobotNo(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
|
||||
public Pair<String, String> getMadAddressRobotNo(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
|
||||
WareHouseLocationDO fromLocation, WareHouseLocationDO toLocation) {
|
||||
String macAddress = "";
|
||||
String robotNo = taskDetailDO.getRobotNo();
|
||||
|
@ -0,0 +1,60 @@
|
||||
package cn.iocoder.yudao.module.system.service.robot.job;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMovePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMoveSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskAutoMoveDO;
|
||||
|
||||
/**
|
||||
* 机器人自动移库 Service 接口
|
||||
*
|
||||
* @author 陈宾顺
|
||||
*/
|
||||
public interface RobotTaskAutoMoveService {
|
||||
|
||||
/**
|
||||
* 创建机器人自动移库
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createTaskAutoMove(@Valid RobotTaskAutoMoveSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新机器人自动移库
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateTaskAutoMove(@Valid RobotTaskAutoMoveSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除机器人自动移库
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteTaskAutoMove(Long id);
|
||||
|
||||
/**
|
||||
* 获得机器人自动移库
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 机器人自动移库
|
||||
*/
|
||||
RobotTaskAutoMoveDO getTaskAutoMove(Long id);
|
||||
|
||||
/**
|
||||
* 获得机器人自动移库分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 机器人自动移库分页
|
||||
*/
|
||||
PageResult<RobotTaskAutoMoveDO> getTaskAutoMovePage(RobotTaskAutoMovePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 自动移库
|
||||
*/
|
||||
void distributeAutoMoveJob();
|
||||
}
|
@ -0,0 +1,412 @@
|
||||
package cn.iocoder.yudao.module.system.service.robot.job;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.mqtt.api.task.RobotTaskApi;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMovePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskAutoMoveSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskAutoMoveDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapItemMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotInformationMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskAutoMoveMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.*;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TASK_AUTO_MOVE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 机器人自动移库 Service 实现类
|
||||
*
|
||||
* @author 陈宾顺
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class RobotTaskAutoMoveServiceImpl implements RobotTaskAutoMoveService {
|
||||
|
||||
@Resource
|
||||
private RobotTaskAutoMoveMapper taskAutoMoveMapper;
|
||||
|
||||
@Autowired
|
||||
private RobotInformationMapper robotInformationMapper;
|
||||
|
||||
@Autowired
|
||||
private RobotTaskMapper robotTaskMapper;
|
||||
|
||||
@Autowired
|
||||
private RobotTaskDetailMapper robotTaskDetailMapper;
|
||||
|
||||
@Resource
|
||||
private RobotTaskApi robotTaskApi;
|
||||
|
||||
@Resource
|
||||
private PositionMapItemMapper positionMapItemMapper;
|
||||
|
||||
@Resource
|
||||
private WareHouseLocationMapper locationMapper;
|
||||
|
||||
@Autowired
|
||||
private DistributeTasksService distributeTasksService;
|
||||
|
||||
@Value("${zn.lane_auto_move:true}")
|
||||
private Boolean laneAutoMove;
|
||||
|
||||
@Override
|
||||
public Long createTaskAutoMove(RobotTaskAutoMoveSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
RobotTaskAutoMoveDO taskAutoMove = BeanUtils.toBean(createReqVO, RobotTaskAutoMoveDO.class);
|
||||
taskAutoMoveMapper.insert(taskAutoMove);
|
||||
// 返回
|
||||
return taskAutoMove.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTaskAutoMove(RobotTaskAutoMoveSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateTaskAutoMoveExists(updateReqVO.getId());
|
||||
// 更新
|
||||
RobotTaskAutoMoveDO updateObj = BeanUtils.toBean(updateReqVO, RobotTaskAutoMoveDO.class);
|
||||
taskAutoMoveMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTaskAutoMove(Long id) {
|
||||
// 校验存在
|
||||
validateTaskAutoMoveExists(id);
|
||||
// 删除
|
||||
taskAutoMoveMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateTaskAutoMoveExists(Long id) {
|
||||
if (taskAutoMoveMapper.selectById(id) == null) {
|
||||
throw exception(TASK_AUTO_MOVE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RobotTaskAutoMoveDO getTaskAutoMove(Long id) {
|
||||
return taskAutoMoveMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<RobotTaskAutoMoveDO> getTaskAutoMovePage(RobotTaskAutoMovePageReqVO pageReqVO) {
|
||||
return taskAutoMoveMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动移库
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void distributeAutoMoveJob() {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> robotAndTaskDetails =
|
||||
distributeTasksService.getRobotAndTaskDetails();
|
||||
|
||||
List<RobotInformationDO> robots = robotAndTaskDetails.getLeft();
|
||||
if (ObjectUtil.isEmpty(robots)) {
|
||||
log.info("没有空闲的机器人能执行移库任务");
|
||||
return;
|
||||
}
|
||||
|
||||
List<RobotTaskDetailDO> taskDetailDOS = robotAndTaskDetails.getRight();
|
||||
if (ObjectUtil.isEmpty(taskDetailDOS)) {
|
||||
log.info("没有需要自动移库的明细任务");
|
||||
return;
|
||||
}
|
||||
|
||||
//查询需要移库的普通库位(非线库)
|
||||
List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> ordinaryPairs = getOrdinaryAutoMoveLocation(taskDetailDOS);
|
||||
|
||||
//查询需要移库的库位(线库)
|
||||
List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> pairs = getLaneAutoMoveLocation(taskDetailDOS);
|
||||
|
||||
if (ObjectUtil.isEmpty(ordinaryPairs) && ObjectUtil.isEmpty(pairs)) {
|
||||
log.info("查不到需要移库的库位");
|
||||
return;
|
||||
}
|
||||
ordinaryPairs.addAll(pairs);
|
||||
//下发任务
|
||||
List<RobotTaskAutoMoveDO> robotTaskAutoMoveDOS = allocationRobot(robots, ordinaryPairs);
|
||||
if (ObjectUtil.isEmpty(robotTaskAutoMoveDOS)) {
|
||||
log.info("暂无需要下发移库的任务");
|
||||
return;
|
||||
}
|
||||
|
||||
taskAutoMoveMapper.insert(robotTaskAutoMoveDOS);
|
||||
Set<String> robotNos = robotTaskAutoMoveDOS.stream().map(RobotTaskAutoMoveDO::getRobotNo).collect(Collectors.toSet());
|
||||
|
||||
List<RobotInformationDO> robotInformationDOS = robotInformationMapper.selectByRobotNos(robotNos);
|
||||
robotInformationDOS.stream().forEach(robotInformationDO -> {
|
||||
robotInformationDO.setRobotStatus(RobotStatusEnum.DOING.getType());
|
||||
});
|
||||
robotInformationMapper.updateBatch(robotInformationDOS);
|
||||
|
||||
List<Long> locationIds = new ArrayList<>();
|
||||
robotTaskAutoMoveDOS.forEach(robotTaskAutoMoveDO -> {
|
||||
locationIds.add(robotTaskAutoMoveDO.getFromLocationId());
|
||||
locationIds.add(robotTaskAutoMoveDO.getToLocationId());
|
||||
});
|
||||
|
||||
List<List<Long>> fromPartition = Lists.partition(locationIds, 100);
|
||||
fromPartition.forEach(list-> {
|
||||
locationMapper.updateLocationLockList(list,0l,LocationLockEnum.NO.getType());
|
||||
});
|
||||
|
||||
// todo 搬运任务下发给机器人
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询需要移库的普通库位(非线库)
|
||||
* @param taskDetailDOS
|
||||
* @return
|
||||
*/
|
||||
private List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> getOrdinaryAutoMoveLocation(List<RobotTaskDetailDO> taskDetailDOS) {
|
||||
List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> result = new ArrayList<>();
|
||||
List<RobotTaskDetailDO> details = taskDetailDOS.stream().filter(v ->
|
||||
(RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(v.getTaskType())
|
||||
|| RobotTaskTypeEnum.TAKE.getType().equals(v.getTaskType())
|
||||
|| RobotTaskTypeEnum.RELEASE.getType().equals(v.getTaskType()))
|
||||
&& ObjectUtil.isEmpty(v.getFromLaneId()))
|
||||
.collect(Collectors.toList());
|
||||
if (ObjectUtil.isEmpty(details)) {
|
||||
log.info("普通库位, 不需要执行移库");
|
||||
return result;
|
||||
}
|
||||
|
||||
for (RobotTaskDetailDO robotTaskDetailDO : details) {
|
||||
Set<Long> doingLocationIds = new HashSet<>();
|
||||
if (ObjectUtil.isNotEmpty(robotTaskDetailDO.getFromLocationId())) {
|
||||
doingLocationIds.add(robotTaskDetailDO.getFromLocationId());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(robotTaskDetailDO.getToLocationId())) {
|
||||
doingLocationIds.add(robotTaskDetailDO.getToLocationId());
|
||||
}
|
||||
if (ObjectUtil.isEmpty(doingLocationIds)) {
|
||||
continue;
|
||||
}
|
||||
List<WareHouseLocationDO> locationDOS = locationMapper.selectNeedMoveLocation(doingLocationIds);
|
||||
if (ObjectUtil.isEmpty(locationDOS)) {
|
||||
log.info("暂无需要自动移库的库位 :{}" ,robotTaskDetailDO);
|
||||
continue;
|
||||
}
|
||||
boolean enableOrLock = locationDOS.stream().anyMatch(v -> LocationEnableEnum.NO.getType().equals(v.getLocationEnable())
|
||||
|| LocationLockEnum.NO.getType().equals(v.getLocationLock()));
|
||||
if (enableOrLock) {
|
||||
log.info("此库位被锁定或者禁用,无法执行移库 :{}",locationDOS);
|
||||
//todo 后期加到告警表里面 方便排查问题
|
||||
continue;
|
||||
}
|
||||
Pair<RobotTaskDetailDO, List<WareHouseLocationDO>> pair = Pair.of(robotTaskDetailDO, locationDOS);
|
||||
result.add(pair);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下发任务
|
||||
* @param robots
|
||||
* @param pairs
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<RobotTaskAutoMoveDO> allocationRobot(List<RobotInformationDO> robots, List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> pairs) {
|
||||
List<RobotTaskAutoMoveDO> list = new ArrayList<>();
|
||||
if (ObjectUtil.isEmpty(robots) || ObjectUtil.isEmpty(pairs)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
//查找空库位
|
||||
// todo 并且 map_item_id没有处理中的任务
|
||||
List<WareHouseLocationDO> emptyLocations = locationMapper.selectList(new LambdaQueryWrapperX<WareHouseLocationDO>()
|
||||
.isNull(WareHouseLocationDO::getLaneId)
|
||||
.eq(WareHouseLocationDO::getLocationUseStatus, LocationUseStatusEnum.NO.getType())
|
||||
.eq(WareHouseLocationDO::getLocationEnable, LocationEnableEnum.YES.getType())
|
||||
.eq(WareHouseLocationDO::getLocationLock, LocationLockEnum.YES.getType())
|
||||
.orderByDesc(WareHouseLocationDO::getLocationNumber));
|
||||
if (ObjectUtil.isEmpty(emptyLocations)) {
|
||||
log.info("查不到空库位,无法执行移库任务");
|
||||
return list;
|
||||
}
|
||||
|
||||
for (Pair<RobotTaskDetailDO, List<WareHouseLocationDO>> pair : pairs) {
|
||||
RobotTaskDetailDO detailDO = pair.getLeft();
|
||||
for (WareHouseLocationDO wareHouseLocationDO : pair.getRight()) {
|
||||
if (ObjectUtil.isEmpty(robots) || ObjectUtil.isEmpty(emptyLocations)) {
|
||||
return list;
|
||||
}
|
||||
// 校验机器人工作区域
|
||||
RobotInformationDO robotInformationDO = robots.stream()
|
||||
.filter(v ->
|
||||
ObjectUtil.isNotEmpty(v.getMacAddress())
|
||||
&& v.getFloorAreaJson().contains(wareHouseLocationDO.getAreaId())
|
||||
&& v.getFloorAreaJson().contains(emptyLocations.get(0).getAreaId()))
|
||||
.findFirst()
|
||||
.orElse(new RobotInformationDO());
|
||||
if (ObjectUtil.isEmpty(robotInformationDO) || ObjectUtil.isEmpty(robotInformationDO.getRobotNo())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RobotTaskAutoMoveDO autoMoveDO = new RobotTaskAutoMoveDO();
|
||||
autoMoveDO.setRobotTaskDetailId(detailDO.getId());
|
||||
autoMoveDO.setRobotTaskId(detailDO.getRobotTaskId());
|
||||
autoMoveDO.setFromLocationId(wareHouseLocationDO.getId());
|
||||
autoMoveDO.setFromLocationNo(wareHouseLocationDO.getLocationNo());
|
||||
autoMoveDO.setToLocationId(emptyLocations.get(0).getId());
|
||||
autoMoveDO.setToLocationNo(emptyLocations.get(0).getLocationNo());
|
||||
autoMoveDO.setFromLaneId(wareHouseLocationDO.getLaneId());
|
||||
autoMoveDO.setTaskStatus(AutoMoveTaskStatusEnum.DOING.getType());
|
||||
autoMoveDO.setPriority(wareHouseLocationDO.getLocationNumber());
|
||||
autoMoveDO.setRobotNo(robotInformationDO.getRobotNo());
|
||||
autoMoveDO.setTaskType(AutoMoveTaskTypeEnum.AUTO_MOVE.getType());
|
||||
autoMoveDO.setMoveType(AutoMoveTypeEnum.GO.getType());
|
||||
autoMoveDO.setStartTime(LocalDateTime.now());
|
||||
list.add(autoMoveDO);
|
||||
|
||||
robots.removeIf(v -> v.getRobotNo().equals(autoMoveDO.getRobotNo()));
|
||||
emptyLocations.removeIf(v -> v.getId().equals(autoMoveDO.getToLocationId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询需要移库的库位(线库)
|
||||
* @param taskDetailDOS
|
||||
* @return
|
||||
*/
|
||||
public List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> getLaneAutoMoveLocation(List<RobotTaskDetailDO> taskDetailDOS) {
|
||||
List<Pair<RobotTaskDetailDO, List<WareHouseLocationDO>>> result = new ArrayList<>();
|
||||
if (ObjectUtil.isEmpty(taskDetailDOS) || !laneAutoMove) {
|
||||
log.info("没有线库的任务明细, 不需要执行线库移库");
|
||||
return result;
|
||||
}
|
||||
//此线库不能有移动过来的任务
|
||||
List<RobotTaskDetailDO> doingTaskDetail = robotTaskDetailMapper.selectList(new LambdaQueryWrapperX<RobotTaskDetailDO>()
|
||||
.eq(RobotTaskDetailDO::getTaskStatus, (RobotTaskStatusEnum.DOING.getType()))
|
||||
.in(RobotTaskDetailDO::getTaskType, RobotTaskTypeEnum.TAKE_RELEASE.getType(), RobotTaskTypeEnum.TAKE.getType()));
|
||||
|
||||
Set<Long> doingTaskDetailLaneIds = new HashSet<>();
|
||||
if (ObjectUtil.isNotEmpty(doingTaskDetail)) {
|
||||
for (RobotTaskDetailDO robotTaskDetailDO : doingTaskDetail) {
|
||||
if (ObjectUtil.isNotEmpty(robotTaskDetailDO.getFromLaneId())) {
|
||||
doingTaskDetailLaneIds.add(robotTaskDetailDO.getFromLaneId());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(robotTaskDetailDO.getToLaneId())) {
|
||||
doingTaskDetailLaneIds.add(robotTaskDetailDO.getToLaneId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//自动移库的任务
|
||||
List<RobotTaskAutoMoveDO> robotTaskAutoMoveDOS = taskAutoMoveMapper.selectList(new LambdaQueryWrapperX<RobotTaskAutoMoveDO>()
|
||||
.eq(RobotTaskAutoMoveDO::getTaskStatus, RobotTaskStatusEnum.DOING.getType()));
|
||||
Set<Long> doingAutoMoveLaneIds = new HashSet<>();
|
||||
Set<Long> doingDetailIds = new HashSet<>();
|
||||
if (ObjectUtil.isNotEmpty(robotTaskAutoMoveDOS)) {
|
||||
robotTaskAutoMoveDOS.forEach(robotTaskAutoMoveDO -> {
|
||||
if (ObjectUtil.isNotEmpty(robotTaskAutoMoveDO.getFromLaneId())) {
|
||||
doingAutoMoveLaneIds.add(robotTaskAutoMoveDO.getFromLaneId());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(robotTaskAutoMoveDO.getRobotTaskDetailId())) {
|
||||
doingDetailIds.add(robotTaskAutoMoveDO.getRobotTaskDetailId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//只有库位为线库,且任务类型为取放货和仅取货的需要移库
|
||||
List<RobotTaskDetailDO> details = taskDetailDOS.stream().filter(v ->
|
||||
(RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(v.getTaskType())
|
||||
|| RobotTaskTypeEnum.TAKE.getType().equals(v.getTaskType()))
|
||||
&& ObjectUtil.isNotEmpty(v.getFromLaneId())
|
||||
&& (/*ObjectUtil.isNotEmpty(doingAutoMoveLaneIds) &&*/ !doingAutoMoveLaneIds.contains(v.getFromLaneId()))
|
||||
&& (/*ObjectUtil.isNotEmpty(doingDetailIds) &&*/ !doingDetailIds.contains(v.getId()))
|
||||
&& (/*ObjectUtil.isNotEmpty(doingTaskDetailLaneIds) &&*/ !doingTaskDetailLaneIds.contains(v.getFromLaneId())))
|
||||
.collect(Collectors.toList());
|
||||
if (ObjectUtil.isEmpty(details)) {
|
||||
log.info("没有线库的任务, 不需要执行线库移库");
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<Long, List<RobotTaskDetailDO>> detailMaps =
|
||||
details.stream().collect(Collectors.groupingBy(RobotTaskDetailDO::getFromLaneId));
|
||||
//查找每一个线库最小的一个库位
|
||||
|
||||
for (Map.Entry<Long, List<RobotTaskDetailDO>> detaiMap : detailMaps.entrySet()) {
|
||||
List<WareHouseLocationDO> locations = new ArrayList<>();
|
||||
RobotTaskDetailDO robotTaskDetail = detaiMap.getValue()
|
||||
.stream()
|
||||
.min(Comparator.comparing(RobotTaskDetailDO::getLocationNumber)).get();
|
||||
if (ObjectUtil.isNotEmpty(robotTaskDetail) && ObjectUtil.isNotEmpty(robotTaskDetail.getLocationNumber())) {
|
||||
WareHouseLocationDO location = WareHouseLocationDO.builder().locationNumber(robotTaskDetail.getLocationNumber())
|
||||
.locationUseStatus(LocationUseStatusEnum.YES.getType())
|
||||
.locationLock(LocationLockEnum.YES.getType())
|
||||
.laneId(detaiMap.getKey()).build();
|
||||
locations.add(location);
|
||||
}
|
||||
|
||||
log.info("查询是否需要执行移库任务的线库id和对应的排序位置 :{}", JSON.toJSONString(locations));
|
||||
if (ObjectUtil.isNotEmpty(locations)) {
|
||||
List<WareHouseLocationDO> wareHouseLocationDOS = locationMapper.selectLocationByList(locations);
|
||||
if (ObjectUtil.isNotEmpty(wareHouseLocationDOS)) {
|
||||
Pair<RobotTaskDetailDO, List<WareHouseLocationDO>> pair = Pair.of(robotTaskDetail, wareHouseLocationDOS);
|
||||
result.add(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -225,4 +225,5 @@ zn:
|
||||
scan_height: 0.4 #扫描高度
|
||||
parm: 5000 #等待时间
|
||||
lift_height: 0.1 #抬高托盘高度
|
||||
move_height: 0.1 #行走高度
|
||||
move_height: 0.1 #行走高度
|
||||
lane_auto_move: true #线库是否自动移库 true:线库执行自动移库 、false:线库关闭执行自动移库
|
@ -481,20 +481,7 @@
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="updateLocationLockStatus">
|
||||
update
|
||||
ware_house_location
|
||||
<set>
|
||||
<if test="taskId != null">
|
||||
task_id = #{taskId},
|
||||
</if>
|
||||
<if test="locationLock != null">
|
||||
location_lock = #{locationLock},
|
||||
</if>
|
||||
</set>
|
||||
where
|
||||
id = #{id}
|
||||
</update>
|
||||
|
||||
|
||||
<update id="updateLocationLockList">
|
||||
update
|
||||
@ -690,4 +677,84 @@
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectLocationByList" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="base_sql"></include>
|
||||
from
|
||||
ware_house_location
|
||||
<where>
|
||||
<foreach collection="locations" item="item" open="(" close=")"
|
||||
separator=",">
|
||||
1=1
|
||||
<if test="item.laneId != null">
|
||||
and lane_id = #{item.laneId}
|
||||
</if>
|
||||
<if test="item.locationNumber != null">
|
||||
and location_number < #{item.locationNumber}
|
||||
</if>
|
||||
<if test="item.locationLock != null">
|
||||
and location_lock = #{item.locationLock}
|
||||
</if>
|
||||
<if test="item.locationUseStatus != null">
|
||||
and location_use_status = #{item.locationUseStatus}
|
||||
</if>
|
||||
<if test="1==1">
|
||||
and deleted = '0'
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
order by location_number asc
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectNeedMoveLocation" resultMap="BaseResultMap">
|
||||
select
|
||||
t2.id,
|
||||
t2.lane_id,
|
||||
t2.lane_name,
|
||||
t2.area_id,
|
||||
t2.area_name,
|
||||
t2.location_no,
|
||||
t2.location_yaw,
|
||||
t2.group_name,
|
||||
t2.sku_info,
|
||||
t2.sku_batch,
|
||||
t2.sku_number,
|
||||
t2.tray_info,
|
||||
t2.location_enable,
|
||||
t2.location_lock,
|
||||
t2.location_use_status,
|
||||
t2.location_x,
|
||||
t2.location_y,
|
||||
t2.location_wide,
|
||||
t2.location_deep,
|
||||
t2.location_height,
|
||||
t2.location_default_height,
|
||||
t2.location_total_height,
|
||||
t2.location_tray_height,
|
||||
t2.location_storey,
|
||||
t2.location_type,
|
||||
t2.location_number,
|
||||
t2.map_id,
|
||||
t2.map_item_id
|
||||
from
|
||||
ware_house_location t1, ware_house_location t2
|
||||
WHERE
|
||||
t1.map_item_id = t2.map_item_id
|
||||
and t1.id in
|
||||
<foreach collection="locationIds" item="id" index="index" open="(" close=")"
|
||||
separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
and t2.location_number < t1.location_number
|
||||
and t2.location_use_status = '1'
|
||||
and t2.id not in
|
||||
<foreach collection="locationIds" item="id" index="index" open="(" close=")"
|
||||
separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
order by t2.location_number asc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@ -0,0 +1,12 @@
|
||||
<?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.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskAutoMoveMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
</mapper>
|
@ -13,6 +13,9 @@
|
||||
<result property="takeId" column="take_id" jdbcType="INTEGER"/>
|
||||
<result property="fromLocationNo" column="from_location_no" jdbcType="VARCHAR"/>
|
||||
<result property="fromLocationId" column="from_location_id" jdbcType="INTEGER"/>
|
||||
<result property="fromLaneId" column="from_lane_id" jdbcType="INTEGER"/>
|
||||
<result property="toLaneId" column="to_lane_id" jdbcType="INTEGER"/>
|
||||
<result property="locationNumber" column="location_number" jdbcType="INTEGER"/>
|
||||
<result property="toLocationNo" column="to_location_no" jdbcType="VARCHAR"/>
|
||||
<result property="toLocationId" column="to_location_id" jdbcType="INTEGER"/>
|
||||
<result property="fromLocationStorey" column="from_location_storey" jdbcType="INTEGER"/>
|
||||
@ -42,6 +45,9 @@
|
||||
take_id,
|
||||
from_location_no,
|
||||
from_location_id,
|
||||
from_lane_id,
|
||||
to_lane_id,
|
||||
location_number
|
||||
to_location_no,
|
||||
to_location_id,
|
||||
robot_no,
|
||||
@ -360,13 +366,13 @@
|
||||
<insert id="insertBatchList" >
|
||||
insert into robot_task_detail(robot_task_id, task_type, release_type, take_type, release_id, take_id,
|
||||
from_location_no, from_location_id, to_location_no, to_location_id, robot_no,from_location_storey,
|
||||
to_location_storey,priority)
|
||||
to_location_storey,priority,from_lane_id,to_lane_id,location_number)
|
||||
values
|
||||
<foreach collection="taskDetailList" item="entity" separator=",">
|
||||
(#{entity.robotTaskId}, #{entity.taskType}, #{entity.releaseType}, #{entity.takeType}, #{entity.releaseId},
|
||||
#{entity.takeId}, #{entity.fromLocationNo}, #{entity.fromLocationId}, #{entity.toLocationNo},
|
||||
#{entity.toLocationId}, #{entity.robotNo}, #{entity.fromLocationStorey}, #{entity.toLocationStorey}
|
||||
, #{entity.priority})
|
||||
, #{entity.priority}, #{entity.fromLaneId}, #{entity.toLaneId}, #{entity.locationNumber})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user