diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/controller/WcsIntegrationController.java b/src/main/java/com/gaotao/modules/automatedWarehouse/controller/WcsIntegrationController.java index 901e4f5..6045f93 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/controller/WcsIntegrationController.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/controller/WcsIntegrationController.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/wcsIntegration") @@ -52,5 +53,75 @@ public class WcsIntegrationController { return R.ok(); } + // ==================== 打托相关接口 - AI制作 ==================== + + /** + * 检查栈板是否存在并获取位置信息 - AI制作 + */ + @PostMapping(value="/checkPalletExists") + @ResponseBody + public R checkPalletExists(@RequestBody Map params) { + try { + Map result = wcsIntegrationService.checkPalletExists(params); + return R.ok().put("positions", result.get("positions")).put("palletType", result.get("palletType")); + } catch (Exception e) { + return R.error(e.getMessage()); + } + } + + /** + * 获取栈板明细 - AI制作 + */ + @PostMapping(value="/getPalletDetails") + @ResponseBody + public R getPalletDetails(@RequestBody Map params) { + try { + List> details = wcsIntegrationService.getPalletDetails(params); + return R.ok().put("details", details); + } catch (Exception e) { + return R.error(e.getMessage()); + } + } + /** + * 根据位置获取层数 - AI制作 + */ + @PostMapping(value="/getLayersByPosition") + @ResponseBody + public R getLayersByPosition(@RequestBody Map params) { + try { + List layers = wcsIntegrationService.getLayersByPosition(params); + return R.ok().put("layers", layers); + } catch (Exception e) { + return R.error(e.getMessage()); + } + } + + /** + * 保存栈板明细(扫进) - AI制作 + */ + @PostMapping(value="/savePalletDetail") + @ResponseBody + public R savePalletDetail(@RequestBody Map params) { + try { + wcsIntegrationService.savePalletDetail(params); + return R.ok(); + } catch (Exception e) { + return R.error(e.getMessage()); + } + } + + /** + * 删除栈板明细(扫出) - AI制作 + */ + @PostMapping(value="/deletePalletDetail") + @ResponseBody + public R deletePalletDetail(@RequestBody Map params) { + try { + wcsIntegrationService.deletePalletDetail(params); + return R.ok(); + } catch (Exception e) { + return R.error(e.getMessage()); + } + } } diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/entity/BufferZoneConfig.java b/src/main/java/com/gaotao/modules/automatedWarehouse/entity/BufferZoneConfig.java new file mode 100644 index 0000000..b110dd1 --- /dev/null +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/entity/BufferZoneConfig.java @@ -0,0 +1,49 @@ +package com.gaotao.modules.automatedWarehouse.entity; + +/** + * 缓冲区配置枚举类 - AI制作 + * 用于定义缓冲区专用的仓库和库位 + */ +public enum BufferZoneConfig { + + /** + * 缓冲区仓库ID + */ + BUFFER_WAREHOUSE_ID("liku"), + + /** + * 缓冲区库位ID + */ + BUFFER_LOCATION_ID("A1"); + + private final String value; + + BufferZoneConfig(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + /** + * 检查是否为缓冲区仓库 + */ + public static boolean isBufferWarehouse(String warehouseId) { + return BUFFER_WAREHOUSE_ID.getValue().equals(warehouseId); + } + + /** + * 检查是否为缓冲区库位 + */ + public static boolean isBufferLocation(String locationId) { + return BUFFER_LOCATION_ID.getValue().equals(locationId); + } + + /** + * 检查是否为缓冲区标签 + */ + public static boolean isBufferLabel(String warehouseId, String locationId) { + return isBufferWarehouse(warehouseId) && isBufferLocation(locationId); + } +} \ No newline at end of file diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java index dfde5e6..003c70c 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java @@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; @Mapper public interface WcsIntegrationMapper { @@ -17,5 +18,62 @@ public interface WcsIntegrationMapper { void batchSaveTransportTask(@Param("list") List transportTaskList); - + // ==================== 打托相关方法 - AI制作 ==================== + + /** + * 检查栈板是否存在 - AI制作 + */ + Map getPalletInfo(@Param("site") String site, @Param("palletId") String palletId); + + /** + * 获取栈板类型的位置信息 - AI制作 + */ + List getPalletTypePositions(@Param("site") String site, @Param("palletType") String palletType); + + /** + * 获取栈板明细 - AI制作 + */ + List> getPalletDetails(@Param("site") String site, @Param("palletId") String palletId, + @Param("position") String position, @Param("layer") Integer layer); + + /** + * 根据位置获取层数 - AI制作 + */ + List getLayersByPosition(@Param("site") String site, @Param("palletId") String palletId, + @Param("position") String position); + + /** + * 验证标签 - AI制作 + */ + Map validateLabel(@Param("site") String site, @Param("serialNo") String serialNo); + + /** + * 获取栈板类型区域信息(用于校验层级规则) - AI制作 + */ + List> getPalletTypeAreaInfo(@Param("site") String site, @Param("palletType") String palletType); + + /** + * 获取栈板指定层的明细统计 - AI制作 + */ + List> getPalletLayerStatistics(@Param("site") String site, @Param("palletId") String palletId, + @Param("layer") Integer layer); + + /** + * 保存栈板明细 - AI制作 + */ + void savePalletDetail(@Param("site") String site, @Param("palletId") String palletId, + @Param("position") String position, @Param("layer") Integer layer, + @Param("serialNo") String serialNo, @Param("partNo") String partNo, + @Param("createBy") String createBy); + + /** + * 根据标签查找栈板信息 - AI制作 + */ + Map findPalletByLabel(@Param("site") String site, @Param("serialNo") String serialNo); + + /** + * 删除栈板明细 - AI制作 + */ + void deletePalletDetail(@Param("site") String site, @Param("palletId") String palletId, + @Param("serialNo") String serialNo); } diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/service/WcsIntegrationService.java b/src/main/java/com/gaotao/modules/automatedWarehouse/service/WcsIntegrationService.java index 5ae7a32..d8a45eb 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/service/WcsIntegrationService.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/service/WcsIntegrationService.java @@ -4,9 +4,37 @@ import com.gaotao.modules.automatedWarehouse.entity.WmsLabelAndPalletData; import com.gaotao.modules.automatedWarehouse.entity.PartPalletData; import java.util.List; +import java.util.Map; public interface WcsIntegrationService { List palletListForPartNo(PartPalletData inData); void callPalletFromWcs(List data); + + // ==================== 打托相关方法 - AI制作 ==================== + + /** + * 检查栈板是否存在并获取位置信息 - AI制作 + */ + Map checkPalletExists(Map params) throws Exception; + + /** + * 获取栈板明细 - AI制作 + */ + List> getPalletDetails(Map params) throws Exception; + + /** + * 根据位置获取层数 - AI制作 + */ + List getLayersByPosition(Map params) throws Exception; + + /** + * 保存栈板明细(扫进) - AI制作 + */ + void savePalletDetail(Map params) throws Exception; + + /** + * 删除栈板明细(扫出) - AI制作 + */ + void deletePalletDetail(Map params) throws Exception; } diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java index a0500bd..0f75b91 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java @@ -1,6 +1,7 @@ package com.gaotao.modules.automatedWarehouse.service.impl; import com.gaotao.modules.api.service.WcsApiService; +import com.gaotao.modules.automatedWarehouse.entity.BufferZoneConfig; import com.gaotao.modules.automatedWarehouse.entity.PartPalletData; import com.gaotao.modules.automatedWarehouse.entity.WmsLabelAndPalletData; import com.gaotao.modules.automatedWarehouse.entity.WmsTransportTask; @@ -14,10 +15,10 @@ import org.apache.shiro.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import java.math.BigDecimal; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -93,4 +94,172 @@ public class WcsIntegrationServiceImpl implements WcsIntegrationService { // TODO: 这里可以调用WCS接口通知立库执行运输任务 wcsApiService.pushAgvTaskApi(saveList); } + + // ==================== 打托相关方法实现 - AI制作 ==================== + + @Override + public Map checkPalletExists(Map params) throws Exception { + String site = (String) params.get("site"); + String palletId = (String) params.get("palletId"); + + if (!StringUtils.hasText(site) || !StringUtils.hasText(palletId)) { + throw new Exception("参数不能为空"); + } + + // 检查栈板是否存在 + Map palletInfo = wcsIntegrationMapper.getPalletInfo(site, palletId); + if (palletInfo == null) { + throw new Exception("栈板不存在"); + } + + // 获取栈板类型的位置信息 + String palletType = (String) palletInfo.get("pallet_type"); + List positions = wcsIntegrationMapper.getPalletTypePositions(site, palletType); + + Map result = new HashMap<>(); + result.put("positions", positions); + result.put("palletType", palletType); + + return result; + } + + @Override + public List> getPalletDetails(Map params) throws Exception { + String site = (String) params.get("site"); + String palletId = (String) params.get("palletId"); + String position = (String) params.get("position"); + Integer layer = null; + + if (params.get("layer") != null && !params.get("layer").equals("")) { + layer = Integer.valueOf(params.get("layer").toString()); + } + + if (!StringUtils.hasText(site) || !StringUtils.hasText(palletId)) { + throw new Exception("参数不能为空"); + } + + return wcsIntegrationMapper.getPalletDetails(site, palletId, position, layer); + } + + @Override + public List getLayersByPosition(Map params) throws Exception { + String site = (String) params.get("site"); + String palletId = (String) params.get("palletId"); + String position = (String) params.get("position"); + + if (!StringUtils.hasText(site) || !StringUtils.hasText(palletId) || !StringUtils.hasText(position)) { + throw new Exception("参数不能为空"); + } + + return wcsIntegrationMapper.getLayersByPosition(site, palletId, position); + } + + @Override + @Transactional + public void savePalletDetail(Map params) throws Exception { + String site = (String) params.get("site"); + String palletId = (String) params.get("palletId"); + String position = (String) params.get("position"); + Integer layer = Integer.valueOf(params.get("layer").toString()); + String serialNo = (String) params.get("serialNo"); + + if (!StringUtils.hasText(site) || !StringUtils.hasText(palletId) || + !StringUtils.hasText(position) || layer == null || !StringUtils.hasText(serialNo)) { + throw new Exception("参数不能为空"); + } + + // 1. 验证标签 + Map labelInfo = wcsIntegrationMapper.validateLabel(site, serialNo); + if (labelInfo == null) { + throw new Exception("标签不存在"); + } + + String inStockFlag = (String) labelInfo.get("inStockFlag"); + String warehouseId = (String) labelInfo.get("warehouseId"); + String locationId = (String) labelInfo.get("locationId"); + + if (!"Y".equals(inStockFlag)) { + throw new Exception("标签不在库状态"); + } + + if (!BufferZoneConfig.isBufferLabel(warehouseId, locationId)) { + throw new Exception("标签不在缓冲区,无法进行打托操作"); + } + + // 2. 检查标签是否已在栈板中(当前栈板或其他栈板) + Map existingPalletInfo = wcsIntegrationMapper.findPalletByLabel(site, serialNo); + if (existingPalletInfo != null) { + String existingPalletId = (String) existingPalletInfo.get("palletId"); + + // 如果标签在当前栈板,提示不要重复扫描 + if (palletId.equals(existingPalletId)) { + throw new Exception("该条码已在本栈板上,请不要重复扫描"); + } + + // 如果标签在其他栈板,检查是否在缓冲区 + if (BufferZoneConfig.isBufferLabel(warehouseId, locationId)) { + wcsIntegrationMapper.deletePalletDetail(site, existingPalletId, serialNo); + } else { + throw new Exception("该条码不在缓冲区,请先移库"); + } + } + + // 3. 层级校验:如果选择第N+1层,必须所有position的第N层都有数据ccl_wms + if (layer > 1) { + // 获取栈板类型信息 + Map palletInfo = wcsIntegrationMapper.getPalletInfo(site, palletId); + String palletType = (String) palletInfo.get("pallet_type"); + + // 获取栈板类型的所有位置 + List allPositions = wcsIntegrationMapper.getPalletTypePositions(site, palletType); + + // 检查前一层(layer-1)的所有位置是否都有数据 + List> prevLayerStats = wcsIntegrationMapper.getPalletLayerStatistics(site, palletId, layer - 1); + + // 将统计结果转换为位置映射 + Set prevLayerPositions = prevLayerStats.stream() + .map(stat -> (String) stat.get("position")) + .collect(Collectors.toSet()); + + // 检查是否所有位置在前一层都有数据 + List missingPositions = allPositions.stream() + .filter(pos -> !prevLayerPositions.contains(pos)) + .collect(Collectors.toList()); + + if (!missingPositions.isEmpty()) { + throw new Exception("第" + (layer - 1) + "层以下位置还未放满,请先放满:" + String.join(", ", missingPositions)); + } + } + + // 4. 保存栈板明细 + String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername(); + String partNo = (String) labelInfo.get("partNo"); + + wcsIntegrationMapper.savePalletDetail(site, palletId, position, layer, serialNo, partNo, username); + } + + @Override + @Transactional + public void deletePalletDetail(Map params) throws Exception { + String site = (String) params.get("site"); + String palletId = (String) params.get("palletId"); + String serialNo = (String) params.get("serialNo"); + + if (!StringUtils.hasText(site) || !StringUtils.hasText(palletId) || !StringUtils.hasText(serialNo)) { + throw new Exception("参数不能为空"); + } + + // 检查标签是否在本栈板中 + Map existingPalletInfo = wcsIntegrationMapper.findPalletByLabel(site, serialNo); + if (existingPalletInfo == null) { + throw new Exception("该条码不在任何栈板上"); + } + + String existingPalletId = (String) existingPalletInfo.get("palletId"); + if (!palletId.equals(existingPalletId)) { + throw new Exception("该条码不在此栈板上"); + } + + wcsIntegrationMapper.deletePalletDetail(site, palletId, serialNo); + } } diff --git a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml index c4f48c0..b899715 100644 --- a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml +++ b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml @@ -1,6 +1,8 @@ + + @@ -56,4 +58,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO pallet_detail (site, pallet_id, position, layer, serial_no, part_no, create_date, create_by) + VALUES (#{site}, #{palletId}, #{position}, #{layer}, #{serialNo}, #{partNo}, GETDATE(), #{createBy}) + + + + + DELETE FROM pallet_detail + WHERE site = #{site} AND pallet_id = #{palletId} AND serial_no = #{serialNo} + + \ No newline at end of file