From 2de7b56a8d818385eb06495a32c6d045c733aee3 Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Mon, 4 Aug 2025 14:34:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B7=A8=E5=8C=BA=E8=B0=83=E6=8B=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrossAreaTransferController.java | 155 +++++++++ .../dao/CrossAreaTransferMapper.java | 71 ++++ .../entity/CrossAreaTransferEntity.java | 101 ++++++ .../service/CrossAreaTransferService.java | 31 ++ .../impl/CrossAreaTransferServiceImpl.java | 304 ++++++++++++++++++ .../impl/LabelSplitMergeServiceImpl.java | 179 ++++++++++- .../impl/PropertyChangeServiceImpl.java | 108 ++++++- .../service/impl/TransHeaderServiceImpl.java | 7 +- .../CrossAreaTransferMapper.xml | 97 ++++++ 9 files changed, 1029 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/gaotao/modules/crossAreaTransfer/controller/CrossAreaTransferController.java create mode 100644 src/main/java/com/gaotao/modules/crossAreaTransfer/dao/CrossAreaTransferMapper.java create mode 100644 src/main/java/com/gaotao/modules/crossAreaTransfer/entity/CrossAreaTransferEntity.java create mode 100644 src/main/java/com/gaotao/modules/crossAreaTransfer/service/CrossAreaTransferService.java create mode 100644 src/main/java/com/gaotao/modules/crossAreaTransfer/service/impl/CrossAreaTransferServiceImpl.java create mode 100644 src/main/resources/mapper/crossAreaTransfer/CrossAreaTransferMapper.xml diff --git a/src/main/java/com/gaotao/modules/crossAreaTransfer/controller/CrossAreaTransferController.java b/src/main/java/com/gaotao/modules/crossAreaTransfer/controller/CrossAreaTransferController.java new file mode 100644 index 0000000..2158b9d --- /dev/null +++ b/src/main/java/com/gaotao/modules/crossAreaTransfer/controller/CrossAreaTransferController.java @@ -0,0 +1,155 @@ +package com.gaotao.modules.crossAreaTransfer.controller; + +import com.gaotao.common.utils.R; +import com.gaotao.modules.crossAreaTransfer.service.CrossAreaTransferService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 跨区调拨控制器 + * + * @author system + * @date 2025-01-01 + */ +@Api(tags = "跨区调拨管理") +@RestController +@RequestMapping("/cross-area-transfer") +public class CrossAreaTransferController { + + private static final Logger logger = LoggerFactory.getLogger(CrossAreaTransferController.class); + + @Autowired + private CrossAreaTransferService crossAreaTransferService; + + /** + * 获取跨区调拨信息 + * + * @param params 查询参数 + * @return 调拨信息 + */ + @ApiOperation("获取跨区调拨信息") + @PostMapping("/getTransferInfo") + public R getTransferInfo(@RequestBody Map params) { + logger.info("获取跨区调拨信息接口调用,参数: {}", params); + + try { + // 参数校验 + String scanCode = (String) params.get("scanCode"); + String transferMode = (String) params.get("transferMode"); + String site = (String) params.get("site"); + String warehouseId = (String) params.get("warehouseId"); + + if (scanCode == null || scanCode.trim().isEmpty()) { + return R.error("扫描码不能为空"); + } + + if (transferMode == null || transferMode.trim().isEmpty()) { + return R.error("调拨模式不能为空"); + } + + if (!"label".equals(transferMode) && !"location".equals(transferMode)) { + return R.error("调拨模式参数错误"); + } + + if (site == null || site.trim().isEmpty()) { + return R.error("站点不能为空"); + } + + if (warehouseId == null || warehouseId.trim().isEmpty()) { + return R.error("仓库ID不能为空"); + } + + Map result = crossAreaTransferService.getTransferInfo(params); + + if ((Integer) result.get("code") == 0) { + return R.ok().put("data", result.get("data")); + } else { + return R.error((String) result.get("msg")); + } + + } catch (Exception e) { + logger.error("获取跨区调拨信息失败", e); + return R.error("获取调拨信息失败: " + e.getMessage()); + } + } + + /** + * 保存跨区调拨 + * + * @param params 调拨参数 + * - scanCode: 扫描码 + * - transferMode: 调拨模式 + * - sourceLocation: 源库位 + * - targetLocation: 目标库位 + * - site: 站点 + * - warehouseId: 仓库ID + * - operator: 操作员 + * @return 操作结果 + */ + @ApiOperation("保存跨区调拨") + @PostMapping("/saveTransfer") + public R saveTransfer(@RequestBody Map params) { + logger.info("保存跨区调拨接口调用,参数: {}", params); + + try { + // 参数校验 + String scanCode = (String) params.get("scanCode"); + String transferMode = (String) params.get("transferMode"); + String sourceLocation = (String) params.get("sourceLocation"); + String targetLocation = (String) params.get("targetLocation"); + String site = (String) params.get("site"); + String warehouseId = (String) params.get("warehouseId"); + String operator = (String) params.get("operator"); + + if (scanCode == null || scanCode.trim().isEmpty()) { + return R.error("扫描码不能为空"); + } + + if (transferMode == null || transferMode.trim().isEmpty()) { + return R.error("调拨模式不能为空"); + } + + if (!"label".equals(transferMode) && !"location".equals(transferMode)) { + return R.error("调拨模式参数错误"); + } + + if (sourceLocation == null || sourceLocation.trim().isEmpty()) { + return R.error("源库位不能为空"); + } + + if (targetLocation == null || targetLocation.trim().isEmpty()) { + return R.error("目标库位不能为空"); + } + + if (site == null || site.trim().isEmpty()) { + return R.error("站点不能为空"); + } + + if (warehouseId == null || warehouseId.trim().isEmpty()) { + return R.error("仓库ID不能为空"); + } + + if (operator == null || operator.trim().isEmpty()) { + return R.error("操作员不能为空"); + } + + boolean success = crossAreaTransferService.saveTransfer(params); + + if (success) { + return R.ok("跨区调拨成功"); + } else { + return R.error("跨区调拨失败"); + } + + } catch (Exception e) { + logger.error("保存跨区调拨失败", e); + return R.error("保存调拨失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gaotao/modules/crossAreaTransfer/dao/CrossAreaTransferMapper.java b/src/main/java/com/gaotao/modules/crossAreaTransfer/dao/CrossAreaTransferMapper.java new file mode 100644 index 0000000..2d3cf4e --- /dev/null +++ b/src/main/java/com/gaotao/modules/crossAreaTransfer/dao/CrossAreaTransferMapper.java @@ -0,0 +1,71 @@ +package com.gaotao.modules.crossAreaTransfer.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gaotao.modules.crossAreaTransfer.entity.CrossAreaTransferEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 跨区调拨Mapper + * + * @author system + * @date 2025-01-01 + */ +@Mapper +public interface CrossAreaTransferMapper extends BaseMapper { + + /** + * 根据标签条码获取库存信息 + * + * @param labelCode 标签条码 + * @param site 站点 + * @param warehouseId 仓库ID + * @return 库存信息 + */ + Map getStockInfoByLabelCode(@Param("labelCode") String labelCode, + @Param("site") String site, + @Param("warehouseId") String warehouseId); + + /** + * 根据库位获取标签列表 + * + * @param locationId 库位ID + * @param site 站点 + * @param warehouseId 仓库ID + * @return 标签列表 + */ + List> getLabelsByLocation(@Param("locationId") String locationId, + @Param("site") String site, + @Param("warehouseId") String warehouseId); + + /** + * 根据库位获取库存信息列表 + * + * @param locationId 库位ID + * @param site 站点 + * @param warehouseId 仓库ID + * @return 库存信息列表 + */ + List> getStockInfoByLocation(@Param("locationId") String locationId, + @Param("site") String site, + @Param("warehouseId") String warehouseId); + + /** + * 更新库存表的库位和仓库信息(按标签调拨) + * + * @param params 更新参数 + * @return 更新行数 + */ + int updateStockLocationAndWarehouse(Map params); + + /** + * 批量更新库存表的库位和仓库信息(按库位调拨) + * + * @param params 更新参数 + * @return 更新行数 + */ + int batchUpdateStockLocationAndWarehouse(Map params); +} diff --git a/src/main/java/com/gaotao/modules/crossAreaTransfer/entity/CrossAreaTransferEntity.java b/src/main/java/com/gaotao/modules/crossAreaTransfer/entity/CrossAreaTransferEntity.java new file mode 100644 index 0000000..ac99016 --- /dev/null +++ b/src/main/java/com/gaotao/modules/crossAreaTransfer/entity/CrossAreaTransferEntity.java @@ -0,0 +1,101 @@ +package com.gaotao.modules.crossAreaTransfer.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 跨区调拨实体类 + * + * @author system + * @date 2025-01-01 + */ +@Data +@TableName("cross_area_transfer") +public class CrossAreaTransferEntity implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 站点 + */ + private String site; + + /** + * 事业部 + */ + private String buNo; + + /** + * 仓库ID + */ + private String warehouseId; + + /** + * 标签条码 + */ + private String labelCode; + + /** + * 物料编码 + */ + private String partNo; + + /** + * 批次号 + */ + private String batchNo; + + /** + * 调拨模式:label-按标签调拨,location-按库位调拨 + */ + private String transferMode; + + /** + * 源库位 + */ + private String sourceLocation; + + /** + * 目标库位 + */ + private String targetLocation; + + /** + * 数量 + */ + private Float quantity; + + /** + * 操作员 + */ + private String operator; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 事务单号 + */ + private String transNo; + + /** + * 状态:0-待处理,1-已完成,2-已取消 + */ + private Integer status; + + /** + * 备注 + */ + private String remark; +} \ No newline at end of file diff --git a/src/main/java/com/gaotao/modules/crossAreaTransfer/service/CrossAreaTransferService.java b/src/main/java/com/gaotao/modules/crossAreaTransfer/service/CrossAreaTransferService.java new file mode 100644 index 0000000..d1e5377 --- /dev/null +++ b/src/main/java/com/gaotao/modules/crossAreaTransfer/service/CrossAreaTransferService.java @@ -0,0 +1,31 @@ +package com.gaotao.modules.crossAreaTransfer.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gaotao.modules.crossAreaTransfer.entity.CrossAreaTransferEntity; + +import java.util.Map; + +/** + * 跨区调拨服务接口 + * + * @author system + * @date 2025-01-01 + */ +public interface CrossAreaTransferService extends IService { + + /** + * 获取跨区调拨信息 + * + * @param params 查询参数 + * @return 调拨信息 + */ + Map getTransferInfo(Map params); + + /** + * 保存跨区调拨 + * + * @param params 调拨参数 + * @return 是否成功 + */ + boolean saveTransfer(Map params); +} \ No newline at end of file diff --git a/src/main/java/com/gaotao/modules/crossAreaTransfer/service/impl/CrossAreaTransferServiceImpl.java b/src/main/java/com/gaotao/modules/crossAreaTransfer/service/impl/CrossAreaTransferServiceImpl.java new file mode 100644 index 0000000..cd0aa17 --- /dev/null +++ b/src/main/java/com/gaotao/modules/crossAreaTransfer/service/impl/CrossAreaTransferServiceImpl.java @@ -0,0 +1,304 @@ +package com.gaotao.modules.crossAreaTransfer.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gaotao.modules.crossAreaTransfer.dao.CrossAreaTransferMapper; +import com.gaotao.modules.crossAreaTransfer.entity.CrossAreaTransferEntity; +import com.gaotao.modules.crossAreaTransfer.service.CrossAreaTransferService; +import com.gaotao.modules.inboundNotification.dao.InboundNotificationHeadMapper; +import com.gaotao.modules.trans.entity.TransDetail; +import com.gaotao.modules.trans.entity.TransDetailDto; +import com.gaotao.modules.trans.entity.TransHeader; +import com.gaotao.modules.trans.service.TransDetailService; +import com.gaotao.modules.trans.service.TransHeaderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 跨区调拨服务实现类 + * + * @author system + * @date 2025-01-01 + */ +@Service +public class CrossAreaTransferServiceImpl extends ServiceImpl implements CrossAreaTransferService { + + private static final Logger logger = LoggerFactory.getLogger(CrossAreaTransferServiceImpl.class); + + @Autowired + private CrossAreaTransferMapper crossAreaTransferMapper; + + @Autowired + private TransHeaderService transHeaderService; + + @Autowired + private TransDetailService transDetailService; + + @Autowired + private InboundNotificationHeadMapper headMapper; + + @Override + public Map getTransferInfo(Map params) { + logger.info("获取跨区调拨信息,参数: {}", params); + + String scanCode = (String) params.get("scanCode"); + String transferMode = (String) params.get("transferMode"); + String site = (String) params.get("site"); + String warehouseId = (String) params.get("warehouseId"); + + Map result = new HashMap<>(); + + try { + if ("label".equals(transferMode)) { + // 按标签调拨:获取标签信息 + Map stockInfo = crossAreaTransferMapper.getStockInfoByLabelCode(scanCode, site, warehouseId); + + if (stockInfo == null) { + logger.warn("未找到标签库存信息,标签条码: {}", scanCode); + result.put("code", 1); + result.put("msg", "未找到该标签的库存信息"); + return result; + } + + // 格式化返回数据 + Map labelInfo = new HashMap<>(); + labelInfo.put("labelCode", stockInfo.get("label_code")); + labelInfo.put("quantity", stockInfo.get("quantity")); + labelInfo.put("warehouseName", stockInfo.get("warehouse_name")); + labelInfo.put("locationId", stockInfo.get("location_id")); + labelInfo.put("status", stockInfo.get("status")); + labelInfo.put("productionDate", stockInfo.get("production_date")); + labelInfo.put("expiryDate", stockInfo.get("expiry_date")); + labelInfo.put("orderRef1", stockInfo.get("order_ref1")); + labelInfo.put("orderRef2", stockInfo.get("order_ref2")); + labelInfo.put("batchNo", stockInfo.get("batch_no")); + labelInfo.put("buNo", stockInfo.get("buNo")); + result.put("code", 0); + result.put("data", labelInfo); + + } else if ("location".equals(transferMode)) { + // 按库位调拨:获取库位下的所有标签 + List> labels = crossAreaTransferMapper.getLabelsByLocation(scanCode, site, warehouseId); + + if (labels == null || labels.isEmpty()) { + logger.warn("该库位下未找到标签,库位: {}", scanCode); + result.put("code", 1); + result.put("msg", "该库位下未找到标签"); + return result; + } + + result.put("code", 0); + result.put("data", labels); + } + + logger.info("获取跨区调拨信息成功,模式: {}, 扫描码: {}", transferMode, scanCode); + return result; + + } catch (Exception e) { + logger.error("获取跨区调拨信息失败", e); + result.put("code", 1); + result.put("msg", "查询失败: " + e.getMessage()); + return result; + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean saveTransfer(Map params) { + logger.info("开始保存跨区调拨,参数: {}", params); + + try { + String scanCode = (String) params.get("scanCode"); + String transferMode = (String) params.get("transferMode"); + String sourceLocation = (String) params.get("sourceLocation"); + String targetLocation = (String) params.get("targetLocation"); + String site = (String) params.get("site"); + String buNo = (String) params.get("buNo"); + String warehouseId = (String) params.get("warehouseId"); + String operator = (String) params.get("operator"); + // 1. 验证库位是否存在且可用 + Map locationInfo = headMapper.validateLocation(targetLocation, site); + if (locationInfo == null || locationInfo.isEmpty()) { + throw new RuntimeException("该库位不存在,请检查"); + } + + String locationStatus = (String) locationInfo.get("status"); + if (!"Y".equals(locationStatus)) { + throw new RuntimeException("该库位已停用,请检查"); + } + + // 2. 根据源库位查询库存信息 + List> stockInfoList = new ArrayList<>(); + if ("label".equals(transferMode)) { + // 按标签调拨:查询单个标签的库存信息 + Map stockInfo = crossAreaTransferMapper.getStockInfoByLabelCode(scanCode, site, warehouseId); + if (stockInfo != null) { + stockInfoList.add(stockInfo); + } + } else { + // 按库位调拨:查询库位下所有标签的库存信息 + stockInfoList = crossAreaTransferMapper.getStockInfoByLocation(sourceLocation, site, warehouseId); + } + + if (stockInfoList.isEmpty()) { + logger.error("未找到库存信息,源库位: {}", sourceLocation); + return false; + } + + // 根据库位获取实际的仓库ID + String actualWarehouseId = (String) locationInfo.get("warehouseId"); + if (actualWarehouseId != null && !actualWarehouseId.trim().isEmpty()) { + warehouseId = actualWarehouseId; + logger.info("根据库位号 {} 获取到仓库ID: {}", targetLocation, warehouseId); + } + + // 3. 更新库存表 - 根据源库位更新到目标库位和仓库 + Map updateParams = new HashMap<>(); + updateParams.put("site", site); + updateParams.put("sourceLocation", sourceLocation); + updateParams.put("targetLocation", targetLocation); + updateParams.put("targetWarehouseId", warehouseId); // 目标仓库ID + updateParams.put("operator", operator); + updateParams.put("updateTime", new Date()); + + int updateCount = 0; + if ("label".equals(transferMode)) { + // 按标签调拨:更新单个标签的库位和仓库 + updateParams.put("labelCode", scanCode); + updateCount = crossAreaTransferMapper.updateStockLocationAndWarehouse(updateParams); + } else { + // 按库位调拨:更新整个库位下所有标签的库位和仓库 + updateCount = crossAreaTransferMapper.batchUpdateStockLocationAndWarehouse(updateParams); + } + + if (updateCount == 0) { + logger.error("更新库存失败,未找到匹配的库存记录"); + return false; + } + + // 5. 生成标签变动事务记录 + generateTransferTransaction(site, warehouseId, scanCode, transferMode, buNo, stockInfoList); + + logger.info("跨区调拨保存成功,模式: {}, 扫描码: {}, 目标库位: {}", transferMode, scanCode, targetLocation); + return true; + + } catch (Exception e) { + logger.error("保存跨区调拨失败", e); + throw new RuntimeException("保存跨区调拨失败: " + e.getMessage()); + } + } + + /** + * 生成跨区调拨事务记录 + */ + private void generateTransferTransaction(String site, String warehouseId, String scanCode, String transferMode, String buNo, List> stockInfoList) { + logger.info("开始生成跨区调拨事务记录,扫描码: {}", scanCode); + + try { + // 构建TransDetailDto对象 + TransDetailDto transDetailDto = new TransDetailDto(); + transDetailDto.setSite(site); + transDetailDto.setRemark("跨区调拨 - " + transferMode); + transDetailDto.setOrderref1(scanCode); // 扫描码(标签或库位) + transDetailDto.setOrderref2(transferMode); // 调拨模式 + transDetailDto.setOrderref3(warehouseId); // 仓库ID + + // 使用TransHeaderService的genTrans方法生成事务头 + // CAT = Cross Area Transfer 跨区调拨 + TransHeader transHeader = transHeaderService.genTrans(transDetailDto, "CAT", warehouseId, buNo); + + if (transHeader == null) { + throw new RuntimeException("生成跨区调拨事务头记录失败"); + } + + logger.info("跨区调拨事务头记录生成成功,事务单号: {}", transHeader.getTransno()); + + // 生成事务明细记录 + generateTransactionDetails(transHeader.getTransno(), stockInfoList, site); + + logger.info("跨区调拨事务记录生成完成,事务单号: {}, 扫描码: {}, 明细记录数: {}", + transHeader.getTransno(), scanCode, stockInfoList.size()); + + } catch (Exception e) { + logger.error("生成跨区调拨事务记录失败", e); + // 不抛出异常,避免影响主流程 + } + } + + /** + * 生成事务明细记录 + */ + private void generateTransactionDetails(String transNo, List> stockInfoList, String site) { + logger.info("开始生成跨区调拨事务明细记录,事务单号: {}, 明细数量: {}", transNo, stockInfoList.size()); + + List transDetailList = new ArrayList<>(); + double itemNo = 1.0; // 行号从1开始 + + for (Map stockInfo : stockInfoList) { + String labelCode = (String) stockInfo.get("label_code"); + String partNo = (String) stockInfo.get("part_no"); + String batchNo = (String) stockInfo.get("batch_no"); + Object quantityObj = stockInfo.get("quantity"); + + // 转换数量 + BigDecimal quantity = convertToDecimal(quantityObj); + + // 构建事务明细记录 + TransDetail transDetail = new TransDetail(); + transDetail.setSite(site); + transDetail.setTransno(transNo); + transDetail.setItemno(itemNo); + transDetail.setPartno(partNo); + transDetail.setTransqty(quantity); + transDetail.setBatchno(batchNo); + transDetail.setDirection("-"); // 调拨方向 + transDetail.setOrderref1(labelCode); // 标签条码 + transDetail.setOrderref2(partNo); // 物料编码 + transDetail.setOrderref3(batchNo); // 批次号 + transDetail.setRemark("跨区调拨 - 标签: " + labelCode); + + transDetailList.add(transDetail); + itemNo += 1.0; // 行号递增 + } + + // 批量保存事务明细记录 + if (!transDetailList.isEmpty()) { + boolean success = transDetailService.saveBatch(transDetailList); + if (!success) { + throw new RuntimeException("跨区调拨事务明细记录保存失败"); + } + logger.info("跨区调拨事务明细记录生成成功,共生成 {} 条明细记录", transDetailList.size()); + } + } + + /** + * 转换数量为BigDecimal + */ + private BigDecimal convertToDecimal(Object quantityObj) { + if (quantityObj == null) { + return BigDecimal.ZERO; + } + + if (quantityObj instanceof BigDecimal) { + return (BigDecimal) quantityObj; + } else if (quantityObj instanceof Number) { + return new BigDecimal(quantityObj.toString()); + } else { + try { + return new BigDecimal(quantityObj.toString()); + } catch (NumberFormatException e) { + logger.warn("数量转换失败,使用默认值0,原值: {}", quantityObj); + return BigDecimal.ZERO; + } + } + } +} diff --git a/src/main/java/com/gaotao/modules/labelSplitMerge/service/impl/LabelSplitMergeServiceImpl.java b/src/main/java/com/gaotao/modules/labelSplitMerge/service/impl/LabelSplitMergeServiceImpl.java index 9f1db9d..153925a 100644 --- a/src/main/java/com/gaotao/modules/labelSplitMerge/service/impl/LabelSplitMergeServiceImpl.java +++ b/src/main/java/com/gaotao/modules/labelSplitMerge/service/impl/LabelSplitMergeServiceImpl.java @@ -4,9 +4,11 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gaotao.modules.labelSplitMerge.dao.LabelSplitMergeMapper; import com.gaotao.modules.labelSplitMerge.entity.LabelSplitMergeEntity; import com.gaotao.modules.labelSplitMerge.service.LabelSplitMergeService; +import com.gaotao.modules.trans.entity.TransDetail; import com.gaotao.modules.trans.entity.TransDetailDto; import com.gaotao.modules.trans.entity.TransHeader; import com.gaotao.modules.trans.entity.TransNoControl; +import com.gaotao.modules.trans.service.TransDetailService; import com.gaotao.modules.trans.service.TransHeaderService; import com.gaotao.modules.trans.service.TransNoControlService; import org.slf4j.Logger; @@ -15,8 +17,11 @@ 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; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -36,6 +41,9 @@ public class LabelSplitMergeServiceImpl extends ServiceImpl result = new HashMap<>(); result.put("newLabelCode", newLabelCode); @@ -202,8 +209,7 @@ public class LabelSplitMergeServiceImpl extends ServiceImpl transDetailList = new ArrayList<>(); + + // 原标签明细记录(减少数量) + TransDetail originalDetail = new TransDetail(); + originalDetail.setSite(site); + originalDetail.setTransno(transNo); + originalDetail.setItemno(1.0); + originalDetail.setPartno(partNo); + originalDetail.setTransqty(new BigDecimal(splitQuantity.toString())); + originalDetail.setBatchno(batchNo); + originalDetail.setDirection("-"); // 减少方向 + originalDetail.setOrderref1(originalLabelCode); // 原标签条码 + originalDetail.setOrderref2(partNo); // 物料编码 + originalDetail.setOrderref3(batchNo); // 批次号 + originalDetail.setRemark("标签拆分 - 原标签减少数量: " + splitQuantity); + transDetailList.add(originalDetail); + + // 新标签明细记录(增加数量) + TransDetail newDetail = new TransDetail(); + newDetail.setSite(site); + newDetail.setTransno(transNo); + newDetail.setItemno(2.0); + newDetail.setPartno(partNo); + newDetail.setTransqty(new BigDecimal(splitQuantity.toString())); + newDetail.setBatchno(batchNo); + newDetail.setDirection("+"); // 增加方向 + newDetail.setOrderref1(newLabelCode); // 新标签条码 + newDetail.setOrderref2(partNo); // 物料编码 + newDetail.setOrderref3(batchNo); // 批次号 + newDetail.setRemark("标签拆分 - 新标签增加数量: " + splitQuantity); + transDetailList.add(newDetail); + + // 批量保存事务明细记录 + if (!transDetailList.isEmpty()) { + boolean success = transDetailService.saveBatch(transDetailList); + if (!success) { + throw new RuntimeException("标签拆分事务明细记录保存失败"); + } + logger.info("标签拆分事务明细记录生成成功,共生成 {} 条明细记录", transDetailList.size()); + } + } + + /** + * 生成标签合并事务明细记录 + */ + private void generateMergeTransactionDetails(String transNo, String sourceLabelCode, String targetLabelCode, + String partNo, String batchNo, Float sourceQuantity, Float targetQuantity, Float mergedQuantity, String site) { + logger.info("开始生成标签合并事务明细记录,事务单号: {}", transNo); + + List transDetailList = new ArrayList<>(); + + // 目标标签明细记录(减少数量 - 被合并掉) + TransDetail targetDetail = new TransDetail(); + targetDetail.setSite(site); + targetDetail.setTransno(transNo); + targetDetail.setItemno(1.0); + targetDetail.setPartno(partNo); + targetDetail.setTransqty(new BigDecimal(targetQuantity.toString())); + targetDetail.setBatchno(batchNo); + targetDetail.setDirection("-"); // 减少方向 + targetDetail.setOrderref1(targetLabelCode); // 目标标签条码 + targetDetail.setOrderref2(partNo); // 物料编码 + targetDetail.setOrderref3(batchNo); // 批次号 + targetDetail.setRemark("标签合并 - 目标标签被合并,数量: " + targetQuantity); + transDetailList.add(targetDetail); + + // 源标签明细记录(增加合并后的总数量) + TransDetail sourceDetail = new TransDetail(); + sourceDetail.setSite(site); + sourceDetail.setTransno(transNo); + sourceDetail.setItemno(2.0); + sourceDetail.setPartno(partNo); + sourceDetail.setTransqty(new BigDecimal(mergedQuantity.toString())); + sourceDetail.setBatchno(batchNo); + sourceDetail.setDirection("+"); // 增加方向 + sourceDetail.setOrderref1(sourceLabelCode); // 源标签条码 + sourceDetail.setOrderref2(partNo); // 物料编码 + sourceDetail.setOrderref3(batchNo); // 批次号 + sourceDetail.setRemark("标签合并 - 源标签获得合并后总数量: " + mergedQuantity); + transDetailList.add(sourceDetail); + + // 批量保存事务明细记录 + if (!transDetailList.isEmpty()) { + boolean success = transDetailService.saveBatch(transDetailList); + if (!success) { + throw new RuntimeException("标签合并事务明细记录保存失败"); + } + logger.info("标签合并事务明细记录生成成功,共生成 {} 条明细记录", transDetailList.size()); + } + } } diff --git a/src/main/java/com/gaotao/modules/propertyChange/service/impl/PropertyChangeServiceImpl.java b/src/main/java/com/gaotao/modules/propertyChange/service/impl/PropertyChangeServiceImpl.java index b6d81f0..711a422 100644 --- a/src/main/java/com/gaotao/modules/propertyChange/service/impl/PropertyChangeServiceImpl.java +++ b/src/main/java/com/gaotao/modules/propertyChange/service/impl/PropertyChangeServiceImpl.java @@ -5,8 +5,10 @@ import com.gaotao.common.utils.DateUtils; import com.gaotao.modules.propertyChange.dao.PropertyChangeMapper; import com.gaotao.modules.propertyChange.entity.PropertyChangeEntity; import com.gaotao.modules.propertyChange.service.PropertyChangeService; +import com.gaotao.modules.trans.entity.TransDetail; import com.gaotao.modules.trans.entity.TransDetailDto; import com.gaotao.modules.trans.entity.TransHeader; +import com.gaotao.modules.trans.service.TransDetailService; import com.gaotao.modules.trans.service.TransHeaderService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,10 +16,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -37,6 +42,9 @@ public class PropertyChangeServiceImpl extends ServiceImpl transDetailList = new ArrayList<>(); + double itemNo = 1.0; // 行号从1开始 + + // 库位变动明细 + if (newLocationId != null && !newLocationId.equals(oldLocationId)) { + TransDetail locationDetail = new TransDetail(); + locationDetail.setSite(site); + locationDetail.setTransno(transNo); + locationDetail.setItemno(itemNo++); + locationDetail.setPartno(partNo); + locationDetail.setTransqty(new BigDecimal(quantity.toString())); + locationDetail.setBatchno(batchNo); + locationDetail.setDirection("M"); // 移动方向 + locationDetail.setOrderref1(labelCode); // 标签条码 + locationDetail.setOrderref2("LOCATION"); // 变动类型 + locationDetail.setOrderref3(oldLocationId + "→" + newLocationId); // 变动内容 + locationDetail.setRemark("库位变动: " + oldLocationId + " → " + newLocationId); + transDetailList.add(locationDetail); + } + + // 生产日期变动明细 + if (newProductionDate != null && !newProductionDate.equals(oldProductionDate)) { + TransDetail productionDateDetail = new TransDetail(); + productionDateDetail.setSite(site); + productionDateDetail.setTransno(transNo); + productionDateDetail.setItemno(itemNo++); + productionDateDetail.setPartno(partNo); + productionDateDetail.setTransqty(new BigDecimal(quantity.toString())); + productionDateDetail.setBatchno(batchNo); + productionDateDetail.setDirection("M"); // 移动方向 + productionDateDetail.setOrderref1(labelCode); // 标签条码 + productionDateDetail.setOrderref2("PROD_DATE"); // 变动类型 + productionDateDetail.setOrderref3((oldProductionDate != null ? oldProductionDate : "空") + "→" + newProductionDate); // 变动内容 + productionDateDetail.setRemark("生产日期变动: " + (oldProductionDate != null ? oldProductionDate : "空") + " → " + newProductionDate); + transDetailList.add(productionDateDetail); + } + + // 有效期变动明细 + if (newExpiryDate != null && !newExpiryDate.equals(oldExpiryDate)) { + TransDetail expiryDateDetail = new TransDetail(); + expiryDateDetail.setSite(site); + expiryDateDetail.setTransno(transNo); + expiryDateDetail.setItemno(itemNo++); + expiryDateDetail.setPartno(partNo); + expiryDateDetail.setTransqty(new BigDecimal(quantity.toString())); + expiryDateDetail.setBatchno(batchNo); + expiryDateDetail.setDirection("M"); // 移动方向 + expiryDateDetail.setOrderref1(labelCode); // 标签条码 + expiryDateDetail.setOrderref2("EXPIRY_DATE"); // 变动类型 + expiryDateDetail.setOrderref3((oldExpiryDate != null ? oldExpiryDate : "空") + "→" + newExpiryDate); // 变动内容 + expiryDateDetail.setRemark("有效期变动: " + (oldExpiryDate != null ? oldExpiryDate : "空") + " → " + newExpiryDate); + transDetailList.add(expiryDateDetail); + } + + // 批量保存事务明细记录 + if (!transDetailList.isEmpty()) { + boolean success = transDetailService.saveBatch(transDetailList); + if (!success) { + throw new RuntimeException("属性变动事务明细记录保存失败"); + } + logger.info("属性变动事务明细记录生成成功,共生成 {} 条明细记录", transDetailList.size()); + } + } } diff --git a/src/main/java/com/gaotao/modules/trans/service/impl/TransHeaderServiceImpl.java b/src/main/java/com/gaotao/modules/trans/service/impl/TransHeaderServiceImpl.java index f3da7ec..55c5e62 100644 --- a/src/main/java/com/gaotao/modules/trans/service/impl/TransHeaderServiceImpl.java +++ b/src/main/java/com/gaotao/modules/trans/service/impl/TransHeaderServiceImpl.java @@ -27,7 +27,6 @@ public class TransHeaderServiceImpl extends ServiceImpl + + + + + + + + + + + + + + + + UPDATE inventory_stock + SET location_id = #{targetLocation}, + warehouse_id = #{targetWarehouseId}, + latest_in_date = #{updateTime} + WHERE roll_no = #{labelCode} + AND location_id = #{sourceLocation} + AND site = #{site} + AND status = '在库' + AND qty_on_hand > 0 + + + + + UPDATE inventory_stock + SET location_id = #{targetLocation}, + warehouse_id = #{targetWarehouseId}, + latest_in_date = #{updateTime} + WHERE location_id = #{sourceLocation} + AND site = #{site} + AND status = '在库' + AND qty_on_hand > 0 + + +