package com.gaotao.modules.handlingunit.controller; import com.gaotao.common.exception.XJException; import com.gaotao.common.utils.R; import com.gaotao.modules.handlingunit.entity.HandlingUnit; import com.gaotao.modules.handlingunit.service.HandlingUnitService; import com.gaotao.modules.handlingunit.service.HandlingUnitIdGeneratorService; import com.gaotao.modules.handlingunit.service.HandlingUnitIdLogService; import com.gaotao.modules.autoWareHourceHaian.service.HaiAnPdaLabelSplitService; import com.gaotao.modules.handlingunit.dao.HandlingUnitMapper; import com.gaotao.modules.sys.controller.AbstractController; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * PDA标签查询控制器 * *

主要功能:

* * * @author System * @since 2025-01-23 */ @Slf4j @RestController @RequestMapping("/pda/label") public class PdaLabelController extends AbstractController { @Autowired private HandlingUnitService handlingUnitService; @Autowired private HandlingUnitMapper handlingUnitMapper; @Autowired private HandlingUnitIdGeneratorService handlingUnitIdGeneratorService; @Autowired private HandlingUnitIdLogService handlingUnitIdLogService; @Autowired private HaiAnPdaLabelSplitService haiAnPdaLabelSplitService; /** * @Author System * @Description 查询标签信息 * @Date 2025/01/23 * @Param [Map] * @return com.gaotao.common.utils.R **/ @PostMapping("query") public R queryLabelInfo(@RequestBody Map params) { try { String site = params == null ? null : (String) params.get("site"); String labelCode = params == null ? null : (String) params.get("labelCode"); log.info("=== 开始查询标签信息 ==="); if (site == null || site.trim().isEmpty()) { return R.error("工厂编码不能为空"); } if (labelCode == null || labelCode.trim().isEmpty()) { return R.error("标签编码不能为空"); } // 按登录大工厂展开小工厂后查标签。查无返回 null;多小工厂重复时由服务抛出明确异常。- rqrq HandlingUnit handlingUnit = handlingUnitService.queryPdaLabelByBigSite(site, labelCode); if (handlingUnit == null) { log.warn("标签不存在: site={}, labelCode={}", site, labelCode); return R.error("标签不存在"); } // 查询只回显真实X/N/Y/Q状态;拆分、发料等写操作各自执行状态准入,Q不会因查询被使用。- rqrq log.info("查询到标签信息: unitId={}, partNo={}, locationId={}, warehouseId={}, batchNo={}, wdr={}", handlingUnit.getUnitId(), handlingUnit.getPartNo(), handlingUnit.getLocationId(), handlingUnit.getWarehouseId(), handlingUnit.getBatchNo(), handlingUnit.getWdr()); log.info("=== 标签信息查询完成 ==="); return R.ok().put("data", handlingUnit); } catch (Exception e) { log.error("=== 查询标签信息失败 === 错误信息: {}", e.getMessage(), e); return R.error("查询失败: " + e.getMessage()); } } /** * @Author rqrq * @Description 取消WMS预定 - rqrq * @Date 2025/11/01 * @Param [Map] * @return com.gaotao.common.utils.R **/ @PostMapping("cancelReserve") public R cancelReserve(@RequestBody Map params) throws Exception { String site = (String) params.get("site"); String unitId = (String) params.get("unitId"); log.info("=== 开始取消WMS预定 - rqrq ==="); log.info("工厂: {}, 标签编码: {}", site, unitId); // 参数验证 - rqrq if (site == null || site.trim().isEmpty()) { throw new RuntimeException("工厂编码不能为空"); } if (unitId == null || unitId.trim().isEmpty()) { throw new RuntimeException("标签编码不能为空"); } // 查询HandlingUnit是否存在 - rqrq HandlingUnit handlingUnit = handlingUnitService.lambdaQuery() .eq(HandlingUnit::getSite, site) .eq(HandlingUnit::getUnitId, unitId.trim()) .one(); if (handlingUnit == null) { log.warn("标签不存在 - rqrq: site={}, unitId={}", site, unitId); throw new RuntimeException("标签不存在"); } // 检查是否被预定 - rqrq if (!"Y".equals(handlingUnit.getReserveFlag())) { log.warn("标签未被预定 - rqrq: site={}, unitId={}", site, unitId); throw new RuntimeException("该标签未被WMS预定"); } // 调用Mapper方法取消预定 - rqrq handlingUnitMapper.cancelReserve(site, unitId); log.info("取消WMS预定成功 - rqrq: unitId={}", unitId); log.info("=== 取消WMS预定完成 - rqrq ==="); return R.ok(); } /** * @Author System * @Description 标签拆分 - 将原标签拆分出指定数量到新标签 * @Date 2025/01/18 * @Param [Map] * @return com.gaotao.common.utils.R **/ @PostMapping("split") @Transactional public R splitLabel(@RequestBody Map params) { try { String site = (String) params.get("site"); String unitId = (String) params.get("unitId"); String operatorName = (String) params.get("operatorName"); BigDecimal splitQty = new BigDecimal(params.get("splitQty").toString()); log.info("=== 开始标签拆分 ==="); log.info("工厂: {}, 原标签: {}, 拆分数量: {}, 操作人: {}", site, unitId, splitQty, operatorName); // 1. 参数验证 if (site == null || site.trim().isEmpty()) { throw new XJException("工厂编码不能为空"); } if (unitId == null || unitId.trim().isEmpty()) { throw new XJException("标签编码不能为空"); } if (splitQty.compareTo(BigDecimal.ZERO) <= 0) { throw new XJException("拆分数量必须大于0"); } // 2. 查询原标签 HandlingUnit originalUnit = handlingUnitService.lambdaQuery() .eq(HandlingUnit::getSite, site) .eq(HandlingUnit::getUnitId, unitId) .one(); if (originalUnit == null) { throw new XJException("原标签不存在"); } // 3. 验证库存状态 if (!"Y".equals(originalUnit.getInStockFlag()) && !"X".equals(originalUnit.getInStockFlag())) { throw new XJException("该标签库存已被消耗,不能拆分"); } // 4. 验证拆分数量 BigDecimal originalQty = originalUnit.getQty(); if (splitQty.compareTo(originalQty) >= 0) { throw new XJException("拆分数量必须小于原标签数量(" + originalQty + ")"); } // 5. 生成新标签编码 String newUnitId = handlingUnitIdGeneratorService.generateUnitId(site); log.info("生成新标签编码: {}", newUnitId); // 6. 创建新标签(复制原标签所有信息,只修改数量) HandlingUnit newUnit = new HandlingUnit(); BeanUtils.copyProperties(originalUnit, newUnit); newUnit.setUnitId(newUnitId); newUnit.setQty(splitQty); // 新标签数量 newUnit.setOriginalQty(splitQty); // 新标签原始数量 newUnit.setSourceType("SPLIT"); // 来源类型:拆分 newUnit.setParentUnitId(unitId); // 原标签编码 newUnit.setCreatedDate(new Date()); newUnit.setCreatedBy(operatorName); newUnit.setModifiedDate(new Date()); newUnit.setModifiedBy(operatorName); newUnit.setRemark("从标签 " + unitId + " 拆分"); // 新标签不得继承原标签预定:预定仍留在原标签剩余量上,避免同一预定单据挂两张标签。海安手工分拣拆分也依赖此口径 - rqrq newUnit.setReserveFlag("N"); newUnit.setReserveOrderRef1(null); newUnit.setReserveOrderRef2(null); newUnit.setReserveOrderRef3(null); // 7. 保存新标签 boolean saveResult = handlingUnitService.save(newUnit); if (!saveResult) { log.error("严重错误:新标签保存返回失败!unitId={}", newUnitId); handlingUnitIdLogService.logUnitIdGeneration( newUnitId, site, "LABEL_SPLIT", unitId, "", originalUnit.getPartNo(), originalUnit.getBatchNo(), splitQty.doubleValue(), operatorName, "N", "保存失败-save返回false" ); throw new XJException("新标签保存失败(save返回false): " + newUnitId); } // 8. 记录新标签生成日志 handlingUnitIdLogService.logUnitIdGeneration( newUnitId, site, "LABEL_SPLIT", unitId, "", originalUnit.getPartNo(), originalUnit.getBatchNo(), splitQty.doubleValue(), operatorName, "Y", "标签拆分成功" ); // 9. 更新原标签数量 BigDecimal remainQty = originalQty.subtract(splitQty); originalUnit.setQty(remainQty); originalUnit.setModifiedDate(new Date()); originalUnit.setModifiedBy(operatorName); boolean updateResult = handlingUnitService.updateById(originalUnit); if (!updateResult) { log.error("严重错误:原标签更新失败!unitId={}", unitId); throw new XJException("原标签更新失败"); } // 海安账套(site以54开头):若原标签已在haian_pallet_detail,同步回写剩余qty;未入盘则跳过 - rqrq haiAnPdaLabelSplitService.syncPalletDetailQtyAfterSplit( originalUnit.getSite(), unitId, remainQty); log.info("=== 标签拆分成功 ==="); log.info("原标签: {} 剩余数量: {}", unitId, remainQty); log.info("新标签: {} 数量: {}", newUnitId, splitQty); // 10. 返回结果(包含原标签和新标签ID,用于打印) Map result = new HashMap<>(); result.put("originalUnitId", unitId); result.put("newUnitId", newUnitId); result.put("originalQty", originalQty); result.put("remainQty", remainQty); result.put("splitQty", splitQty); return R.ok().put("data", result); } catch (XJException e) { log.error("=== 标签拆分失败 === 错误信息: {}", e.getMessage()); return R.error(e.getMessage()); } catch (Exception e) { log.error("=== 标签拆分失败 === 错误信息: {}", e.getMessage(), e); return R.error("拆分失败: " + e.getMessage()); } } }