Browse Source
feat(check): 新增盘点模式管理及自动盘盈盘亏处理功能
feat(check): 新增盘点模式管理及自动盘盈盘亏处理功能
- 添加盘点模式开关接口,支持获取和更新系统盘点模式状态 - 实现自动盘盈盘亏处理服务,支持批量处理盘点差异结果 - 创建盘点调整相关实体类,包括调整项、标签明细、请求参数和结果实体 - 集成事务处理机制,自动生成盘亏(PK)和盘盈(PY)事务单据 - 提供盘盈盘亏事务记录查询接口,支持查看处理明细和子明细 - 完善库存更新逻辑,处理完成后自动更新标签数量和库存状态master
12 changed files with 1605 additions and 0 deletions
-
131src/main/java/com/gaotao/common/utils/CountModeChecker.java
-
84src/main/java/com/gaotao/modules/check/controller/PhysicalInventoryController.java
-
102src/main/java/com/gaotao/modules/check/entity/CountAdjustmentItem.java
-
119src/main/java/com/gaotao/modules/check/entity/CountAdjustmentLabelItem.java
-
39src/main/java/com/gaotao/modules/check/entity/CountAdjustmentRequest.java
-
75src/main/java/com/gaotao/modules/check/entity/CountAdjustmentResult.java
-
116src/main/java/com/gaotao/modules/check/entity/CountAdjustmentTransData.java
-
85src/main/java/com/gaotao/modules/check/entity/CountAdjustmentTransSubData.java
-
116src/main/java/com/gaotao/modules/check/mapper/CountAdjustmentMapper.java
-
84src/main/java/com/gaotao/modules/check/service/CountAdjustmentService.java
-
502src/main/java/com/gaotao/modules/check/service/impl/CountAdjustmentServiceImpl.java
-
152src/main/resources/mapper/check/CountAdjustmentMapper.xml
@ -0,0 +1,131 @@ |
|||||
|
package com.gaotao.common.utils; |
||||
|
|
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
/** |
||||
|
* 盘点模式检查工具类 - rqrq |
||||
|
* |
||||
|
* <p>用于快速判断当前是否处于盘点模式,如果是盘点模式则抛出异常阻止其他业务操作</p> |
||||
|
* |
||||
|
* <p><b>使用方式:</b></p> |
||||
|
* <pre> |
||||
|
* // 1. 注入工具类 |
||||
|
* @Autowired |
||||
|
* private CountModeChecker countModeChecker; |
||||
|
* |
||||
|
* // 2. 在业务方法开头调用检查 |
||||
|
* public void yourBusinessMethod(String site) { |
||||
|
* countModeChecker.checkNotInCountMode(site); // 如果是盘点模式会抛出异常 |
||||
|
* // ... 业务逻辑 |
||||
|
* } |
||||
|
* |
||||
|
* // 3. 也可以只获取状态不抛异常 |
||||
|
* if (countModeChecker.isInCountMode(site)) { |
||||
|
* // 处理盘点模式的情况 |
||||
|
* } |
||||
|
* </pre> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class CountModeChecker { |
||||
|
|
||||
|
@Autowired |
||||
|
private JdbcTemplate jdbcTemplate; |
||||
|
|
||||
|
/** |
||||
|
* 检查当前是否在盘点模式,如果是则抛出异常 - rqrq |
||||
|
* |
||||
|
* <p>业务方法开头调用此方法,可以快速阻止盘点模式下的其他操作</p> |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @throws RuntimeException 如果当前处于盘点模式 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
public void checkNotInCountMode(String site) { |
||||
|
if (isInCountMode(site)) { |
||||
|
throw new RuntimeException("当前处于盘点模式,无法进行此操作,请先关闭盘点模式"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 检查当前是否在盘点模式,如果是则抛出自定义异常信息 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param customMessage 自定义错误信息 |
||||
|
* @throws RuntimeException 如果当前处于盘点模式 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
public void checkNotInCountMode(String site, String customMessage) { |
||||
|
if (isInCountMode(site)) { |
||||
|
throw new RuntimeException(customMessage); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 判断当前是否处于盘点模式 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @return true=盘点模式 false=非盘点模式 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
public boolean isInCountMode(String site) { |
||||
|
if (!StringUtils.hasText(site)) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
String countModeValue = getCountModeValue(site); |
||||
|
return "Y".equals(countModeValue); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取盘点模式参数值 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @return Y=盘点模式 N=非盘点模式 null=未配置 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
public String getCountModeValue(String site) { |
||||
|
try { |
||||
|
String sql = "SELECT parameter_value FROM wms_sys_parameter WHERE site = ? AND parameter_key = 'IF_COUNT'"; |
||||
|
return jdbcTemplate.queryForObject(sql, String.class, site); |
||||
|
} catch (Exception e) { |
||||
|
// 查询失败或无数据时返回N(默认非盘点模式) |
||||
|
return "N"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 检查当前必须在盘点模式,如果不是则抛出异常 - rqrq |
||||
|
* |
||||
|
* <p>盘点相关业务方法开头调用此方法,确保只有盘点模式下才能执行</p> |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @throws RuntimeException 如果当前不在盘点模式 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
public void checkMustInCountMode(String site) { |
||||
|
if (!isInCountMode(site)) { |
||||
|
throw new RuntimeException("当前不在盘点模式,无法进行此操作,请先开启盘点模式"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 检查当前必须在盘点模式,如果不是则抛出自定义异常信息 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param customMessage 自定义错误信息 |
||||
|
* @throws RuntimeException 如果当前不在盘点模式 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
public void checkMustInCountMode(String site, String customMessage) { |
||||
|
if (!isInCountMode(site)) { |
||||
|
throw new RuntimeException(customMessage); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,102 @@ |
|||||
|
package com.gaotao.modules.check.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.apache.ibatis.type.Alias; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整明细项实体类 - 按ERP维度汇总后的盘盈盘亏数据 - rqrq |
||||
|
* |
||||
|
* <p><b>用途:</b>用于盘盈盘亏处理时按维度汇总的库存数据</p> |
||||
|
* |
||||
|
* <p><b>汇总维度:</b></p> |
||||
|
* <ul> |
||||
|
* <li>site - 工厂编码</li> |
||||
|
* <li>warehouseId - 仓库ID</li> |
||||
|
* <li>locationId - 库位ID</li> |
||||
|
* <li>partNo - 物料号</li> |
||||
|
* <li>batchNo - 批号</li> |
||||
|
* <li>wdr - WDR</li> |
||||
|
* <li>expiredDate - 过期日期</li> |
||||
|
* <li>engChgLevel - 工程变更级别</li> |
||||
|
* </ul> |
||||
|
* |
||||
|
* <p><b>业务逻辑:</b></p> |
||||
|
* <pre> |
||||
|
* // 根据diffQty判断盘盈盘亏 |
||||
|
* if (diffQty > 0) { |
||||
|
* // 盘盈:库存增加 |
||||
|
* } else if (diffQty < 0) { |
||||
|
* // 盘亏:库存减少 |
||||
|
* } |
||||
|
* </pre> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Data |
||||
|
@Alias("CountAdjustmentItem") |
||||
|
public class CountAdjustmentItem { |
||||
|
|
||||
|
// ==================== 维度字段 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 工厂编码 |
||||
|
*/ |
||||
|
private String site; |
||||
|
|
||||
|
/** |
||||
|
* 仓库ID |
||||
|
*/ |
||||
|
private String warehouseId; |
||||
|
|
||||
|
/** |
||||
|
* 库位ID |
||||
|
*/ |
||||
|
private String locationId; |
||||
|
|
||||
|
/** |
||||
|
* 物料号 |
||||
|
*/ |
||||
|
private String partNo; |
||||
|
|
||||
|
/** |
||||
|
* 批号 |
||||
|
*/ |
||||
|
private String batchNo; |
||||
|
|
||||
|
/** |
||||
|
* WDR(物料追溯号) |
||||
|
*/ |
||||
|
private String wdr; |
||||
|
|
||||
|
/** |
||||
|
* 过期日期 |
||||
|
*/ |
||||
|
private Date expiredDate; |
||||
|
|
||||
|
/** |
||||
|
* 工程变更级别 |
||||
|
*/ |
||||
|
private String engChgLevel; |
||||
|
|
||||
|
// ==================== 数量字段 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 汇总后的差异数量 |
||||
|
* <p>正数=盘盈,负数=盘亏</p> |
||||
|
*/ |
||||
|
private BigDecimal diffQty; |
||||
|
|
||||
|
// ==================== 关联明细 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 该维度下的所有标签明细列表 |
||||
|
* <p>用于生成trans_detail_sub</p> |
||||
|
*/ |
||||
|
private List<CountAdjustmentLabelItem> labelItems; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,119 @@ |
|||||
|
package com.gaotao.modules.check.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.apache.ibatis.type.Alias; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整标签明细实体类 - 标签级别的盘盈盘亏数据 - rqrq |
||||
|
* |
||||
|
* <p><b>用途:</b>用于盘盈盘亏处理时记录每个标签的调整信息</p> |
||||
|
* |
||||
|
* <p><b>数据来源:</b></p> |
||||
|
* <ul> |
||||
|
* <li>count_result表:盘点结果信息</li> |
||||
|
* <li>handling_unit表:标签详细信息</li> |
||||
|
* </ul> |
||||
|
* |
||||
|
* <p><b>业务逻辑:</b></p> |
||||
|
* <pre> |
||||
|
* // 1. 用于生成trans_detail_sub记录 |
||||
|
* // 2. 用于更新handling_unit.qty |
||||
|
* if (newQty <= 0) { |
||||
|
* // 设置in_stock_flag = 'N' |
||||
|
* } |
||||
|
* </pre> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Data |
||||
|
@Alias("CountAdjustmentLabelItem") |
||||
|
public class CountAdjustmentLabelItem { |
||||
|
|
||||
|
// ==================== 盘点结果字段 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 盘点结果ID |
||||
|
*/ |
||||
|
private Long countResultId; |
||||
|
|
||||
|
/** |
||||
|
* 盘点单号 |
||||
|
*/ |
||||
|
private String countNo; |
||||
|
|
||||
|
/** |
||||
|
* 盘点结果类型 |
||||
|
* <p>QTY_DIFF=数量差异,MISSING=缺失</p> |
||||
|
*/ |
||||
|
private String countResult; |
||||
|
|
||||
|
/** |
||||
|
* 差异数量 |
||||
|
* <p>正数=盘盈,负数=盘亏</p> |
||||
|
*/ |
||||
|
private BigDecimal diffQty; |
||||
|
|
||||
|
// ==================== 标签基本信息 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 工厂编码 |
||||
|
*/ |
||||
|
private String site; |
||||
|
|
||||
|
/** |
||||
|
* 标签号(handling_unit.unit_id) |
||||
|
*/ |
||||
|
private String unitId; |
||||
|
|
||||
|
/** |
||||
|
* 栈板号 |
||||
|
*/ |
||||
|
private String palletId; |
||||
|
|
||||
|
// ==================== 库存维度字段 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 物料号 |
||||
|
*/ |
||||
|
private String partNo; |
||||
|
|
||||
|
/** |
||||
|
* 标签当前数量 |
||||
|
*/ |
||||
|
private BigDecimal qty; |
||||
|
|
||||
|
/** |
||||
|
* 批号 |
||||
|
*/ |
||||
|
private String batchNo; |
||||
|
|
||||
|
/** |
||||
|
* 库位ID |
||||
|
*/ |
||||
|
private String locationId; |
||||
|
|
||||
|
/** |
||||
|
* 仓库ID |
||||
|
*/ |
||||
|
private String warehouseId; |
||||
|
|
||||
|
/** |
||||
|
* WDR(物料追溯号) |
||||
|
*/ |
||||
|
private String wdr; |
||||
|
|
||||
|
/** |
||||
|
* 过期日期 |
||||
|
*/ |
||||
|
private Date expiredDate; |
||||
|
|
||||
|
/** |
||||
|
* 工程变更级别 |
||||
|
*/ |
||||
|
private String engChgLevel; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,39 @@ |
|||||
|
package com.gaotao.modules.check.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.apache.ibatis.type.Alias; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整请求参数实体类 - rqrq |
||||
|
* |
||||
|
* <p><b>用途:</b>用于自动处理盈亏功能的请求参数传递</p> |
||||
|
* |
||||
|
* <p><b>使用场景:</b></p> |
||||
|
* <ul> |
||||
|
* <li>Controller接收前端请求参数</li> |
||||
|
* <li>Service层方法入参</li> |
||||
|
* </ul> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Data |
||||
|
@Alias("CountAdjustmentRequest") |
||||
|
public class CountAdjustmentRequest { |
||||
|
|
||||
|
/** |
||||
|
* 工厂编码(必填) |
||||
|
*/ |
||||
|
private String site; |
||||
|
|
||||
|
/** |
||||
|
* 盘点单号(必填) |
||||
|
*/ |
||||
|
private String countNo; |
||||
|
|
||||
|
/** |
||||
|
* 操作用户名(必填) |
||||
|
*/ |
||||
|
private String username; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,75 @@ |
|||||
|
package com.gaotao.modules.check.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.apache.ibatis.type.Alias; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整处理结果实体类 - rqrq |
||||
|
* |
||||
|
* <p><b>用途:</b>用于返回自动处理盈亏的执行结果</p> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Data |
||||
|
@Alias("CountAdjustmentResult") |
||||
|
public class CountAdjustmentResult { |
||||
|
|
||||
|
/** |
||||
|
* 处理是否成功 |
||||
|
*/ |
||||
|
private boolean success; |
||||
|
|
||||
|
/** |
||||
|
* 结果消息 |
||||
|
*/ |
||||
|
private String message; |
||||
|
|
||||
|
/** |
||||
|
* 生成的盘亏单据号列表 |
||||
|
*/ |
||||
|
private List<String> lossTransNoList; |
||||
|
|
||||
|
/** |
||||
|
* 生成的盘盈单据号列表 |
||||
|
*/ |
||||
|
private List<String> profitTransNoList; |
||||
|
|
||||
|
/** |
||||
|
* 处理的盘亏记录数 |
||||
|
*/ |
||||
|
private int lossCount; |
||||
|
|
||||
|
/** |
||||
|
* 处理的盘盈记录数 |
||||
|
*/ |
||||
|
private int profitCount; |
||||
|
|
||||
|
/** |
||||
|
* 处理的标签数 |
||||
|
*/ |
||||
|
private int labelCount; |
||||
|
|
||||
|
/** |
||||
|
* 创建成功结果 - rqrq |
||||
|
*/ |
||||
|
public static CountAdjustmentResult success(String message) { |
||||
|
CountAdjustmentResult result = new CountAdjustmentResult(); |
||||
|
result.setSuccess(true); |
||||
|
result.setMessage(message); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建失败结果 - rqrq |
||||
|
*/ |
||||
|
public static CountAdjustmentResult fail(String message) { |
||||
|
CountAdjustmentResult result = new CountAdjustmentResult(); |
||||
|
result.setSuccess(false); |
||||
|
result.setMessage(message); |
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,116 @@ |
|||||
|
package com.gaotao.modules.check.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.apache.ibatis.type.Alias; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
/** |
||||
|
* 盘盈盘亏事务明细实体类 - 用于查询展示 - rqrq |
||||
|
* |
||||
|
* <p><b>用途:</b>用于前端盘盈盘亏记录页签左侧列表展示</p> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Data |
||||
|
@Alias("CountAdjustmentTransData") |
||||
|
public class CountAdjustmentTransData { |
||||
|
|
||||
|
// ==================== trans_header字段 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 工厂编码 |
||||
|
*/ |
||||
|
private String site; |
||||
|
|
||||
|
/** |
||||
|
* 事务号 |
||||
|
*/ |
||||
|
private String transNo; |
||||
|
|
||||
|
/** |
||||
|
* 事务日期 |
||||
|
*/ |
||||
|
private Date transDate; |
||||
|
|
||||
|
/** |
||||
|
* 事务类型 |
||||
|
* <p>PK=盘亏,PY=盘盈</p> |
||||
|
*/ |
||||
|
private String transTypeDb; |
||||
|
|
||||
|
/** |
||||
|
* 事务类型描述 |
||||
|
*/ |
||||
|
private String transTypeDesc; |
||||
|
|
||||
|
/** |
||||
|
* 仓库ID |
||||
|
*/ |
||||
|
private String warehouseId; |
||||
|
|
||||
|
/** |
||||
|
* 关联盘点单号(存储在order_ref1) |
||||
|
*/ |
||||
|
private String orderRef1; |
||||
|
|
||||
|
/** |
||||
|
* 备注 |
||||
|
*/ |
||||
|
private String remark; |
||||
|
|
||||
|
/** |
||||
|
* 操作用户 |
||||
|
*/ |
||||
|
private String userName; |
||||
|
|
||||
|
// ==================== trans_detail字段 ==================== |
||||
|
|
||||
|
/** |
||||
|
* 行号 |
||||
|
*/ |
||||
|
private Double itemNo; |
||||
|
|
||||
|
/** |
||||
|
* 物料号 |
||||
|
*/ |
||||
|
private String partNo; |
||||
|
|
||||
|
/** |
||||
|
* 事务数量 |
||||
|
*/ |
||||
|
private BigDecimal transQty; |
||||
|
|
||||
|
/** |
||||
|
* 批号 |
||||
|
*/ |
||||
|
private String batchNo; |
||||
|
|
||||
|
/** |
||||
|
* 库位ID |
||||
|
*/ |
||||
|
private String locationId; |
||||
|
|
||||
|
/** |
||||
|
* 方向(IN=入库,OUT=出库) |
||||
|
*/ |
||||
|
private String direction; |
||||
|
|
||||
|
/** |
||||
|
* 方向描述 |
||||
|
*/ |
||||
|
private String directionDesc; |
||||
|
|
||||
|
/** |
||||
|
* WDR号 |
||||
|
*/ |
||||
|
private String wdrNo; |
||||
|
|
||||
|
/** |
||||
|
* 工程变更级别 |
||||
|
*/ |
||||
|
private String engChgLevel; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,85 @@ |
|||||
|
package com.gaotao.modules.check.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.apache.ibatis.type.Alias; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
/** |
||||
|
* 盘盈盘亏事务子明细实体类 - 用于查询展示 - rqrq |
||||
|
* |
||||
|
* <p><b>用途:</b>用于前端盘盈盘亏记录页签右侧列表展示</p> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Data |
||||
|
@Alias("CountAdjustmentTransSubData") |
||||
|
public class CountAdjustmentTransSubData { |
||||
|
|
||||
|
/** |
||||
|
* 工厂编码 |
||||
|
*/ |
||||
|
private String site; |
||||
|
|
||||
|
/** |
||||
|
* 事务号 |
||||
|
*/ |
||||
|
private String transNo; |
||||
|
|
||||
|
/** |
||||
|
* 行号 |
||||
|
*/ |
||||
|
private Double itemNo; |
||||
|
|
||||
|
/** |
||||
|
* 子行号 |
||||
|
*/ |
||||
|
private String subNo; |
||||
|
|
||||
|
/** |
||||
|
* 子数量 |
||||
|
*/ |
||||
|
private Double subQty; |
||||
|
|
||||
|
/** |
||||
|
* 方向(IN=入库,OUT=出库) |
||||
|
*/ |
||||
|
private String direction; |
||||
|
|
||||
|
/** |
||||
|
* 方向描述 |
||||
|
*/ |
||||
|
private String directionDesc; |
||||
|
|
||||
|
/** |
||||
|
* 标签号 |
||||
|
*/ |
||||
|
private String handlingUnitId; |
||||
|
|
||||
|
/** |
||||
|
* 物料号 |
||||
|
*/ |
||||
|
private String partNo; |
||||
|
|
||||
|
/** |
||||
|
* 批号 |
||||
|
*/ |
||||
|
private String batchNo; |
||||
|
|
||||
|
/** |
||||
|
* 库位ID |
||||
|
*/ |
||||
|
private String locationId; |
||||
|
|
||||
|
/** |
||||
|
* 工程变更级别 |
||||
|
*/ |
||||
|
private String engChgLevel; |
||||
|
|
||||
|
/** |
||||
|
* 栈板号(存储在order_ref1) |
||||
|
*/ |
||||
|
private String palletId; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,116 @@ |
|||||
|
package com.gaotao.modules.check.mapper; |
||||
|
|
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentLabelItem; |
||||
|
import com.gaotao.modules.trans.entity.TransDetail; |
||||
|
import com.gaotao.modules.trans.entity.TransDetailSub; |
||||
|
import org.apache.ibatis.annotations.Mapper; |
||||
|
import org.apache.ibatis.annotations.Param; |
||||
|
|
||||
|
|
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentTransData; |
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentTransSubData; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整Mapper接口 - rqrq |
||||
|
* |
||||
|
* <p><b>功能:</b>提供盘盈盘亏处理相关的数据库操作</p> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Mapper |
||||
|
public interface CountAdjustmentMapper { |
||||
|
|
||||
|
/** |
||||
|
* 统计需要系统处理的异常结果数量 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param countNo 盘点单号 |
||||
|
* @return int 记录数 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
int countSystemHandleRecords(@Param("site") String site, @Param("countNo") String countNo); |
||||
|
|
||||
|
/** |
||||
|
* 查询待系统处理的标签明细(排除SURPLUS类型)- rqrq |
||||
|
* |
||||
|
* <p>关联handling_unit获取标签详细信息</p> |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param countNo 盘点单号 |
||||
|
* @return List<CountAdjustmentLabelItem> 标签明细列表 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
List<CountAdjustmentLabelItem> querySystemHandleLabels(@Param("site") String site, @Param("countNo") String countNo); |
||||
|
|
||||
|
/** |
||||
|
* 插入事务明细 - rqrq |
||||
|
* |
||||
|
* @param detail 事务明细 |
||||
|
* @return int 影响行数 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
int insertTransDetail(TransDetail detail); |
||||
|
|
||||
|
/** |
||||
|
* 插入事务子明细 - rqrq |
||||
|
* |
||||
|
* @param sub 事务子明细 |
||||
|
* @return int 影响行数 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
int insertTransDetailSub(TransDetailSub sub); |
||||
|
|
||||
|
/** |
||||
|
* 更新标签数量 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param unitId 标签号 |
||||
|
* @param qty 新数量 |
||||
|
* @param inStockFlag 在库标记 |
||||
|
* @param username 操作用户 |
||||
|
* @return int 影响行数 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
int updateHandlingUnitQty(@Param("site") String site, |
||||
|
@Param("unitId") String unitId, |
||||
|
@Param("qty") BigDecimal qty, |
||||
|
@Param("inStockFlag") String inStockFlag, |
||||
|
@Param("username") String username); |
||||
|
|
||||
|
/** |
||||
|
* 更新盘点结果处理标记 - rqrq |
||||
|
* |
||||
|
* @param countResultId 盘点结果ID |
||||
|
* @param username 操作用户 |
||||
|
* @return int 影响行数 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
int updateCountResultHandleFlag(@Param("countResultId") Long countResultId, |
||||
|
@Param("username") String username); |
||||
|
|
||||
|
// ==================== 盘盈盘亏记录查询 ==================== - rqrq |
||||
|
|
||||
|
/** |
||||
|
* 查询盘盈盘亏事务头和明细 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param countNo 盘点单号(存储在order_ref1中) |
||||
|
* @return List<CountAdjustmentTransData> 事务列表 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
List<CountAdjustmentTransData> queryAdjustmentTransList(@Param("site") String site, @Param("countNo") String countNo); |
||||
|
|
||||
|
/** |
||||
|
* 查询事务子明细 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param transNo 事务号 |
||||
|
* @return List<CountAdjustmentTransSubData> 子明细列表 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
List<CountAdjustmentTransSubData> queryAdjustmentTransSubList(@Param("site") String site, @Param("transNo") String transNo); |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,84 @@ |
|||||
|
package com.gaotao.modules.check.service; |
||||
|
|
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentRequest; |
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentResult; |
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentTransData; |
||||
|
import com.gaotao.modules.check.entity.CountAdjustmentTransSubData; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整服务接口 - 用于自动处理盘盈盘亏 - rqrq |
||||
|
* |
||||
|
* <p><b>功能说明:</b></p> |
||||
|
* <ul> |
||||
|
* <li>自动处理系统处理方式的盘点异常结果</li> |
||||
|
* <li>生成盘亏(PK)和盘盈(PY)事务单据</li> |
||||
|
* <li>更新库存和标签数量</li> |
||||
|
* </ul> |
||||
|
* |
||||
|
* <p><b>处理范围:</b></p> |
||||
|
* <ul> |
||||
|
* <li>QTY_DIFF(数量差异):差异数量正数=盘盈,负数=盘亏</li> |
||||
|
* <li>MISSING(标签缺失):差异数量为负数=盘亏</li> |
||||
|
* <li>SURPLUS(多出标签):不处理,需手工处理</li> |
||||
|
* </ul> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
public interface CountAdjustmentService { |
||||
|
|
||||
|
/** |
||||
|
* 检查是否有需要系统处理的异常结果 - rqrq |
||||
|
* |
||||
|
* @param request 请求参数(包含site和countNo) |
||||
|
* @return int 需要处理的记录数,0表示无需处理 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
int checkSystemHandleCount(CountAdjustmentRequest request); |
||||
|
|
||||
|
/** |
||||
|
* 执行自动盘盈盘亏处理 - rqrq |
||||
|
* |
||||
|
* <p><b>处理流程:</b></p> |
||||
|
* <ol> |
||||
|
* <li>查询所有待系统处理的盘点结果(handle_type='SYSTEM' AND handle_flag='N')</li> |
||||
|
* <li>排除SURPLUS类型(多出标签不处理)</li> |
||||
|
* <li>关联handling_unit获取标签详细信息</li> |
||||
|
* <li>按ERP维度汇总差异数量</li> |
||||
|
* <li>分离盘盈和盘亏数据</li> |
||||
|
* <li>按仓库分组处理盘亏:生成PK单据、更新库存</li> |
||||
|
* <li>按仓库分组处理盘盈:生成PY单据、更新库存</li> |
||||
|
* <li>逐个标签更新handling_unit.qty</li> |
||||
|
* <li>更新盘点结果handle_flag='Y'</li> |
||||
|
* </ol> |
||||
|
* |
||||
|
* @param request 请求参数(包含site、countNo、username) |
||||
|
* @return CountAdjustmentResult 处理结果 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
CountAdjustmentResult executeSystemAdjustment(CountAdjustmentRequest request); |
||||
|
|
||||
|
// ==================== 盘盈盘亏记录查询 ==================== - rqrq |
||||
|
|
||||
|
/** |
||||
|
* 查询盘盈盘亏事务记录 - rqrq |
||||
|
* |
||||
|
* @param request 请求参数(包含site和countNo) |
||||
|
* @return List<CountAdjustmentTransData> 事务列表 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
List<CountAdjustmentTransData> queryAdjustmentTransList(CountAdjustmentRequest request); |
||||
|
|
||||
|
/** |
||||
|
* 查询盘盈盘亏事务子明细 - rqrq |
||||
|
* |
||||
|
* @param site 工厂编码 |
||||
|
* @param transNo 事务号 |
||||
|
* @return List<CountAdjustmentTransSubData> 子明细列表 |
||||
|
* @author rqrq |
||||
|
*/ |
||||
|
List<CountAdjustmentTransSubData> queryAdjustmentTransSubList(String site, String transNo); |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,502 @@ |
|||||
|
package com.gaotao.modules.check.service.impl; |
||||
|
|
||||
|
import com.gaotao.modules.check.entity.*; |
||||
|
import com.gaotao.modules.check.mapper.CountAdjustmentMapper; |
||||
|
import com.gaotao.modules.check.service.CountAdjustmentService; |
||||
|
import com.gaotao.modules.trans.entity.TransHeader; |
||||
|
import com.gaotao.modules.trans.entity.TransDetail; |
||||
|
import com.gaotao.modules.trans.entity.TransDetailSub; |
||||
|
import com.gaotao.modules.trans.entity.TransNoControl; |
||||
|
import com.gaotao.modules.trans.service.TransNoControlService; |
||||
|
import com.gaotao.modules.trans.service.TransHeaderService; |
||||
|
import com.gaotao.modules.warehouse.service.InventoryStockService; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
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.*; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
/** |
||||
|
* 盘点调整服务实现类 - 自动处理盘盈盘亏 - rqrq |
||||
|
* |
||||
|
* <p><b>处理流程:</b></p> |
||||
|
* <ol> |
||||
|
* <li>查询待系统处理的盘点结果(handle_type='SYSTEM' AND handle_flag='N')</li> |
||||
|
* <li>排除SURPLUS类型(多出标签需手工处理)</li> |
||||
|
* <li>关联handling_unit获取标签详细信息</li> |
||||
|
* <li>按ERP维度汇总差异数量</li> |
||||
|
* <li>分离盘盈(diffQty>0)和盘亏(diffQty<0)数据</li> |
||||
|
* <li>处理盘亏:生成PK单据、减少库存</li> |
||||
|
* <li>处理盘盈:生成PY单据、增加库存</li> |
||||
|
* <li>逐个标签更新handling_unit.qty</li> |
||||
|
* <li>更新盘点结果handle_flag='Y'</li> |
||||
|
* </ol> |
||||
|
* |
||||
|
* @author rqrq |
||||
|
* @date 2025/12/23 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class CountAdjustmentServiceImpl implements CountAdjustmentService { |
||||
|
|
||||
|
@Autowired |
||||
|
private CountAdjustmentMapper countAdjustmentMapper; |
||||
|
|
||||
|
@Autowired |
||||
|
private TransNoControlService transNoService; |
||||
|
|
||||
|
@Autowired |
||||
|
private TransHeaderService transHeaderService; |
||||
|
|
||||
|
@Autowired |
||||
|
private InventoryStockService inventoryStockService; |
||||
|
|
||||
|
/** |
||||
|
* 检查是否有需要系统处理的异常结果 - rqrq |
||||
|
*/ |
||||
|
@Override |
||||
|
public int checkSystemHandleCount(CountAdjustmentRequest request) { |
||||
|
log.info("开始检查系统处理异常数量 - rqrq,site={}, countNo={}", request.getSite(), request.getCountNo()); |
||||
|
|
||||
|
// 参数校验 - rqrq |
||||
|
if (!StringUtils.hasText(request.getSite())) { |
||||
|
throw new RuntimeException("站点不能为空"); |
||||
|
} |
||||
|
if (!StringUtils.hasText(request.getCountNo())) { |
||||
|
throw new RuntimeException("盘点单号不能为空"); |
||||
|
} |
||||
|
|
||||
|
int count = countAdjustmentMapper.countSystemHandleRecords(request.getSite(), request.getCountNo()); |
||||
|
log.info("检查系统处理异常数量完成,共{}条记录 - rqrq", count); |
||||
|
return count; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 执行自动盘盈盘亏处理 - rqrq |
||||
|
*/ |
||||
|
@Override |
||||
|
@Transactional(rollbackFor = Exception.class) |
||||
|
public CountAdjustmentResult executeSystemAdjustment(CountAdjustmentRequest request) { |
||||
|
log.info("开始执行自动盘盈盘亏处理 - rqrq,site={}, countNo={}, username={}", |
||||
|
request.getSite(), request.getCountNo(), request.getUsername()); |
||||
|
|
||||
|
// 1. 参数校验 - rqrq |
||||
|
validateRequest(request); |
||||
|
|
||||
|
// 2. 查询待系统处理的盘点结果(排除SURPLUS类型)- rqrq |
||||
|
List<CountAdjustmentLabelItem> labelItems = countAdjustmentMapper.querySystemHandleLabels( |
||||
|
request.getSite(), request.getCountNo()); |
||||
|
|
||||
|
if (labelItems == null || labelItems.isEmpty()) { |
||||
|
log.info("没有需要系统处理的异常结果 - rqrq"); |
||||
|
return CountAdjustmentResult.fail("无异常结果需要系统处理"); |
||||
|
} |
||||
|
log.info("查询到待处理标签明细:{}条 - rqrq", labelItems.size()); |
||||
|
|
||||
|
// 3. 按ERP维度汇总差异数量 - rqrq |
||||
|
List<CountAdjustmentItem> summaryItems = summarizeByErpDimension(labelItems); |
||||
|
log.info("按ERP维度汇总后:{}条记录 - rqrq", summaryItems.size()); |
||||
|
|
||||
|
// 4. 分离盘盈和盘亏数据 - rqrq |
||||
|
List<CountAdjustmentItem> lossItems = summaryItems.stream() |
||||
|
.filter(item -> item.getDiffQty().compareTo(BigDecimal.ZERO) < 0) |
||||
|
.collect(Collectors.toList()); |
||||
|
List<CountAdjustmentItem> profitItems = summaryItems.stream() |
||||
|
.filter(item -> item.getDiffQty().compareTo(BigDecimal.ZERO) > 0) |
||||
|
.collect(Collectors.toList()); |
||||
|
|
||||
|
log.info("盘亏记录:{}条,盘盈记录:{}条 - rqrq", lossItems.size(), profitItems.size()); |
||||
|
|
||||
|
// 5. 创建结果对象 - rqrq |
||||
|
CountAdjustmentResult result = new CountAdjustmentResult(); |
||||
|
result.setSuccess(true); |
||||
|
result.setLossTransNoList(new ArrayList<>()); |
||||
|
result.setProfitTransNoList(new ArrayList<>()); |
||||
|
result.setLossCount(lossItems.size()); |
||||
|
result.setProfitCount(profitItems.size()); |
||||
|
result.setLabelCount(labelItems.size()); |
||||
|
|
||||
|
// 6. 处理盘亏(按仓库分组)- rqrq |
||||
|
if (!lossItems.isEmpty()) { |
||||
|
processLossItems(lossItems, request, result); |
||||
|
} |
||||
|
|
||||
|
// 7. 处理盘盈(按仓库分组)- rqrq |
||||
|
if (!profitItems.isEmpty()) { |
||||
|
processProfitItems(profitItems, request, result); |
||||
|
} |
||||
|
|
||||
|
// 8. 逐个标签更新handling_unit.qty - rqrq |
||||
|
updateHandlingUnitQty(labelItems, request.getUsername()); |
||||
|
|
||||
|
// 9. 更新盘点结果handle_flag='Y' - rqrq |
||||
|
updateCountResultHandleFlag(labelItems, request.getUsername()); |
||||
|
|
||||
|
result.setMessage("处理完成,盘亏" + result.getLossCount() + "条,盘盈" + result.getProfitCount() + "条"); |
||||
|
log.info("自动盘盈盘亏处理完成 - rqrq,{}", result.getMessage()); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 参数校验 - rqrq |
||||
|
*/ |
||||
|
private void validateRequest(CountAdjustmentRequest request) { |
||||
|
if (!StringUtils.hasText(request.getSite())) { |
||||
|
throw new RuntimeException("站点不能为空"); |
||||
|
} |
||||
|
if (!StringUtils.hasText(request.getCountNo())) { |
||||
|
throw new RuntimeException("盘点单号不能为空"); |
||||
|
} |
||||
|
if (!StringUtils.hasText(request.getUsername())) { |
||||
|
throw new RuntimeException("操作用户不能为空"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 按ERP维度汇总差异数量 - rqrq |
||||
|
* |
||||
|
* <p>汇总维度:site + warehouseId + locationId + partNo + batchNo + wdr + expiredDate + engChgLevel</p> |
||||
|
*/ |
||||
|
private List<CountAdjustmentItem> summarizeByErpDimension(List<CountAdjustmentLabelItem> labelItems) { |
||||
|
// 使用Map按维度汇总 - rqrq |
||||
|
Map<String, CountAdjustmentItem> summaryMap = new HashMap<>(); |
||||
|
|
||||
|
for (CountAdjustmentLabelItem label : labelItems) { |
||||
|
// 构建维度Key - rqrq |
||||
|
String key = buildDimensionKey(label); |
||||
|
|
||||
|
CountAdjustmentItem item = summaryMap.get(key); |
||||
|
if (item == null) { |
||||
|
item = new CountAdjustmentItem(); |
||||
|
item.setSite(label.getSite()); |
||||
|
item.setWarehouseId(label.getWarehouseId()); |
||||
|
item.setLocationId(label.getLocationId()); |
||||
|
item.setPartNo(label.getPartNo()); |
||||
|
item.setBatchNo(label.getBatchNo()); |
||||
|
item.setWdr(label.getWdr()); |
||||
|
item.setExpiredDate(label.getExpiredDate()); |
||||
|
item.setEngChgLevel(label.getEngChgLevel()); |
||||
|
item.setDiffQty(BigDecimal.ZERO); |
||||
|
item.setLabelItems(new ArrayList<>()); |
||||
|
summaryMap.put(key, item); |
||||
|
} |
||||
|
|
||||
|
// 累加差异数量 - rqrq |
||||
|
item.setDiffQty(item.getDiffQty().add(label.getDiffQty())); |
||||
|
item.getLabelItems().add(label); |
||||
|
} |
||||
|
|
||||
|
return new ArrayList<>(summaryMap.values()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 构建维度Key - rqrq |
||||
|
*/ |
||||
|
private String buildDimensionKey(CountAdjustmentLabelItem label) { |
||||
|
return String.join("||", |
||||
|
nullToEmpty(label.getSite()), |
||||
|
nullToEmpty(label.getWarehouseId()), |
||||
|
nullToEmpty(label.getLocationId()), |
||||
|
nullToEmpty(label.getPartNo()), |
||||
|
nullToEmpty(label.getBatchNo()), |
||||
|
nullToEmpty(label.getWdr()), |
||||
|
label.getExpiredDate() != null ? label.getExpiredDate().toString() : "", |
||||
|
nullToEmpty(label.getEngChgLevel()) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private String nullToEmpty(String str) { |
||||
|
return str != null ? str : ""; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 处理盘亏(按仓库分组)- rqrq |
||||
|
* |
||||
|
* <p><b>处理流程:</b></p> |
||||
|
* <ol> |
||||
|
* <li>按site+warehouseId分组</li> |
||||
|
* <li>每组生成一个盘亏单据(PK)</li> |
||||
|
* <li>创建trans_header(order_ref1=盘点单号)</li> |
||||
|
* <li>创建trans_detail(按维度)</li> |
||||
|
* <li>创建trans_detail_sub(按标签)</li> |
||||
|
* <li>减少库存</li> |
||||
|
* </ol> |
||||
|
*/ |
||||
|
private void processLossItems(List<CountAdjustmentItem> lossItems, |
||||
|
CountAdjustmentRequest request, |
||||
|
CountAdjustmentResult result) { |
||||
|
log.info("开始处理盘亏,共{}条记录 - rqrq", lossItems.size()); |
||||
|
|
||||
|
// 按site+warehouseId分组 - rqrq |
||||
|
Map<String, List<CountAdjustmentItem>> groupedItems = lossItems.stream() |
||||
|
.collect(Collectors.groupingBy(item -> item.getSite() + "||" + item.getWarehouseId())); |
||||
|
|
||||
|
for (Map.Entry<String, List<CountAdjustmentItem>> entry : groupedItems.entrySet()) { |
||||
|
String[] keys = entry.getKey().split("\\|\\|"); |
||||
|
String site = keys[0]; |
||||
|
String warehouseId = keys.length > 1 ? keys[1] : ""; |
||||
|
List<CountAdjustmentItem> items = entry.getValue(); |
||||
|
|
||||
|
// 生成盘亏单据号 - rqrq |
||||
|
TransNoControl transData = transNoService.getTransNo(site, "PK", 10); |
||||
|
String transNo = transData.getNewTransNo(); |
||||
|
log.info("生成盘亏单据号:{} - rqrq", transNo); |
||||
|
|
||||
|
// 创建trans_header - rqrq |
||||
|
TransHeader header = createTransHeader(site, transNo, warehouseId, "PK", |
||||
|
request.getCountNo(), request.getUsername()); |
||||
|
transHeaderService.save(header); |
||||
|
|
||||
|
// 创建trans_detail和trans_detail_sub - rqrq |
||||
|
int itemNo = 1; |
||||
|
for (CountAdjustmentItem item : items) { |
||||
|
// 创建trans_detail - rqrq |
||||
|
TransDetail detail = createTransDetail(transNo, itemNo, item, "OUT"); |
||||
|
countAdjustmentMapper.insertTransDetail(detail); |
||||
|
|
||||
|
// 创建trans_detail_sub(按标签)- rqrq |
||||
|
int subNo = 1; |
||||
|
for (CountAdjustmentLabelItem label : item.getLabelItems()) { |
||||
|
TransDetailSub sub = createTransDetailSub(transNo, itemNo, subNo, label, "OUT"); |
||||
|
countAdjustmentMapper.insertTransDetailSub(sub); |
||||
|
subNo++; |
||||
|
} |
||||
|
|
||||
|
// 减少库存 - rqrq |
||||
|
inventoryStockService.reduceStockWithLock( |
||||
|
item.getSite(), |
||||
|
item.getWarehouseId(), |
||||
|
item.getPartNo(), |
||||
|
item.getBatchNo(), |
||||
|
item.getLocationId(), |
||||
|
item.getDiffQty().abs(), |
||||
|
item.getWdr(), |
||||
|
item.getEngChgLevel() |
||||
|
); |
||||
|
|
||||
|
itemNo++; |
||||
|
} |
||||
|
|
||||
|
result.getLossTransNoList().add(transNo); |
||||
|
} |
||||
|
|
||||
|
log.info("盘亏处理完成,生成{}个单据 - rqrq", result.getLossTransNoList().size()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 处理盘盈(按仓库分组)- rqrq |
||||
|
*/ |
||||
|
private void processProfitItems(List<CountAdjustmentItem> profitItems, |
||||
|
CountAdjustmentRequest request, |
||||
|
CountAdjustmentResult result) { |
||||
|
log.info("开始处理盘盈,共{}条记录 - rqrq", profitItems.size()); |
||||
|
|
||||
|
// 按site+warehouseId分组 - rqrq |
||||
|
Map<String, List<CountAdjustmentItem>> groupedItems = profitItems.stream() |
||||
|
.collect(Collectors.groupingBy(item -> item.getSite() + "||" + item.getWarehouseId())); |
||||
|
|
||||
|
for (Map.Entry<String, List<CountAdjustmentItem>> entry : groupedItems.entrySet()) { |
||||
|
String[] keys = entry.getKey().split("\\|\\|"); |
||||
|
String site = keys[0]; |
||||
|
String warehouseId = keys.length > 1 ? keys[1] : ""; |
||||
|
List<CountAdjustmentItem> items = entry.getValue(); |
||||
|
|
||||
|
// 生成盘盈单据号 - rqrq |
||||
|
TransNoControl transData = transNoService.getTransNo(site, "PY", 10); |
||||
|
String transNo = transData.getNewTransNo(); |
||||
|
log.info("生成盘盈单据号:{} - rqrq", transNo); |
||||
|
|
||||
|
// 创建trans_header - rqrq |
||||
|
TransHeader header = createTransHeader(site, transNo, warehouseId, "PY", |
||||
|
request.getCountNo(), request.getUsername()); |
||||
|
transHeaderService.save(header); |
||||
|
|
||||
|
// 创建trans_detail和trans_detail_sub - rqrq |
||||
|
int itemNo = 1; |
||||
|
for (CountAdjustmentItem item : items) { |
||||
|
// 创建trans_detail - rqrq |
||||
|
TransDetail detail = createTransDetail(transNo, itemNo, item, "IN"); |
||||
|
countAdjustmentMapper.insertTransDetail(detail); |
||||
|
|
||||
|
// 创建trans_detail_sub(按标签)- rqrq |
||||
|
int subNo = 1; |
||||
|
for (CountAdjustmentLabelItem label : item.getLabelItems()) { |
||||
|
TransDetailSub sub = createTransDetailSub(transNo, itemNo, subNo, label, "IN"); |
||||
|
countAdjustmentMapper.insertTransDetailSub(sub); |
||||
|
subNo++; |
||||
|
} |
||||
|
|
||||
|
// 增加库存 - rqrq |
||||
|
inventoryStockService.updateStockWithLock( |
||||
|
item.getSite(), |
||||
|
item.getWarehouseId(), |
||||
|
item.getPartNo(), |
||||
|
item.getBatchNo(), |
||||
|
item.getLocationId(), |
||||
|
item.getWdr(), |
||||
|
item.getDiffQty(), |
||||
|
"N", |
||||
|
item.getEngChgLevel() |
||||
|
); |
||||
|
|
||||
|
itemNo++; |
||||
|
} |
||||
|
|
||||
|
result.getProfitTransNoList().add(transNo); |
||||
|
} |
||||
|
|
||||
|
log.info("盘盈处理完成,生成{}个单据 - rqrq", result.getProfitTransNoList().size()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建事务头 - rqrq |
||||
|
*/ |
||||
|
private TransHeader createTransHeader(String site, String transNo, String warehouseId, |
||||
|
String transType, String countNo, String username) { |
||||
|
TransHeader header = new TransHeader(); |
||||
|
header.setSite(site); |
||||
|
header.setTransNo(transNo); |
||||
|
header.setTransDate(new Date()); |
||||
|
header.setTransTypeDb(transType); |
||||
|
header.setWarehouseId(warehouseId); |
||||
|
header.setUserId(username); |
||||
|
header.setUserName(username); |
||||
|
header.setOrderRef1(countNo); // 关联盘点单号 - rqrq |
||||
|
header.setRemark(transType.equals("PK") ? "盘亏处理" : "盘盈处理"); |
||||
|
header.setStatus("COMPLETED"); |
||||
|
header.setStatusDb("COMPLETED"); |
||||
|
header.setEnterDate(new Date()); |
||||
|
header.setIfsFlag("N"); |
||||
|
return header; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建事务明细 - rqrq |
||||
|
*/ |
||||
|
private TransDetail createTransDetail(String transNo, int itemNo, |
||||
|
CountAdjustmentItem item, String direction) { |
||||
|
TransDetail detail = new TransDetail(); |
||||
|
detail.setSite(item.getSite()); |
||||
|
detail.setTransNo(transNo); |
||||
|
detail.setItemNo((double) itemNo); |
||||
|
detail.setPartNo(item.getPartNo()); |
||||
|
detail.setTransQty(item.getDiffQty().abs()); |
||||
|
detail.setBatchNo(item.getBatchNo()); |
||||
|
detail.setLocationId(item.getLocationId()); |
||||
|
detail.setDirection(direction); |
||||
|
detail.setWdrNo(item.getWdr()); |
||||
|
detail.setEngChgLevel(item.getEngChgLevel()); |
||||
|
return detail; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建事务子明细 - rqrq |
||||
|
*/ |
||||
|
private TransDetailSub createTransDetailSub(String transNo, int itemNo, int subNo, |
||||
|
CountAdjustmentLabelItem label, String direction) { |
||||
|
TransDetailSub sub = new TransDetailSub(); |
||||
|
sub.setSite(label.getSite()); |
||||
|
sub.setTransNo(transNo); |
||||
|
sub.setItemNo((double) itemNo); |
||||
|
sub.setSubNo(String.valueOf(subNo)); |
||||
|
sub.setSubQty(label.getDiffQty().abs().doubleValue()); |
||||
|
sub.setDirection(direction); |
||||
|
sub.setHandlingUnitId(label.getUnitId()); |
||||
|
sub.setPartNo(label.getPartNo()); |
||||
|
sub.setBatchNo(label.getBatchNo()); |
||||
|
sub.setLocationId(label.getLocationId()); |
||||
|
sub.setEngChgLevel(label.getEngChgLevel()); |
||||
|
sub.setOrderRef1(label.getPalletId()); // 记录栈板号 - rqrq |
||||
|
return sub; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新标签数量 - rqrq |
||||
|
* |
||||
|
* <p>如果更新后qty<=0,设置in_stock_flag='N'</p> |
||||
|
*/ |
||||
|
private void updateHandlingUnitQty(List<CountAdjustmentLabelItem> labelItems, String username) { |
||||
|
log.info("开始更新标签数量,共{}个标签 - rqrq", labelItems.size()); |
||||
|
|
||||
|
for (CountAdjustmentLabelItem label : labelItems) { |
||||
|
// 计算新数量 - rqrq |
||||
|
BigDecimal newQty = label.getQty().add(label.getDiffQty()); |
||||
|
String inStockFlag = newQty.compareTo(BigDecimal.ZERO) > 0 ? "Y" : "N"; |
||||
|
|
||||
|
// 如果新数量小于0,设为0 - rqrq |
||||
|
if (newQty.compareTo(BigDecimal.ZERO) < 0) { |
||||
|
newQty = BigDecimal.ZERO; |
||||
|
} |
||||
|
|
||||
|
// 更新handling_unit - rqrq |
||||
|
countAdjustmentMapper.updateHandlingUnitQty( |
||||
|
label.getSite(), |
||||
|
label.getUnitId(), |
||||
|
newQty, |
||||
|
inStockFlag, |
||||
|
username |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
log.info("标签数量更新完成 - rqrq"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新盘点结果处理标记 - rqrq |
||||
|
*/ |
||||
|
private void updateCountResultHandleFlag(List<CountAdjustmentLabelItem> labelItems, String username) { |
||||
|
log.info("开始更新盘点结果处理标记 - rqrq"); |
||||
|
|
||||
|
for (CountAdjustmentLabelItem label : labelItems) { |
||||
|
countAdjustmentMapper.updateCountResultHandleFlag(label.getCountResultId(), username); |
||||
|
} |
||||
|
|
||||
|
log.info("盘点结果处理标记更新完成 - rqrq"); |
||||
|
} |
||||
|
|
||||
|
// ==================== 盘盈盘亏记录查询 ==================== - rqrq |
||||
|
|
||||
|
/** |
||||
|
* 查询盘盈盘亏事务记录 - rqrq |
||||
|
*/ |
||||
|
@Override |
||||
|
public List<CountAdjustmentTransData> queryAdjustmentTransList(CountAdjustmentRequest request) { |
||||
|
log.info("开始查询盘盈盘亏事务记录 - rqrq,site={}, countNo={}", request.getSite(), request.getCountNo()); |
||||
|
|
||||
|
if (!StringUtils.hasText(request.getSite())) { |
||||
|
throw new RuntimeException("站点不能为空"); |
||||
|
} |
||||
|
if (!StringUtils.hasText(request.getCountNo())) { |
||||
|
throw new RuntimeException("盘点单号不能为空"); |
||||
|
} |
||||
|
|
||||
|
List<CountAdjustmentTransData> list = countAdjustmentMapper.queryAdjustmentTransList( |
||||
|
request.getSite(), request.getCountNo()); |
||||
|
log.info("查询盘盈盘亏事务记录完成,共{}条记录 - rqrq", list != null ? list.size() : 0); |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询盘盈盘亏事务子明细 - rqrq |
||||
|
*/ |
||||
|
@Override |
||||
|
public List<CountAdjustmentTransSubData> queryAdjustmentTransSubList(String site, String transNo) { |
||||
|
log.info("开始查询盘盈盘亏事务子明细 - rqrq,site={}, transNo={}", site, transNo); |
||||
|
|
||||
|
if (!StringUtils.hasText(site)) { |
||||
|
throw new RuntimeException("站点不能为空"); |
||||
|
} |
||||
|
if (!StringUtils.hasText(transNo)) { |
||||
|
throw new RuntimeException("事务号不能为空"); |
||||
|
} |
||||
|
|
||||
|
List<CountAdjustmentTransSubData> list = countAdjustmentMapper.queryAdjustmentTransSubList(site, transNo); |
||||
|
log.info("查询盘盈盘亏事务子明细完成,共{}条记录 - rqrq", list != null ? list.size() : 0); |
||||
|
return list; |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,152 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.gaotao.modules.check.mapper.CountAdjustmentMapper"> |
||||
|
|
||||
|
<!-- rqrq - 统计需要系统处理的异常结果数量 --> |
||||
|
<select id="countSystemHandleRecords" resultType="int"> |
||||
|
SELECT COUNT(1) |
||||
|
FROM count_result |
||||
|
WHERE site = #{site} |
||||
|
AND count_no = #{countNo} |
||||
|
AND handle_flag = 'N' |
||||
|
AND handle_type = 'SYSTEM' |
||||
|
AND count_result != 'SURPLUS' |
||||
|
AND count_result != 'OK' |
||||
|
</select> |
||||
|
|
||||
|
<!-- rqrq - 查询待系统处理的标签明细(排除SURPLUS类型)--> |
||||
|
<select id="querySystemHandleLabels" resultType="CountAdjustmentLabelItem"> |
||||
|
SELECT |
||||
|
r.id AS countResultId, |
||||
|
r.count_no AS countNo, |
||||
|
r.count_result AS countResult, |
||||
|
r.diff_qty AS diffQty, |
||||
|
r.site AS site, |
||||
|
r.unit_id AS unitId, |
||||
|
r.pallet_id AS palletId, |
||||
|
h.part_no AS partNo, |
||||
|
h.qty AS qty, |
||||
|
h.batch_no AS batchNo, |
||||
|
h.location_id AS locationId, |
||||
|
h.warehouse_id AS warehouseId, |
||||
|
h.wdr AS wdr, |
||||
|
h.expired_date AS expiredDate, |
||||
|
h.eng_chg_level AS engChgLevel |
||||
|
FROM count_result r |
||||
|
LEFT JOIN handling_unit h ON r.site = h.site AND r.unit_id = h.unit_id |
||||
|
WHERE r.site = #{site} |
||||
|
AND r.count_no = #{countNo} |
||||
|
AND r.handle_flag = 'N' |
||||
|
AND r.handle_type = 'SYSTEM' |
||||
|
AND r.count_result != 'SURPLUS' |
||||
|
AND r.count_result != 'OK' |
||||
|
ORDER BY r.id |
||||
|
</select> |
||||
|
|
||||
|
<!-- rqrq - 插入事务明细 --> |
||||
|
<insert id="insertTransDetail"> |
||||
|
INSERT INTO trans_detail ( |
||||
|
site, trans_no, item_no, part_no, trans_qty, |
||||
|
batch_no, location_id, direction, wdr_no, eng_chg_level |
||||
|
) VALUES ( |
||||
|
#{site}, #{transNo}, #{itemNo}, #{partNo}, #{transQty}, |
||||
|
#{batchNo}, #{locationId}, #{direction}, #{wdrNo}, #{engChgLevel} |
||||
|
) |
||||
|
</insert> |
||||
|
|
||||
|
<!-- rqrq - 插入事务子明细 --> |
||||
|
<insert id="insertTransDetailSub"> |
||||
|
INSERT INTO trans_detail_sub ( |
||||
|
site, trans_no, item_no, sub_no, sub_qty, direction, |
||||
|
handling_unit_id, part_no, batch_no, location_id, eng_chg_level, order_ref1 |
||||
|
) VALUES ( |
||||
|
#{site}, #{transNo}, #{itemNo}, #{subNo}, #{subQty}, #{direction}, |
||||
|
#{handlingUnitId}, #{partNo}, #{batchNo}, #{locationId}, #{engChgLevel}, #{orderRef1} |
||||
|
) |
||||
|
</insert> |
||||
|
|
||||
|
<!-- rqrq - 更新标签数量 --> |
||||
|
<update id="updateHandlingUnitQty"> |
||||
|
UPDATE handling_unit |
||||
|
SET qty = #{qty}, |
||||
|
in_stock_flag = #{inStockFlag}, |
||||
|
modified_by = #{username}, |
||||
|
modified_date = GETDATE() |
||||
|
WHERE site = #{site} |
||||
|
AND unit_id = #{unitId} |
||||
|
</update> |
||||
|
|
||||
|
<!-- rqrq - 更新盘点结果处理标记 --> |
||||
|
<update id="updateCountResultHandleFlag"> |
||||
|
UPDATE count_result |
||||
|
SET handle_flag = 'Y', |
||||
|
handle_time = GETDATE(), |
||||
|
handle_by = #{username} |
||||
|
WHERE id = #{countResultId} |
||||
|
</update> |
||||
|
|
||||
|
<!-- rqrq - 查询盘盈盘亏事务头和明细 --> |
||||
|
<select id="queryAdjustmentTransList" resultType="CountAdjustmentTransData"> |
||||
|
SELECT |
||||
|
h.site, |
||||
|
h.trans_no AS transNo, |
||||
|
h.trans_date AS transDate, |
||||
|
h.trans_type_db AS transTypeDb, |
||||
|
CASE h.trans_type_db |
||||
|
WHEN 'PK' THEN '盘亏' |
||||
|
WHEN 'PY' THEN '盘盈' |
||||
|
ELSE h.trans_type_db |
||||
|
END AS transTypeDesc, |
||||
|
h.warehouse_id AS warehouseId, |
||||
|
h.order_ref1 AS orderRef1, |
||||
|
h.remark, |
||||
|
h.user_name AS userName, |
||||
|
d.item_no AS itemNo, |
||||
|
d.part_no AS partNo, |
||||
|
d.trans_qty AS transQty, |
||||
|
d.batch_no AS batchNo, |
||||
|
d.location_id AS locationId, |
||||
|
d.direction, |
||||
|
CASE d.direction |
||||
|
WHEN 'IN' THEN '入库' |
||||
|
WHEN 'OUT' THEN '出库' |
||||
|
ELSE d.direction |
||||
|
END AS directionDesc, |
||||
|
d.wdr_no AS wdrNo, |
||||
|
d.eng_chg_level AS engChgLevel |
||||
|
FROM trans_header h |
||||
|
INNER JOIN trans_detail d ON h.site = d.site AND h.trans_no = d.trans_no |
||||
|
WHERE h.site = #{site} |
||||
|
AND h.order_ref1 = #{countNo} |
||||
|
AND h.trans_type_db IN ('PK', 'PY') |
||||
|
ORDER BY h.trans_no, d.item_no |
||||
|
</select> |
||||
|
|
||||
|
<!-- rqrq - 查询事务子明细 --> |
||||
|
<select id="queryAdjustmentTransSubList" resultType="CountAdjustmentTransSubData"> |
||||
|
SELECT |
||||
|
site, |
||||
|
trans_no AS transNo, |
||||
|
item_no AS itemNo, |
||||
|
sub_no AS subNo, |
||||
|
sub_qty AS subQty, |
||||
|
direction, |
||||
|
CASE direction |
||||
|
WHEN 'IN' THEN '入库' |
||||
|
WHEN 'OUT' THEN '出库' |
||||
|
ELSE direction |
||||
|
END AS directionDesc, |
||||
|
handling_unit_id AS handlingUnitId, |
||||
|
part_no AS partNo, |
||||
|
batch_no AS batchNo, |
||||
|
location_id AS locationId, |
||||
|
eng_chg_level AS engChgLevel, |
||||
|
order_ref1 AS palletId |
||||
|
FROM trans_detail_sub |
||||
|
WHERE site = #{site} |
||||
|
AND trans_no = #{transNo} |
||||
|
ORDER BY item_no, sub_no |
||||
|
</select> |
||||
|
|
||||
|
</mapper> |
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue