From 32f9edffc326ffb51ccb41039db332d20a5a977d Mon Sep 17 00:00:00 2001 From: "HUOJIN\\92525" <925259474@qq.com> Date: Sun, 21 Dec 2025 17:58:47 +0800 Subject: [PATCH] no message --- .../agvTask/service/IAgvTaskService.java | 11 ++ .../service/impl/AgvTaskServiceImpl.java | 54 +++++- .../base/controller/AreaController.java | 6 +- .../base/controller/ItemController.java | 7 +- .../base/controller/PointController.java | 5 +- .../base/controller/StockController.java | 21 ++- .../org/cpte/modules/base/entity/Stock.java | 10 +- .../modules/base/service/IStockService.java | 11 +- .../base/service/impl/PointServiceImpl.java | 4 - .../base/service/impl/StockServiceImpl.java | 20 +- .../service/IConveyorLineService.java | 9 + .../service/processor/ScanTrayProcessor.java | 30 +-- .../service/impl/IHikAgvServiceImpl.java | 14 +- .../service/impl/InventoryLogServiceImpl.java | 10 +- .../receive/controller/AsnController.java | 2 + .../modules/receive/entity/AsnDetail.java | 10 + .../receive/service/IAsnDetailService.java | 50 +++++ .../modules/receive/service/IAsnService.java | 28 +-- .../service/impl/AsnDetailServiceImpl.java | 156 +++++++++++++++- .../receive/service/impl/AsnServiceImpl.java | 100 +--------- .../service/processor/ReceiveProcessor.java | 95 ++-------- .../cpte/modules/receive/vo/ReceiveData.java | 2 +- .../saiWms/controller/SaiWmsController.java | 5 + .../saiWms/service/impl/ISMOMServiceImpl.java | 36 +++- .../processor/InBoundTaskProcessor.java | 51 +----- .../processor/OutBoundTaskProcessor.java | 20 +- .../service/processor/SyncStockProcessor.java | 22 +-- .../shipping/controller/PickController.java | 36 +++- .../shipping/service/IPickDetailService.java | 127 ++++++++++--- .../shipping/service/IPickService.java | 22 --- .../service/impl/PickDetailServiceImpl.java | 168 +++++++++++++++++ .../service/impl/PickServiceImpl.java | 96 +--------- .../service/processor/AllocateProcessor.java | 49 +---- .../processor/CancelAllocateProcessor.java | 171 +++++++----------- .../service/processor/PickProcessor.java | 87 ++++----- .../cpte/modules/shipping/vo/PickData.java | 2 + .../service/impl/ITesAgvServiceImpl.java | 2 +- .../org/cpte/modules/utils/BatchUtil.java | 2 +- 38 files changed, 840 insertions(+), 711 deletions(-) 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 b47ddac..f9c3fd3 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 @@ -2,6 +2,10 @@ package org.cpte.modules.agvTask.service; import org.cpte.modules.agvTask.entity.AgvTask; import com.baomidou.mybatisplus.extension.service.IService; +import org.cpte.modules.base.entity.Point; +import org.cpte.modules.base.entity.Stock; +import org.cpte.modules.conveyorLine.vo.ScanTrayData; +import org.cpte.modules.receive.entity.Asn; import java.util.List; @@ -40,4 +44,11 @@ public interface IAgvTaskService extends IService { */ AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor); + /** + * 处理AGV任务 + * @param data 扫描数据 + * @param dstPoint 目标库位 + */ + void processAgvTask(ScanTrayData data, Point dstPoint); + } 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 261fb03..6e89ca4 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 @@ -2,13 +2,22 @@ package org.cpte.modules.agvTask.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import org.apache.commons.collections4.CollectionUtils; 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.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.enums.*; +import org.cpte.modules.conveyorLine.vo.ScanTrayData; +import org.cpte.modules.receive.entity.Asn; +import org.cpte.modules.receive.entity.AsnDetail; +import org.cpte.modules.receive.mapper.AsnDetailMapper; +import org.cpte.modules.receive.mapper.AsnMapper; +import org.cpte.modules.shipping.mapper.PickMapper; import org.jeecg.common.system.vo.LoginUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -28,9 +37,18 @@ import java.util.List; @Service public class AgvTaskServiceImpl extends ServiceImpl implements IAgvTaskService { + @Autowired + private AsnMapper asnMapper; + + @Autowired + private AsnDetailMapper asnDetailMapper; + + @Autowired + private IPointService pointService; + @Override @Transactional(rollbackFor = Exception.class) - public AgvTask createAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type,Integer izAll, String agvVendor) { + public AgvTask createAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor) { LoginUser sysUser = null; try { sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); @@ -62,7 +80,7 @@ public class AgvTaskServiceImpl extends ServiceImpl impl } @Override - public AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type,Integer izAll, String agvVendor) { + public AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor) { LoginUser sysUser = null; try { sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); @@ -92,4 +110,30 @@ public class AgvTaskServiceImpl extends ServiceImpl impl .createTime(new Date()) .build(); } + + @Transactional(rollbackFor = Exception.class) + public void processAgvTask(ScanTrayData data, Point dstPoint) { + Asn asn = data.getAsn(); + asn.setStatus(AsnStatusEnum.SCAN.getValue()); + asnMapper.updateById(asn); + + //写入工作站和终点库位 + Point station = data.getStation(); + List asnDetails = data.getAsnDetails(); + for (AsnDetail asnDetail : data.getAsnDetails()) { + asnDetail.setStationId(station.getId()); + asnDetail.setToPointId(dstPoint.getId()); + } + if (CollectionUtils.isNotEmpty(asnDetails)) { + asnDetailMapper.updateById(asnDetails); + } + + //锁定目标库位 + pointService.bindPoint(dstPoint); + + //验证通过,生成Tes任务 + Stock stock = data.getStock(); + createAgvTask(asn.getId(), stock.getStockCode(), station.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.TES.getValue()); + + } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/AreaController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/AreaController.java index 185b231..4aa5190 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/AreaController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/AreaController.java @@ -55,11 +55,7 @@ public class AreaController extends JeecgController { @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "keyword", required = false) String keyword, HttpServletRequest req) { - // 自定义查询规则 - Map customeRuleMap = new HashMap<>(); - customeRuleMap.put("areaCode", QueryRuleEnum.RIGHT_LIKE); - customeRuleMap.put("areaName", QueryRuleEnum.RIGHT_LIKE); - QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(area, req.getParameterMap(), customeRuleMap); + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(area, req.getParameterMap()); // 如果提供了 keyword,则同时对 areaCode 和 areaName 进行模糊搜索 if (StringUtils.isNotBlank(keyword)) { queryWrapper.and(wrapper -> wrapper.likeRight("area_code", keyword).or().likeRight("area_name", keyword)); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/ItemController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/ItemController.java index de49b6c..70a1d3f 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/ItemController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/ItemController.java @@ -72,11 +72,8 @@ public class ItemController extends JeecgController { @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "keyword", required = false) String keyword, HttpServletRequest req) { - // 自定义查询规则 - Map customeRuleMap = new HashMap<>(); - customeRuleMap.put("itemCode", QueryRuleEnum.RIGHT_LIKE); - customeRuleMap.put("itemName", QueryRuleEnum.RIGHT_LIKE); - QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(item, req.getParameterMap(),customeRuleMap); + + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(item, req.getParameterMap()); // 如果提供了 keyword,则同时对 areaCode 和 areaName 进行模糊搜索 if (StringUtils.isNotBlank(keyword)) { queryWrapper.and(wrapper -> wrapper.likeRight("item_code", keyword).or().likeRight("item_name", keyword)); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/PointController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/PointController.java index 3a2b4f9..f20d039 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/PointController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/PointController.java @@ -70,10 +70,7 @@ public class PointController extends JeecgController { @RequestParam(name = "keyword", required = false) String keyword, HttpServletRequest req) { - // 自定义查询规则 - Map customeRuleMap = new HashMap<>(); - customeRuleMap.put("pointCode", QueryRuleEnum.RIGHT_LIKE); - QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(point, req.getParameterMap(), customeRuleMap); + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(point, req.getParameterMap()); // 如果提供了 keyword,则同时对 pointCode 模糊搜索 if (StringUtils.isNotBlank(keyword)) { queryWrapper.and(wrapper -> wrapper.likeRight("point_code", keyword)); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/StockController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/StockController.java index d29012a..eabdef5 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/StockController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/controller/StockController.java @@ -9,9 +9,12 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; +import org.cpte.modules.inventory.entity.Inventory; +import org.cpte.modules.inventory.mapper.InventoryMapper; import org.jeecg.common.api.vo.Result; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryRuleEnum; @@ -55,6 +58,9 @@ public class StockController extends JeecgController { @Autowired private IStockService stockService; + @Autowired + private InventoryMapper inventoryMapper; + /** * 分页列表查询 * @@ -71,15 +77,22 @@ public class StockController extends JeecgController { @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "keyword", required = false) String keyword, + @RequestParam(name = "izScan", required = false) boolean izScan, HttpServletRequest req) { - // 自定义查询规则 - Map customeRuleMap = new HashMap<>(); - customeRuleMap.put("stockCode", QueryRuleEnum.RIGHT_LIKE); - QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(stock, req.getParameterMap(), customeRuleMap); + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(stock, req.getParameterMap()); // 如果提供了 keyword,则同时对 pointCode 模糊搜索 if (StringUtils.isNotBlank(keyword)) { queryWrapper.and(wrapper -> wrapper.likeRight("stock_code", keyword)); } + + //是否扫描 + if (izScan) { + /*List inventories = inventoryMapper.selectList(null); + List stockIds = inventories.stream().map(Inventory::getStockId).distinct().toList(); + queryWrapper.notIn("id", stockIds);*/ + queryWrapper.notExists("SELECT 1 FROM data_inventory WHERE stock_id = base_stock.id"); + } + queryWrapper.orderByAsc("stock_code"); Page page = new Page(pageNo, pageSize); IPage pageList = stockService.page(page, queryWrapper); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Stock.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Stock.java index ab2d529..4fc7561 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Stock.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/entity/Stock.java @@ -40,15 +40,7 @@ public class Stock implements Serializable { @Schema(description = "主键") @JsonSerialize(using = ToStringSerializer.class) private java.lang.Long id; - /** - * 库位ID - */ - @Excel(name = "库位ID", width = 15) - @Schema(description = "库位ID") - @Dict(dictTable = "base_point", dicCode = "id", dicText = "point_code") - @TableField(fill = FieldFill.INSERT_UPDATE) - @JsonSerialize(using = ToStringSerializer.class) - private java.lang.Long pointId; + /** * 容器编码 */ 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 036dec4..4dc75fb 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 @@ -42,9 +42,8 @@ public interface IStockService extends IService { * 绑定容器 * * @param stock 容器 - * @param point 容器位置 */ - void bindStock(Stock stock, Point point); + void bindStock(Stock stock); /** * 根据容器编码集合查询容器信息 @@ -70,5 +69,11 @@ public interface IStockService extends IService { */ Map queryByStockIdsToMap(List stockIds); - + /** + * 批量操作 + * + * @param insertToStock 创建的容器 + * @param updateToStock 更新的容器 + */ + void batchOperation(List insertToStock, List updateToStock); } 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 b02ea48..69c691f 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 @@ -5,7 +5,6 @@ import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; import org.cpte.modules.base.entity.Point; 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; @@ -29,9 +28,6 @@ import java.util.Map; @Service public class PointServiceImpl extends ServiceImpl implements IPointService { - @Autowired - private IAreaService iAreaService; - @Autowired private RedisUtil redisUtil; 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 f09b90c..e11b405 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 @@ -12,10 +12,13 @@ import org.cpte.modules.base.service.IStockService; import org.cpte.modules.constant.enums.CommonStatusEnum; import org.cpte.modules.constant.enums.StockTypeEnum; import org.cpte.modules.saiWms.request.SyncStockRequest; +import org.cpte.modules.utils.BatchUtil; 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.util.*; @@ -28,6 +31,9 @@ import java.util.*; @Service public class StockServiceImpl extends ServiceImpl implements IStockService { + @Autowired + private BatchUtil batchUtil; + @Override public Stock buildStocK(SyncStockRequest.StockDTO stockDTO) { LoginUser sysUser = null; @@ -79,8 +85,7 @@ public class StockServiceImpl extends ServiceImpl implements } @Override - public void bindStock(Stock stock, Point point) { - stock.setPointId(point == null ? null : point.getId()); + public void bindStock(Stock stock) { stock.setStatus(CommonStatusEnum.USED.getValue()); this.baseMapper.updateById(stock); } @@ -134,4 +139,15 @@ public class StockServiceImpl extends ServiceImpl implements } return stockMap; } + + @Override + @Transactional(rollbackFor = Exception.class) + public void batchOperation(List insertToStock, List updateToStock) { + if (CollectionUtils.isNotEmpty(insertToStock)) { + batchUtil.saveBatchStock(insertToStock); + } + if (CollectionUtils.isNotEmpty(updateToStock)) { + batchUtil.batchUpdateStocks(updateToStock); + } + } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java index 4725cd1..eec9803 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/IConveyorLineService.java @@ -1,7 +1,10 @@ package org.cpte.modules.conveyorLine.service; import com.alibaba.fastjson.JSONObject; +import org.cpte.modules.base.entity.Point; +import org.cpte.modules.base.entity.Stock; import org.cpte.modules.conveyorLine.request.ScanTrayRequest; +import org.cpte.modules.receive.entity.Asn; public interface IConveyorLineService { @@ -12,5 +15,11 @@ public interface IConveyorLineService { */ void scanTray(ScanTrayRequest scanTrayRequest); + /** + * 显示 输送线大屏显示 + * + * @param conveyorLine conveyorLine + */ JSONObject showConveyorLine(String conveyorLine); + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java index 56fd33f..44b8812 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java @@ -3,7 +3,6 @@ package org.cpte.modules.conveyorLine.service.processor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.cpte.modules.agvTask.mapper.AgvTaskMapper; import org.cpte.modules.agvTask.service.IAgvTaskService; import org.cpte.modules.base.entity.Item; import org.cpte.modules.base.entity.ItemKey; @@ -26,7 +25,6 @@ import org.cpte.modules.receive.mapper.AsnDetailMapper; import org.cpte.modules.receive.mapper.AsnMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.Comparator; @@ -61,9 +59,6 @@ public class ScanTrayProcessor { @Autowired private InventoryMapper inventoryMapper; - @Autowired - private AgvTaskMapper agvTaskMapper; - @Autowired private IPointService pointService; @@ -90,7 +85,7 @@ public class ScanTrayProcessor { Point dstPoint = allocatePoint(data.getItemKeys(), data.getStation(), areaCode); // 5.生成TES任务 - processAgvTask(data.getAsn(), data.getStock(), data.getStation(), dstPoint); + agvTaskService.processAgvTask(data, dstPoint); } /** @@ -157,6 +152,12 @@ public class ScanTrayProcessor { private void validateTray(ScanTrayData data) { Long stockId = data.getStock().getId(); String stockCode = data.getStock().getStockCode(); + Asn asn = data.getAsn(); + //验证当前托盘是否生成了TES任务 + if (AsnStatusEnum.SCAN.getValue().equals(asn.getStatus())) { + throw new RuntimeException("【" + stockCode + "】托盘已扫描,请勿重复扫描"); + } + List asnDetails = asnDetailMapper.queryByStockCode(stockId, AsnStatusEnum.CREATED.getValue()); if (CollectionUtils.isEmpty(asnDetails)) { throw new RuntimeException("【" + stockCode + "】托盘,无入库任务"); @@ -167,10 +168,7 @@ public class ScanTrayProcessor { throw new RuntimeException("【" + stockCode + "】托盘已入库"); } - //验证当前托盘是否生成了TES任务 - if (agvTaskMapper.existsByStockCode(stockCode, AgvVendorEnum.TES.getValue()) != null) { - throw new RuntimeException("【" + stockCode + "】托盘已扫描,请勿重复扫描"); - } + } /** @@ -395,16 +393,4 @@ public class ScanTrayProcessor { // 距离越小分数越高 return Math.max(0, 100 - (distance / 100.0)); } - - @Transactional(rollbackFor = Exception.class) - public void processAgvTask(Asn asn, Stock stock, Point station, Point dstPoint) { - asn.setStatus(AsnStatusEnum.SCAN.getValue()); - asnMapper.updateById(asn); - //锁定目标库位 - pointService.bindPoint(dstPoint); - - //验证通过,生成Tes任务 - agvTaskService.createAgvTask(asn.getId(), stock.getStockCode(), station.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.TES.getValue()); - } - } 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 7184b5b..d07215c 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 @@ -132,12 +132,6 @@ public class IHikAgvServiceImpl implements IHikAgvService { if (agvTask == null) { throw new RuntimeException("【" + taskReporterRequest.getRobotTaskCode() + "】任务不存在"); } - Point point = null; - Stock stock = stock = iStockService.validateStock(agvTask.getCarrierCode()); - if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) { - point = iPointService.validatePoint(agvTask.getEndCode()); - } - String status = taskReporterRequest.getExtra().getValues().getMethod(); switch (status) { case "outbin": @@ -146,7 +140,7 @@ public class IHikAgvServiceImpl implements IHikAgvService { break; case "end": //任务完成 - handleEnd(agvTask, stock, point); + handleEnd(agvTask); break; } } @@ -223,11 +217,7 @@ public class IHikAgvServiceImpl implements IHikAgvService { * * @param agvTask 任务 */ - private void handleEnd(AgvTask agvTask, Stock stock, Point point) { - if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) { - //绑定容器和点位 - iStockService.bindStock(stock, point); - } + private void handleEnd(AgvTask agvTask) { //更新任务状态 agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue()); agvTask.setEndTime(new Date()); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventoryLog/service/impl/InventoryLogServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventoryLog/service/impl/InventoryLogServiceImpl.java index f4d2244..75fe99e 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventoryLog/service/impl/InventoryLogServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventoryLog/service/impl/InventoryLogServiceImpl.java @@ -82,7 +82,6 @@ public class InventoryLogServiceImpl extends ServiceImpl { */ public List selectByMainId(Long mainId); + /** + * 保存主表信息 + * + * @param asn 入库单 + * @param asnDetailList 入库明细 + */ + void processorSaveMain(Asn asn, List asnDetailList); + + /** + * 入库处理 + * + * @param inboundRequest 入库参数 + * @param itemMap 物料 + * @param srcPoint 起点 + * @param stock 容器 + */ + void processInboundTask(InboundRequest inboundRequest, Map itemMap, Point srcPoint, Stock stock); + /** * 刷新入库单 * @@ -38,6 +58,27 @@ public interface IAsnDetailService extends IService { */ void refreshAsn(Asn asn, List asnDetails); + /** + * 构建入库单 + * + * @param inboundRequest 入库请求 + * @return Asn + */ + Asn buildAsn(InboundRequest inboundRequest); + + /** + * 构建入库单明细 + * + * @param inboundDetails 入库单明细 + * @param itemMap 物料信息 + * @param stock 容器 + * @param srcPoint 源库位 + * @param station 工作站 + * @return AsnDetail + */ + List buildAsnDetail(List inboundDetails, Map itemMap, Stock stock, Point srcPoint, Point station); + + /** * 构建入库记录 * @@ -49,5 +90,14 @@ public interface IAsnDetailService extends IService { */ ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId); + /** + * 批量操作 + * + * @param updateToAsnDetail 更新入库单明细 + * @param records 创建收货记录 + * @param inventoryMap 创建库存 + * @param inventoryLogs 创建库存日志 + */ + void batchOperation(List updateToAsnDetail, List records, Map inventoryMap, List inventoryLogs); } 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 c40f044..da3d7f0 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,9 +1,12 @@ package org.cpte.modules.receive.service; +import org.cpte.modules.agvTask.entity.AgvTask; import org.cpte.modules.base.entity.Item; import org.cpte.modules.base.entity.ItemKey; import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; +import org.cpte.modules.inventory.entity.Inventory; +import org.cpte.modules.inventoryLog.entity.InventoryLog; import org.cpte.modules.receive.entity.AsnDetail; import org.cpte.modules.receive.entity.Asn; import com.baomidou.mybatisplus.extension.service.IService; @@ -54,32 +57,13 @@ public interface IAsnService extends IService { */ public void delBatchMain(Collection idList); - /** - * 构建入库单 - * - * @param inboundRequest 入库请求 - * @return Asn - */ - Asn buildAsn(InboundRequest inboundRequest); - - /** - * 构建入库单明细 - * - * @param inboundDetails 入库单明细 - * @param itemMap 物料信息 - * @param stock 容器 - * @param srcPoint 源库位 - * @param dstPoint 目标库位 - * @return AsnDetail - */ - List buildAsnDetail(List inboundDetails, Map itemMap, Stock stock, Point srcPoint, Point dstPoint); - /** * 收货操作 * * @param asnId 入库单ID - * @param pointCode 目标库位 */ - void receiveAsn(Long asnId, String pointCode); + void receiveAsn(Long asnId); + + } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnDetailServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnDetailServiceImpl.java index 7a447db..7ce80a7 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnDetailServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/impl/AsnDetailServiceImpl.java @@ -1,11 +1,19 @@ package org.cpte.modules.receive.service.impl; import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.shiro.SecurityUtils; +import org.cpte.modules.agvTask.service.IAgvTaskService; import org.cpte.modules.base.entity.Item; import org.cpte.modules.base.entity.ItemKey; import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; -import org.cpte.modules.constant.enums.AsnStatusEnum; +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.inventory.entity.Inventory; +import org.cpte.modules.inventoryLog.entity.InventoryLog; import org.cpte.modules.receive.entity.Asn; import org.cpte.modules.receive.entity.AsnDetail; import org.cpte.modules.receive.entity.ReceiveRecord; @@ -13,7 +21,9 @@ import org.cpte.modules.receive.mapper.AsnDetailMapper; import org.cpte.modules.receive.mapper.AsnMapper; import org.cpte.modules.receive.service.IAsnDetailService; import org.cpte.modules.saiWms.request.InboundRequest; -import org.cpte.modules.shipping.mapper.PickMapper; +import org.cpte.modules.serialNumber.AsnSerialNumberRule; +import org.cpte.modules.utils.BatchUtil; +import org.jeecg.common.system.vo.LoginUser; import org.springframework.stereotype.Service; import java.math.BigDecimal; @@ -21,9 +31,11 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; /** * @Description: 入库明细 @@ -37,11 +49,93 @@ public class AsnDetailServiceImpl extends ServiceImpl selectByMainId(Long mainId) { return this.baseMapper.selectByMainId(mainId); } + @Override + @Transactional(rollbackFor = Exception.class) + public void processorSaveMain(Asn asn, List asnDetailList) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + asn.setSysOrgCode(sysUser.getOrgCode()); + String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO); + asn.setOrderNo(orderNo); + asnMapper.insert(asn); + + if (asnDetailList == null || asnDetailList.isEmpty()) { + throw new RuntimeException("请新增入库明细"); + } + + AtomicInteger lineNoCounter = new AtomicInteger(1); + for (AsnDetail entity : asnDetailList) { + if (entity.getLineNo() == null || entity.getLineNo() == 0) { + entity.setLineNo(lineNoCounter.getAndIncrement()); + } + entity.setAsnId(asn.getId()); + entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + entity.setSysOrgCode(sysUser.getOrgCode()); + this.baseMapper.insert(entity); + } + //刷新入库单 + refreshAsn(asn, asnDetailList); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void processInboundTask(InboundRequest inboundRequest, Map itemMap, Point srcPoint, Stock stock) { + //1.获取工作站 + Point station = null; + if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) { + station = getStationPoint(inboundRequest.getType()); + } + + //2.构建入库单和入库明细 + Asn asn = buildAsn(inboundRequest); + List asnDetails = buildAsnDetail(inboundRequest.getDetails(), itemMap, stock, srcPoint, station); + processorSaveMain(asn, asnDetails); + + //3.绑定容器 + stockService.bindStock(stock); + + //4.成品入库,生成AGV任务 + if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType()) && station != null) { + agvTaskService.createAgvTask(asn.getId(), stock.getStockCode(), srcPoint.getPointCode(), station.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue()); + } + } + + /** + * 获取工作站 + * + * @param orderType 任务类型 + * @return Point + */ + private Point getStationPoint(Integer orderType) { + Point dstPoint = null; + if (AsnOrderTypeEnum.PRODUCT.getValue().equals(orderType)) { + //1.获取入库输送线工作台点位为终点,均衡分配点位-轮询方式 + dstPoint = pointService.getWorkStationPoint(null, AreaTypeEnum.RK_DOCK.getValue(), GeneralConstant.RK_DOCK_TASK_INDEX); + } + return dstPoint; + } + + public void refreshAsn(Asn asn, List asnDetails) { if (asnDetails == null) { @@ -77,6 +171,45 @@ public class AsnDetailServiceImpl extends ServiceImpl buildAsnDetail(List inboundDetails, Map itemMap, Stock stock, Point srcPoint, Point station) { + List newDetailList = new ArrayList<>(); + for (InboundRequest.InboundDetail detail : inboundDetails) { + AsnDetail asnDetail = AsnDetail.builder() + .lineNo(Integer.parseInt(detail.getLineNo())) + .itemId(itemMap.get(detail.getItem()).getId()) + .unit(detail.getUnit()) + .orderQty(BigDecimal.valueOf(detail.getQty())) + .receivedQty(BigDecimal.ZERO) + .stockId(stock.getId()) + .fromPointId(srcPoint == null ? null : srcPoint.getId()) + .stationId(station== null ? null : station.getId()) + .status(AsnStatusEnum.CREATED.getValue()) + .project(detail.getProject()) + .taskNo(detail.getTaskNo()) + .propC1(detail.getLotAtt04()) + .propC3(detail.getLotAtt010()) + .build(); + newDetailList.add(asnDetail); + } + return newDetailList; + + } + + @Override public ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId) { return ReceiveRecord.builder() @@ -96,4 +229,23 @@ public class AsnDetailServiceImpl extends ServiceImpl updateToAsnDetail, List records, + Map inventoryMap, List inventoryLogs) { + if (CollectionUtils.isNotEmpty(updateToAsnDetail)) { + batchUtil.updateBatchAsnDetail(updateToAsnDetail); + } + if (CollectionUtils.isNotEmpty(records)) { + batchUtil.saveBatchReceiveRecord(records); + } + if (inventoryMap != null && !inventoryMap.isEmpty()) { + List createToInventory = new ArrayList<>(inventoryMap.values()); + batchUtil.saveBatchInventory(createToInventory); + } + if (CollectionUtils.isNotEmpty(inventoryLogs)) { + batchUtil.saveBatchInventoryLog(inventoryLogs); + } + } } 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 f13e800..67448e9 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 @@ -2,11 +2,10 @@ package org.cpte.modules.receive.service.impl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.shiro.SecurityUtils; +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.base.entity.Stock; -import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.AsnStatusEnum; import org.cpte.modules.receive.entity.Asn; import org.cpte.modules.receive.entity.AsnDetail; @@ -16,12 +15,7 @@ import org.cpte.modules.receive.service.IAsnDetailService; import org.cpte.modules.receive.service.IAsnService; import org.cpte.modules.receive.service.processor.ReceiveProcessor; import org.cpte.modules.saiWms.request.InboundRequest; -import org.cpte.modules.serialNumber.AsnSerialNumberRule; import org.cpte.modules.utils.RedisDistributedLockUtil; -import org.cpte.modules.utils.SwmsLoginUtil; -import org.jeecg.common.system.vo.LoginUser; -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; @@ -42,22 +36,13 @@ import java.util.concurrent.atomic.AtomicInteger; @Slf4j public class AsnServiceImpl extends ServiceImpl implements IAsnService { - @Autowired private AsnDetailMapper asnDetailMapper; @Autowired - private OpenApiMapper openApiMapper; - @Autowired - private SysDictMapper sysDictMapper; - @Autowired private IAsnDetailService asnDetailService; @Autowired private ReceiveProcessor receiveProcessor; @Autowired - private SwmsLoginUtil swmsLoginUtil; - @Autowired - private AsnSerialNumberRule asnSerialNumberRule; - @Autowired private RedisDistributedLockUtil redissonLock; @Override @@ -69,7 +54,7 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS if (StringUtils.isEmpty(lockValue)) { throw new RuntimeException("入库单创建中,请稍后重试"); } - processorSaveMain(asn, asnDetailList); + asnDetailService.processorSaveMain(asn, asnDetailList); } catch (Exception e) { log.error("入库单创建异常", e); throw e; @@ -80,40 +65,6 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS } } - /** - * 保存主表信息 - * - * @param asn 入库单 - * @param asnDetailList 入库明细 - */ - @Transactional(rollbackFor = Exception.class) - public void processorSaveMain(Asn asn, List asnDetailList) { - LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); - asn.setSysOrgCode(sysUser.getOrgCode()); - String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO); - asn.setOrderNo(orderNo); - this.baseMapper.insert(asn); - - if (asnDetailList == null || asnDetailList.isEmpty()) { - throw new RuntimeException("请新增入库明细"); - } - - AtomicInteger lineNoCounter = new AtomicInteger(1); - for (AsnDetail entity : asnDetailList) { - if (entity.getLineNo() == null || entity.getLineNo() == 0) { - entity.setLineNo(lineNoCounter.getAndIncrement()); - } - entity.setAsnId(asn.getId()); - entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); - entity.setSysOrgCode(sysUser.getOrgCode()); - asnDetailMapper.insert(entity); - } - //刷新入库单 - asnDetailService.refreshAsn(asn, asnDetailList); - } - - @Override @Transactional(rollbackFor = Exception.class) public void updateMain(Asn asn, List asnDetailList) { @@ -123,10 +74,6 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS throw new RuntimeException("请新增入库明细"); } - if (asnDetailList.size() > 1) { - throw new RuntimeException("入库明细只允许新增一条"); - } - AtomicInteger lineNoCounter = new AtomicInteger(1); for (AsnDetail entity : asnDetailList) { if (entity.getLineNo() == null || entity.getLineNo() == 0) { @@ -172,47 +119,8 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除"); } } - @Override - public Asn buildAsn(InboundRequest inboundRequest) { - return Asn.builder() - .thirdOrderNo(inboundRequest.getOrderNo()) - .no(inboundRequest.getNo()) - .whCode(inboundRequest.getWhCode()) - .supplierCode(inboundRequest.getSupplierCode()) - .orderType(inboundRequest.getType()) - .status(AsnStatusEnum.CREATED.getValue()) - .orderDate(new Date()) - .build(); - } - - @Override - public List buildAsnDetail(List inboundDetails, Map itemMap, Stock stock, Point srcPoint, Point dstPoint) { - List newDetailList = new ArrayList<>(); - for (InboundRequest.InboundDetail detail : inboundDetails) { - AsnDetail asnDetail = AsnDetail.builder() - .lineNo(Integer.parseInt(detail.getLineNo())) - .itemId(itemMap.get(detail.getItem()).getId()) - .unit(detail.getUnit()) - .orderQty(BigDecimal.valueOf(detail.getQty())) - .receivedQty(BigDecimal.ZERO) - .stockId(stock.getId()) - .fromPointId(srcPoint == null ? null : srcPoint.getId()) - .toPointId(dstPoint == null ? null : dstPoint.getId()) - .status(AsnStatusEnum.CREATED.getValue()) - .project(detail.getProject()) - .taskNo(detail.getTaskNo()) - .propC1(detail.getLotAtt04()) - .propC3(detail.getLotAtt010()) - .build(); - newDetailList.add(asnDetail); - } - return newDetailList; - - } - - @Override - public void receiveAsn(Long asnId, String pointCode) { + public void receiveAsn(Long asnId) { String lockKey = "asn:" + asnId; String lockValue = null; try { @@ -220,7 +128,7 @@ public class AsnServiceImpl extends ServiceImpl implements IAsnS if (StringUtils.isEmpty(lockValue)) { throw new RuntimeException("收货处理中,请稍后重试"); } - receiveProcessor.receiveAsn(asnId, pointCode); + receiveProcessor.receiveAsn(asnId); } catch (Exception e) { log.error("收货处理异常", e); throw e; diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/processor/ReceiveProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/processor/ReceiveProcessor.java index d3e1e9e..200cbaf 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/processor/ReceiveProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/service/processor/ReceiveProcessor.java @@ -8,8 +8,6 @@ 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.IItemKeyService; -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.inventory.entity.Inventory; import org.cpte.modules.inventory.service.IInventoryService; @@ -22,11 +20,9 @@ import org.cpte.modules.receive.mapper.AsnDetailMapper; import org.cpte.modules.receive.mapper.AsnMapper; import org.cpte.modules.receive.service.IAsnDetailService; import org.cpte.modules.receive.vo.ReceiveData; -import org.cpte.modules.utils.BatchUtil; import org.cpte.modules.utils.BigDecimalUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.ArrayList; @@ -42,10 +38,10 @@ import java.util.Map; public class ReceiveProcessor { @Autowired - private StockMapper stockMapper; + private PointMapper pointMapper; @Autowired - private PointMapper pointMapper; + private StockMapper stockMapper; @Autowired private AsnMapper asnMapper; @@ -53,12 +49,6 @@ public class ReceiveProcessor { @Autowired private AsnDetailMapper asnDetailMapper; - @Autowired - private IStockService stockService; - - @Autowired - private IPointService pointService; - @Autowired private IAsnDetailService asnDetailService; @@ -74,18 +64,15 @@ public class ReceiveProcessor { @Autowired private ReceiveBackProcessor receiveBackProcessor; - @Autowired - private BatchUtil batchUtil; /** * 收货 * - * @param asnId 入库单 - * @param dstPointCode 目标库位 + * @param asnId 入库单 */ - public void receiveAsn(Long asnId, String dstPointCode) { + public void receiveAsn(Long asnId) { // 1.数据准备 - ReceiveData data = prepareReceiveData(asnId, dstPointCode); + ReceiveData data = prepareReceiveData(asnId); //3.创建数据结构 List updateToAsnDetail = new ArrayList<>(); @@ -97,14 +84,11 @@ public class ReceiveProcessor { receive(data, updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs); //5.批量操作 - batchOperation(updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs); + asnDetailService.batchOperation(updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs); //6.刷新入库 refreshData(data); - //7.更新容器状态和位置 - updateStockAndPoint(data.getStock(), data.getDstPoint()); - //8.回传 receiveBackProcessor.receiveBack(data.getAsn(), data.getStock()); } @@ -112,11 +96,10 @@ public class ReceiveProcessor { /** * 数据准备 * - * @param asnId 入库单 - * @param dstPointCode 目标库位 + * @param asnId 入库单 * @return ReceiveData */ - private ReceiveData prepareReceiveData(Long asnId, String dstPointCode) { + private ReceiveData prepareReceiveData(Long asnId) { ReceiveData data = new ReceiveData(); Asn asn = asnMapper.selectById(asnId); data.setAsn(asn); @@ -124,13 +107,13 @@ public class ReceiveProcessor { List asnDetails = asnDetailMapper.selectByMainId(asnId); if (CollectionUtils.isNotEmpty(asnDetails)) { data.setAsnDetails(asnDetails); + Stock stock = stockMapper.selectById(asnDetails.get(0).getStockId()); data.setStock(stock); + + Point point = pointMapper.selectById(asnDetails.get(0).getToPointId()); + data.setPoint(point); } - - Point dstPoint = pointMapper.queryByPointCode(dstPointCode); - data.setDstPoint(dstPoint); - return data; } @@ -149,8 +132,7 @@ public class ReceiveProcessor { Map inventoryMap, List inventoryLogs) { Asn asn = data.getAsn(); - Point dstPoint = data.getDstPoint(); - Stock stock = data.getStock(); + for (AsnDetail asnDetail : data.getAsnDetails()) { BigDecimal unreceivedQty = BigDecimalUtil.subtract(asnDetail.getOrderQty(), asnDetail.getReceivedQty(), 0); if (unreceivedQty.compareTo(BigDecimal.ZERO) <= 0) { @@ -170,14 +152,14 @@ public class ReceiveProcessor { ItemKey itemKey = itemKeyService.createItemKey(asnDetail.getItemId(), asn.getWhCode(), asnDetail.getProject(), asnDetail.getTaskNo(), asnDetail.getPropC1(), asnDetail.getPropC3()); //生成入库记录 - ReceiveRecord receiveRecord = asnDetailService.buildReceiveRecord(asnDetail, receivedQty, itemKey, dstPoint.getId()); + ReceiveRecord receiveRecord = asnDetailService.buildReceiveRecord(asnDetail, receivedQty, itemKey, asnDetail.getToPointId()); records.add(receiveRecord); // 生成库存 - Inventory inventory = createInventory(asn, receiveRecord, itemKey, stock, receivedQty, inventoryMap); + Inventory inventory = createInventory(asn, receiveRecord, itemKey, asnDetail.getStockId(), receivedQty, inventoryMap); //添加库存日志 - InventoryLog inventoryLog = inventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getToPointId(),receivedQty, asn.getThirdOrderNo(), receiveRecord.getId(), receiveRecord.getDescription()); + InventoryLog inventoryLog = inventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getFromPointId() == null ? asnDetail.getStationId() : asnDetail.getFromPointId(), receivedQty, asn.getThirdOrderNo(), receiveRecord.getId(), receiveRecord.getDescription()); inventoryLogs.add(inventoryLog); } } @@ -189,12 +171,12 @@ public class ReceiveProcessor { * @param asn 入库单 * @param receiveRecord 收货记录 * @param itemKey 物料属性 - * @param stock 容器 + * @param stockId 容器 * @param receivedQty 收货数量 * @param inventoryMap 创建库存 */ - private Inventory createInventory(Asn asn, ReceiveRecord receiveRecord, ItemKey itemKey, Stock stock, BigDecimal receivedQty, Map inventoryMap) { - Inventory inventory = inventoryService.buildInventory(stock.getId(), BigDecimal.ZERO, asn, receiveRecord); + private Inventory createInventory(Asn asn, ReceiveRecord receiveRecord, ItemKey itemKey, Long stockId, BigDecimal receivedQty, Map inventoryMap) { + Inventory inventory = inventoryService.buildInventory(stockId, BigDecimal.ZERO, asn, receiveRecord); //根据itemKey更新库存 Inventory targetInventory = inventoryMap.getOrDefault(itemKey.getId(), inventory); BigDecimal newReceivedQty = BigDecimalUtil.add(targetInventory.getQuantity(), receivedQty, 0); @@ -203,33 +185,6 @@ public class ReceiveProcessor { return targetInventory; } - - /** - * 批量操作 - * - * @param updateToAsnDetail 更新入库单明细 - * @param records 创建收货记录 - * @param inventoryMap 创建库存 - * @param inventoryLogs 创建库存日志 - */ - @Transactional(rollbackFor = Exception.class) - public void batchOperation(List updateToAsnDetail, List records, - Map inventoryMap, List inventoryLogs) { - if (CollectionUtils.isNotEmpty(updateToAsnDetail)) { - batchUtil.updateBatchAsnDetail(updateToAsnDetail); - } - if (CollectionUtils.isNotEmpty(records)) { - batchUtil.saveBatchReceiveRecord(records); - } - if (inventoryMap != null && !inventoryMap.isEmpty()) { - List createToInventory = new ArrayList<>(inventoryMap.values()); - batchUtil.saveBatchInventory(createToInventory); - } - if (CollectionUtils.isNotEmpty(inventoryLogs)) { - batchUtil.saveBatchInventoryLog(inventoryLogs); - } - } - /** * 刷新出库单 * @@ -239,16 +194,4 @@ public class ReceiveProcessor { asnDetailService.refreshAsn(data.getAsn(), data.getAsnDetails()); } - /** - * 更新容器状态和位置 - * - * @param stock 托盘 - * @param dstPoint 目标库位 - */ - @Transactional(rollbackFor = Exception.class) - public void updateStockAndPoint(Stock stock, Point dstPoint) { - //更新容器状态和位置 - stockService.bindStock(stock, dstPoint); - pointService.bindPoint(dstPoint); - } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/vo/ReceiveData.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/vo/ReceiveData.java index 738af81..bc93495 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/vo/ReceiveData.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/vo/ReceiveData.java @@ -13,5 +13,5 @@ public class ReceiveData { private Asn asn ; private List asnDetails; private Stock stock; - private Point dstPoint; + private Point 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 0b82818..58918a9 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 @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; +import org.cpte.modules.receive.service.IAsnService; import org.cpte.modules.saiWms.request.CallAgvRequest; import org.cpte.modules.saiWms.request.InboundRequest; import org.cpte.modules.saiWms.request.OutboundRequest; @@ -11,6 +12,7 @@ import org.cpte.modules.saiWms.request.SyncStockRequest; import org.cpte.modules.saiWms.service.ISMOMService; import org.jeecg.common.api.vo.Result; import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.config.shiro.IgnoreAuth; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -26,6 +28,9 @@ public class SaiWmsController { @Autowired private ISMOMService iSaiWmsService; + @Autowired + private IAsnService asnService; + /** * 容器同步 * diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISMOMServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISMOMServiceImpl.java index c08d284..02b4b17 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISMOMServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/impl/ISMOMServiceImpl.java @@ -36,12 +36,44 @@ public class ISMOMServiceImpl implements ISMOMService { @Override public void inBoundTask(InboundRequest inboundRequest) { - inBoundTaskProcessor.inBoundTask(inboundRequest); + //5.入库处理 + String lockKey = "inbound:" + inboundRequest.getNo(); + String lockValue = null; + try { + lockValue = redissonLock.tryLock(lockKey, 10); + if (StringUtils.isEmpty(lockValue)) { + throw new RuntimeException("入库单接收中,请稍后重试"); + } + inBoundTaskProcessor.inBoundTask(inboundRequest); + } catch (Exception e) { + log.error("入库单接收异常", e); + throw e; + } finally { + if (StringUtils.isNotEmpty(lockValue)) { + redissonLock.unlock(lockKey, lockValue); + } + } + } @Override public void outBoundTask(OutboundRequest outboundRequest) { - outBoundTaskProcessor.outBoundTask(outboundRequest); + String lockKey = "outbound:" + outboundRequest.getNo(); + String lockValue = null; + try { + lockValue = redissonLock.tryLock(lockKey, 10); + if (StringUtils.isEmpty(lockValue)) { + throw new RuntimeException("出库单接收中,请稍后重试"); + } + outBoundTaskProcessor.outBoundTask(outboundRequest); + } catch (Exception e) { + log.error("出库单接收异常", e); + throw e; + } finally { + if (StringUtils.isNotEmpty(lockValue)) { + redissonLock.unlock(lockKey, lockValue); + } + } } @Override diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/InBoundTaskProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/InBoundTaskProcessor.java index b02fc81..0c232d7 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/InBoundTaskProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/InBoundTaskProcessor.java @@ -19,8 +19,10 @@ import org.cpte.modules.inventory.mapper.InventoryMapper; import org.cpte.modules.receive.entity.Asn; import org.cpte.modules.receive.entity.AsnDetail; import org.cpte.modules.receive.mapper.AsnMapper; +import org.cpte.modules.receive.service.IAsnDetailService; import org.cpte.modules.receive.service.IAsnService; import org.cpte.modules.saiWms.request.InboundRequest; +import org.cpte.modules.utils.RedisDistributedLockUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -53,10 +55,7 @@ public class InBoundTaskProcessor { private IPointService pointService; @Autowired - private IAsnService asnService; - - @Autowired - private IAgvTaskService agvTaskService; + private IAsnDetailService asnDetailService; /** * 接收入库任务 @@ -77,34 +76,7 @@ public class InBoundTaskProcessor { Point srcPoint = validateSrcPoint(inboundRequest.getType(), inboundRequest.getLocationFrom()); //5.入库处理 - processInboundTask(inboundRequest, itemMap, srcPoint, stock); - } - - /** - * 入库处理 - * - * @param inboundRequest 入库参数 - * @param itemMap 物料 - * @param srcPoint 起点 - * @param stock 容器 - */ - @Transactional(rollbackFor = Exception.class) - private void processInboundTask(InboundRequest inboundRequest, Map itemMap, Point srcPoint, Stock stock) { - //1.获取终点 - Point dstPoint = getDstPoint(inboundRequest.getType()); - - //2.构建入库单和入库明细 - Asn createAsn = asnService.buildAsn(inboundRequest); - List asnDetails = asnService.buildAsnDetail(inboundRequest.getDetails(), itemMap, stock, srcPoint, dstPoint); - asnService.saveMain(createAsn, asnDetails); - - //3.绑定容器和起点 - stockService.bindStock(stock, srcPoint); - - //4.成品入库,生成AGV任务 - if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) { - agvTaskService.createAgvTask(createAsn.getId(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue()); - } + asnDetailService.processInboundTask(inboundRequest, itemMap, srcPoint, stock); } @@ -229,19 +201,4 @@ public class InBoundTaskProcessor { return srcPoint; } - /** - * 获取终点 - * - * @param orderType 任务类型 - * @return Point - */ - private Point getDstPoint(Integer orderType) { - Point dstPoint = null; - if (AsnOrderTypeEnum.PRODUCT.getValue().equals(orderType)) { - //1.获取入库输送线工作台点位为终点,均衡分配点位-轮询方式 - dstPoint = pointService.getWorkStationPoint(null, AreaTypeEnum.RK_DOCK.getValue(), GeneralConstant.RK_DOCK_TASK_INDEX); - } - return dstPoint; - } - } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/OutBoundTaskProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/OutBoundTaskProcessor.java index 0407547..8a1aba7 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/OutBoundTaskProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/OutBoundTaskProcessor.java @@ -14,6 +14,7 @@ import org.cpte.modules.saiWms.request.OutboundRequest; 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.IPickDetailService; import org.cpte.modules.shipping.service.IPickService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -39,7 +40,7 @@ public class OutBoundTaskProcessor { private IPointService pointService; @Autowired - private IPickService pickService; + private IPickDetailService pickDetailService; /** @@ -58,24 +59,9 @@ public class OutBoundTaskProcessor { Map itemMap = validateItem(outboundRequest.getDetails()); //5.出库处理 - processOutBoundTask(outboundRequest, itemMap); + pickDetailService.processOutBoundTask(outboundRequest, itemMap); } - /** - * 出库处理 - * - * @param outboundRequest 出库参数 - * @param itemMap 物料 - */ - @Transactional(rollbackFor = Exception.class) - private void processOutBoundTask(OutboundRequest outboundRequest, Map itemMap) { - // 创建出库单和明细 - Pick createPick = pickService.buildPick(outboundRequest); - List pickDetails = pickService.buildPickDetail(outboundRequest.getDetails(), itemMap); - pickService.saveMain(createPick, pickDetails); - } - - /** * 出库参数校验 * diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/SyncStockProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/SyncStockProcessor.java index 48aece7..94b8d4d 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/SyncStockProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/saiWms/service/processor/SyncStockProcessor.java @@ -23,8 +23,7 @@ public class SyncStockProcessor { @Autowired private IStockService stockService; - @Autowired - private BatchUtil batchUtil; + /** * 接收容器同步信息 @@ -46,7 +45,7 @@ public class SyncStockProcessor { processStock(syncStockRequest.getStocks(), stockMap, insertToStock, updateToStock); //5.批量操作 - batchOperation(insertToStock, updateToStock); + stockService.batchOperation(insertToStock, updateToStock); } /** @@ -125,21 +124,4 @@ public class SyncStockProcessor { } } } - - /** - * 批量操作 - * - * @param insertToStock 创建的容器 - * @param updateToStock 更新的容器 - */ - @Transactional(rollbackFor = Exception.class) - public void batchOperation(List insertToStock, List updateToStock) { - if (CollectionUtils.isNotEmpty(insertToStock)) { - batchUtil.saveBatchStock(insertToStock); - } - if (CollectionUtils.isNotEmpty(updateToStock)) { - batchUtil.batchUpdateStocks(updateToStock); - } - } - } 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 680311b..5466527 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 @@ -11,6 +11,7 @@ import org.apache.commons.lang3.StringUtils; import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.serialNumber.PickSerialNumberRule; import org.cpte.modules.shipping.entity.Task; +import org.cpte.modules.shipping.mapper.TaskMapper; import org.cpte.modules.shipping.service.ITaskService; import org.jeecg.common.system.query.QueryRuleEnum; import org.jeecgframework.poi.excel.ExcelImportUtil; @@ -55,6 +56,8 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; @RequestMapping("/shipping/pick") @Slf4j public class PickController { + @Autowired + private TaskMapper taskMapper; @Autowired private IPickService pickService; @Autowired @@ -81,9 +84,7 @@ public class PickController { @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(pick, req.getParameterMap()); - List status = Arrays.stream(req.getParameterMap().get("status[]")).toList(); - queryWrapper.in("status", status); - Page page = new Page(pageNo, pageSize); + Page page = new Page<>(pageNo, pageSize); IPage pageList = pickService.page(page, queryWrapper); return Result.OK(pageList); } @@ -280,8 +281,8 @@ public class PickController { return Result.OK("文件导入失败!"); } - @AutoLog(value = "出库分配") - @Operation(summary = "出库分配") + @AutoLog(value = "批量分配") + @Operation(summary = "批量分配") @RequiresPermissions("shipping:data_pick:allocatePick") @GetMapping(value = "/allocatePick") public Result allocatePick(@RequestParam(name = "ids", required = true) String ids) { @@ -304,13 +305,13 @@ public class PickController { } } - @AutoLog(value = "取消分配") - @Operation(summary = "取消分配") + @AutoLog(value = "批量取消分配") + @Operation(summary = "批量取消分配") @RequiresPermissions("shipping:data_pick:cancelAllocate") @GetMapping(value = "/cancelAllocate") public Result cancelAllocate(@RequestParam(name = "ids", required = true) String ids) { if (StringUtils.isEmpty(ids)) { - return Result.error("请选择需要取消的出库单"); + return Result.error("请选择需取消的出库单"); } try { List idsList = Arrays.asList(ids.split(",")); @@ -327,4 +328,23 @@ public class PickController { return Result.error("取消异常:" + e.getMessage()); } } + + @AutoLog(value = "批量拣货") + @Operation(summary = "批量拣货") + @RequiresPermissions("shipping:data_pick:pickTask") + @GetMapping(value = "/pickTask") + public Result pickTask(@RequestParam(name = "ids", required = true) String ids) { + if (StringUtils.isEmpty(ids)) { + return Result.error("请选择需要拣货的出库单"); + } + try { + List idsList = Arrays.asList(ids.split(",")); + List pickIds = idsList.stream().map(Long::parseLong).toList(); + List tasks = taskMapper.queryByPickIds(pickIds); + pickService.pickTask(tasks); + return Result.OK("拣货成功"); + } catch (Exception e) { + return Result.error("拣货异常:" + e.getMessage()); + } + } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickDetailService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickDetailService.java index 46e8be0..b44fcb0 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickDetailService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickDetailService.java @@ -1,50 +1,119 @@ 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.inventory.entity.Inventory; +import org.cpte.modules.saiWms.request.OutboundRequest; import org.cpte.modules.shipping.entity.Pick; import org.cpte.modules.shipping.entity.PickDetail; import com.baomidou.mybatisplus.extension.service.IService; +import org.cpte.modules.shipping.entity.Task; + import java.util.List; import java.util.Map; /** * @Description: 出库明细 * @author: cpte - * @Date: 2025-11-14 + * @Date: 2025-11-14 * @Version: V1.0 */ public interface IPickDetailService extends IService { - /** - * 通过主表id查询子表数据 - * - * @param mainId 主表id - * @return List - */ - public List selectByMainId(Long mainId); + /** + * 构建出库单 + * + * @param outboundRequest 出库单请求 + * @return 出库单 + */ + Pick buildPick(OutboundRequest outboundRequest); - /** - * 根据出库单ID查询出库单Map - * - * @param pickIds 出库单ID集合 - * @return Map - */ - Map queryByPickIdsToMap(List pickIds); - - /** - * 根据出库单明细ID查询出库单明细Map - * - * @param pickDetailIds 出库单明细ID集合 - * @return Map - */ - Map queryByPickDetailIdsToMap(List pickDetailIds); + /** + * 构建出库单明细 + * + * @param details 出库单明细 + * @param exitItemMap 物料 + * @return 出库单明细 + */ + List buildPickDetail(List details, Map exitItemMap); + /** + * 通过主表id查询子表数据 + * + * @param mainId 主表id + * @return List + */ + public List selectByMainId(Long mainId); + + /** + * 根据出库单ID查询出库单Map + * + * @param pickIds 出库单ID集合 + * @return Map + */ + Map queryByPickIdsToMap(List pickIds); + + /** + * 根据出库单明细ID查询出库单明细Map + * + * @param pickDetailIds 出库单明细ID集合 + * @return Map + */ + Map queryByPickDetailIdsToMap(List pickDetailIds); + + /** + * 保存主表及从表 + * + * @param pick 出库单 + * @param pickDetailList 出库单明细 + */ + void processorSaveMain(Pick pick, List pickDetailList); + + /** + * 处理出库任务 + * + * @param outboundRequest 出库参数 + * @param itemMap 物料 + */ + void processOutBoundTask(OutboundRequest outboundRequest, Map itemMap); + + /** + * 批量操作 + * + * @param inventoryUpdateMap 库存更新 + * @param pickDetailUpdateMap 出库单明细更新 + * @param createToTask 创建任务 + */ + void batchOperationAllocate(Map inventoryUpdateMap, Map pickDetailUpdateMap, List createToTask); + + /** + * 批量操作 + * + * @param inventoryUpdateMap 库存更新 + * @param pickDetailUpdateMap 出库单明细更新 + * @param deleteToTask 删除任务 + */ + void batchOperationCancel(Map inventoryUpdateMap, Map pickDetailUpdateMap, List deleteToTask); + /** - * 刷新出库单 - * - * @param pick 出库单 - * @param pickDetails 出库单明细 - */ - void refreshPick(Pick pick, List pickDetails); + * 批量操作 + * + * @param deleteToInventory 删除库存 + * @param pickDetailUpdateMap 出库单明细更新 + * @param updateToTask 更新任务 + * @param updateToStock 更新库存 + * @param updateToPoint 更新点位 + */ + void batchOperationPick(List deleteToInventory, Map pickDetailUpdateMap, List updateToTask, List updateToStock, List updateToPoint); + + /** + * 刷新出库单 + * + * @param pick 出库单 + * @param pickDetails 出库单明细 + */ + void refreshPick(Pick pick, List pickDetails); } 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 4885032..1ad71f6 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 @@ -1,8 +1,5 @@ package org.cpte.modules.shipping.service; -import org.cpte.modules.base.entity.Item; -import org.cpte.modules.base.entity.Point; -import org.cpte.modules.saiWms.request.OutboundRequest; import org.cpte.modules.shipping.entity.PickDetail; import org.cpte.modules.shipping.entity.Pick; import com.baomidou.mybatisplus.extension.service.IService; @@ -11,7 +8,6 @@ import org.cpte.modules.shipping.entity.Task; import java.io.Serializable; import java.util.Collection; import java.util.List; -import java.util.Map; /** * @Description: 出库单 @@ -51,24 +47,6 @@ public interface IPickService extends IService { */ public void delBatchMain(Collection idList); - /** - * 构建出库单 - * - * @param outboundRequest 出库单请求 - * @return 出库单 - */ - Pick buildPick(OutboundRequest outboundRequest); - - /** - * 构建出库单明细 - * - * @param details 出库单明细 - * @param exitItemMap 物料 - * @return 出库单明细 - */ - List buildPickDetail(List details, Map exitItemMap); - - /** * 分配出库单 * diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickDetailServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickDetailServiceImpl.java index a4dbc4b..d51db82 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickDetailServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickDetailServiceImpl.java @@ -1,19 +1,37 @@ package org.cpte.modules.shipping.service.impl; import org.apache.commons.collections4.CollectionUtils; +import org.apache.shiro.SecurityUtils; +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.IPointService; +import org.cpte.modules.base.service.IStockService; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.PickStatusEnum; +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.saiWms.request.OutboundRequest; +import org.cpte.modules.serialNumber.PickSerialNumberRule; 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.mapper.TaskMapper; import org.cpte.modules.shipping.service.IPickDetailService; +import org.cpte.modules.utils.BatchUtil; +import org.jeecg.common.system.vo.LoginUser; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; /** * @Description: 出库明细 @@ -26,11 +44,66 @@ public class PickDetailServiceImpl extends ServiceImpl selectByMainId(Long mainId) { return this.baseMapper.selectByMainId(mainId); } + @Override + public Pick buildPick(OutboundRequest outboundRequest) { + return Pick.builder() + .thirdOrderNo(outboundRequest.getOrderNo()) + .no(outboundRequest.getNo()) + .whCode(outboundRequest.getWhCode()) + .customerCode(outboundRequest.getCustomerCode()) + .orderType(outboundRequest.getType()) + .status(PickStatusEnum.CREATED.getValue()) + .orderDate(new Date()) + .build(); + } + + @Override + public List buildPickDetail(List details, Map exitItemMap) { + List newDetailList = new ArrayList<>(); + for (OutboundRequest.OutboundDetail detail : details) { + PickDetail pickDetail = PickDetail.builder() + .lineNo(Integer.parseInt(detail.getLineNo())) + .itemId(exitItemMap.get(detail.getItem()).getId()) + .unit(detail.getUnit()) + .orderQty(BigDecimal.valueOf(detail.getQty())) + .allocatedQty(BigDecimal.ZERO) + .pickedQty(BigDecimal.ZERO) + .status(PickStatusEnum.CREATED.getValue()) + .project(detail.getProject()) + .taskNo(detail.getTaskNo()) + .propC1(detail.getLotAtt04()) + .propC3(detail.getLotAtt010()) + .build(); + newDetailList.add(pickDetail); + } + return newDetailList; + } + /** * 获取出库单Map * @@ -67,6 +140,101 @@ public class PickDetailServiceImpl extends ServiceImpl pickDetailList) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + pick.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + pick.setSysOrgCode(sysUser.getOrgCode()); + String orderNo = pickSerialNumberRule.generateSerialNumber(GeneralConstant.PICK_ORDER_NO); + pick.setOrderNo(orderNo); + pickMapper.insert(pick); + + if (pickDetailList == null || pickDetailList.isEmpty()) { + throw new RuntimeException("请新增出库明细"); + } + + // 获取当前出库单下已存在的最大序号 + Integer maxLineNo = this.baseMapper.queryMaxLineNoByPickId(pick.getId()); + AtomicInteger lineNoCounter = new AtomicInteger((maxLineNo != null) ? maxLineNo + 1 : 1); + + for (PickDetail entity : pickDetailList) { + if (entity.getLineNo() == null || entity.getLineNo() == 0) { + entity.setLineNo(lineNoCounter.getAndIncrement()); + } + entity.setPickId(pick.getId()); + entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); + entity.setSysOrgCode(sysUser.getOrgCode()); + this.baseMapper.insert(entity); + } + //刷新出库单 + refreshPick(pick, pickDetailList); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void processOutBoundTask(OutboundRequest outboundRequest, Map itemMap) { + // 创建出库单和明细 + Pick createPick = buildPick(outboundRequest); + List pickDetails = buildPickDetail(outboundRequest.getDetails(), itemMap); + processorSaveMain(createPick, pickDetails); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void batchOperationAllocate(Map inventoryUpdateMap, Map pickDetailUpdateMap, List createToTask) { + + List updateToInventory = new ArrayList<>(inventoryUpdateMap.values()); + List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); + if (CollectionUtils.isNotEmpty(updateToInventory)) { + batchUtil.updateBatchInventory(updateToInventory); + } + if (CollectionUtils.isNotEmpty(updateToPickDetail)) { + batchUtil.updateBatchPickDetail(updateToPickDetail); + } + if (CollectionUtils.isNotEmpty(createToTask)) { + batchUtil.saveBatchTask(createToTask); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void batchOperationCancel(Map inventoryUpdateMap, Map pickDetailUpdateMap, List deleteToTask) { + List updateToInventory = new ArrayList<>(inventoryUpdateMap.values()); + List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); + if (CollectionUtils.isNotEmpty(updateToInventory)) { + batchUtil.updateBatchInventory(updateToInventory); + } + if (CollectionUtils.isNotEmpty(updateToPickDetail)) { + batchUtil.updateBatchPickDetail(updateToPickDetail); + } + if (CollectionUtils.isNotEmpty(deleteToTask)) { + taskMapper.deleteByIds(deleteToTask); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void batchOperationPick(List deleteToInventory, Map pickDetailUpdateMap, List updateToTask, List updateToStock, List updateToPoint) { + if (CollectionUtils.isNotEmpty(deleteToInventory)) { + List deleteToInventoryIds = deleteToInventory.stream().map(Inventory::getId).toList(); + inventoryMapper.deleteByIds(deleteToInventoryIds); + } + List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); + if (CollectionUtils.isNotEmpty(updateToPickDetail)) { + batchUtil.updateBatchPickDetail(updateToPickDetail); + } + if (CollectionUtils.isNotEmpty(updateToTask)) { + batchUtil.updateBatchTask(updateToTask); + } + if (CollectionUtils.isNotEmpty(updateToStock)) { + stockService.updateBatchById(updateToStock); + } + if (CollectionUtils.isNotEmpty(updateToPoint)) { + pointService.updateBatchById(updateToPoint); + } + } + /** * 刷新出库单状态 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 b0887af..29bbf04 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 @@ -1,49 +1,27 @@ package org.cpte.modules.shipping.service.impl; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.shiro.SecurityUtils; -import org.cpte.modules.constant.GeneralConstant; -import org.cpte.modules.base.entity.Item; import org.cpte.modules.constant.enums.*; -import org.cpte.modules.inventory.entity.Inventory; -import org.cpte.modules.inventory.service.IInventoryService; -import org.cpte.modules.inventoryLog.service.IInventoryLogService; -import org.cpte.modules.saiWms.request.OutboundRequest; -import org.cpte.modules.saiWms.request.SMOMRequest; -import org.cpte.modules.serialNumber.PickSerialNumberRule; 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.mapper.TaskMapper; import org.cpte.modules.shipping.service.processor.AllocateProcessor; import org.cpte.modules.shipping.service.processor.CancelAllocateProcessor; import org.cpte.modules.shipping.service.IPickDetailService; import org.cpte.modules.shipping.service.IPickService; import org.cpte.modules.shipping.service.processor.PickProcessor; -import org.cpte.modules.utils.BatchUtil; -import org.cpte.modules.utils.BigDecimalUtil; import org.cpte.modules.utils.RedisDistributedLockUtil; -import org.cpte.modules.utils.SwmsLoginUtil; import org.jeecg.common.constant.CommonConstant; -import org.jeecg.common.system.vo.LoginUser; import org.jeecg.modules.base.service.BaseCommonService; -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; import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; -import java.math.BigDecimal; -import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -64,8 +42,6 @@ public class PickServiceImpl extends ServiceImpl implements IP @Autowired private BaseCommonService baseCommonService; @Autowired - private PickSerialNumberRule pickSerialNumberRule; - @Autowired private AllocateProcessor allocateProcessor; @Autowired private CancelAllocateProcessor cancelAllocateProcessor; @@ -84,7 +60,7 @@ public class PickServiceImpl extends ServiceImpl implements IP if (StringUtils.isEmpty(lockValue)) { throw new RuntimeException("出库单创建中,请稍后重试"); } - processorSaveMain(pick, pickDetailList); + pickDetailService.processorSaveMain(pick, pickDetailList); } catch (Exception e) { log.error("出库单创建异常", e); throw e; @@ -95,43 +71,6 @@ public class PickServiceImpl extends ServiceImpl implements IP } } - /** - * 保存主表及从表 - * - * @param pick 出库单 - * @param pickDetailList 出库单明细 - */ - @Transactional(rollbackFor = Exception.class) - public void processorSaveMain(Pick pick, List pickDetailList) { - LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - pick.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); - pick.setSysOrgCode(sysUser.getOrgCode()); - String orderNo = pickSerialNumberRule.generateSerialNumber(GeneralConstant.PICK_ORDER_NO); - pick.setOrderNo(orderNo); - this.baseMapper.insert(pick); - - if (pickDetailList == null || pickDetailList.isEmpty()) { - throw new RuntimeException("请新增出库明细"); - } - - // 获取当前出库单下已存在的最大序号 - Integer maxLineNo = pickDetailMapper.queryMaxLineNoByPickId(pick.getId()); - AtomicInteger lineNoCounter = new AtomicInteger((maxLineNo != null) ? maxLineNo + 1 : 1); - - for (PickDetail entity : pickDetailList) { - if (entity.getLineNo() == null || entity.getLineNo() == 0) { - entity.setLineNo(lineNoCounter.getAndIncrement()); - } - entity.setPickId(pick.getId()); - entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds())); - entity.setSysOrgCode(sysUser.getOrgCode()); - pickDetailMapper.insert(entity); - } - //刷新出库单 - pickDetailService.refreshPick(pick, pickDetailList); - } - - @Override @Transactional(rollbackFor = Exception.class) public void updateMain(Pick pick, List pickDetailList) { @@ -206,40 +145,7 @@ public class PickServiceImpl extends ServiceImpl implements IP } } - @Override - public Pick buildPick(OutboundRequest outboundRequest) { - return Pick.builder() - .thirdOrderNo(outboundRequest.getOrderNo()) - .no(outboundRequest.getNo()) - .whCode(outboundRequest.getWhCode()) - .customerCode(outboundRequest.getCustomerCode()) - .orderType(outboundRequest.getType()) - .status(PickStatusEnum.CREATED.getValue()) - .orderDate(new Date()) - .build(); - } - @Override - public List buildPickDetail(List details, Map exitItemMap) { - List newDetailList = new ArrayList<>(); - for (OutboundRequest.OutboundDetail detail : details) { - PickDetail pickDetail = PickDetail.builder() - .lineNo(Integer.parseInt(detail.getLineNo())) - .itemId(exitItemMap.get(detail.getItem()).getId()) - .unit(detail.getUnit()) - .orderQty(BigDecimal.valueOf(detail.getQty())) - .allocatedQty(BigDecimal.ZERO) - .pickedQty(BigDecimal.ZERO) - .status(PickStatusEnum.CREATED.getValue()) - .project(detail.getProject()) - .taskNo(detail.getTaskNo()) - .propC1(detail.getLotAtt04()) - .propC3(detail.getLotAtt010()) - .build(); - newDetailList.add(pickDetail); - } - return newDetailList; - } @Override public List allocatePick(List pickIds) { diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java index 030a525..8ced83d 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java @@ -26,12 +26,10 @@ import org.cpte.modules.shipping.service.ITaskService; import org.cpte.modules.shipping.vo.AllocationData; import org.cpte.modules.shipping.vo.InventoryScore; import org.cpte.modules.shipping.vo.ItemGroupKey; -import org.cpte.modules.utils.BatchUtil; import org.cpte.modules.utils.BigDecimalUtil; import org.cpte.modules.utils.RedisDistributedLockUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; @@ -83,9 +81,6 @@ public class AllocateProcessor { @Autowired private MoveSerialNumberRule moveSerialNumberRule; - @Autowired - private BatchUtil batchUtil; - @Autowired private RedisDistributedLockUtil redissonLock; @@ -121,7 +116,7 @@ public class AllocateProcessor { moveTask(createToTask, movePoints); //6.批量操作 - batchOperation(inventoryUpdateMap, pickDetailUpdateMap, createToTask); + pickDetailService.batchOperationAllocate(inventoryUpdateMap, pickDetailUpdateMap, createToTask); //7.刷新出库单 refreshData(data); @@ -261,7 +256,7 @@ public class AllocateProcessor { } // 分配库存 - String lockKey = "allocate:" + pickDetail.getId(); + String lockKey = "allocate:" + pick.getId(); String lockValue = null; try { lockValue = redissonLock.tryLock(lockKey, 10); @@ -271,7 +266,7 @@ public class AllocateProcessor { allocateInventory(pickDetail, item, pick, matchedInventories, inventoryUpdateMap, pickDetailUpdateMap, createToTask, movePoints, data, unAllocatedQty, errorMsgSet); } catch (Exception e) { - log.error("分配异常,明细ID: {}", pickDetail.getId(), e); + log.error("分配异常,出库单ID: {}", pick.getId(), e); throw e; } finally { if (StringUtils.isNotEmpty(lockValue)) { @@ -279,7 +274,6 @@ public class AllocateProcessor { } } - } /** @@ -339,15 +333,16 @@ public class AllocateProcessor { List matchedInventories, Map inventoryUpdateMap, Map pickDetailUpdateMap, List createToTask, List movePoints, AllocationData data, BigDecimal totalUnAllocatedQty, Set errorMsgSet) { + // 智能排序库存 List scoredInventories = scoreInventories(matchedInventories); //未分配数量 BigDecimal remainingQty = totalUnAllocatedQty; for (InventoryScore inventoryScore : scoredInventories) { + if (remainingQty.compareTo(BigDecimal.ZERO) <= 0) { break; } - Inventory inventory = inventoryScore.getInventory(); // 库存可用数量 @@ -363,13 +358,10 @@ public class AllocateProcessor { updatePickDetailAllocation(pickDetail, allocateQty, pickDetailUpdateMap); // 创建任务 createPickTask(pickDetail, pick, item, inventory, inventoryScore, allocateQty, createToTask, data); - // 获取需要移位的库位 getMovePoints(inventoryScore, movePoints); - // 记录分配日志 inventoryLogService.addAllocInventoryLog(inventory, inventoryScore.getOutPoint().getId(), allocateQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription()); - // 更新剩余未分配数量 remainingQty = BigDecimalUtil.subtract(remainingQty, allocateQty, 0); @@ -378,6 +370,8 @@ public class AllocateProcessor { if (remainingQty.compareTo(BigDecimal.ZERO) > 0) { addInventoryErrorMsg(pick, pickDetail, item, remainingQty, errorMsgSet); } + + } /** @@ -527,6 +521,7 @@ public class AllocateProcessor { Map inventoryUpdateMap) { Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory); BigDecimal newQueuedQty = BigDecimalUtil.add(targetInventory.getQueuedQty(), allocateQty, 0); + log.info("更新库存分配数: {}", newQueuedQty); targetInventory.setQueuedQty(newQueuedQty); targetInventory.setStatus(InventoryStatusEnum.ALLOCATED.getValue()); inventoryUpdateMap.put(targetInventory.getId(), targetInventory); @@ -684,7 +679,7 @@ public class AllocateProcessor { .filter(point -> !createTaskIds.contains(point.getId())) .toList(); if (CollectionUtils.isNotEmpty(pointsToMove)) { - List moveToTask = bulidMoveTask(pointsToMove); + List moveToTask = buildMoveTask(pointsToMove); if (CollectionUtils.isNotEmpty(moveToTask)) { createToTask.addAll(moveToTask); } @@ -699,7 +694,7 @@ public class AllocateProcessor { * @param movePoints 移位库位 * @return 移位任务 */ - public List bulidMoveTask(List movePoints) { + public List buildMoveTask(List movePoints) { List moveList = new ArrayList<>(); //库存 @@ -748,30 +743,6 @@ public class AllocateProcessor { return scanTrayProcessor.allocatePoint(itemKeyIds, currentPoint, areaCode); } - - /** - * 批量操作 - * - * @param inventoryUpdateMap 更新库存 - * @param pickDetailUpdateMap 更新出库明细 - * @param createToTask 创建出库任务 - */ - @Transactional(rollbackFor = Exception.class) - public void batchOperation(Map inventoryUpdateMap, Map pickDetailUpdateMap, List createToTask) { - - List updateToInventory = new ArrayList<>(inventoryUpdateMap.values()); - List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); - if (CollectionUtils.isNotEmpty(updateToInventory)) { - batchUtil.updateBatchInventory(updateToInventory); - } - if (CollectionUtils.isNotEmpty(updateToPickDetail)) { - batchUtil.updateBatchPickDetail(updateToPickDetail); - } - if (CollectionUtils.isNotEmpty(createToTask)) { - batchUtil.saveBatchTask(createToTask); - } - } - /** * 刷新出库单 * diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/CancelAllocateProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/CancelAllocateProcessor.java index 2e8daee..5598ad7 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/CancelAllocateProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/CancelAllocateProcessor.java @@ -1,7 +1,7 @@ package org.cpte.modules.shipping.service.processor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.cpte.modules.constant.enums.InventoryStatusEnum; import org.cpte.modules.constant.enums.PickStatusEnum; import org.cpte.modules.inventory.entity.Inventory; @@ -14,11 +14,10 @@ import org.cpte.modules.shipping.mapper.PickDetailMapper; import org.cpte.modules.shipping.mapper.TaskMapper; import org.cpte.modules.shipping.service.IPickDetailService; import org.cpte.modules.shipping.vo.CancelAllocateData; -import org.cpte.modules.utils.BatchUtil; import org.cpte.modules.utils.BigDecimalUtil; +import org.cpte.modules.utils.RedisDistributedLockUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; @@ -47,7 +46,7 @@ public class CancelAllocateProcessor { private IInventoryLogService inventoryLogService; @Autowired - private BatchUtil batchUtils; + private RedisDistributedLockUtil redissonLock; /** * 取消分配 @@ -71,7 +70,7 @@ public class CancelAllocateProcessor { cancelAllocate(data, inventoryUpdateMap, pickDetailUpdateMap, deleteToTask, errorMsgSet); //4.批量操作 - batchOperation(inventoryUpdateMap, pickDetailUpdateMap, deleteToTask); + pickDetailService.batchOperationCancel(inventoryUpdateMap, pickDetailUpdateMap, deleteToTask); //5.刷新出库单 refreshData(data); @@ -125,7 +124,6 @@ public class CancelAllocateProcessor { try { cancelAllocateTask(task, data, inventoryUpdateMap, pickDetailUpdateMap, deleteToTask, errorMsgSet); } catch (Exception e) { - log.error("取消任务失败,任务ID: {}", task.getId(), e); errorMsgSet.add(String.format("取消任务失败,任务号:%s,原因:%s", task.getTaskNo(), e.getMessage())); } @@ -145,35 +143,49 @@ public class CancelAllocateProcessor { private void cancelAllocateTask(Task task, CancelAllocateData data, Map inventoryUpdateMap, Map pickDetailUpdateMap, List deleteToTask, Set errorMsgSet) { Pick pick = data.getPickMap().get(task.getPickId()); - PickDetail pickDetail = data.getPickDetailIdMap().get(task.getPickDetailId()); - if (task.getAgvTaskId() != null) { - errorMsgSet.add(String.format("取消失败:【%s】已生成AGV任务", task.getTaskNo())); - return; + String lockKey = "cancel:" + pick.getId(); + String lockValue = null; + try { + lockValue = redissonLock.tryLock(lockKey, 10); + if (StringUtils.isEmpty(lockValue)) { + throw new RuntimeException("分配处理中,请稍后重试"); + } + PickDetail pickDetail = data.getPickDetailIdMap().get(task.getPickDetailId()); + if (task.getAgvTaskId() != null) { + errorMsgSet.add(String.format("取消失败:【%s】已生成AGV任务", task.getTaskNo())); + return; + } + + Inventory inventory = data.getInventoryMap().get(task.getInventoryId()); + if (inventory == null) { + errorMsgSet.add(String.format("取消失败:【%s】库存不存在", task.getTaskNo())); + return; + } + if (inventory.getQueuedQty().compareTo(BigDecimal.ZERO) <= 0) { + errorMsgSet.add(String.format("取消失败:【%s】库存已取消分配", task.getTaskNo())); + return; + } + BigDecimal cancelQty = task.getPlanQty(); + + //更新库存 + updateInventoryAllocation(inventory, cancelQty, inventoryUpdateMap); + + //更新出库明细 + updatePickDetailAllocation(pickDetail, cancelQty, pickDetailUpdateMap); + + //删除任务 + deleteToTask.add(task); + + // 记录取消分配日志 + inventoryLogService.addUnAllocInventoryLog(inventory, cancelQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription()); + } catch (Exception e) { + log.error("分配异常,出库单ID: {}", pick.getId(), e); + throw e; + } finally { + if (StringUtils.isNotEmpty(lockValue)) { + redissonLock.unlock(lockKey, lockValue); + } } - - Inventory inventory = data.getInventoryMap().get(task.getInventoryId()); - if (inventory == null) { - errorMsgSet.add(String.format("取消失败:【%s】库存不存在", task.getTaskNo())); - return; - } - if (inventory.getQueuedQty().compareTo(BigDecimal.ZERO) <= 0) { - errorMsgSet.add(String.format("取消失败:【%s】库存已取消分配", task.getTaskNo())); - return; - } - BigDecimal cancelQty = task.getPlanQty(); - - //更新库存 - updateInventoryAllocation(inventory, cancelQty, inventoryUpdateMap); - - //更新出库明细 - updatePickDetailAllocation(pickDetail, cancelQty, pickDetailUpdateMap); - - //删除任务 - deleteToTask.add(task); - - // 记录取消分配日志 - inventoryLogService.addUnAllocInventoryLog(inventory, cancelQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription()); - } /** @@ -185,30 +197,13 @@ public class CancelAllocateProcessor { */ private void updateInventoryAllocation(Inventory inventory, BigDecimal cancelQty, Map inventoryUpdateMap) { + Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory); - Inventory inventoryToUpdate = inventoryUpdateMap.computeIfAbsent( - inventory.getId(), id -> { - // 2. 用Builder实现拷贝 - return Inventory.builder() - .id(inventory.getId()) - .itemId(inventory.getItemId()) - .itemKeyId(inventory.getItemKeyId()) - .pointId(inventory.getPointId()) - .stockId(inventory.getStockId()) - .quantity(inventory.getQuantity()) - .queuedQty(inventory.getQueuedQty()) - .status(inventory.getStatus()) - .description(inventory.getDescription()) - .sysOrgCode(inventory.getSysOrgCode()) - .tenantId(inventory.getTenantId()) - .createBy(inventory.getCreateBy()) - .createTime(inventory.getCreateTime()) - .build(); - }); - BigDecimal newCancelQty = BigDecimalUtil.subtract(inventoryToUpdate.getQueuedQty(), cancelQty, 0); - inventoryToUpdate.setQueuedQty(newCancelQty); - Integer inv_status = inventoryToUpdate.getQueuedQty().compareTo(BigDecimal.ZERO) > 0 ? InventoryStatusEnum.ALLOCATED.getValue() : InventoryStatusEnum.AVAILABLE.getValue(); - inventoryToUpdate.setStatus(inv_status); + BigDecimal newCancelQty = BigDecimalUtil.subtract(targetInventory.getQueuedQty(), cancelQty, 0); + targetInventory.setQueuedQty(newCancelQty); + Integer inv_status = targetInventory.getQueuedQty().compareTo(BigDecimal.ZERO) > 0 ? InventoryStatusEnum.ALLOCATED.getValue() : InventoryStatusEnum.AVAILABLE.getValue(); + targetInventory.setStatus(inv_status); + inventoryUpdateMap.put(targetInventory.getId(), targetInventory); } /** @@ -221,65 +216,21 @@ public class CancelAllocateProcessor { private void updatePickDetailAllocation(PickDetail pickDetail, BigDecimal cancelQty, Map pickDetailUpdateMap) { - PickDetail detailToUpdate = pickDetailUpdateMap.computeIfAbsent( - pickDetail.getId(), id -> { - // 2. 用Builder实现拷贝 - return PickDetail.builder() - .id(pickDetail.getId()) - .pickId(pickDetail.getPickId()) - .itemId(pickDetail.getItemId()) - .lineNo(pickDetail.getLineNo()) - .unit(pickDetail.getUnit()) - .project(pickDetail.getProject()) - .taskNo(pickDetail.getTaskNo()) - .orderQty(pickDetail.getOrderQty()) - .allocatedQty(pickDetail.getAllocatedQty()) - .pickedQty(pickDetail.getPickedQty()) - .status(pickDetail.getStatus()) - .propC1(pickDetail.getPropC1()) - .propC3(pickDetail.getPropC3()) - .description(pickDetail.getDescription()) - .tenantId(pickDetail.getTenantId()) - .sysOrgCode(pickDetail.getSysOrgCode()) - .createBy(pickDetail.getCreateBy()) - .createTime(pickDetail.getCreateTime()) - .build(); - }); + PickDetail targetPickDetail = pickDetailUpdateMap.getOrDefault(pickDetail.getId(), pickDetail); - BigDecimal newCancelQty = BigDecimalUtil.subtract(detailToUpdate.getAllocatedQty(), cancelQty, 0); - detailToUpdate.setAllocatedQty(newCancelQty); + BigDecimal newCancelQty = BigDecimalUtil.subtract(targetPickDetail.getAllocatedQty(), cancelQty, 0); + targetPickDetail.setAllocatedQty(newCancelQty); // 更新状态 - Integer status=PickStatusEnum.CREATED.getValue(); - BigDecimal allocateQty = detailToUpdate.getAllocatedQty(); - if (detailToUpdate.getOrderQty().compareTo(allocateQty)<=0) { + Integer status = PickStatusEnum.CREATED.getValue(); + BigDecimal allocateQty = targetPickDetail.getAllocatedQty(); + if (targetPickDetail.getOrderQty().compareTo(allocateQty) <= 0) { status = PickStatusEnum.ASSIGNED.getValue(); - } else if(detailToUpdate.getOrderQty().compareTo(allocateQty)>0 && allocateQty.compareTo(BigDecimal.ZERO)>0){ + } else if (targetPickDetail.getOrderQty().compareTo(allocateQty) > 0 && allocateQty.compareTo(BigDecimal.ZERO) > 0) { status = PickStatusEnum.PARTIAL.getValue(); } - detailToUpdate.setStatus(status); - } - - /** - * 批量操作 - * - * @param inventoryUpdateMap 更新库存 - * @param pickDetailUpdateMap 更新出库明细 - * @param deleteToTask 删除出库任务 - */ - @Transactional(rollbackFor = Exception.class) - public void batchOperation(Map inventoryUpdateMap, Map pickDetailUpdateMap, List deleteToTask) { - List updateToInventory = new ArrayList<>(inventoryUpdateMap.values()); - List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); - if (CollectionUtils.isNotEmpty(updateToInventory)) { - batchUtils.updateBatchInventory(updateToInventory); - } - if (CollectionUtils.isNotEmpty(updateToPickDetail)) { - batchUtils.updateBatchPickDetail(updateToPickDetail); - } - if (CollectionUtils.isNotEmpty(deleteToTask)) { - taskMapper.deleteByIds(deleteToTask); - } + targetPickDetail.setStatus(status); + pickDetailUpdateMap.put(targetPickDetail.getId(), targetPickDetail); } /** diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/PickProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/PickProcessor.java index baca892..57947e4 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/PickProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/PickProcessor.java @@ -2,9 +2,10 @@ package org.cpte.modules.shipping.service.processor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +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.enums.CommonStatusEnum; import org.cpte.modules.constant.enums.PickStatusEnum; @@ -18,14 +19,12 @@ import org.cpte.modules.shipping.entity.Task; import org.cpte.modules.shipping.mapper.PickDetailMapper; import org.cpte.modules.shipping.service.IPickDetailService; import org.cpte.modules.shipping.vo.PickData; -import org.cpte.modules.utils.BatchUtil; import org.cpte.modules.utils.BigDecimalUtil; import org.cpte.modules.utils.RedisDistributedLockUtil; import org.jeecg.common.constant.CommonConstant; import org.jeecg.modules.base.service.BaseCommonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.ArrayList; @@ -43,6 +42,9 @@ public class PickProcessor { @Autowired private PickDetailMapper pickDetailMapper; + @Autowired + private IPointService pointService; + @Autowired private IStockService stockService; @@ -58,9 +60,6 @@ public class PickProcessor { @Autowired private BaseCommonService baseCommonService; - @Autowired - private BatchUtil batchUtil; - @Autowired private PickBackProcessor pickBackProcessor; @@ -78,15 +77,17 @@ public class PickProcessor { //2.创建数据结构 List deleteToInventory = new ArrayList<>(); + Map inventoryUpdateMap = new HashMap<>(); Map pickDetailUpdateMap = new HashMap<>(); List updateToTask = new ArrayList<>(); List updateToStock = new ArrayList<>(); + List updateToPoint = new ArrayList<>(); //3.拣货 - pickTask(data, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock); + pickTask(data, pickDetailUpdateMap, updateToTask, deleteToInventory,inventoryUpdateMap, updateToStock, updateToPoint); //4.批量操作 - batchOperation(deleteToInventory, pickDetailUpdateMap, updateToTask, updateToStock); + pickDetailService.batchOperationPick(deleteToInventory, pickDetailUpdateMap, updateToTask, updateToStock, updateToPoint); //5.刷新出库单 refreshData(data); @@ -124,6 +125,11 @@ public class PickProcessor { List stockIds = inventoryMap.values().stream().map(Inventory::getStockId).distinct().toList(); Map stockMap = stockService.queryByStockIdsToMap(stockIds); data.setStockMap(stockMap); + + //库存点位 + List pointIds = inventoryMap.values().stream().map(Inventory::getPointId).distinct().toList(); + Map pointMap = pointService.queryByPointIdsToMap(pointIds); + data.setPointMap(pointMap); return data; } @@ -132,10 +138,10 @@ public class PickProcessor { * * @param data 数据 */ - private void pickTask(PickData data, Map pickDetailUpdateMap, List updateToTask, List deleteToInventory, List updateToStock) { + private void pickTask(PickData data, Map pickDetailUpdateMap, List updateToTask, List deleteToInventory, Map inventoryUpdateMap, List updateToStock, List updateToPoint) { for (Task task : data.getTasks()) { try { - processorTaskLock(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock); + processorTaskLock(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, inventoryUpdateMap,updateToStock, updateToPoint); } catch (Exception e) { log.error("拣货异常", e); //记录拣货异常日志 @@ -154,16 +160,17 @@ public class PickProcessor { * @param deleteToInventory 删除库存集合 * @param updateToStock 更新容器状态集合 */ - private void processorTaskLock(PickData data, Task task, Map pickDetailUpdateMap, List updateToTask, List deleteToInventory, List updateToStock) { + private void processorTaskLock(PickData data, Task task, Map pickDetailUpdateMap, List updateToTask, List deleteToInventory, Map inventoryUpdateMap, List updateToStock, List updateToPoint) { // 拣货处理 - String lockKey = "task:" + task.getId(); + Pick pick = data.getPickMap().get(task.getPickId()); + String lockKey = "task:" + pick.getId(); String lockValue = null; try { lockValue = redissonLock.tryLock(lockKey, 10); if (StringUtils.isEmpty(lockValue)) { throw new RuntimeException("拣货处理中,请稍后重试"); } - processorTask(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock); + processorTask(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, inventoryUpdateMap, updateToStock, updateToPoint); } catch (Exception e) { log.error("拣货异常", e); throw e; @@ -172,6 +179,7 @@ public class PickProcessor { redissonLock.unlock(lockKey, lockValue); } } + } @@ -185,7 +193,7 @@ public class PickProcessor { * @param deleteToInventory 删除库存集合 * @param updateToStock 更新容器状态集合 */ - private void processorTask(PickData data, Task task, Map pickDetailUpdateMap, List updateToTask, List deleteToInventory, List updateToStock) { + private void processorTask(PickData data, Task task, Map pickDetailUpdateMap, List updateToTask, List deleteToInventory, Map inventoryUpdateMap, List updateToStock, List updateToPoint) { BigDecimal pickedQty = BigDecimalUtil.subtract(task.getPlanQty(), task.getMoveQty(), 0); if (pickedQty.compareTo(BigDecimal.ZERO) <= 0) { @@ -208,8 +216,11 @@ public class PickProcessor { //更新容器状态 updateToStock(data, task, updateToStock); + //更新点位状态 + updateToPoint(data, task, updateToPoint); + //添加库存日志 - addInventoryLog(data, task, pickedQty); + addInventoryLog(data, task, pickedQty, inventoryUpdateMap); } /** @@ -287,9 +298,23 @@ public class PickProcessor { private void updateToStock(PickData data, Task task, List updateToStock) { Stock stock = data.getStockMap().get(task.getStockId()); if (!updateToStock.contains(stock)) { - stock.setPointId(null); stock.setStatus(CommonStatusEnum.FREE.getValue()); updateToStock.add(stock); + + } + } + + /** + * 更新点位状态 + * + * @param data 数据 + * @param updateToPoint 点位更新集合 + */ + private void updateToPoint(PickData data, Task task, List updateToPoint) { + Point point = data.getPointMap().get(task.getFromPointId()); + if (!updateToPoint.contains(point)) { + point.setStatus(CommonStatusEnum.FREE.getValue()); + updateToPoint.add(point); } } @@ -300,35 +325,11 @@ public class PickProcessor { * @param task 任务 * @param pickedQty 拣货数量 */ - private void addInventoryLog(PickData data, Task task, BigDecimal pickedQty) { + private void addInventoryLog(PickData data, Task task, BigDecimal pickedQty, Map inventoryUpdateMap) { Inventory inventory = data.getInventoryMap().get(task.getInventoryId()); + updateInventory(inventory, pickedQty, inventoryUpdateMap); Pick pick = data.getPickMap().get(task.getPickId()); - inventoryLogService.addPickInventoryLog(inventory, task.getToPointId(), pickedQty, pick.getOrderNo(), task.getId(), null); - } - - /** - * 批量操作 - * - * @param deleteToInventory 删除库存 - * @param pickDetailUpdateMap 更新出库明细 - * @param updateToTask 创建出库任务 - */ - @Transactional(rollbackFor = Exception.class) - public void batchOperation(List deleteToInventory, Map pickDetailUpdateMap, List updateToTask, List updateToStock) { - if (CollectionUtils.isNotEmpty(deleteToInventory)) { - List deleteToInventoryIds = deleteToInventory.stream().map(Inventory::getId).toList(); - inventoryService.removeByIds(deleteToInventoryIds); - } - List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); - if (CollectionUtils.isNotEmpty(updateToPickDetail)) { - batchUtil.updateBatchPickDetail(updateToPickDetail); - } - if (CollectionUtils.isNotEmpty(updateToTask)) { - batchUtil.updateBatchTask(updateToTask); - } - if (CollectionUtils.isNotEmpty(updateToStock)) { - stockService.updateBatchById(updateToStock); - } + inventoryLogService.addPickInventoryLog(inventoryUpdateMap.get(inventory.getId()), task.getToPointId(), pickedQty, pick.getOrderNo(), task.getId(), null); } /** diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/PickData.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/PickData.java index 2932782..c8f9e2c 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/PickData.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/vo/PickData.java @@ -1,6 +1,7 @@ package org.cpte.modules.shipping.vo; import lombok.Data; +import org.cpte.modules.base.entity.Point; import org.cpte.modules.base.entity.Stock; import org.cpte.modules.inventory.entity.Inventory; import org.cpte.modules.shipping.entity.Pick; @@ -14,6 +15,7 @@ import java.util.Map; public class PickData { private List tasks; private Map stockMap; + private Map pointMap; private Map pickMap; private Map pickDetailMap; private Map inventoryMap; 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 453ea26..6d932ce 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 @@ -223,7 +223,7 @@ public class ITesAgvServiceImpl implements ITesAgvService { private void handleEnd(Long asnId, AgvTask agvTask) { if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) { //收货 - asnService.receiveAsn(asnId, agvTask.getEndCode()); + asnService.receiveAsn(asnId); } else if (BusinessTypeEnum.OUTBOUND.getValue().equals(agvTask.getType())) { //拣货 List tasks = taskMapper.queryByAgvTask(agvTask.getId()); diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtil.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtil.java index a29578f..83880f9 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtil.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/utils/BatchUtil.java @@ -265,7 +265,7 @@ public class BatchUtil { ps.setLong(2, record.getAsnId()); ps.setLong(3, record.getAsnDetailId()); ps.setLong(4, record.getStockId()); - ps.setLong(5, record.getFromPointId()); + ps.setObject(5, record.getFromPointId()); ps.setLong(6, record.getToPointId()); ps.setLong(7, record.getItemId()); ps.setLong(8, record.getItemKeyId());