7 changed files with 200 additions and 0 deletions
-
27src/main/java/com/gaotao/modules/warehouse/controller/LabelInventoryStockController.java
-
19src/main/java/com/gaotao/modules/warehouse/dao/LabelInventoryStockMapper.java
-
22src/main/java/com/gaotao/modules/warehouse/entity/dto/LabelInventoryStockQueryDto.java
-
23src/main/java/com/gaotao/modules/warehouse/entity/vo/LabelInventoryStockRow.java
-
10src/main/java/com/gaotao/modules/warehouse/service/LabelInventoryStockService.java
-
49src/main/java/com/gaotao/modules/warehouse/service/impl/LabelInventoryStockServiceImpl.java
-
50src/main/resources/mapper/warehouse/LabelInventoryStockMapper.xml
@ -0,0 +1,27 @@ |
|||
package com.gaotao.modules.warehouse.controller; |
|||
|
|||
import com.gaotao.common.utils.PageUtils; |
|||
import com.gaotao.common.utils.R; |
|||
import com.gaotao.modules.warehouse.entity.dto.LabelInventoryStockQueryDto; |
|||
import com.gaotao.modules.warehouse.service.LabelInventoryStockService; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
/** 新版库存管理查询入口,与仍供旧页面使用的inventory_stock接口隔离 - rqrq */ |
|||
@RestController |
|||
@RequestMapping("/warehouse") |
|||
public class LabelInventoryStockController { |
|||
@Autowired |
|||
private LabelInventoryStockService labelInventoryStockService; |
|||
|
|||
/** 页面查询及分批导出共用POST,分页统一返回page,Controller不处理聚合或业务校验 - rqrq */ |
|||
@PostMapping("getLabelInventoryStockList") |
|||
public R getLabelInventoryStockList(@RequestBody LabelInventoryStockQueryDto query) { |
|||
// 委托Service按请求工厂校验并查询标签汇总,失败交由统一异常处理 - rqrq |
|||
PageUtils page = labelInventoryStockService.getLabelInventoryStockList(query); |
|||
return R.ok().put("page", page); |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.gaotao.modules.warehouse.dao; |
|||
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.gaotao.modules.warehouse.entity.dto.LabelInventoryStockQueryDto; |
|||
import com.gaotao.modules.warehouse.entity.vo.LabelInventoryStockRow; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
/** 标签库存汇总独立只读Mapper,不接入旧库存更新流程 - rqrq */ |
|||
@Mapper |
|||
public interface LabelInventoryStockMapper { |
|||
/** 统计分组后的库存行数;与列表共用筛选,避免SQL Server的带ORDER BY子查询计数错误 - rqrq */ |
|||
long countLabelInventoryStock(@Param("query") LabelInventoryStockQueryDto query); |
|||
|
|||
/** 按六个库存维度聚合后分页;NOLOCK允许脏读,仅供查询和导出,不用于库存扣减依据 - rqrq */ |
|||
IPage<LabelInventoryStockRow> getLabelInventoryStockList( |
|||
Page<LabelInventoryStockRow> page, @Param("query") LabelInventoryStockQueryDto query); |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
package com.gaotao.modules.warehouse.entity.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** 标签库存汇总查询入参,仅用于只读页面及导出,不映射inventory_stock - rqrq */ |
|||
@Data |
|||
public class LabelInventoryStockQueryDto { |
|||
/** 页面明确传入的标签工厂编码,默认来自当前用户site;精确匹配handling_unit.site,必填不落库 - rqrq */ |
|||
private String site; |
|||
/** 仓库筛选,精确匹配handling_unit.warehouse_id;空值不过滤,不落库 - rqrq */ |
|||
private String warehouseId; |
|||
/** 物料编码筛选,沿用原页面包含匹配;空值不过滤,不落库 - rqrq */ |
|||
private String partNo; |
|||
/** 批次筛选,沿用原页面包含匹配;空值不过滤,不落库 - rqrq */ |
|||
private String batchNo; |
|||
/** 库位筛选,沿用原页面包含匹配;空值不过滤,不落库 - rqrq */ |
|||
private String locationId; |
|||
/** 汇总结果页码,从1开始;页面和分批导出共用,不落库 - rqrq */ |
|||
private Integer page = 1; |
|||
/** 每页汇总行数,默认20,最大1000以支持分批导出;不是标签条数,不落库 - rqrq */ |
|||
private Integer size = 20; |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
package com.gaotao.modules.warehouse.entity.vo; |
|||
|
|||
import lombok.Data; |
|||
import java.math.BigDecimal; |
|||
|
|||
/** handling_unit分组后的只读库存行,供库存管理页面和导出消费,不落库 - rqrq */ |
|||
@Data |
|||
public class LabelInventoryStockRow { |
|||
/** 分组工厂,来源handling_unit.site;保持标签实际工厂,不转换父site - rqrq */ |
|||
private String site; |
|||
/** 分组仓库,来源handling_unit.warehouse_id;不落库 - rqrq */ |
|||
private String warehouseId; |
|||
/** 分组物料编码,来源handling_unit.part_no;不落库 - rqrq */ |
|||
private String partNo; |
|||
/** 分组批次,来源handling_unit.batch_no;不落库 - rqrq */ |
|||
private String batchNo; |
|||
/** 分组库位,来源handling_unit.location_id;不落库 - rqrq */ |
|||
private String locationId; |
|||
/** 分组WDR,来源handling_unit.wdr,空值保持原值,不混并不同WDR - rqrq */ |
|||
private String wdr; |
|||
/** 现有库存:同组在库标签qty之和,沿用物料库存单位;含冻结/预留,不等同可用库存 - rqrq */ |
|||
private BigDecimal qtyOnHand = BigDecimal.ZERO; |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
package com.gaotao.modules.warehouse.service; |
|||
|
|||
import com.gaotao.common.utils.PageUtils; |
|||
import com.gaotao.modules.warehouse.entity.dto.LabelInventoryStockQueryDto; |
|||
|
|||
/** 库存管理新版页面的标签聚合查询,不负责库存写入或旧库存接口兼容 - rqrq */ |
|||
public interface LabelInventoryStockService { |
|||
/** 校验工厂/分页并返回标签库存聚合分页;失败抛业务异常,不静默返回错误库存 - rqrq */ |
|||
PageUtils getLabelInventoryStockList(LabelInventoryStockQueryDto query); |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
package com.gaotao.modules.warehouse.service.impl; |
|||
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.gaotao.common.exception.XJException; |
|||
import com.gaotao.common.utils.PageUtils; |
|||
import com.gaotao.modules.warehouse.dao.LabelInventoryStockMapper; |
|||
import com.gaotao.modules.warehouse.entity.dto.LabelInventoryStockQueryDto; |
|||
import com.gaotao.modules.warehouse.entity.vo.LabelInventoryStockRow; |
|||
import com.gaotao.modules.warehouse.service.LabelInventoryStockService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
/** 只读标签库存查询:不写表、不调用IFS/WCS,NOLOCK的非一致读风险只限查询结果 - rqrq */ |
|||
@Slf4j |
|||
@Service |
|||
public class LabelInventoryStockServiceImpl implements LabelInventoryStockService { |
|||
@Autowired |
|||
private LabelInventoryStockMapper labelInventoryStockMapper; |
|||
|
|||
/** 必须使用请求site,保留旧筛选的精确/包含语义;限制单批规模,不影响业务库存更新 - rqrq */ |
|||
@Override |
|||
public PageUtils getLabelInventoryStockList(LabelInventoryStockQueryDto query) { |
|||
if (query == null || StringUtils.isBlank(query.getSite())) { |
|||
throw new XJException("工厂编码不能为空"); |
|||
} |
|||
if (query.getPage() == null || query.getPage() < 1) { |
|||
throw new XJException("页码必须大于0"); |
|||
} |
|||
if (query.getSize() == null || query.getSize() < 1 || query.getSize() > 1000) { |
|||
throw new XJException("每页数量必须在1到1000之间,请分批查询或导出"); |
|||
} |
|||
// 仅清理查询输入两端空格,不推断父工厂、不增加冻结/预留/立库状态限制 - rqrq |
|||
query.setSite(query.getSite().trim()); |
|||
query.setWarehouseId(StringUtils.trimToNull(query.getWarehouseId())); |
|||
query.setPartNo(StringUtils.trimToNull(query.getPartNo())); |
|||
query.setBatchNo(StringUtils.trimToNull(query.getBatchNo())); |
|||
query.setLocationId(StringUtils.trimToNull(query.getLocationId())); |
|||
// 单独统计聚合行数,避免分页插件将含ORDER BY的原SQL包成SQL Server不支持的计数子查询 - rqrq |
|||
long total = labelInventoryStockMapper.countLabelInventoryStock(query); |
|||
Page<LabelInventoryStockRow> page = new Page<>(query.getPage(), query.getSize(), false); |
|||
page.setTotal(total); |
|||
// Mapper按相同筛选先SUM再分页;失败直接传播,前端结束loading并展示错误,不返回伪造库存 - rqrq |
|||
IPage<LabelInventoryStockRow> result = labelInventoryStockMapper.getLabelInventoryStockList(page, query); |
|||
return new PageUtils(result); |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
<?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.warehouse.dao.LabelInventoryStockMapper"> |
|||
<!-- 列表和计数共用筛选,均按请求site精确查询;无锁读取风险见下方说明 - rqrq --> |
|||
<sql id="labelInventoryFilter"> |
|||
WHERE h.site = #{query.site} |
|||
AND h.in_stock_flag = 'Y' |
|||
<if test="query.warehouseId != null and query.warehouseId != ''"> |
|||
AND h.warehouse_id = #{query.warehouseId} |
|||
</if> |
|||
<if test="query.partNo != null and query.partNo != ''"> |
|||
AND h.part_no LIKE '%' + #{query.partNo} + '%' |
|||
</if> |
|||
<if test="query.batchNo != null and query.batchNo != ''"> |
|||
AND h.batch_no LIKE '%' + #{query.batchNo} + '%' |
|||
</if> |
|||
<if test="query.locationId != null and query.locationId != ''"> |
|||
AND h.location_id LIKE '%' + #{query.locationId} + '%' |
|||
</if> |
|||
</sql> |
|||
|
|||
<!-- 只统计库存分组,不统计标签数;计数子查询不含ORDER BY,兼容SQL Server - rqrq --> |
|||
<select id="countLabelInventoryStock" resultType="java.lang.Long"> |
|||
SELECT COUNT_BIG(1) |
|||
FROM ( |
|||
SELECT 1 AS groupValue |
|||
FROM handling_unit h WITH (NOLOCK) |
|||
<include refid="labelInventoryFilter"/> |
|||
GROUP BY h.site, h.warehouse_id, h.part_no, h.batch_no, h.location_id, h.wdr |
|||
) inventoryGroups |
|||
</select> |
|||
<!-- |
|||
现有库存以标签在库标记Y为唯一状态口径,保留冻结/预留标签,不关联栈板或inventory_stock。 |
|||
按用户要求使用NOLOCK:并发更新时允许脏读、漏读或重复读取,统计/导出不是一致性快照,禁止作为扣库存依据。 |
|||
必须先GROUP BY再分页,ORDER BY覆盖全部分组键,避免同库存维度跨页顺序不确定。 - rqrq |
|||
--> |
|||
<select id="getLabelInventoryStockList" resultType="com.gaotao.modules.warehouse.entity.vo.LabelInventoryStockRow"> |
|||
SELECT h.site AS site, |
|||
h.warehouse_id AS warehouseId, |
|||
h.part_no AS partNo, |
|||
h.batch_no AS batchNo, |
|||
h.location_id AS locationId, |
|||
h.wdr AS wdr, |
|||
SUM(ISNULL(h.qty, 0)) AS qtyOnHand |
|||
FROM handling_unit h WITH (NOLOCK) |
|||
<include refid="labelInventoryFilter"/> |
|||
GROUP BY h.site, h.warehouse_id, h.part_no, h.batch_no, h.location_id, h.wdr |
|||
ORDER BY h.site, h.warehouse_id, h.part_no, h.batch_no, h.location_id, h.wdr |
|||
</select> |
|||
</mapper> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue