product stock total for page
This commit is contained in:
@@ -12,6 +12,7 @@ import com.imyeyu.api.modules.gao.vo.GaoProductStockChangeRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualInBatchRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualInBatchRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPageResult;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockRecordPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockRecordPage;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -40,11 +41,14 @@ public class GaoProductStockController {
|
|||||||
private final GaoProductStockRecordService recordService;
|
private final GaoProductStockRecordService recordService;
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
|
|
||||||
|
/// 分页查询产品库存;指定 SKU 时附带基础单位库存统计
|
||||||
|
/// @param page 分页与筛选条件
|
||||||
|
/// @return 库存分页结果,指定 SKU 时包含基础单位库存统计
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@RequireGaoPermission(GaoPermissionCode.PRODUCT_STOCK_READ)
|
@RequireGaoPermission(GaoPermissionCode.PRODUCT_STOCK_READ)
|
||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
public PageResult<GaoProductStock> list(@RequestBody GaoProductStockPage page) {
|
public GaoProductStockPageResult list(@RequestBody GaoProductStockPage page) {
|
||||||
TimiException.required(page, "not found stock page");
|
TimiException.required(page, "not found stock page");
|
||||||
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
|
||||||
return stockService.pageByQuery(page);
|
return stockService.pageByQuery(page);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.imyeyu.api.modules.gao.mapper;
|
|||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoProductStock;
|
import com.imyeyu.api.modules.gao.entity.GaoProductStock;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPageResult;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
@@ -23,6 +24,11 @@ public interface GaoProductStockMapper extends BaseMapper<GaoProductStock, Strin
|
|||||||
/// 按条件查询库存余额
|
/// 按条件查询库存余额
|
||||||
List<GaoProductStock> selectByQuery(GaoProductStockPage page);
|
List<GaoProductStock> selectByQuery(GaoProductStockPage page);
|
||||||
|
|
||||||
|
/// 按条件统计基础单位库存数量
|
||||||
|
/// @param page 库存分页查询条件
|
||||||
|
/// @return 匹配 SKU 的库存数量汇总,数量均为基础单位
|
||||||
|
GaoProductStockPageResult selectQuantitySummaryByQuery(GaoProductStockPage page);
|
||||||
|
|
||||||
/// 按产品汇总库存数量
|
/// 按产品汇总库存数量
|
||||||
long countProductByQuery(GaoProductStockPage page);
|
long countProductByQuery(GaoProductStockPage page);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.imyeyu.api.modules.gao.vo.GaoProductStockChangeRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualInBatchRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualInBatchRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPageResult;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -20,8 +21,10 @@ import java.util.List;
|
|||||||
/// @since 2026-09-02
|
/// @since 2026-09-02
|
||||||
public interface GaoProductStockService {
|
public interface GaoProductStockService {
|
||||||
|
|
||||||
/// 查询库存余额
|
/// 分页查询库存余额;指定 SKU 时附带基础单位库存统计
|
||||||
PageResult<GaoProductStock> pageByQuery(GaoProductStockPage page);
|
/// @param page 分页与筛选条件
|
||||||
|
/// @return 库存分页结果,指定 SKU 时包含基础单位库存统计
|
||||||
|
GaoProductStockPageResult pageByQuery(GaoProductStockPage page);
|
||||||
|
|
||||||
/// 按产品汇总查询库存
|
/// 按产品汇总查询库存
|
||||||
PageResult<GaoProductStockProductView> pageProductByQuery(GaoProductStockPage page);
|
PageResult<GaoProductStockProductView> pageProductByQuery(GaoProductStockPage page);
|
||||||
|
|||||||
+9
-2
@@ -19,6 +19,7 @@ import com.imyeyu.api.modules.gao.vo.GaoProductStockChangeRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualInBatchRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualInBatchRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockManualRevokeRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPage;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockPageResult;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
import com.imyeyu.api.modules.gao.vo.GaoProductStockProductView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
import com.imyeyu.api.modules.gao.vo.GaoStockChangeItem;
|
||||||
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
@@ -62,10 +63,16 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<GaoProductStock> pageByQuery(GaoProductStockPage page) {
|
public GaoProductStockPageResult pageByQuery(GaoProductStockPage page) {
|
||||||
TimiException.required(page, "not found stock page");
|
TimiException.required(page, "not found stock page");
|
||||||
PageResult<GaoProductStock> result = new PageResult<>();
|
GaoProductStockPageResult result = new GaoProductStockPageResult();
|
||||||
result.setTotal(stockMapper.countByQuery(page));
|
result.setTotal(stockMapper.countByQuery(page));
|
||||||
|
if (page.getSkuId() != null && !page.getSkuId().isBlank()) {
|
||||||
|
GaoProductStockPageResult summary = stockMapper.selectQuantitySummaryByQuery(page);
|
||||||
|
result.setOnHandQuantityTotal(summary.getOnHandQuantityTotal());
|
||||||
|
result.setReservedQuantityTotal(summary.getReservedQuantityTotal());
|
||||||
|
result.setAvailableQuantityTotal(summary.getAvailableQuantityTotal());
|
||||||
|
}
|
||||||
List<GaoProductStock> list = stockMapper.selectByQuery(page);
|
List<GaoProductStock> list = stockMapper.selectByQuery(page);
|
||||||
Map<String, Attachment> photoMap = attachmentService.mapFirstImageByIdList(
|
Map<String, Attachment> photoMap = attachmentService.mapFirstImageByIdList(
|
||||||
Attachment.BizType.GAO_PRODUCT_SKU,
|
Attachment.BizType.GAO_PRODUCT_SKU,
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ public class GaoProductStockPage extends BasePage {
|
|||||||
/// 产品 ID
|
/// 产品 ID
|
||||||
private String productId;
|
private String productId;
|
||||||
|
|
||||||
|
/// SKU ID
|
||||||
|
private String skuId;
|
||||||
|
|
||||||
/// 产品或 SKU 名称、拼音、编码、规格摘要关键词
|
/// 产品或 SKU 名称、拼音、编码、规格摘要关键词
|
||||||
private String keyword;
|
private String keyword;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
|
import com.imyeyu.api.modules.gao.entity.GaoProductStock;
|
||||||
|
import com.imyeyu.spring.bean.PageResult;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/// GAO 产品库存分页查询结果
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-10-14
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class GaoProductStockPageResult extends PageResult<GaoProductStock> {
|
||||||
|
|
||||||
|
/// SKU 筛选条件下的实际库存合计,基础单位
|
||||||
|
private BigDecimal onHandQuantityTotal;
|
||||||
|
|
||||||
|
/// SKU 筛选条件下的已预占库存合计,基础单位
|
||||||
|
private BigDecimal reservedQuantityTotal;
|
||||||
|
|
||||||
|
/// SKU 筛选条件下的可用库存合计,基础单位
|
||||||
|
private BigDecimal availableQuantityTotal;
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
||||||
|
<if test="skuId != null and skuId.trim() != ''">AND k.`id` = #{skuId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
|
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
|
||||||
@@ -64,10 +65,29 @@
|
|||||||
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
||||||
|
<if test="skuId != null and skuId.trim() != ''">AND k.`id` = #{skuId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
||||||
ORDER BY p.`sort`, p.`name`, p.`code`, k.`sort`, k.`name`, k.`code`
|
ORDER BY p.`sort`, p.`name`, p.`code`, k.`sort`, k.`name`, k.`code`
|
||||||
LIMIT #{offset}, #{limit}
|
LIMIT #{offset}, #{limit}
|
||||||
</select>
|
</select>
|
||||||
|
<select id="selectQuantitySummaryByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoProductStockPageResult">
|
||||||
|
SELECT COALESCE(SUM(COALESCE(s.`on_hand_quantity`, 0)), 0) AS `on_hand_quantity_total`,
|
||||||
|
COALESCE(SUM(COALESCE(s.`reserved_quantity`, 0)), 0) AS `reserved_quantity_total`,
|
||||||
|
COALESCE(SUM(COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0)), 0) AS `available_quantity_total`
|
||||||
|
FROM `gao_product_sku` k
|
||||||
|
JOIN `gao_product` p ON p.`id` = k.`product_id`
|
||||||
|
LEFT JOIN `gao_product_stock` s ON s.`sku_id` = k.`id`
|
||||||
|
<choose>
|
||||||
|
<when test="storeId != null and storeId != ''">AND s.`store_id` = #{storeId}</when>
|
||||||
|
<otherwise>AND s.`store_id` = k.`store_id`</otherwise>
|
||||||
|
</choose>
|
||||||
|
WHERE p.`deleted_at` IS NULL AND k.`deleted_at` IS NULL
|
||||||
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
|
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
||||||
|
<if test="skuId != null and skuId.trim() != ''">AND k.`id` = #{skuId}</if>
|
||||||
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
||||||
|
</select>
|
||||||
<select id="countProductByQuery" resultType="long">
|
<select id="countProductByQuery" resultType="long">
|
||||||
SELECT COUNT(DISTINCT p.`id`)
|
SELECT COUNT(DISTINCT p.`id`)
|
||||||
FROM `gao_product_sku` k
|
FROM `gao_product_sku` k
|
||||||
|
|||||||
Reference in New Issue
Block a user