diff --git a/src/main/java/com/gaotao/modules/warehouse/controller/LabelInventoryStockController.java b/src/main/java/com/gaotao/modules/warehouse/controller/LabelInventoryStockController.java new file mode 100644 index 00000000..691bdc9e --- /dev/null +++ b/src/main/java/com/gaotao/modules/warehouse/controller/LabelInventoryStockController.java @@ -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); + } +} diff --git a/src/main/java/com/gaotao/modules/warehouse/dao/LabelInventoryStockMapper.java b/src/main/java/com/gaotao/modules/warehouse/dao/LabelInventoryStockMapper.java new file mode 100644 index 00000000..6a16d006 --- /dev/null +++ b/src/main/java/com/gaotao/modules/warehouse/dao/LabelInventoryStockMapper.java @@ -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 getLabelInventoryStockList( + Page page, @Param("query") LabelInventoryStockQueryDto query); +} diff --git a/src/main/java/com/gaotao/modules/warehouse/entity/dto/LabelInventoryStockQueryDto.java b/src/main/java/com/gaotao/modules/warehouse/entity/dto/LabelInventoryStockQueryDto.java new file mode 100644 index 00000000..6433f74a --- /dev/null +++ b/src/main/java/com/gaotao/modules/warehouse/entity/dto/LabelInventoryStockQueryDto.java @@ -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; +} diff --git a/src/main/java/com/gaotao/modules/warehouse/entity/vo/LabelInventoryStockRow.java b/src/main/java/com/gaotao/modules/warehouse/entity/vo/LabelInventoryStockRow.java new file mode 100644 index 00000000..0c5d47ac --- /dev/null +++ b/src/main/java/com/gaotao/modules/warehouse/entity/vo/LabelInventoryStockRow.java @@ -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; +} diff --git a/src/main/java/com/gaotao/modules/warehouse/service/LabelInventoryStockService.java b/src/main/java/com/gaotao/modules/warehouse/service/LabelInventoryStockService.java new file mode 100644 index 00000000..f4f48657 --- /dev/null +++ b/src/main/java/com/gaotao/modules/warehouse/service/LabelInventoryStockService.java @@ -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); +} diff --git a/src/main/java/com/gaotao/modules/warehouse/service/impl/LabelInventoryStockServiceImpl.java b/src/main/java/com/gaotao/modules/warehouse/service/impl/LabelInventoryStockServiceImpl.java new file mode 100644 index 00000000..947b136a --- /dev/null +++ b/src/main/java/com/gaotao/modules/warehouse/service/impl/LabelInventoryStockServiceImpl.java @@ -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 page = new Page<>(query.getPage(), query.getSize(), false); + page.setTotal(total); + // Mapper按相同筛选先SUM再分页;失败直接传播,前端结束loading并展示错误,不返回伪造库存 - rqrq + IPage result = labelInventoryStockMapper.getLabelInventoryStockList(page, query); + return new PageUtils(result); + } +} diff --git a/src/main/resources/mapper/warehouse/LabelInventoryStockMapper.xml b/src/main/resources/mapper/warehouse/LabelInventoryStockMapper.xml new file mode 100644 index 00000000..53977355 --- /dev/null +++ b/src/main/resources/mapper/warehouse/LabelInventoryStockMapper.xml @@ -0,0 +1,50 @@ + + + + + + WHERE h.site = #{query.site} + AND h.in_stock_flag = 'Y' + + AND h.warehouse_id = #{query.warehouseId} + + + AND h.part_no LIKE '%' + #{query.partNo} + '%' + + + AND h.batch_no LIKE '%' + #{query.batchNo} + '%' + + + AND h.location_id LIKE '%' + #{query.locationId} + '%' + + + + + + + +