From da421426d06706384988c9d86273483b717b54f0 Mon Sep 17 00:00:00 2001 From: "HUOJIN\\92525" Date: Fri, 21 Nov 2025 14:31:01 +0800 Subject: [PATCH] no message --- cpte-boot-base-core/pom.xml | 1 + .../desform/aitest/json/ai_control_main.json | 2 +- .../agvTask/controller/AgvTaskController.java | 238 +++++++------- .../agvTask/service/IAgvTaskService.java | 17 +- .../service/impl/AgvTaskServiceImpl.java | 48 ++- .../org/cpte/modules/base/entity/Point.java | 6 +- .../modules/base/service/IPointService.java | 26 ++ .../modules/base/service/IStockService.java | 15 + .../base/service/impl/PointServiceImpl.java | 43 ++- .../base/service/impl/StockServiceImpl.java | 17 + .../cpte/modules/constant/CommonConstant.java | 21 -- .../modules/constant/GeneralConstant.java | 57 ++++ .../modules/constant/enums/AreaTypeEnum.java | 15 + .../cpte/modules/constant/enums/BaseEnum.java | 97 ------ .../constant/enums/BusinessTypeEnum.java | 2 +- .../modules/constant/enums/TaskTypeEnum.java | 26 ++ .../impl/IConveyorLineServiceImpl.java | 18 +- .../hikAgv/controller/HikAgvController.java | 1 - .../service/impl/IHikAgvServiceImpl.java | 53 ++-- .../service/impl/InventoryServiceImpl.java | 5 +- .../cpte/modules/quartz/job/AllocateJob.java | 32 +- .../cpte/modules/quartz/job/HikAgvJob.java | 20 +- .../cpte/modules/quartz/job/TesAgvJob.java | 15 +- .../receive/controller/AsnController.java | 4 +- .../org/cpte/modules/receive/entity/Asn.java | 16 + .../modules/receive/entity/AsnDetail.java | 15 +- .../modules/receive/entity/ReceiveRecord.java | 13 +- .../modules/receive/service/IAsnService.java | 9 + .../receive/service/impl/AsnServiceImpl.java | 140 +++++++-- .../saiWms/controller/SaiWmsController.java | 2 - .../saiWms/request/InboundRequest.java | 2 + .../saiWms/service/ISaiWmsService.java | 5 + .../service/impl/ISaiWmsServiceImpl.java | 41 +-- .../shipping/controller/PickController.java | 32 +- .../cpte/modules/shipping/entity/Task.java | 197 ++++++++++++ .../shipping/mapper/PickDetailMapper.java | 11 +- .../modules/shipping/mapper/PickMapper.java | 13 + .../modules/shipping/mapper/TaskMapper.java | 25 ++ .../shipping/mapper/xml/PickDetailMapper.xml | 10 + .../shipping/mapper/xml/TaskMapper.xml | 5 + .../shipping/service/IPickService.java | 12 +- .../shipping/service/ITaskService.java | 60 ++++ .../service/impl/PickServiceImpl.java | 63 +++- .../service/impl/TaskServiceImpl.java | 156 ++++++++++ .../modules/shipping/vo/TaskGroupKey.java | 25 ++ .../tesAgv/controller/TesAgvController.java | 1 - .../service/impl/ITesAgvServiceImpl.java | 33 +- .../org/cpte/modules/utils/BatchUtils.java | 294 ++++++++++++++++++ .../modules/openapi/filter/ApiAuthFilter.java | 2 +- .../modules/openapi/mapper/OpenApiMapper.java | 10 + .../src/main/resources/application-dev.yml | 2 +- .../src/main/resources/application-prod.yml | 2 +- .../src/test/java/org/jeecg/TestMain.java | 34 +- .../openapi/test/SampleOpenApiTest.java | 2 +- 54 files changed, 1581 insertions(+), 430 deletions(-) delete mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/CommonConstant.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/GeneralConstant.java delete mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BaseEnum.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/TaskTypeEnum.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/entity/Task.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/TaskMapper.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/TaskMapper.xml create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/ITaskService.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/TaskServiceImpl.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/TaskGroupKey.java create mode 100644 cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtils.java diff --git a/cpte-boot-base-core/pom.xml b/cpte-boot-base-core/pom.xml index d08ee04..ff29ec4 100644 --- a/cpte-boot-base-core/pom.xml +++ b/cpte-boot-base-core/pom.xml @@ -367,5 +367,6 @@ org.jeecgframework.boot3 jeecg-boot-starter-chatgpt + \ No newline at end of file diff --git a/cpte-boot-module/cpte-module-demo/src/main/resources/static/desform/aitest/json/ai_control_main.json b/cpte-boot-module/cpte-module-demo/src/main/resources/static/desform/aitest/json/ai_control_main.json index 495cb6c..8f231a9 100644 --- a/cpte-boot-module/cpte-module-demo/src/main/resources/static/desform/aitest/json/ai_control_main.json +++ b/cpte-boot-module/cpte-module-demo/src/main/resources/static/desform/aitest/json/ai_control_main.json @@ -2877,7 +2877,7 @@ "advancedSetting": { "defaultValue": { "type": "compose", - "value": "https://help.jeecg.com/", + "value": "https://help.cpte.com/", "format": "string", "allowFunc": true, "valueSplit": "", diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/controller/AgvTaskController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/controller/AgvTaskController.java index 295499b..4ae5814 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/controller/AgvTaskController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/controller/AgvTaskController.java @@ -8,8 +8,15 @@ import java.util.stream.Collectors; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; + import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.cpte.modules.agvTask.mapper.AgvTaskMapper; +import org.cpte.modules.constant.enums.AgvStatusEnum; +import org.cpte.modules.constant.enums.AgvVendorEnum; +import org.cpte.modules.hikAgv.service.IHikAgvService; +import org.cpte.modules.shipping.entity.Task; +import org.cpte.modules.tesAgv.service.ITesAgvService; import org.jeecg.common.api.vo.Result; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryRuleEnum; @@ -22,6 +29,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; +import org.jeecg.config.shiro.IgnoreAuth; import org.jeecgframework.poi.excel.ExcelImportUtil; import org.jeecgframework.poi.excel.def.NormalExcelConstants; import org.jeecgframework.poi.excel.entity.ExportParams; @@ -38,127 +46,128 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; import org.jeecg.common.aspect.annotation.AutoLog; import org.apache.shiro.authz.annotation.RequiresPermissions; - /** + +/** * @Description: AGV任务表 * @author: cpte - * @Date: 2025-11-06 + * @Date: 2025-11-06 * @Version: V1.0 */ -@Tag(name="AGV任务表") +@Tag(name = "AGV任务表") @RestController @RequestMapping("/agvTask") @Slf4j public class AgvTaskController extends JeecgController { - @Autowired - private IAgvTaskService agvTaskService; - - /** - * 分页列表查询 - * - * @param agvTask - * @param pageNo - * @param pageSize - * @param req - * @return - */ - //@AutoLog(value = "AGV任务表-分页列表查询") - @Operation(summary="AGV任务表-分页列表查询") - @GetMapping(value = "/list") - public Result> queryPageList(AgvTask agvTask, - @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, - @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, - HttpServletRequest req) { + @Autowired + private IAgvTaskService agvTaskService; + + /** + * 分页列表查询 + * + * @param agvTask + * @param pageNo + * @param pageSize + * @param req + * @return + */ + //@AutoLog(value = "AGV任务表-分页列表查询") + @Operation(summary = "AGV任务表-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList(AgvTask agvTask, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(agvTask, req.getParameterMap()); - Page page = new Page(pageNo, pageSize); - IPage pageList = agvTaskService.page(page, queryWrapper); - return Result.OK(pageList); - } - - /** - * 添加 - * - * @param agvTask - * @return - */ - @AutoLog(value = "AGV任务表-添加") - @Operation(summary="AGV任务表-添加") - @RequiresPermissions("agvTask:data_agv_task:add") - @PostMapping(value = "/add") - public Result add(@RequestBody AgvTask agvTask) { - agvTaskService.save(agvTask); - return Result.OK("添加成功!"); - } - - /** - * 编辑 - * - * @param agvTask - * @return - */ - @AutoLog(value = "AGV任务表-编辑") - @Operation(summary="AGV任务表-编辑") - @RequiresPermissions("agvTask:data_agv_task:edit") - @RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) - public Result edit(@RequestBody AgvTask agvTask) { - agvTaskService.updateById(agvTask); - return Result.OK("编辑成功!"); - } - - /** - * 通过id删除 - * - * @param id - * @return - */ - @AutoLog(value = "AGV任务表-通过id删除") - @Operation(summary="AGV任务表-通过id删除") - @RequiresPermissions("agvTask:data_agv_task:delete") - @DeleteMapping(value = "/delete") - public Result delete(@RequestParam(name="id",required=true) String id) { - agvTaskService.removeById(id); - return Result.OK("删除成功!"); - } - - /** - * 批量删除 - * - * @param ids - * @return - */ - @AutoLog(value = "AGV任务表-批量删除") - @Operation(summary="AGV任务表-批量删除") - @RequiresPermissions("agvTask:data_agv_task:deleteBatch") - @DeleteMapping(value = "/deleteBatch") - public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { - this.agvTaskService.removeByIds(Arrays.asList(ids.split(","))); - return Result.OK("批量删除成功!"); - } - - /** - * 通过id查询 - * - * @param id - * @return - */ - //@AutoLog(value = "AGV任务表-通过id查询") - @Operation(summary="AGV任务表-通过id查询") - @GetMapping(value = "/queryById") - public Result queryById(@RequestParam(name="id",required=true) String id) { - AgvTask agvTask = agvTaskService.getById(id); - if(agvTask==null) { - return Result.error("未找到对应数据"); - } - return Result.OK(agvTask); - } + Page page = new Page(pageNo, pageSize); + IPage pageList = agvTaskService.page(page, queryWrapper); + return Result.OK(pageList); + } /** - * 导出excel - * - * @param request - * @param agvTask - */ + * 添加 + * + * @param agvTask + * @return + */ + @AutoLog(value = "AGV任务表-添加") + @Operation(summary = "AGV任务表-添加") + @RequiresPermissions("agvTask:data_agv_task:add") + @PostMapping(value = "/add") + public Result add(@RequestBody AgvTask agvTask) { + agvTaskService.save(agvTask); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param agvTask + * @return + */ + @AutoLog(value = "AGV任务表-编辑") + @Operation(summary = "AGV任务表-编辑") + @RequiresPermissions("agvTask:data_agv_task:edit") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST}) + public Result edit(@RequestBody AgvTask agvTask) { + agvTaskService.updateById(agvTask); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "AGV任务表-通过id删除") + @Operation(summary = "AGV任务表-通过id删除") + @RequiresPermissions("agvTask:data_agv_task:delete") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + agvTaskService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "AGV任务表-批量删除") + @Operation(summary = "AGV任务表-批量删除") + @RequiresPermissions("agvTask:data_agv_task:deleteBatch") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + this.agvTaskService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + //@AutoLog(value = "AGV任务表-通过id查询") + @Operation(summary = "AGV任务表-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + AgvTask agvTask = agvTaskService.getById(id); + if (agvTask == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(agvTask); + } + + /** + * 导出excel + * + * @param request + * @param agvTask + */ @RequiresPermissions("agvTask:data_agv_task:exportXls") @RequestMapping(value = "/exportXls") public ModelAndView exportXls(HttpServletRequest request, AgvTask agvTask) { @@ -166,16 +175,15 @@ public class AgvTaskController extends JeecgController } /** - * 通过excel导入数据 - * - * @param request - * @param response - * @return - */ + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ @RequiresPermissions("agvTask:data_agv_task:importExcel") @RequestMapping(value = "/importExcel", method = RequestMethod.POST) public Result importExcel(HttpServletRequest request, HttpServletResponse response) { return super.importExcel(request, response, AgvTask.class); } - } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java index 7fec850..aeada5e 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/IAgvTaskService.java @@ -16,7 +16,6 @@ public interface IAgvTaskService extends IService { * 创建agvTask任务 * * @param businessDetailId 业务ID - * @param status 状态 * @param carrierCode 容器 * @param startCode 起点 * @param endCode 终点 @@ -24,6 +23,20 @@ public interface IAgvTaskService extends IService { * @param type 业务类型 * @param agvVendor 供应商 */ - AgvTask createAgvTask(Long businessDetailId, Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor); + AgvTask createAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor); + + /** + * 创建agvTask任务 + * + * @param businessDetailId 业务ID + * @param carrierCode 容器 + * @param startCode 起点 + * @param endCode 终点 + * @param taskType 任务类型 + * @param type 业务类型 + * @param agvVendor 供应商 + */ + AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor); + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java index 0cb8c54..5ec38af 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/agvTask/service/impl/AgvTaskServiceImpl.java @@ -1,16 +1,20 @@ package org.cpte.modules.agvTask.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.shiro.SecurityUtils; import org.cpte.modules.agvTask.entity.AgvTask; import org.cpte.modules.agvTask.mapper.AgvTaskMapper; import org.cpte.modules.agvTask.service.IAgvTaskService; +import org.cpte.modules.constant.enums.AgvStatusEnum; import org.cpte.modules.constant.enums.AgvVendorEnum; import org.cpte.modules.constant.enums.StockTypeEnum; +import org.jeecg.common.system.vo.LoginUser; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; import java.util.List; /** @@ -24,7 +28,13 @@ public class AgvTaskServiceImpl extends ServiceImpl impl @Override @Transactional(rollbackFor = Exception.class) - public AgvTask createAgvTask(Long businessDetailId, Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor) { + public AgvTask createAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor) { + LoginUser sysUser = null; + try { + sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + } catch (Exception e) { + log.error("获取登录用户信息失败"); + } int priority = 99; if (AgvVendorEnum.TES.getValue().equals(agvVendor)) { priority = 3; @@ -33,14 +43,48 @@ public class AgvTaskServiceImpl extends ServiceImpl impl .businessDetailId(businessDetailId) .carrierCode(carrierCode) .type(type) - .status(status) + .status(AgvStatusEnum.CREATED.getValue()) .startCode(startCode) .endCode(endCode) .carrierType(StockTypeEnum.TRAY.getValue()) .taskType(taskType) .priority(priority) .agvVendor(agvVendor) + .sysOrgCode(sysUser == null ? "A05" : sysUser.getOrgCode()) + .tenantId(sysUser == null ? 1000L : Long.parseLong(sysUser.getRelTenantIds())) + .createBy(sysUser == null ? "system" : sysUser.getUsername()) + .createTime(new Date()) .build(); return this.save(agvTask) ? agvTask : null; } + + @Override + public AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor) { + LoginUser sysUser = null; + try { + sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + } catch (Exception e) { + log.error("获取登录用户信息失败"); + } + int priority = 99; + if (AgvVendorEnum.TES.getValue().equals(agvVendor)) { + priority = 3; + } + return AgvTask.builder() + .businessDetailId(businessDetailId) + .carrierCode(carrierCode) + .type(type) + .status(AgvStatusEnum.CREATED.getValue()) + .startCode(startCode) + .endCode(endCode) + .carrierType(StockTypeEnum.TRAY.getValue()) + .taskType(taskType) + .priority(priority) + .agvVendor(agvVendor) + .sysOrgCode(sysUser == null ? "A05" : sysUser.getOrgCode()) + .tenantId(sysUser == null ? 1000L : Long.parseLong(sysUser.getRelTenantIds())) + .createBy(sysUser == null ? "system" : sysUser.getUsername()) + .createTime(new Date()) + .build(); + } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Point.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Point.java index 635742a..353d7a6 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Point.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Point.java @@ -65,19 +65,19 @@ public class Point implements Serializable { */ @Excel(name = "排", width = 15) @Schema(description = "排") - private java.lang.String rows; + private java.lang.String rowNum; /** * 列 */ @Excel(name = "列", width = 15) @Schema(description = "列") - private java.lang.String cols; + private java.lang.String colNum; /** * 层 */ @Excel(name = "层", width = 15) @Schema(description = "层") - private java.lang.String layers; + private java.lang.String layerNum; /** * 描述 */ diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IPointService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IPointService.java index 977cf4b..1cb5b1b 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IPointService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IPointService.java @@ -1,4 +1,5 @@ package org.cpte.modules.base.service; +import org.apache.ibatis.annotations.Param; import org.cpte.modules.base.entity.Point; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; @@ -19,6 +20,19 @@ public interface IPointService extends IService { */ Point validatePoint(String pointCode); + /** + * 占用点位 + * @param point 点位 + */ + void bindPoint(Point point); + + /** + * 释放点位 + * @param point 点位 + */ + void unbindPoint(Point point); + + /** * 根据库位编码集合查询库位信息 * @@ -42,4 +56,16 @@ public interface IPointService extends IService { * @return Map */ Map queryByPointIdsToMap(List pointIds); + + /** + * 获取输送线工作台点位,均衡分配点位任务 + * + * @param status 状态 + * @param areaCode 库区编码 + * @param key 索引 + * @return pointEntity + */ + Point getWorkStationPoint(Integer status,String areaCode, String key); + + Point queryToPoint(String pointCode,Integer status,String areaCode); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IStockService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IStockService.java index 97199c5..6ada0e6 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IStockService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/IStockService.java @@ -1,5 +1,6 @@ package org.cpte.modules.base.service; +import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; import com.baomidou.mybatisplus.extension.service.IService; @@ -21,6 +22,20 @@ public interface IStockService extends IService { */ Stock validateStock(String stockCode); + /** + * 验证容器状态 + * @param stock 容器 + */ + void validateStockStatus(Stock stock); + + /** + * 绑定容器 + * + * @param stock 容器 + * @param point 容器位置 + */ + void bindStock(Stock stock, Point point); + /** * 根据容器编码集合查询容器信息 * diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/PointServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/PointServiceImpl.java index 44a0d03..2913824 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/PointServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/PointServiceImpl.java @@ -3,14 +3,13 @@ package org.cpte.modules.base.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.cpte.modules.base.entity.Area; import org.cpte.modules.base.entity.Point; -import org.cpte.modules.base.entity.Stock; -import org.cpte.modules.base.mapper.AreaMapper; import org.cpte.modules.base.mapper.PointMapper; import org.cpte.modules.base.service.IAreaService; import org.cpte.modules.base.service.IPointService; +import org.cpte.modules.constant.enums.AreaTypeEnum; +import org.cpte.modules.constant.enums.CommonStatusEnum; +import org.jeecg.common.util.RedisUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -35,6 +34,9 @@ public class PointServiceImpl extends ServiceImpl implements @Autowired private PointMapper pointMapper; + @Autowired + private RedisUtil redisUtil; + /** * 验证库位 * @@ -56,6 +58,18 @@ public class PointServiceImpl extends ServiceImpl implements return point; } + @Override + public void bindPoint(Point point) { + point.setStatus(CommonStatusEnum.USED.getValue()); + pointMapper.updateById(point); + } + + @Override + public void unbindPoint(Point point) { + point.setStatus(CommonStatusEnum.FREE.getValue()); + pointMapper.updateById(point); + } + /** * 根据库位编码集合查询库位信息 * @@ -106,4 +120,25 @@ public class PointServiceImpl extends ServiceImpl implements } return pointMap; } + + @Override + public Point getWorkStationPoint(Integer status, String areaCode, String key) { + List dstPointList = pointMapper.queryPoints(null, status, areaCode); + if (dstPointList.isEmpty()) { + String desc = AreaTypeEnum.getDescByValue(areaCode); + throw new RuntimeException("【" + desc + "】" + "无空闲库位"); + } + long currentIndex = redisUtil.incr(key, 1) % dstPointList.size(); + return dstPointList.get((int) currentIndex); + } + + @Override + public Point queryToPoint(String pointCode, Integer status, String areaCode) { + Point dstPoint = null; + List dstPointList = pointMapper.queryPoints(pointCode, status, areaCode); + if (dstPointList.isEmpty()) { + throw new RuntimeException("【" + AreaTypeEnum.CPCCQ.getDesc() + "】无空闲库位"); + } + return dstPoint = dstPointList.get(0); + } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/StockServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/StockServiceImpl.java index 676ae15..4c77b15 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/StockServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/impl/StockServiceImpl.java @@ -3,11 +3,14 @@ package org.cpte.modules.base.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; +import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; import org.cpte.modules.base.entity.Stock; import org.cpte.modules.base.mapper.StockMapper; import org.cpte.modules.base.mapper.StockMapper; import org.cpte.modules.base.service.IStockService; +import org.cpte.modules.constant.enums.CommonStatusEnum; +import org.cpte.modules.constant.enums.StockTypeEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -51,6 +54,20 @@ public class StockServiceImpl extends ServiceImpl implements return stock; } + @Override + public void validateStockStatus(Stock stock) { + if (CommonStatusEnum.USED.getValue().equals(stock.getStatus())) { + throw new RuntimeException(stock.getStockCode() + "容器已占用,请更换容器!"); + } + } + + @Override + public void bindStock(Stock stock, Point point) { + stock.setPointId(point.getId()); + stock.setStatus(CommonStatusEnum.USED.getValue()); + stockMapper.updateById(stock); + } + /** * 根据容器编码集合查询容器信息 diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/CommonConstant.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/CommonConstant.java deleted file mode 100644 index 8855b31..0000000 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/CommonConstant.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.cpte.modules.constant; - -/** - * 通用常量 - */ -public interface CommonConstant { - /** - * 入库输送线任务均衡索引 - */ - String RK_DOCK_TASK_INDEX = "rk_dock_task_index"; - - /** - * 入库单规则编码 - */ - String ASN_ORDER_NO = "asn_order_no"; - - /** - * 出库单规则编码 - */ - String PICK_ORDER_NO = "pick_order_no"; -} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/GeneralConstant.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/GeneralConstant.java new file mode 100644 index 0000000..e04818d --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/GeneralConstant.java @@ -0,0 +1,57 @@ +package org.cpte.modules.constant; + +/** + * 通用常量 + */ +public interface GeneralConstant { + /** + * 接口开关 + */ + final String OPEN_FLAG = "OPEN"; + + /** + * 成功码 + */ + final String AGV_SUCCESS_CODE = "SUCCESS"; + + /** + * 失败码 + */ + final String AGV_FAIL_CODE = "FAILED"; + + /** + * 成功码 + */ + final Integer TES_SUCCESS_CODE = 0; + + /** + * 失败码 + */ + final Integer TES_FAIL_CODE = 500; + + /** + * 入库输送线任务均衡索引 + */ + String RK_DOCK_TASK_INDEX = "rk_dock_task_index"; + + /** + * 出库输送线任务均衡索引 + */ + String CK_DOCK_TASK_INDEX = "ck_dock_task_index"; + + + /** + * 入库单规则编码 + */ + String ASN_ORDER_NO = "asn_order_no"; + + /** + * 出库单规则编码 + */ + String PICK_ORDER_NO = "pick_order_no"; + + /** + * 入库回传接口 + */ + String INBOUND_CALLBACK = "7Q7sqpIh"; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/AreaTypeEnum.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/AreaTypeEnum.java index f011766..67c5f2e 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/AreaTypeEnum.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/AreaTypeEnum.java @@ -31,4 +31,19 @@ public enum AreaTypeEnum { this.desc = desc; } + /** + * 根据值获取描述 + * + * @param value 值 + * @return 枚举 + */ + public static String getDescByValue(String value) { + for (AreaTypeEnum item : AreaTypeEnum.values()) { + if (item.value.equals(value)) { + return item.desc; + } + } + return null; + } + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BaseEnum.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BaseEnum.java deleted file mode 100644 index 73a1b92..0000000 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BaseEnum.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.cpte.modules.constant.enums; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONAware; -import com.alibaba.fastjson.JSONObject; -import com.google.common.base.CaseFormat; -import lombok.Data; - -import java.util.LinkedHashMap; -import java.util.Objects; - -/** - * 枚举类接口 - * - * @Author YouChain: 胡克 - * @Date 2018-07-17 21:22:12 - * @Email huoj@youchain56.com - */ -public interface BaseEnum { - - /** - * 获取枚举类的值 - * - * @return - */ - Object getValue(); - - /** - * 获取枚举类的说明 - * - * @return String - */ - String getDesc(); - - /** - * 比较参数是否与枚举类的value相同 - * - * @param value - * @return boolean - */ - default boolean equalsValue(Object value) { - return Objects.equals(getValue(), value); - } - - /** - * 比较枚举类是否相同 - * - * @param baseEnum - * @return boolean - */ - default boolean equals(BaseEnum baseEnum) { - return Objects.equals(getValue(), baseEnum.getValue()) && Objects.equals(getDesc(), baseEnum.getDesc()); - } - - /** - * 返回枚举类的说明 - * - * @param clazz 枚举类类对象 - * @return - */ - static String getInfo(Class clazz) { - BaseEnum[] enums = clazz.getEnumConstants(); - LinkedHashMap json = new LinkedHashMap<>(enums.length); - for (BaseEnum e : enums) { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("value", new DeletedQuotationAware(e.getValue())); - jsonObject.put("desc", new DeletedQuotationAware(e.getDesc())); - json.put(e.toString(), jsonObject); - } - - String enumJson = JSON.toJSONString(json, true); - enumJson = enumJson.replaceAll("\"", ""); - enumJson = enumJson.replaceAll("\t", "  "); - enumJson = enumJson.replaceAll("\n", "
"); - String prefix = "
export const " + CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName() + " =
"); - return prefix + enumJson + "
"; - } - - @Data - class DeletedQuotationAware implements JSONAware { - - private String value; - - public DeletedQuotationAware(Object value) { - if (value instanceof String) { - this.value = "'" + value + "'"; - } else { - this.value = value.toString(); - } - } - - @Override - public String toJSONString() { - return value; - } - } -} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BusinessTypeEnum.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BusinessTypeEnum.java index 2e61242..eebda47 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BusinessTypeEnum.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/BusinessTypeEnum.java @@ -3,7 +3,7 @@ package org.cpte.modules.constant.enums; import lombok.Getter; /** - * 业务类型枚举 + * AGV业务类型枚举 * * @author: cpte */ diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/TaskTypeEnum.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/TaskTypeEnum.java new file mode 100644 index 0000000..accc8f4 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/constant/enums/TaskTypeEnum.java @@ -0,0 +1,26 @@ +package org.cpte.modules.constant.enums; + +import lombok.Getter; + +@Getter +public enum TaskTypeEnum { + PICK(1, "出库"), + ; + + TaskTypeEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + /** + * 值 + */ + final Integer value; + + /** + * 描述 + */ + final String desc; + + +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java index df29f09..86ae322 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/impl/IConveyorLineServiceImpl.java @@ -7,6 +7,7 @@ import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; import org.cpte.modules.base.mapper.PointMapper; import org.cpte.modules.base.mapper.StockMapper; +import org.cpte.modules.base.service.IPointService; import org.cpte.modules.constant.enums.*; import org.cpte.modules.conveyorLine.request.ScanTrayRequest; import org.cpte.modules.conveyorLine.service.IConveyorLineService; @@ -38,6 +39,9 @@ public class IConveyorLineServiceImpl implements IConveyorLineService { @Autowired private InventoryMapper inventoryMapper; + @Autowired + private IPointService pointService; + @Autowired private IAgvTaskService iAgvTaskService; @@ -64,19 +68,17 @@ public class IConveyorLineServiceImpl implements IConveyorLineService { throw new RuntimeException("【" + scanTrayRequest.getStockCode() + "】托盘已扫描,请勿重复扫描"); } + //输送线的起点 + Point srcPoint=pointMapper.selectById(asnDetail.getToPointId()); + //通过算法获取目标点位 - List dstPointList = pointMapper.queryPoints(null, CommonStatusEnum.FREE.getValue(), AreaTypeEnum.CPCCQ.getValue()); - if (dstPointList.isEmpty()) { - throw new RuntimeException("【" + AreaTypeEnum.CPCCQ.getDesc() + "】无空闲库位"); - } - Point dstPoint = dstPointList.get(0); + Point dstPoint=pointService.queryToPoint(null, CommonStatusEnum.FREE.getValue(), AreaTypeEnum.CPCCQ.getValue()); //锁定目标库位 - dstPoint.setStatus(CommonStatusEnum.USED.getValue()); - pointMapper.updateById(dstPoint); + pointService.bindPoint(dstPoint); //验证通过,生成Tes任务 - iAgvTaskService.createAgvTask(asnDetail.getId(), AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), null, dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.TES.getValue()); + iAgvTaskService.createAgvTask(asnDetail.getId(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.TES.getValue()); } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java index b64935b..c578038 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/controller/HikAgvController.java @@ -47,7 +47,6 @@ public class HikAgvController { @AutoLog(value = "海康AGV-任务上报") @Operation(summary = "海康AGV-任务上报") @PostMapping(value = "/reporter/task") - @IgnoreAuth public HikResult taskReporter(@RequestBody TaskReporterRequest taskReporterRequest) { try { iHikAgvService.taskReporter(taskReporterRequest); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java index 39097f9..f9443fe 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/hikAgv/service/impl/IHikAgvServiceImpl.java @@ -7,6 +7,11 @@ import org.apache.commons.lang3.StringUtils; import org.cpte.modules.agvTask.entity.AgvTask; import org.cpte.modules.agvTask.mapper.AgvTaskMapper; import org.cpte.modules.agvTask.service.IAgvTaskService; +import org.cpte.modules.base.entity.Point; +import org.cpte.modules.base.entity.Stock; +import org.cpte.modules.base.service.IPointService; +import org.cpte.modules.base.service.IStockService; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.*; import org.cpte.modules.hikAgv.request.SubmitRequest; import org.cpte.modules.hikAgv.request.TaskReporterRequest; @@ -25,27 +30,18 @@ import java.util.*; @Slf4j public class IHikAgvServiceImpl implements IHikAgvService { - /** - * 接口开关 - */ - final String open_flag = "OPEN"; - - /** - * 成功码 - */ - final String success_code = "SUCCESS"; - - /** - * 失败码 - */ - final String fail_code = "FAILED"; - @Autowired private SysDictMapper sysDictMapper; @Autowired private AgvTaskMapper agvTaskMapper; + @Autowired + private IStockService iStockService; + + @Autowired + private IPointService iPointService; + @Autowired private IAgvTaskService iAgvTaskService; @@ -61,7 +57,7 @@ public class IHikAgvServiceImpl implements IHikAgvService { SubmitRequest.TargetRoute dstTargetRoute = createDstTargetRoute(agvTask); submitRequest.setTargetRoute(Arrays.asList(srcTargetRoute, dstTargetRoute)); - submitRequest.setInitPriority( agvTask.getPriority()); + submitRequest.setInitPriority(agvTask.getPriority()); LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); String deadline = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); @@ -85,8 +81,8 @@ public class IHikAgvServiceImpl implements IHikAgvService { public void sendHikAgvTask(String url, String json, AgvTask agvTask) { log.info("请求报文:{}", json); // 检查接口开关, 未开启则返回 - if (sysDictMapper.queryByDictCode(open_flag) == null) { - updateAgvTaskResponse(agvTask, "接口未开启", fail_code); + if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) { + updateAgvTaskResponse(agvTask, "接口未开启", GeneralConstant.AGV_FAIL_CODE); return; } @@ -112,16 +108,14 @@ public class IHikAgvServiceImpl implements IHikAgvService { code = resulObject.getString("code"); message = resulObject.getString("message"); - if (!success_code.equals(code)) { + if (!GeneralConstant.AGV_SUCCESS_CODE.equals(code)) { throw new RuntimeException("AGV返回消息:" + message); } // 更新任务状态 updateAgvTaskResponse(agvTask, message, code); } catch (Exception e) { - // 记录异常到 AgvTask - updateAgvTaskResponse(agvTask, e.getMessage(), fail_code); - throw e; // 继续向上抛出异常供 Controller 层处理 + updateAgvTaskResponse(agvTask, e.getMessage(), GeneralConstant.AGV_FAIL_CODE); } } @@ -132,6 +126,8 @@ public class IHikAgvServiceImpl implements IHikAgvService { if (agvTask == null) { throw new RuntimeException("【" + taskReporterRequest.getRobotTaskCode() + "】任务不存在"); } + Stock stock = iStockService.validateStock(agvTask.getCarrierCode()); + Point point = iPointService.validatePoint(agvTask.getEndCode()); String status = taskReporterRequest.getExtra().getValues().getMethod(); switch (status) { case "outbin": @@ -140,7 +136,7 @@ public class IHikAgvServiceImpl implements IHikAgvService { break; case "end": //任务完成 - handleEnd(agvTask); + handleEnd(agvTask, stock, point); break; case "resend": //重新发送 @@ -164,7 +160,10 @@ public class IHikAgvServiceImpl implements IHikAgvService { * * @param agvTask 任务 */ - private void handleEnd(AgvTask agvTask) { + private void handleEnd(AgvTask agvTask, Stock stock, Point point) { + //绑定容器和点位 + iStockService.bindStock(stock, point); + //更新任务状态 agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue()); agvTask.setEndTime(new Date()); agvTaskMapper.updateById(agvTask); @@ -176,11 +175,11 @@ public class IHikAgvServiceImpl implements IHikAgvService { * @param agvTask 任务 */ private void handleResend(AgvTask agvTask) { - Long count = agvTaskMapper.existsByStockCode(agvTask.getCarrierCode(),AgvVendorEnum.HIK.getValue()); + Long count = agvTaskMapper.existsByStockCode(agvTask.getCarrierCode(), AgvVendorEnum.HIK.getValue()); if (count > 0) { throw new RuntimeException("任务已重新生成,请勿重复操作! "); } - AgvTask newAgvTask = iAgvTaskService.createAgvTask(agvTask.getBusinessDetailId(),AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(),AgvVendorEnum.HIK.getValue()); + AgvTask newAgvTask = iAgvTaskService.createAgvTask(agvTask.getBusinessDetailId(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), AgvVendorEnum.HIK.getValue()); switch (agvTask.getType()) { case "INBOUND": case "OUTBOUND": @@ -195,7 +194,7 @@ public class IHikAgvServiceImpl implements IHikAgvService { private void updateAgvTaskResponse(AgvTask agvTask, String message, String code) { if (agvTask != null) { - if (success_code.equals(code)) { + if (GeneralConstant.AGV_SUCCESS_CODE.equals(code)) { agvTask.setStatus(AgvStatusEnum.EXECUTING.getValue()); } agvTask.setResMessage(message); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/service/impl/InventoryServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/service/impl/InventoryServiceImpl.java index adeba64..8928d3d 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/service/impl/InventoryServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/service/impl/InventoryServiceImpl.java @@ -41,7 +41,7 @@ public class InventoryServiceImpl extends ServiceImpl pickDetailList = pickDetailMapper.queryUnallocatedPickDetail(); - if (pickDetailList.isEmpty()) { + // 查询未分配或者部分分配的出库 + List pickList = pickMapper.queryUnallocatedPick(); + if (pickList.isEmpty()) { return; } - // 分配出库明细 + // 分配出库 long startTime = System.currentTimeMillis(); - List resultMsg = iPickService.allocatePickDetail2(pickDetailList); + List resultMsg = iPickService.allocatePick2(pickList); long endTime = System.currentTimeMillis(); log.info("分配出库明细耗时:{}ms", endTime - startTime); if (CollectionUtils.isNotEmpty(resultMsg)) { @@ -69,6 +78,13 @@ public class AllocateJob implements Job { } } } + + //生成出库AGV出库任务 + long startTime2 = System.currentTimeMillis(); + List taskList = taskMapper.queryUnallocatedTask(); + iTaskService.generateAgvTask(taskList); + long endTime2 = System.currentTimeMillis(); + log.info("生成AGV出库任务耗时:{}ms", endTime2 - startTime2); } /** diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/HikAgvJob.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/HikAgvJob.java index c5e7219..808c488 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/HikAgvJob.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/HikAgvJob.java @@ -30,19 +30,15 @@ public class HikAgvJob implements Job { } String taskSubmitUrl = "http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit"; for (AgvTask agvTask : agvTaskList) { - try { - // 判断起点无任务才允许下发 - boolean isStartCodeAvailable = agvTaskMapper.existsByStartCode(agvTask.getStartCode(), AgvVendorEnum.HIK.getValue()) == 0; - if (isStartCodeAvailable) { - hikAgvService.sendHikAgvTask( - taskSubmitUrl, - hikAgvService.generateHikAgvTaskJson(agvTask), - agvTask - ); - } - } catch (Exception e) { - log.error("发送AGV任务失败,任务ID: {}", agvTask.getId(), e); + boolean isStartCodeAvailable = agvTaskMapper.existsByStartCode(agvTask.getStartCode(), AgvVendorEnum.HIK.getValue()) == 0; + if (isStartCodeAvailable) { + hikAgvService.sendHikAgvTask( + taskSubmitUrl, + hikAgvService.generateHikAgvTaskJson(agvTask), + agvTask + ); } + } } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/TesAgvJob.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/TesAgvJob.java index 87b2742..d0a3e31 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/TesAgvJob.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/quartz/job/TesAgvJob.java @@ -31,15 +31,12 @@ public class TesAgvJob implements Job { } String taskSubmitUrl = "http://localhost:8000/cpte-wms/tes/apiv2/newMovePodTask"; for (AgvTask agvTask : agvTaskList) { - try { - tesAgvService.sendTesAgvTask( - taskSubmitUrl, - tesAgvService.generateTesAgvTaskJson(agvTask), - agvTask - ); - } catch (Exception e) { - log.error("发送AGV任务失败,任务ID: {}", agvTask.getId(), e); - } + tesAgvService.sendTesAgvTask( + taskSubmitUrl, + tesAgvService.generateTesAgvTaskJson(agvTask), + agvTask + ); + } } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/controller/AsnController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/controller/AsnController.java index da46220..b92dcb5 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/controller/AsnController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/controller/AsnController.java @@ -8,7 +8,7 @@ import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.cpte.modules.constant.CommonConstant; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.serialNumber.AsnSerialNumberRule; import org.jeecgframework.poi.excel.ExcelImportUtil; import org.jeecgframework.poi.excel.def.NormalExcelConstants; @@ -92,7 +92,7 @@ public class AsnController { @PostMapping(value = "/add") public Result add(@RequestBody AsnPage asnPage) { Asn asn = new Asn(); - String orderNo = asnSerialNumberRule.generateSerialNumber(CommonConstant.ASN_ORDER_NO); + String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO); asn.setOrderNo(orderNo); BeanUtils.copyProperties(asnPage, asn); asnService.saveMain(asn, asnPage.getAsnDetailList()); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java index a9a3ab7..6d86358 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java @@ -111,6 +111,22 @@ public class Asn implements Serializable { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Schema(description = "订单日期") private java.util.Date orderDate; + + /** + * 返回报文 + */ + @Excel(name = "返回报文", width = 15) + @Schema(description = "返回报文") + private java.lang.String resMessage; + + /** + * 回传时间 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "回传时间") + private java.util.Date resTime; + /** * 所属部门 */ diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/AsnDetail.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/AsnDetail.java index aef54e0..cb035fc 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/AsnDetail.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/AsnDetail.java @@ -65,13 +65,20 @@ public class AsnDetail implements Serializable { @Schema(description = "容器") @JsonSerialize(using = ToStringSerializer.class) private java.lang.Long stockId; + /** - * 库位 + * 起点库位 */ - @Excel(name = "库位", width = 15) - @Schema(description = "库位") + @Schema(description = "起点库位") @JsonSerialize(using = ToStringSerializer.class) - private java.lang.Long pointId; + private java.lang.Long fromPointId; + /** + * 终点库位 + */ + @Schema(description = "终点库位") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long toPointId; + /** * 行号 */ diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/ReceiveRecord.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/ReceiveRecord.java index e3372dc..8f96eec 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/ReceiveRecord.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/ReceiveRecord.java @@ -45,11 +45,18 @@ public class ReceiveRecord implements Serializable { @JsonSerialize(using = ToStringSerializer.class) private java.lang.Long stockId; /** - * 库位 + * 起点库位 */ - @Schema(description = "库位") + @Schema(description = "起点库位") @JsonSerialize(using = ToStringSerializer.class) - private java.lang.Long pointId; + private java.lang.Long fromPointId; + /** + * 终点库位 + */ + @Schema(description = "终点库位") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long toPointId; + /** * 物料 */ diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/IAsnService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/IAsnService.java index 5c5a546..aac4dc7 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/IAsnService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/IAsnService.java @@ -1,5 +1,6 @@ package org.cpte.modules.receive.service; +import org.cpte.modules.base.entity.Stock; import org.cpte.modules.receive.entity.AsnDetail; import org.cpte.modules.receive.entity.Asn; import com.baomidou.mybatisplus.extension.service.IService; @@ -54,4 +55,12 @@ public interface IAsnService extends IService { */ void receiveGoods(Long asnDetailId, String pointCode); + /** + * 入库任务回传 + * + * @param asn 入库单 + * @param asnDetail 入库明细 + * @param stock 容器 + */ + void receiveCallback(Asn asn, AsnDetail asnDetail, Stock stock); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnServiceImpl.java index 877f37b..61c666a 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnServiceImpl.java @@ -1,13 +1,21 @@ package org.cpte.modules.receive.service.impl; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; import org.cpte.modules.base.mapper.PointMapper; import org.cpte.modules.base.mapper.StockMapper; +import org.cpte.modules.base.service.IPointService; +import org.cpte.modules.base.service.IStockService; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.AsnStatusEnum; import org.cpte.modules.constant.enums.CommonStatusEnum; import org.cpte.modules.inventory.entity.Inventory; +import org.cpte.modules.inventory.mapper.InventoryMapper; import org.cpte.modules.inventory.service.IInventoryService; import org.cpte.modules.inventoryLog.service.IInventoryLogService; import org.cpte.modules.receive.entity.Asn; @@ -18,6 +26,11 @@ import org.cpte.modules.receive.mapper.AsnMapper; import org.cpte.modules.receive.mapper.ReceiveRecordMapper; import org.cpte.modules.receive.service.IAsnService; import org.cpte.modules.utils.BigDecimalUtil; +import org.jeecg.common.config.TenantContext; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.openapi.mapper.OpenApiMapper; +import org.jeecg.modules.system.mapper.SysDictMapper; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -40,6 +53,7 @@ import java.util.concurrent.atomic.AtomicInteger; @Service @Slf4j public class AsnServiceImpl extends ServiceImpl implements IAsnService { + @Autowired private StockMapper stockMapper; @Autowired @@ -51,6 +65,16 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS @Autowired private ReceiveRecordMapper receiveRecordMapper; @Autowired + private InventoryMapper inventoryMapper; + @Autowired + private OpenApiMapper openApiMapper; + @Autowired + private SysDictMapper sysDictMapper; + @Autowired + private IStockService iStockService; + @Autowired + private IPointService iPointService; + @Autowired private IInventoryService iInventoryService; @Autowired private IInventoryLogService iInventoryLogService; @@ -58,13 +82,16 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS @Override @Transactional(rollbackFor = Exception.class) public void saveMain(Asn asn, List asnDetailList) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + asn.setSysOrgCode(sysUser.getOrgCode()); asnMapper.insert(asn); if (asnDetailList == null || asnDetailList.isEmpty()) { throw new RuntimeException("请新增入库明细"); } - if(asnDetailList.size()>1){ + if (asnDetailList.size() > 1) { throw new RuntimeException("入库明细只允许新增一条"); } @@ -74,6 +101,8 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS entity.setLineNo(lineNoCounter.getAndIncrement()); } entity.setAsnId(asn.getId()); + asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + asn.setSysOrgCode(sysUser.getOrgCode()); asnDetailMapper.insert(entity); } //刷新入库单 @@ -124,7 +153,7 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS throw new RuntimeException("请新增入库明细"); } - if(asnDetailList.size()>1){ + if (asnDetailList.size() > 1) { throw new RuntimeException("入库明细只允许新增一条"); } @@ -183,6 +212,11 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS throw new RuntimeException("未匹配到入库任务【" + asnDetailId + "】"); } + //验证容器是否入库 + if (inventoryMapper.queryByStockId(asnDetail.getStockId()) != null) { + throw new RuntimeException("【" + asnDetail.getStockId() + "】容器已入库"); + } + //入库单 Asn asn = this.getById(asnDetail.getAsnId()); @@ -214,10 +248,90 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS refreshAsn(asn, asnDetailMapper.selectByMainId(asn.getId())); //更新容器状态和位置 - updateStockPoint(stock, dstPoint); + iStockService.bindStock(stock, dstPoint); + iPointService.bindPoint(dstPoint); //添加库存日志 - iInventoryLogService.addInboundInventoryLog(inventory, asnDetail.getPointId(), receivedQty, asn.getOrderNo(), asnDetail.getId(), asnDetail.getDescription()); + iInventoryLogService.addInboundInventoryLog(inventory, asnDetail.getToPointId(), receivedQty, asn.getOrderNo(), asnDetail.getId(), asnDetail.getDescription()); + + //回传 + receiveCallback(asn, asnDetail, stock); + } + + + /** + * 入库任务回传JSON + */ + private String receiveCallbackJson(Asn asn, AsnDetail asnDetail, Stock stock) { + JSONObject jsonObject = new JSONObject(true); + jsonObject.put("No", asn.getNo()); + jsonObject.put("OrderNo", asn.getThirdOrderNo()); + jsonObject.put("State", 5); + jsonObject.put("LineNo", asnDetail.getLineNo()); + jsonObject.put("Lpn", stock.getStockCode()); + jsonObject.put("Qty", asnDetail.getOrderQty()); + jsonObject.put("Project", asnDetail.getProject()); + jsonObject.put("TaskNo", asnDetail.getTaskNo()); + jsonObject.put("LotAtt04", asnDetail.getPropC1()); + jsonObject.put("LotAtt010", asnDetail.getPropC3()); + return jsonObject.toJSONString(); + } + + @Override + public void receiveCallback(Asn asn, AsnDetail asnDetail, Stock stock) { + String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK); + String json = receiveCallbackJson(asn, asnDetail, stock); + + log.info("入库回传请求报文:{}", json); + // 检查接口开关, 未开启则返回 + if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) { + updateAsnDetailResponse(asn, "接口未开启"); + return; + } + + Boolean Success = null; + String Message = null; + try { + //String result = HttpPostUtil.sendPostReq(url, json); + String result = "{\n" + + " \"Success\": false,\n" + + " \"Message\": \"入库回传失败\"\n" + + "}"; + if (StringUtils.isEmpty(result)) { + Message = "入库回传返回信息:接口调用失败"; + throw new RuntimeException(Message); + } + + JSONObject resulObject = JSON.parseObject(result); + if (resulObject == null) { + Message = "入库回传返回信息:接口返回为空"; + throw new RuntimeException(Message); + } + + Success = resulObject.getBoolean("Success"); + Message = resulObject.getString("Message"); + + if (!Success) { + throw new RuntimeException("入库回传返回信息:" + Message); + } + updateAsnDetailResponse(asn, Message); + } catch (Exception e) { + updateAsnDetailResponse(asn, e.getMessage()); + } + } + + /** + * 更新任务状态 + * + * @param asn 入库单 + * @param message 信息 + */ + private void updateAsnDetailResponse(Asn asn, String message) { + if (asn != null) { + asn.setResMessage(message); + asn.setResTime(new Date()); + asnMapper.updateById(asn); + } } /** @@ -227,7 +341,8 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS ReceiveRecord receiveRecord = ReceiveRecord.builder() .asnDetailId(asnDetail.getId()) .stockId(asnDetail.getStockId()) - .pointId(dstPointId) + .fromPointId(asnDetail.getToPointId()) + .toPointId(dstPointId) .itemId(asnDetail.getItemId()) .receivedQty(receivedQty) .propC1(asnDetail.getPropC1()) @@ -244,19 +359,4 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS return receiveRecord; } - - /** - * 更新容器位置和状态 - */ - private void updateStockPoint(Stock stock, Point point) { - stock.setPointId(point.getId()); - stock.setStatus(CommonStatusEnum.USED.getValue()); - stockMapper.updateById(stock); - - // 更新库位状态为占用 - point.setStatus(CommonStatusEnum.USED.getValue()); // 占用状态 - pointMapper.updateById(point); - } - - } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/controller/SaiWmsController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/controller/SaiWmsController.java index 1cb7a6a..7768540 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/controller/SaiWmsController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/controller/SaiWmsController.java @@ -33,7 +33,6 @@ public class SaiWmsController { @AutoLog(value = "入库任务下发") @Operation(summary = "赛意WMS-入库任务下发") @PostMapping(value = "/inBound/inBoundTask") - @IgnoreAuth public Result inBoundTask(@RequestBody @Valid InboundRequest inboundRequest) { iSaiWmsService.inBoundTask(inboundRequest); return Result.OK("操作成功!"); @@ -47,7 +46,6 @@ public class SaiWmsController { @AutoLog(value = "出库任务下发") @Operation(summary = "赛意WMS-出库任务下发") @PostMapping(value = "/outBound/outBoundTask") - @IgnoreAuth public Result outBoundTask(@RequestBody @Valid OutboundRequest outboundRequest) { iSaiWmsService.outBoundTask(outboundRequest); return Result.OK("操作成功!"); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/request/InboundRequest.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/request/InboundRequest.java index 716cd37..7dc3c9f 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/request/InboundRequest.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/request/InboundRequest.java @@ -1,10 +1,12 @@ package org.cpte.modules.saiWms.request; import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; import java.math.BigDecimal; import java.util.List; diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/ISaiWmsService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/ISaiWmsService.java index 39307df..6f97bdf 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/ISaiWmsService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/ISaiWmsService.java @@ -1,5 +1,8 @@ package org.cpte.modules.saiWms.service; +import org.cpte.modules.base.entity.Stock; +import org.cpte.modules.receive.entity.Asn; +import org.cpte.modules.receive.entity.AsnDetail; import org.cpte.modules.saiWms.request.InboundRequest; import org.cpte.modules.saiWms.request.OutboundRequest; @@ -17,4 +20,6 @@ public interface ISaiWmsService { * @param outboundRequest 请求参数 */ void outBoundTask(OutboundRequest outboundRequest); + + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISaiWmsServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISaiWmsServiceImpl.java index f32861b..0fa29f5 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISaiWmsServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISaiWmsServiceImpl.java @@ -5,11 +5,10 @@ import org.cpte.modules.agvTask.service.IAgvTaskService; import org.cpte.modules.base.entity.Item; import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; -import org.cpte.modules.base.mapper.PointMapper; import org.cpte.modules.base.service.IItemService; import org.cpte.modules.base.service.IPointService; import org.cpte.modules.base.service.IStockService; -import org.cpte.modules.constant.CommonConstant; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.*; import org.cpte.modules.receive.entity.Asn; import org.cpte.modules.receive.entity.AsnDetail; @@ -24,7 +23,6 @@ import org.cpte.modules.shipping.entity.Pick; import org.cpte.modules.shipping.entity.PickDetail; import org.cpte.modules.shipping.mapper.PickMapper; import org.cpte.modules.shipping.service.IPickService; -import org.jeecg.common.util.RedisUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,10 +34,6 @@ import java.util.*; @Slf4j public class ISaiWmsServiceImpl implements ISaiWmsService { - - @Autowired - private PointMapper pointMapper; - @Autowired private AsnMapper asnMapper; @@ -61,7 +55,6 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { @Autowired private IPickService pickService; - @Autowired private IAgvTaskService iAgvTaskService; @@ -71,8 +64,6 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { @Autowired private PickSerialNumberRule pickSerialNumberRule; - @Autowired - private RedisUtil redisUtil; @Override @Transactional(rollbackFor = Exception.class) @@ -99,25 +90,22 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { Stock stock = iStockService.validateStock(stockCode); //获取输送线工作台点位,均衡分配点位任务-轮询方式 - List dstPointList = pointMapper.queryPoints(null, CommonStatusEnum.FREE.getValue(), AreaTypeEnum.RK_DOCK.getValue()); - if (dstPointList.isEmpty()) { - throw new RuntimeException("【" + AreaTypeEnum.RK_DOCK.getDesc() + "】" + "无空闲库位"); - } - String key = CommonConstant.RK_DOCK_TASK_INDEX; - long currentIndex = redisUtil.incr(key, 1) % dstPointList.size(); - Point dstPoint = dstPointList.get((int) currentIndex); + Point dstPoint = iPointService.getWorkStationPoint(CommonStatusEnum.FREE.getValue(), AreaTypeEnum.RK_DOCK.getValue(), GeneralConstant.RK_DOCK_TASK_INDEX); // 创建入库单和明细 Asn createAsn = buildAsn(inboundRequest); - AsnDetail asnDetail = buildAsnDetail(detail, srcPoint, item, stock); + AsnDetail asnDetail = buildAsnDetail(detail, srcPoint,dstPoint, item, stock); // 保存入库单和入库明细 asnService.saveMain(createAsn, Collections.singletonList(asnDetail)); + //绑定容器和起点 + iStockService.bindStock(stock, srcPoint); + //成品入库需要生成AGV if (AsnOrderTypeEnum.PRODUCT.getValue().equals(createAsn.getOrderType())) { //创建AGV任务 - iAgvTaskService.createAgvTask(asnDetail.getId(), AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.HIK.getValue()); + iAgvTaskService.createAgvTask(asnDetail.getId(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.HIK.getValue()); } } @@ -156,7 +144,7 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { * 构建入库单 */ private Asn buildAsn(InboundRequest inboundRequest) { - String orderNo = asnSerialNumberRule.generateSerialNumber(CommonConstant.ASN_ORDER_NO); + String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO); return Asn.builder() .orderNo(orderNo) .thirdOrderNo(inboundRequest.getOrderNo()) @@ -166,16 +154,13 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { .orderType(inboundRequest.getType()) .status(AsnStatusEnum.CREATED.getValue()) .orderDate(new Date()) - .sysOrgCode("A05") - .tenantId(1000L) - .createBy("赛意") .build(); } /** * 构建入库明细 */ - private AsnDetail buildAsnDetail(InboundRequest.InboundDetail detail, Point srcPoint, Item item, Stock stock) { + private AsnDetail buildAsnDetail(InboundRequest.InboundDetail detail, Point srcPoint, Point dstPoint, Item item, Stock stock) { // 由于明细只有一条,直接构建单个明细对象 return AsnDetail.builder() .lineNo(Integer.parseInt(detail.getLineNo())) @@ -184,7 +169,8 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { .orderQty(detail.getQty()) .receivedQty(BigDecimal.ZERO) .stockId(stock.getId()) - .pointId(srcPoint.getId()) + .fromPointId(srcPoint.getId()) + .toPointId(dstPoint.getId()) .status(AsnStatusEnum.CREATED.getValue()) .project(detail.getProject()) .taskNo(detail.getTaskNo()) @@ -198,7 +184,7 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { * 构建出库单 */ private Pick buildPick(OutboundRequest outboundRequest) { - String orderNo = pickSerialNumberRule.generateSerialNumber(CommonConstant.PICK_ORDER_NO); + String orderNo = pickSerialNumberRule.generateSerialNumber(GeneralConstant.PICK_ORDER_NO); return Pick.builder() .orderNo(orderNo) .thirdOrderNo(outboundRequest.getOrderNo()) @@ -208,9 +194,6 @@ public class ISaiWmsServiceImpl implements ISaiWmsService { .orderType(outboundRequest.getType()) .status(PickStatusEnum.CREATED.getValue()) .orderDate(new Date()) - .sysOrgCode("A05") - .tenantId(1000L) - .createBy("赛意") .build(); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/controller/PickController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/controller/PickController.java index 852d0c0..4cf2599 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/controller/PickController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/controller/PickController.java @@ -9,8 +9,15 @@ import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.cpte.modules.constant.CommonConstant; +import jakarta.validation.Valid; +import org.cpte.modules.constant.GeneralConstant; +import org.cpte.modules.saiWms.request.InboundRequest; import org.cpte.modules.serialNumber.PickSerialNumberRule; +import org.cpte.modules.shipping.entity.Task; +import org.cpte.modules.shipping.mapper.PickMapper; +import org.cpte.modules.shipping.mapper.TaskMapper; +import org.cpte.modules.shipping.service.ITaskService; +import org.jeecg.config.shiro.IgnoreAuth; import org.jeecgframework.poi.excel.ExcelImportUtil; import org.jeecgframework.poi.excel.def.NormalExcelConstants; import org.jeecgframework.poi.excel.entity.ExportParams; @@ -53,11 +60,17 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; @RequestMapping("/shipping/pick") @Slf4j public class PickController { + @Autowired + private PickMapper pickMapper; + @Autowired + private TaskMapper taskMapper; @Autowired private IPickService pickService; @Autowired private IPickDetailService pickDetailService; @Autowired + private ITaskService taskService; + @Autowired private PickSerialNumberRule pickSerialNumberRule; /** @@ -94,7 +107,7 @@ public class PickController { @PostMapping(value = "/add") public Result add(@RequestBody PickPage pickPage) { Pick pick = new Pick(); - String orderNo = pickSerialNumberRule.generateSerialNumber(CommonConstant.PICK_ORDER_NO); + String orderNo = pickSerialNumberRule.generateSerialNumber(GeneralConstant.PICK_ORDER_NO); pick.setOrderNo(orderNo); BeanUtils.copyProperties(pickPage, pick); pickService.saveMain(pick, pickPage.getPickDetailList()); @@ -267,4 +280,19 @@ public class PickController { return Result.OK("文件导入失败!"); } + /** + * 出库分配 + */ + @AutoLog(value = "出库分配") + @Operation(summary = "出库分配") + @PostMapping(value = "/allocatedPick") + @IgnoreAuth + public Result allocatedPick() { + List pickList = pickMapper.queryUnallocatedPick(); + pickService.allocatePick2(pickList); + List taskList = taskMapper.queryUnallocatedTask(); + taskService.generateAgvTask(taskList); + return Result.OK("操作成功!"); + } + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/entity/Task.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/entity/Task.java new file mode 100644 index 0000000..d8b27b2 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/entity/Task.java @@ -0,0 +1,197 @@ +package org.cpte.modules.shipping.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * @Description: 任务 + * @author: cpte + * @Date: 2025-11-17 + * @Version: V1.0 + */ +@TableName("data_task") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "任务") +public class Task implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "id") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long id; + /** + * 任务编号 + */ + @Excel(name = "任务编号", width = 15) + @Schema(description = "任务编号") + private java.lang.String taskNo; + /** + * 商品ID + */ + @Excel(name = "商品ID", width = 15) + @Schema(description = "商品ID") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long itemId; + + @Schema(description = "商品") + private java.lang.String itemCode; + + /** + * 原库位 + */ + @Excel(name = "原库位", width = 15) + @Schema(description = "原库位") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long fromPointId; + + @Excel(name = "原库位", width = 15) + private java.lang.String fromPointCode; + + /** + * 目标库位 + */ + @Excel(name = "目标库位", width = 15) + @Schema(description = "目标库位") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long toPointId; + + @Schema(description = "目标库位") + private java.lang.String toPointCode; + /** + * 容器 + */ + @Excel(name = "容器", width = 15) + @Schema(description = "容器") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long stockId; + + @Schema(description = "容器") + private java.lang.String stockCode; + /** + * 出库单ID + */ + @Excel(name = "出库单ID", width = 15) + @Schema(description = "出库单ID") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long pickId; + /** + * 出库明细ID + */ + @Excel(name = "出库明细ID", width = 15) + @Schema(description = "出库明细ID") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long pickDetailId; + /** + * 库存ID + */ + @Excel(name = "库存ID", width = 15) + @Schema(description = "库存ID") + @JsonSerialize(using = ToStringSerializer.class) + private java.lang.Long inventoryId; + + /** + * agvID + */ + @Excel(name = "agvID", width = 15) + @Schema(description = "agvID") + private java.lang.Long agvTaskId; + + /** + * 计划数量 + */ + @Excel(name = "计划数量", width = 15) + @Schema(description = "计划数量") + private java.math.BigDecimal planQty; + /** + * 已完成数量 + */ + @Excel(name = "已完成数量", width = 15) + @Schema(description = "已完成数量") + private java.math.BigDecimal moveQty; + /** + * 任务类型:1=拣货任务 + */ + @Excel(name = "任务类型", width = 15) + @Schema(description = "任务类型") + private java.lang.Integer taskType; + /** + * 任务状态:1=已创建,2=已完成,3=已取消 + */ + @Excel(name = "任务状态", width = 15) + @Schema(description = "任务状态") + private java.lang.Integer taskStatus; + + /** + * 是否整托0整托,1拆托 + */ + @Excel(name = "是否整托", width = 15) + @Schema(description = "是否整托") + private java.lang.Integer izAll; + /** + * 开始时间 + */ + @Excel(name = "开始时间", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "开始时间") + private java.util.Date startTime; + /** + * 完成时间 + */ + @Excel(name = "完成时间", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "完成时间") + private java.util.Date completeTime; + /** + * 所属部门 + */ + @Schema(description = "所属部门") + private java.lang.String sysOrgCode; + /** + * 仓库ID + */ + @Excel(name = "仓库ID", width = 15) + @Schema(description = "仓库ID") + private java.lang.Long tenantId; + /** + * 创建人 + */ + @Schema(description = "创建人") + private java.lang.String createBy; + /** + * 创建日期 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "创建日期") + private java.util.Date createTime; + /** + * 更新人 + */ + @Schema(description = "更新人") + private java.lang.String updateBy; + /** + * 更新日期 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "更新日期") + private java.util.Date updateTime; +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickDetailMapper.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickDetailMapper.java index 00f59a4..3d57358 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickDetailMapper.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickDetailMapper.java @@ -31,10 +31,13 @@ public interface PickDetailMapper extends BaseMapper { */ public List selectByMainId(@Param("mainId") Long mainId); - @Select("select * from data_pick_detail where status = 1 " + - "union all " + - "select * from data_pick_detail where status = 2 ") - List queryUnallocatedPickDetail(); + /** + * 通过出库单id集合查询出库明细 + * + * @param pickIds 出库单id集合 + * @return List + */ + List queryByPickIds(@Param("pickIds") List pickIds); @Select("select MAX(line_no) from data_pick_detail where pick_id = #{pickId} ") Integer queryMaxLineNoByPickId(@Param("pickId") Long pickId); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickMapper.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickMapper.java index 3c8b9a0..f9803da 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickMapper.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/PickMapper.java @@ -5,6 +5,9 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.cpte.modules.shipping.entity.Pick; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.cpte.modules.shipping.entity.PickDetail; + +import java.util.List; /** * @Description: 出库单 @@ -23,4 +26,14 @@ public interface PickMapper extends BaseMapper { @Select("select * from data_pick where no = #{no} for update ") Pick queryByNo(@Param("no") String no); + /** + * 查询未分配的出库单:已创建或者部分分配 + * + * @return List + */ + @Select("select id from data_pick where status = 1 " + + "union all " + + "select id from data_pick where status = 2 ") + List queryUnallocatedPick(); + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/TaskMapper.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/TaskMapper.java new file mode 100644 index 0000000..5a38f1f --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/TaskMapper.java @@ -0,0 +1,25 @@ +package org.cpte.modules.shipping.mapper; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.cpte.modules.shipping.entity.Pick; +import org.cpte.modules.shipping.entity.Task; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.util.List; + +/** + * @Description: 任务 + * @author: cpte + * @Date: 2025-11-17 + * @Version: V1.0 + */ +public interface TaskMapper extends BaseMapper { + /** + * 查询未分配的AGV的Task任务 + * + * @return List + */ + @Select("select * from data_task where agv_task_id is null order by create_time") + List queryUnallocatedTask(); +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/PickDetailMapper.xml b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/PickDetailMapper.xml index 087918b..1f4e42c 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/PickDetailMapper.xml +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/PickDetailMapper.xml @@ -15,4 +15,14 @@ WHERE pick_id = #{mainId} + + diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/TaskMapper.xml b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/TaskMapper.xml new file mode 100644 index 0000000..d97e630 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/mapper/xml/TaskMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java index c663893..e638970 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java @@ -47,17 +47,17 @@ public interface IPickService extends IService { public void delBatchMain(Collection idList); /** - * 分配出库单明细 + * 分配出库单 * - * @param pickDetails 出库单明细集合 + * @param pickIds 出库单集合 */ - List allocatePickDetail(List pickDetails); + List allocatePick(List pickIds); /** - * 分配出库单明细 + * 分配出库单 * - * @param pickDetails 出库单明细集合 + * @param pickIds 出库单集合 */ - List allocatePickDetail2(List pickDetails); + List allocatePick2(List pickIds); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/ITaskService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/ITaskService.java new file mode 100644 index 0000000..85fcd9a --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/ITaskService.java @@ -0,0 +1,60 @@ +package org.cpte.modules.shipping.service; + +import org.cpte.modules.base.entity.Item; +import org.cpte.modules.base.entity.Point; +import org.cpte.modules.base.entity.Stock; +import org.cpte.modules.shipping.entity.Task; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.math.BigDecimal; +import java.util.List; + +/** + * @Description: 任务 + * @author: cpte + * @Date: 2025-11-17 + * @Version: V1.0 + */ +public interface ITaskService extends IService { + /** + * 创建任务 + * + * @param taskNo 任务编号 + * @param taskType 任务类型 + * @param item 物料 + * @param fromPoint 原点位 + * @param toPoint 目标点位 + * @param stock 容器 + * @param pickId 出库单ID + * @param pickDetailId 出库单明细ID + * @param inventoryId 库存ID + * @param planQty 计划数量 + * @param izAll 是否整托 + * @return Task + */ + Task createTask(String taskNo, Integer taskType, Item item, Point fromPoint, Point toPoint, Stock stock, Long pickId, Long pickDetailId, Long inventoryId, BigDecimal planQty, Integer izAll); + + /** + * 构建任务 + * + * @param taskNo 任务编号 + * @param taskType 任务类型 + * @param item 物料 + * @param fromPoint 原点位 + * @param toPoint 目标点位 + * @param stock 容器 + * @param pickId 出库单ID + * @param pickDetailId 出库单明细ID + * @param inventoryId 库存ID + * @param planQty 计划数量 + * @param izAll 是否整托 + * @return Task + */ + Task bulidTask(String taskNo, Integer taskType, Item item, Point fromPoint, Point toPoint, Stock stock, Long pickId, Long pickDetailId, Long inventoryId, BigDecimal planQty, Integer izAll); + + /** + * 根据Task集合生成AGV出库任务 + */ + void generateAgvTask(List taskList); + +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java index eefdfbb..2ce049e 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java @@ -2,28 +2,31 @@ package org.cpte.modules.shipping.service.impl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.shiro.SecurityUtils; import org.apache.shiro.lang.util.StringUtils; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.base.entity.Item; import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; import org.cpte.modules.base.service.IItemService; import org.cpte.modules.base.service.IPointService; import org.cpte.modules.base.service.IStockService; -import org.cpte.modules.constant.enums.AsnStatusEnum; -import org.cpte.modules.constant.enums.InventoryStatusEnum; -import org.cpte.modules.constant.enums.PickStatusEnum; +import org.cpte.modules.constant.enums.*; import org.cpte.modules.inventory.entity.Inventory; import org.cpte.modules.inventory.mapper.InventoryMapper; -import org.cpte.modules.inventory.service.IInventoryService; import org.cpte.modules.inventoryLog.service.IInventoryLogService; import org.cpte.modules.shipping.entity.Pick; import org.cpte.modules.shipping.entity.PickDetail; +import org.cpte.modules.shipping.entity.Task; import org.cpte.modules.shipping.mapper.PickDetailMapper; import org.cpte.modules.shipping.mapper.PickMapper; import org.cpte.modules.shipping.service.IPickService; +import org.cpte.modules.shipping.service.ITaskService; import org.cpte.modules.shipping.vo.InventoryGroupKey; +import org.cpte.modules.utils.BatchUtils; import org.cpte.modules.utils.BigDecimalUtil; import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.system.vo.LoginUser; import org.jeecg.modules.base.service.BaseCommonService; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -59,9 +62,13 @@ public class PickServiceImpl extends ServiceImpl implements IP @Autowired private IPointService iPointService; @Autowired + private ITaskService iTaskService; + @Autowired private IInventoryLogService iInventoryLogService; @Autowired private BaseCommonService baseCommonService; + @Autowired + private BatchUtils batchUtils; /** * 获取出库单Map @@ -82,6 +89,9 @@ public class PickServiceImpl extends ServiceImpl implements IP @Override @Transactional(rollbackFor = Exception.class) public void saveMain(Pick pick, List pickDetailList) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + pick.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + pick.setSysOrgCode(sysUser.getOrgCode()); pickMapper.insert(pick); if (pickDetailList == null || pickDetailList.isEmpty()) { @@ -97,6 +107,8 @@ public class PickServiceImpl extends ServiceImpl implements IP entity.setLineNo(lineNoCounter.getAndIncrement()); } entity.setPickId(pick.getId()); + entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + entity.setSysOrgCode(sysUser.getOrgCode()); pickDetailMapper.insert(entity); } //刷新出库单 @@ -231,13 +243,15 @@ public class PickServiceImpl extends ServiceImpl implements IP @Override @Transactional(rollbackFor = Exception.class) - public List allocatePickDetail(List pickDetails) { + public List allocatePick(List pickIds) { List errorMsgList = new ArrayList<>(); //查询出库单 - List pickIds = pickDetails.stream().map(PickDetail::getPickId).distinct().toList(); Map pickMap = queryByPickIdsToMap(pickIds); + //查询出库单明细 + List pickDetails = pickDetailMapper.queryByPickIds(pickIds); + //获取不为null、空字符的批次号 List propC1List = pickDetails.stream().map(PickDetail::getPropC1).filter(Objects::nonNull).filter(e -> !e.isEmpty()).distinct().toList(); @@ -378,15 +392,17 @@ public class PickServiceImpl extends ServiceImpl implements IP @Override @Transactional(rollbackFor = Exception.class) - public List allocatePickDetail2(List pickDetails) { + public List allocatePick2(List pickIds) { // 错误信息去重(LinkedHashSet保证顺序和唯一) Set errorMsgSet = new LinkedHashSet<>(); // -------------------------- 1. 查询关联数据(批量查询,减少DB交互)-------------------------- - //获取出库单 - List pickIds = pickDetails.stream().map(PickDetail::getPickId).distinct().toList(); + //查询出库单 Map pickMap = queryByPickIdsToMap(pickIds); + //查询出库单明细 + List pickDetails = pickDetailMapper.queryByPickIds(pickIds); + //获取物料 List itemIds = pickDetails.stream().map(PickDetail::getItemId).distinct().toList(); Map itemMap = iItemService.queryByItemIdsToMap(itemIds); @@ -426,6 +442,7 @@ public class PickServiceImpl extends ServiceImpl implements IP // -------------------------- 3. 创建更新列表--------------------------- List updateToInventory = new ArrayList<>(); List updateToPickDetail = new ArrayList<>(); + List createToTask = new ArrayList<>(); // -------------------------- 4. 循环分配库存 ------------------- for (PickDetail pickDetail : pickDetails) { @@ -451,6 +468,11 @@ public class PickServiceImpl extends ServiceImpl implements IP item.getItemCode(), item.getId(), pickDetail.getPropC1(), pickDetail.getPropC3(), pick.getWhCode())); continue; } + + //获取输送线工作台点位,均衡分配点位任务-轮询方式 + Point toPoint = iPointService.getWorkStationPoint(CommonStatusEnum.FREE.getValue(), AreaTypeEnum.CK_DOCK.getValue(), GeneralConstant.CK_DOCK_TASK_INDEX); + //记录当前容器 + Long currStockId = 0L; for (Inventory inventory : matchedInventories) { if (unAllocatedQty.compareTo(BigDecimal.ZERO) <= 0) { break; @@ -475,13 +497,23 @@ public class PickServiceImpl extends ServiceImpl implements IP //容器 Stock stock = stockMap.get(inventory.getStockId()); //库位 - Point point = pointMap.get(inventory.getPointId()); - String tuoType = inventory.getQuantity().compareTo(allocateQty) == 0 ? "整托" : "拆托"; - log.info("生成拣货任务: 容器:{} - 库位:{} - 类型:{}- 分配数量:{}", stock.getStockCode(), point.getPointCode(), tuoType, allocateQty); + Point fromPoint = pointMap.get(inventory.getPointId()); + //是否整托:0整托、1拆托 + Integer izAll = inventory.getQuantity().compareTo(allocateQty) == 0 ? 0 : 1; + //判断当前容器是否一致,同一个容器去同一个目标库位 + if (!currStockId.equals(stock.getId())) { + toPoint = iPointService.getWorkStationPoint(CommonStatusEnum.FREE.getValue(), AreaTypeEnum.CK_DOCK.getValue(), GeneralConstant.CK_DOCK_TASK_INDEX); + } + //构建拣货任务存入集合批量新增 + Task task = iTaskService.bulidTask(pick.getNo() + "_" + pickDetail.getLineNo(), TaskTypeEnum.PICK.getValue(), item, fromPoint, toPoint, stock, pick.getId(), pickDetail.getId(), inventory.getId(), allocateQty, izAll); + createToTask.add(task); + log.info("生成拣货任务:{}- 容器:{} - 库位:{} - 类型:{}- 分配数量:{}", task.getTaskNo(), stock.getStockCode(), fromPoint.getPointCode(), izAll, allocateQty); //分配库存日志 iInventoryLogService.addAllocInventoryLog(inventory, allocateQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription()); //更新未分配数量 unAllocatedQty = BigDecimalUtil.subtract(unAllocatedQty, allocateQty, 0); + //更新当前容器 + currStockId = stock.getId(); } //分配后仍有缺货,记录错误 if (unAllocatedQty.compareTo(BigDecimal.ZERO) > 0) { @@ -494,10 +526,13 @@ public class PickServiceImpl extends ServiceImpl implements IP // -------------------------- 5. 批量更新(减少DB交互)-------------------------- if (CollectionUtils.isNotEmpty(updateToInventory)) { - inventoryMapper.updateById(updateToInventory); + batchUtils.updateBatchInventory(updateToInventory); } if (CollectionUtils.isNotEmpty(updateToPickDetail)) { - pickDetailMapper.updateById(updateToPickDetail); + batchUtils.updateBatchPickDetail(updateToPickDetail); + } + if (CollectionUtils.isNotEmpty(createToTask)) { + batchUtils.saveBatchTask(createToTask); } // -------------------------- 6. 刷新出库单状态 -------------------------- diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/TaskServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/TaskServiceImpl.java new file mode 100644 index 0000000..e331480 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/TaskServiceImpl.java @@ -0,0 +1,156 @@ +package org.cpte.modules.shipping.service.impl; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.shiro.SecurityUtils; +import org.cpte.modules.agvTask.entity.AgvTask; +import org.cpte.modules.agvTask.service.IAgvTaskService; +import org.cpte.modules.base.entity.Item; +import org.cpte.modules.base.entity.Point; +import org.cpte.modules.base.entity.Stock; +import org.cpte.modules.constant.enums.AgvVendorEnum; +import org.cpte.modules.constant.enums.BusinessTypeEnum; +import org.cpte.modules.shipping.entity.Task; +import org.cpte.modules.shipping.mapper.TaskMapper; +import org.cpte.modules.shipping.service.ITaskService; +import org.cpte.modules.shipping.vo.TaskGroupKey; +import org.cpte.modules.utils.BatchUtils; +import org.jeecg.common.system.vo.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 任务 + * @author: cpte + * @Date: 2025-11-17 + * @Version: V1.0 + */ +@Service +public class TaskServiceImpl extends ServiceImpl implements ITaskService { + + @Autowired + private IAgvTaskService agvTaskService; + + @Autowired + private BatchUtils batchUtils; + + @Override + @Transactional(rollbackFor = Exception.class) + public Task createTask(String taskNo, Integer taskType, Item item, Point fromPoint, Point toPoint, Stock stock, Long pickId, Long pickDetailId, Long inventoryId, BigDecimal planQty, Integer izAll) { + LoginUser sysUser = null; + try { + sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + } catch (Exception e) { + log.error("获取登录用户信息失败"); + } + Task task = Task.builder() + .taskNo(taskNo) + .itemId(item.getId()) + .itemCode(item.getItemCode()) + .fromPointId(fromPoint.getId()) + .fromPointCode(fromPoint.getPointCode()) + .toPointId(toPoint.getId()) + .toPointCode(toPoint.getPointCode()) + .stockId(stock.getId()) + .stockCode(stock.getStockCode()) + .pickId(pickId) + .pickDetailId(pickDetailId) + .inventoryId(inventoryId) + .planQty(planQty) + .moveQty(BigDecimal.ZERO) + .taskStatus(1) + .taskType(taskType) + .izAll(izAll) + .sysOrgCode(sysUser == null ? "A05" : sysUser.getOrgCode()) + .tenantId(sysUser == null ? 1000L : Long.parseLong(sysUser.getRelTenantIds())) + .createBy(sysUser == null ? "system" : sysUser.getUsername()) + .createTime(new Date()) + .build(); + this.save(task); + return task; + } + + @Override + public Task bulidTask(String taskNo, Integer taskType, Item item, Point fromPoint, Point toPoint, Stock stock, Long pickId, Long pickDetailId, Long inventoryId, BigDecimal planQty, Integer izAll) { + LoginUser sysUser = null; + try { + sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + } catch (Exception e) { + log.error("获取登录用户信息失败"); + } + return Task.builder() + .taskNo(taskNo) + .itemId(item.getId()) + .itemCode(item.getItemCode()) + .fromPointId(fromPoint.getId()) + .fromPointCode(fromPoint.getPointCode()) + .toPointId(toPoint.getId()) + .toPointCode(toPoint.getPointCode()) + .stockId(stock.getId()) + .stockCode(stock.getStockCode()) + .pickId(pickId) + .pickDetailId(pickDetailId) + .inventoryId(inventoryId) + .planQty(planQty) + .moveQty(BigDecimal.ZERO) + .taskStatus(1) + .taskType(taskType) + .izAll(izAll) + .sysOrgCode(sysUser == null ? "A05" : sysUser.getOrgCode()) + .tenantId(sysUser == null ? 1000L : Long.parseLong(sysUser.getRelTenantIds())) + .createBy(sysUser == null ? "system" : sysUser.getUsername()) + .createTime(new Date()) + .build(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void generateAgvTask(List taskList) { + if (CollectionUtils.isEmpty(taskList)) { + return; + } + //根据stockCode、fromPointCode、toPointCode 分组 + Map> taskGroupMap = taskList.stream() + .sorted(Comparator.comparing(Task::getCreateTime)) + .collect(Collectors.groupingBy(task -> TaskGroupKey.of( + task.getStockCode(), + task.getFromPointCode(), + task.getToPointCode() + ))); + + //批量创建AGV任务 + List createToAgvTaskList = new ArrayList<>(); + Map groupToAgvTaskMap = new HashMap<>(); + for (Map.Entry> entry : taskGroupMap.entrySet()) { + TaskGroupKey key = entry.getKey(); + if(!groupToAgvTaskMap.containsKey(key)){ + AgvTask agvTask = agvTaskService.bulidAgvTask(null, key.getStockCode(), key.getFromPointCode(), key.getToPointCode(), null, BusinessTypeEnum.OUTBOUND.getValue(), AgvVendorEnum.TES.getValue()); + createToAgvTaskList.add(agvTask); + groupToAgvTaskMap.put(key, agvTask); // 建立映射 + } + } + if (CollectionUtils.isNotEmpty(createToAgvTaskList)) { + batchUtils.saveBatchAgvTask(createToAgvTaskList); + } + + //批量更新任务 + List updateToTaskList = new ArrayList<>(); + for (Map.Entry> entry : taskGroupMap.entrySet()) { + TaskGroupKey key = entry.getKey(); + AgvTask agvTask = groupToAgvTaskMap.get(key); // 通过key获取 + List list = entry.getValue(); + for (Task task : list) { + task.setAgvTaskId(agvTask.getId()); + updateToTaskList.add(task); + } + } + if (CollectionUtils.isNotEmpty(updateToTaskList)) { + batchUtils.updateBatchTask(updateToTaskList); + } + } +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/TaskGroupKey.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/TaskGroupKey.java new file mode 100644 index 0000000..fa7d1d8 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/TaskGroupKey.java @@ -0,0 +1,25 @@ +package org.cpte.modules.shipping.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode +public class TaskGroupKey { + private String stockCode; // 容器 + private String fromPointCode; // 原点位 + private String toPointCode; // 目标点位 + + public static TaskGroupKey of(String stockCode, String fromPointCode, String toPointCode) { + return new TaskGroupKey( + StringUtils.defaultIfBlank(stockCode, ""), // 空值统一为"",避免分组不一致 + StringUtils.defaultIfBlank(fromPointCode, ""), + StringUtils.defaultIfBlank(toPointCode, "") + ); + } +} diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/controller/TesAgvController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/controller/TesAgvController.java index e7aa3d3..2c1a5b1 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/controller/TesAgvController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/controller/TesAgvController.java @@ -52,7 +52,6 @@ public class TesAgvController { @AutoLog(value = "TesAGV-任务上报") @Operation(summary = "TesAGV-任务上报") @PostMapping(value = "/callBackTask") - @IgnoreAuth public TesResult callBackTask(@RequestBody TesCallbackRequest tesCallbackRequest) { try { iTesAgvService.callBackTask(tesCallbackRequest); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/service/impl/ITesAgvServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/service/impl/ITesAgvServiceImpl.java index 3ffee93..53b0b0b 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/service/impl/ITesAgvServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/tesAgv/service/impl/ITesAgvServiceImpl.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils; import org.cpte.modules.agvTask.entity.AgvTask; import org.cpte.modules.agvTask.mapper.AgvTaskMapper; import org.cpte.modules.agvTask.service.IAgvTaskService; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.AgvStatusEnum; import org.cpte.modules.constant.enums.AgvVendorEnum; import org.cpte.modules.receive.service.IAsnService; @@ -24,21 +25,6 @@ import java.util.*; @Slf4j public class ITesAgvServiceImpl implements ITesAgvService { - /** - * 接口开关 - */ - final String open_flag = "OPEN"; - - /** - * 成功码 - */ - final Integer success_code = 0; - - /** - * 失败码 - */ - final Integer fail_code = 500; - @Autowired private SysDictMapper sysDictMapper; @@ -83,8 +69,8 @@ public class ITesAgvServiceImpl implements ITesAgvService { public void sendTesAgvTask(String url, String json, AgvTask agvTask) { log.info("请求报文:{}", json); // 检查接口开关, 未开启则返回 - if (sysDictMapper.queryByDictCode(open_flag) == null) { - updateAgvTaskResponse(agvTask, "接口未开启", fail_code); + if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) { + updateAgvTaskResponse(agvTask, "接口未开启", GeneralConstant.TES_FAIL_CODE); return; } @@ -94,7 +80,7 @@ public class ITesAgvServiceImpl implements ITesAgvService { //String result = HttpPostUtil.sendPostReq(url, json); String result = "{" + " \"returnCode\":0," + - " \"returnMsg\":\"succ\"," + + " \"returnMsg\":\"成功\"," + " \"returnUserMsg\":\"成功\"," + " \"data\":{" + " \"taskID\":74602" + @@ -112,9 +98,9 @@ public class ITesAgvServiceImpl implements ITesAgvService { } returnCode = resulObject.getInteger("returnCode"); - returnMsg = resulObject.getString("returnUserMsg"); + returnMsg = resulObject.getString("returnMsg"); - if (!success_code.equals(returnCode)) { + if (!GeneralConstant.TES_SUCCESS_CODE.equals(returnCode)) { throw new RuntimeException("Tes返回消息:" + returnMsg); } @@ -122,8 +108,7 @@ public class ITesAgvServiceImpl implements ITesAgvService { updateAgvTaskResponse(agvTask, returnMsg, returnCode); } catch (Exception e) { // 记录异常到 AgvTask - updateAgvTaskResponse(agvTask, e.getMessage(), fail_code); - throw e; // 继续向上抛出异常供 Controller 层处理 + updateAgvTaskResponse(agvTask, e.getMessage(), GeneralConstant.TES_FAIL_CODE); } } @@ -186,7 +171,7 @@ public class ITesAgvServiceImpl implements ITesAgvService { if (count > 0) { throw new RuntimeException("任务已重新生成,请勿重复操作! "); } - AgvTask newAgvTask = iAgvTaskService.createAgvTask(agvTask.getBusinessDetailId(), AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), AgvVendorEnum.TES.getValue()); + AgvTask newAgvTask = iAgvTaskService.createAgvTask(agvTask.getBusinessDetailId(),agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), AgvVendorEnum.TES.getValue()); switch (agvTask.getType()) { case "INBOUND": case "OUTBOUND": @@ -208,7 +193,7 @@ public class ITesAgvServiceImpl implements ITesAgvService { */ private void updateAgvTaskResponse(AgvTask agvTask, String message, Integer code) { if (agvTask != null) { - if (success_code.equals(code)) { + if (GeneralConstant.TES_SUCCESS_CODE.equals(code)) { agvTask.setStatus(AgvStatusEnum.EXECUTING.getValue()); } agvTask.setResMessage(message); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtils.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtils.java new file mode 100644 index 0000000..133c688 --- /dev/null +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtils.java @@ -0,0 +1,294 @@ +package org.cpte.modules.utils; + +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import org.cpte.modules.agvTask.entity.AgvTask; +import org.cpte.modules.base.entity.Item; +import org.cpte.modules.base.entity.Point; +import org.cpte.modules.inventory.entity.Inventory; +import org.cpte.modules.shipping.entity.PickDetail; +import org.cpte.modules.shipping.entity.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.List; +import java.util.function.BiConsumer; + +@Service +public class BatchUtils { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // 默认批次大小 + private static final int BATCH_SIZE = 1000; + + /** + * 泛型批量插入方法 + */ + private void batchInsert(String sql, List dataList, BiConsumer setter) { + batchExecute(sql, dataList, setter); + } + + /** + * 泛型批量更新方法 + */ + private void batchUpdate(String sql, List dataList, BiConsumer setter) { + batchExecute(sql, dataList, setter); + } + + + /** + * 分批执行SQL语句(支持插入与更新) + * + * @param sql SQL语句 + * @param dataList 数据列表 + * @param setter 设置每个对象对应PreparedStatement值的方法 + * @param 对象类型 + */ + private void batchExecute(String sql, List dataList, BiConsumer setter) { + for (int i = 0; i < dataList.size(); i += BATCH_SIZE) { + int endIndex = Math.min(i + BATCH_SIZE, dataList.size()); + List subList = dataList.subList(i, endIndex); + + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int idx) throws SQLException { + T data = subList.get(idx); + setter.accept(ps, data); + } + + @Override + public int getBatchSize() { + return subList.size(); + } + }); + } + } + + + /** + * 批量插入物料数据 + */ + @Transactional + public void saveBatchItem(List items) { + String sql = "INSERT INTO base_item (item_code,item_name,description,iz_active, del_flag,sys_org_code,tenant_id,create_by,create_time) VALUES (?,?,?,?,?,?,?,?,?)"; + batchInsert(sql, items, (ps, item) -> { + try { + ps.setString(1, item.getItemCode()); + ps.setString(2, item.getItemName()); + ps.setString(3, item.getDescription()); + ps.setInt(4, item.getIzActive()); + ps.setInt(5, item.getDelFlag()); + ps.setString(6, item.getSysOrgCode()); + ps.setLong(7, item.getTenantId()); + ps.setString(8, item.getCreateBy()); + ps.setDate(9, new Date(item.getCreateTime().getTime())); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + /** + * 批量更新物料 + */ + @Transactional + public void updateBatchItem(List items) { + String sql = "UPDATE base_item SET item_code = ?, item_name = ?, description = ?, iz_active = ?, del_flag = ? WHERE id = ?"; + batchUpdate(sql, items, (ps, item) -> { + try { + ps.setString(1, item.getItemCode()); + ps.setString(2, item.getItemName()); + ps.setString(3, item.getDescription()); + ps.setInt(4, item.getIzActive()); + ps.setInt(5, item.getDelFlag()); + ps.setLong(6, item.getId()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + /** + * 批量插入点位数据 + */ + @Transactional + public void saveBatchPoint(List points) { + String sql = "INSERT INTO base_point (area_id, point_code,status,row_num,col_num,layer_num,description,iz_active,del_flag,sys_org_code,tenant_id,create_by,create_time) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"; + batchInsert(sql, points, (ps, point) -> { + try { + ps.setLong(1, point.getAreaId()); + ps.setString(2, point.getPointCode()); + ps.setInt(3, point.getStatus()); + ps.setString(4, point.getRowNum()); + ps.setString(5, point.getColNum()); + ps.setString(6, point.getLayerNum()); + ps.setString(7, point.getDescription()); + ps.setInt(8, point.getIzActive()); + ps.setInt(9, point.getDelFlag()); + ps.setString(10, point.getSysOrgCode()); + ps.setLong(11, point.getTenantId()); + ps.setString(12, point.getCreateBy()); + ps.setDate(13, new Date(point.getCreateTime().getTime())); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + /** + * 批量更新点位 + */ + @Transactional + public void batchUpdatePoints(List points) { + String sql = "UPDATE base_point SET area_id = ?, point_code = ?, status = ?, row_num = ?, col_num = ?, layer_num = ?, description = ?, iz_active = ?, del_flag = ? WHERE id = ?"; + batchUpdate(sql, points, (ps, point) -> { + try { + ps.setLong(1, point.getAreaId()); + ps.setString(2, point.getPointCode()); + ps.setInt(3, point.getStatus()); + ps.setString(4, point.getRowNum()); + ps.setString(5, point.getColNum()); + ps.setString(6, point.getLayerNum()); + ps.setString(7, point.getDescription()); + ps.setInt(8, point.getIzActive()); + ps.setInt(9, point.getDelFlag()); + ps.setLong(10, point.getId()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + + /** + * 批量更新出库明细 + */ + @Transactional + public void updateBatchPickDetail(List pickDetails) { + String sql = "UPDATE data_pick_detail SET allocated_qty = ?, status = ? where id = ?"; + batchUpdate(sql, pickDetails, (ps, pickDetail) -> { + try { + ps.setBigDecimal(1, pickDetail.getAllocatedQty()); + ps.setInt(2, pickDetail.getStatus()); + ps.setLong(3, pickDetail.getId()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + + } + + /** + * 批量插Task任务 + */ + @Transactional + public void saveBatchTask(List tasks) { + String sql = "INSERT INTO data_task (id,task_no,item_id,item_code,from_point_id,from_point_code,to_point_id,to_point_code,stock_id,stock_code,pick_id,pick_detail_id,inventory_id,plan_qty,move_qty,task_type,task_status,iz_all,sys_org_code,tenant_id,create_by,create_time) " + + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + batchInsert(sql, tasks, (ps, task) -> { + try { + ps.setLong(1, IdWorker.getId()); + ps.setString(2, task.getTaskNo()); + ps.setLong(3, task.getItemId()); + ps.setString(4, task.getItemCode()); + ps.setLong(5, task.getFromPointId()); + ps.setString(6, task.getFromPointCode()); + ps.setLong(7, task.getToPointId()); + ps.setString(8, task.getToPointCode()); + ps.setLong(9, task.getStockId()); + ps.setString(10, task.getStockCode()); + ps.setLong(11, task.getPickId()); + ps.setLong(12, task.getPickDetailId()); + ps.setLong(13, task.getInventoryId()); + ps.setBigDecimal(14, task.getPlanQty()); + ps.setBigDecimal(15, task.getMoveQty()); + ps.setInt(16, task.getTaskType()); + ps.setInt(17, task.getTaskStatus()); + ps.setInt(18, task.getIzAll()); + ps.setString(19, task.getSysOrgCode()); + ps.setLong(20, task.getTenantId()); + ps.setString(21, task.getCreateBy()); + ps.setTimestamp(22, new Timestamp(task.getCreateTime().getTime())); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + /** + * 批量更新Task任务 + */ + @Transactional + public void updateBatchTask(List tasks) { + String sql = "UPDATE data_task SET agv_task_id = ? where id = ? "; + batchUpdate(sql, tasks, (ps, task) -> { + try { + ps.setObject(1, task.getAgvTaskId()); + ps.setLong(2, task.getId()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + + } + + /** + * 批量插AgvTask任务 + */ + @Transactional + public void saveBatchAgvTask(List agvTasks) { + String sql = "INSERT INTO data_agv_task (id,business_detail_id,carrier_code,carrier_type,task_type,type,status,priority,start_code,end_code,agv_vendor,sys_org_code,tenant_id,create_by,create_time) " + + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + batchInsert(sql, agvTasks, (ps, agvTask) -> { + try { + long id = IdWorker.getId(); + agvTask.setId(id); // 关键:将生成的ID赋值给对象,解决null问题 + ps.setLong(1, id); + ps.setObject(2, agvTask.getBusinessDetailId()); + ps.setString(3, agvTask.getCarrierCode()); + ps.setString(4, agvTask.getCarrierType()); + ps.setString(5, agvTask.getTaskType()); + ps.setString(6, agvTask.getType()); + ps.setInt(7, agvTask.getStatus()); + ps.setInt(8, agvTask.getPriority()); + ps.setString(9, agvTask.getStartCode()); + ps.setString(10, agvTask.getEndCode()); + ps.setString(11, agvTask.getAgvVendor()); + ps.setString(12, agvTask.getSysOrgCode()); + ps.setLong(13, agvTask.getTenantId()); + ps.setString(14, agvTask.getCreateBy()); + ps.setTimestamp(15, new Timestamp(agvTask.getCreateTime().getTime())); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + /** + * 批量更新库存 + */ + @Transactional + public void updateBatchInventory(List inventories) { + String sql = "UPDATE data_inventory SET queued_qty = ?, status = ? where id = ?"; + batchUpdate(sql, inventories, (ps, inventory) -> { + try { + ps.setBigDecimal(1, inventory.getQueuedQty()); + ps.setInt(2, inventory.getStatus()); + ps.setLong(3, inventory.getId()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + +} + diff --git a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java index 1b6cd2a..051cc2e 100644 --- a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java +++ b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java @@ -200,6 +200,6 @@ public class ApiAuthFilter implements Filter { public static void main(String[] args) { long timestamp = System.currentTimeMillis(); System.out.println("timestamp:" + timestamp); - System.out.println("signature:" + md5("ak-eAU25mrMxhtaZsyS" + "rjxMqB6YyUXpSHAz4DCIz8vZ5aozQQiV" + timestamp)); + System.out.println("signature:" + md5("ak-h98TNj1bO5258uuS" + "E20j9w4vkTkLkv6tjALrzYqcybrvDaCx" + timestamp)); } } diff --git a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/mapper/OpenApiMapper.java b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/mapper/OpenApiMapper.java index f9a4b67..a5b8a90 100644 --- a/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/mapper/OpenApiMapper.java +++ b/cpte-module-system/cpte-system-biz/src/main/java/org/jeecg/modules/openapi/mapper/OpenApiMapper.java @@ -2,8 +2,18 @@ package org.jeecg.modules.openapi.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import org.jeecg.modules.openapi.entity.OpenApi; @Mapper public interface OpenApiMapper extends BaseMapper { + /** + * 通过接口地址获取原始地址 + * + * @param requestUrl 接口地址 + * @return String + */ + @Select("select origin_url from open_api where request_url = #{requestUrl}") + String getRequestUrl(@Param("requestUrl") String requestUrl); } diff --git a/cpte-module-system/cpte-system-start/src/main/resources/application-dev.yml b/cpte-module-system/cpte-system-start/src/main/resources/application-dev.yml index c8ab7d5..d4b616b 100644 --- a/cpte-module-system/cpte-system-start/src/main/resources/application-dev.yml +++ b/cpte-module-system/cpte-system-start/src/main/resources/application-dev.yml @@ -150,7 +150,7 @@ spring: merge-sql: true datasource: master: - url: jdbc:mysql://47.103.100.52:53306/cpte-wms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai + url: jdbc:mysql://47.103.100.52:53306/cpte-wms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true username: root password: Youchain@56 driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/cpte-module-system/cpte-system-start/src/main/resources/application-prod.yml b/cpte-module-system/cpte-system-start/src/main/resources/application-prod.yml index e724746..616cdc0 100644 --- a/cpte-module-system/cpte-system-start/src/main/resources/application-prod.yml +++ b/cpte-module-system/cpte-system-start/src/main/resources/application-prod.yml @@ -142,7 +142,7 @@ spring: slow-sql-millis: 5000 datasource: master: - url: jdbc:mysql://10.180.9.60:3306/cpte-wms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai + url: jdbc:mysql://10.180.9.60:3306/cpte-wms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true username: root password: cpte@123 driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/TestMain.java b/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/TestMain.java index 35bf160..161c807 100644 --- a/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/TestMain.java +++ b/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/TestMain.java @@ -7,6 +7,9 @@ import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + /** * @Description: TODO * @author: scott @@ -14,7 +17,11 @@ import org.springframework.http.ResponseEntity; */ public class TestMain { public static void main(String[] args) { - // 请求地址 + long timestamp = System.currentTimeMillis(); + System.out.println("timestamp:" + timestamp); + System.out.println("signature:" + md5("ak-h98TNj1bO5258uuS" + "E20j9w4vkTkLkv6tjALrzYqcybrvDaCx" + timestamp)); + + /* // 请求地址 String url = "https://api3.boot.jeecg.com/sys/user/list"; // 请求 Header (用于传递Token) HttpHeaders headers = getHeaders(); @@ -30,7 +37,32 @@ public class TestMain { System.out.println("返回结果:" + result.getBody().toJSONString()); } else { System.out.println("查询失败"); + }*/ + } + + public static String md5(String sourceStr) { + String result = ""; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(sourceStr.getBytes(StandardCharsets.UTF_8)); + byte[] hash = md.digest(); + int i; + StringBuffer buf = new StringBuffer(32); + for (int offset = 0; offset < hash.length; offset++) { + i = hash[offset]; + if (i < 0) { + i += 256; + } + if (i < 16) { + buf.append("0"); + } + buf.append(Integer.toHexString(i)); + } + result = buf.toString(); + } catch (Exception e) { + System.out.println("sign签名错误" + e); } + return result; } private static HttpHeaders getHeaders() { String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.50h-g6INOZRVnznExiawFb1U6PPjcVVA4POeYRA5a5Q"; diff --git a/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/modules/openapi/test/SampleOpenApiTest.java b/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/modules/openapi/test/SampleOpenApiTest.java index ce55cfb..680860e 100644 --- a/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/modules/openapi/test/SampleOpenApiTest.java +++ b/cpte-module-system/cpte-system-start/src/test/java/org/jeecg/modules/openapi/test/SampleOpenApiTest.java @@ -15,7 +15,7 @@ import java.security.MessageDigest; public class SampleOpenApiTest { - private final String base_url = "http://localhost:8080/jeecg-boot"; + private final String base_url = "http://localhost:8080/cpte-wms"; private final String appKey = "ak-pFjyNHWRsJEFWlu6"; private final String searchKey = "4hV5dBrZtmGAtPdbA5yseaeKRYNpzGsS";