diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 11c167f73..e26a81efe 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -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, "机器人自动移库不存在"); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskAutoMoveController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskAutoMoveController.java new file mode 100644 index 000000000..e75a41f5d --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskAutoMoveController.java @@ -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 createTaskAutoMove(@Valid @RequestBody RobotTaskAutoMoveSaveReqVO createReqVO) { + return success(taskAutoMoveService.createTaskAutoMove(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新机器人自动移库") + @PreAuthorize("@ss.hasPermission('robot:task-auto-move:update')") + public CommonResult 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 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 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> getTaskAutoMovePage(@Valid RobotTaskAutoMovePageReqVO pageReqVO) { + PageResult 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 list = taskAutoMoveService.getTaskAutoMovePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "机器人自动移库.xls", "数据", RobotTaskAutoMoveRespVO.class, + BeanUtils.toBean(list, RobotTaskAutoMoveRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMovePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMovePageReqVO.java new file mode 100644 index 000000000..aa838d4d9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMovePageReqVO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMoveRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMoveRespVO.java new file mode 100644 index 000000000..9661a85b7 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMoveRespVO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMoveSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMoveSaveReqVO.java new file mode 100644 index 000000000..7daf06b9e --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskAutoMoveSaveReqVO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java index a35ee8981..3fde6a450 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java @@ -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(前端不用传此字段)") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java index 79d86b125..06c1c9684 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java @@ -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; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java index d597bb276..ef5e7db32 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java @@ -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; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java index 32a23e67c..11b545391 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java @@ -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") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskAutoMoveDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskAutoMoveDO.java new file mode 100644 index 000000000..8cec79bb6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskAutoMoveDO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java index 077b6e980..a1198dfa8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java @@ -59,6 +59,18 @@ public class RobotTaskDetailDO extends BaseDO { * 计算后的来源库位id */ private Long fromLocationId; + /** + * 取货线库id + */ + private Long fromLaneId; + /** + * 放货线库id + */ + private Long toLaneId; + /** + * 取货库位的排序的位置,越大越优先堆放 + */ + private Long locationNumber; /** * 计算后的目标库位编号 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/houselocation/WareHouseLocationMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/houselocation/WareHouseLocationMapper.java index 06f5822dc..2e0bc867e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/houselocation/WareHouseLocationMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/houselocation/WareHouseLocationMapper.java @@ -73,14 +73,6 @@ public interface WareHouseLocationMapper extends BaseMapperX getLocationByName(WareHouseLocationVO requestVO); + + /** + * 查询相通的线库 且 有货的 排序的位置较小的库位 + * @param locations + * @return + */ + List selectLocationByList(@Param("locations") List locations); + + /** + * 查询需要移库的库位 + * @param locationIds + * @return + */ + List selectNeedMoveLocation(@Param("locationIds") Set locationIds); } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskAutoMoveMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskAutoMoveMapper.java new file mode 100644 index 000000000..492d858bb --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskAutoMoveMapper.java @@ -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 { + + default PageResult selectPage(RobotTaskAutoMovePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .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)); + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTaskStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTaskStatusEnum.java new file mode 100644 index 000000000..1941ca473 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTaskStatusEnum.java @@ -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; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTaskTypeEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTaskTypeEnum.java new file mode 100644 index 000000000..c4e9a1782 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTaskTypeEnum.java @@ -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; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTypeEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTypeEnum.java new file mode 100644 index 000000000..64ff1315c --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/AutoMoveTypeEnum.java @@ -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; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/CommandTypeEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/CommandTypeEnum.java index 365fb46ac..0c5bfcaa9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/CommandTypeEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/CommandTypeEnum.java @@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.system.enums.robot; import lombok.AllArgsConstructor; import lombok.Getter; +/** + * 下发给车机的类型 + */ @Getter @AllArgsConstructor public enum CommandTypeEnum { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/DoCycleEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/DoCycleEnum.java index ecb2dbc1e..5373e7b4f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/DoCycleEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/DoCycleEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationEnableEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationEnableEnum.java index 0d2bb1610..f97e896d8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationEnableEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationEnableEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationLockEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationLockEnum.java index c4b479d45..0e0bda9ec 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationLockEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationLockEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationUseStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationUseStatusEnum.java index f0db19aff..b9aee545a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationUseStatusEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/LocationUseStatusEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MontageTaskEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MontageTaskEnum.java index c319e28ea..724b310e8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MontageTaskEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MontageTaskEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MoveAllEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MoveAllEnum.java index 8f56a390f..e9267f2ba 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MoveAllEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/MoveAllEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/ReleaseTakeEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/ReleaseTakeEnum.java index 7fc8b6e01..46f05ce9f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/ReleaseTakeEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/ReleaseTakeEnum.java @@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; /** - * 放货类型 + * 放货类型robot_task_detail的release_type */ @Getter @AllArgsConstructor diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotMoveStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotMoveStatusEnum.java new file mode 100644 index 000000000..2da31b462 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotMoveStatusEnum.java @@ -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; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskDetailStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskDetailStatusEnum.java index 9b2167431..8391c786d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskDetailStatusEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskDetailStatusEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskModelEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskModelEnum.java index 50ea957d8..6eca501fd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskModelEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskModelEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskStatusEnum.java index 86b039ed0..6cfd88c95 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskStatusEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskStatusEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskTypeEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskTypeEnum.java index 813447a2d..8bc9675f4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskTypeEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/RobotTaskTypeEnum.java @@ -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 { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java index a5010a8ce..99a5998fa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java @@ -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 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); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java index 165e82d6b..1507b4f3e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java @@ -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 taskDOS = taskMapper.selectList(new LambdaQueryWrapperX() + .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 locationIds) { - locationMapper.updateLocationLockStatus(robotTaskVo.getFromLocationId(),0,robotTaskVo.getRobotTaskId()); + Set 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()); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksService.java index cfed30e6c..f6bd9c157 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksService.java @@ -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> getRobotAndTaskDetails(); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksServiceImpl.java index fb812204f..195403b9a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/DistributeTasksServiceImpl.java @@ -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> robotAndTaskDetails = getRobotAndTaskDetails(); + List robots = robotAndTaskDetails.getLeft(); + if (ObjectUtil.isEmpty(robots)) { + return; + } + + List taskDetailDOS = robotAndTaskDetails.getRight(); + if (ObjectUtil.isEmpty(taskDetailDOS)) { + return; + } + + //任务下发给机器人 + distributeTasks(robots,taskDetailDOS); + } + + /** + * 获取待执行的机器人和任务 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Pair, List> getRobotAndTaskDetails() { + Pair, List> pair = Pair.of(new ArrayList<>(), new ArrayList<>());; TenantContextHolder.setTenantId(1L); List robots = robotInformationMapper.selectList(new LambdaQueryWrapperX() .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 detailDongIds = robotTaskDetailMapper.getDoingTaskIds(); List 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 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 getMadAddressRobotNo(RobotTaskDetailDO taskDetailDO, List robots, + public Pair getMadAddressRobotNo(RobotTaskDetailDO taskDetailDO, List robots, WareHouseLocationDO fromLocation, WareHouseLocationDO toLocation) { String macAddress = ""; String robotNo = taskDetailDO.getRobotNo(); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveService.java new file mode 100644 index 000000000..afaf95d7c --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveService.java @@ -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 getTaskAutoMovePage(RobotTaskAutoMovePageReqVO pageReqVO); + + /** + * 自动移库 + */ + void distributeAutoMoveJob(); +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java new file mode 100644 index 000000000..2f0b5c50e --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java @@ -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 getTaskAutoMovePage(RobotTaskAutoMovePageReqVO pageReqVO) { + return taskAutoMoveMapper.selectPage(pageReqVO); + } + + /** + * 自动移库 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void distributeAutoMoveJob() { + TenantContextHolder.setTenantId(1L); + Pair, List> robotAndTaskDetails = + distributeTasksService.getRobotAndTaskDetails(); + + List robots = robotAndTaskDetails.getLeft(); + if (ObjectUtil.isEmpty(robots)) { + log.info("没有空闲的机器人能执行移库任务"); + return; + } + + List taskDetailDOS = robotAndTaskDetails.getRight(); + if (ObjectUtil.isEmpty(taskDetailDOS)) { + log.info("没有需要自动移库的明细任务"); + return; + } + + //查询需要移库的普通库位(非线库) + List>> ordinaryPairs = getOrdinaryAutoMoveLocation(taskDetailDOS); + + //查询需要移库的库位(线库) + List>> pairs = getLaneAutoMoveLocation(taskDetailDOS); + + if (ObjectUtil.isEmpty(ordinaryPairs) && ObjectUtil.isEmpty(pairs)) { + log.info("查不到需要移库的库位"); + return; + } + ordinaryPairs.addAll(pairs); + //下发任务 + List robotTaskAutoMoveDOS = allocationRobot(robots, ordinaryPairs); + if (ObjectUtil.isEmpty(robotTaskAutoMoveDOS)) { + log.info("暂无需要下发移库的任务"); + return; + } + + taskAutoMoveMapper.insert(robotTaskAutoMoveDOS); + Set robotNos = robotTaskAutoMoveDOS.stream().map(RobotTaskAutoMoveDO::getRobotNo).collect(Collectors.toSet()); + + List robotInformationDOS = robotInformationMapper.selectByRobotNos(robotNos); + robotInformationDOS.stream().forEach(robotInformationDO -> { + robotInformationDO.setRobotStatus(RobotStatusEnum.DOING.getType()); + }); + robotInformationMapper.updateBatch(robotInformationDOS); + + List locationIds = new ArrayList<>(); + robotTaskAutoMoveDOS.forEach(robotTaskAutoMoveDO -> { + locationIds.add(robotTaskAutoMoveDO.getFromLocationId()); + locationIds.add(robotTaskAutoMoveDO.getToLocationId()); + }); + + List> fromPartition = Lists.partition(locationIds, 100); + fromPartition.forEach(list-> { + locationMapper.updateLocationLockList(list,0l,LocationLockEnum.NO.getType()); + }); + + // todo 搬运任务下发给机器人 + + } + + /** + * 查询需要移库的普通库位(非线库) + * @param taskDetailDOS + * @return + */ + private List>> getOrdinaryAutoMoveLocation(List taskDetailDOS) { + List>> result = new ArrayList<>(); + List 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 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 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> pair = Pair.of(robotTaskDetailDO, locationDOS); + result.add(pair); + } + return result; + } + + /** + * 下发任务 + * @param robots + * @param pairs + */ + @Transactional(rollbackFor = Exception.class) + public List allocationRobot(List robots, List>> pairs) { + List list = new ArrayList<>(); + if (ObjectUtil.isEmpty(robots) || ObjectUtil.isEmpty(pairs)) { + return list; + } + + //查找空库位 + // todo 并且 map_item_id没有处理中的任务 + List emptyLocations = locationMapper.selectList(new LambdaQueryWrapperX() + .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> 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>> getLaneAutoMoveLocation(List taskDetailDOS) { + List>> result = new ArrayList<>(); + if (ObjectUtil.isEmpty(taskDetailDOS) || !laneAutoMove) { + log.info("没有线库的任务明细, 不需要执行线库移库"); + return result; + } + //此线库不能有移动过来的任务 + List doingTaskDetail = robotTaskDetailMapper.selectList(new LambdaQueryWrapperX() + .eq(RobotTaskDetailDO::getTaskStatus, (RobotTaskStatusEnum.DOING.getType())) + .in(RobotTaskDetailDO::getTaskType, RobotTaskTypeEnum.TAKE_RELEASE.getType(), RobotTaskTypeEnum.TAKE.getType())); + + Set 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 robotTaskAutoMoveDOS = taskAutoMoveMapper.selectList(new LambdaQueryWrapperX() + .eq(RobotTaskAutoMoveDO::getTaskStatus, RobotTaskStatusEnum.DOING.getType())); + Set doingAutoMoveLaneIds = new HashSet<>(); + Set 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 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> detailMaps = + details.stream().collect(Collectors.groupingBy(RobotTaskDetailDO::getFromLaneId)); + //查找每一个线库最小的一个库位 + + for (Map.Entry> detaiMap : detailMaps.entrySet()) { + List 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 wareHouseLocationDOS = locationMapper.selectLocationByList(locations); + if (ObjectUtil.isNotEmpty(wareHouseLocationDOS)) { + Pair> pair = Pair.of(robotTaskDetail, wareHouseLocationDOS); + result.add(pair); + } + } + } + + return result; + } + + + + + + + + + + + + + + + + + + + + + + + + + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml index 98498c837..fdf19167c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml @@ -225,4 +225,5 @@ zn: scan_height: 0.4 #扫描高度 parm: 5000 #等待时间 lift_height: 0.1 #抬高托盘高度 - move_height: 0.1 #行走高度 \ No newline at end of file + move_height: 0.1 #行走高度 + lane_auto_move: true #线库是否自动移库 true:线库执行自动移库 、false:线库关闭执行自动移库 \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/houselocation/WareHouseLocationMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/houselocation/WareHouseLocationMapper.xml index 9329642d4..d83ccbe9e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/houselocation/WareHouseLocationMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/houselocation/WareHouseLocationMapper.xml @@ -481,20 +481,7 @@ where id = #{id} - - update - ware_house_location - - - task_id = #{taskId}, - - - location_lock = #{locationLock}, - - - where - id = #{id} - + update @@ -690,4 +677,84 @@ + + + + + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskAutoMoveMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskAutoMoveMapper.xml new file mode 100644 index 000000000..cfa179926 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskAutoMoveMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml index c3f4aaa3f..a8c6bba64 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml @@ -13,6 +13,9 @@ + + + @@ -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 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 (#{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})