add gao product SKU

This commit is contained in:
Timi
2026-09-07 12:07:18 +08:00
parent 3a4386261c
commit 37dc1c9904
84 changed files with 2697 additions and 620 deletions
@@ -5,6 +5,10 @@
AND p.`deleted_at` IS NULL
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
<if test="productId != null and productId != ''">AND p.`id` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND EXISTS (
SELECT 1 FROM `gao_product_sku` k_filter
WHERE k_filter.`id` = #{skuId} AND k_filter.`product_id` = p.`id` AND k_filter.`deleted_at` IS NULL
)</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
</sql>
@@ -14,7 +18,8 @@
AND i.`deleted_at` IS NULL
AND o.`status` &lt;&gt; 'CANCELLED'
<if test="storeId != null and storeId != ''">AND o.`store_id` = #{storeId}</if>
<if test="productId != null and productId != ''">AND i.`product_id` = #{productId}</if>
<if test="productId != null and productId != ''">AND i.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND i.`sku_id` = #{skuId}</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
AND o.`purchased_at` &gt;= #{beginAt}
@@ -27,10 +32,12 @@
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` ELSE 0 END), 0) AS `directQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` ELSE 0 END), 0) AS `packageQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN COALESCE(i.`line_amount`, 0) ELSE 0 END), 0) AS `directSaleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id` AND p.`store_id` = o.`store_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE 1 = 1
<include refid="orderProductFilter"/>
GROUP BY DATE_FORMAT(FROM_UNIXTIME(o.`purchased_at` / 1000), '%Y%m%d')
@@ -39,22 +46,24 @@
<select id="selectSalesRank" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSalesRankView">
SELECT
i.`product_id` AS `productId`,
i.`product_id_snapshot` AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` ELSE 0 END), 0) AS `directQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` ELSE 0 END), 0) AS `packageQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN COALESCE(i.`line_amount`, 0) ELSE 0 END), 0) AS `directSaleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id` AND p.`store_id` = o.`store_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE 1 = 1
<include refid="orderProductFilter"/>
GROUP BY i.`product_id`
ORDER BY (SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` ELSE 0 END)
+ SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` ELSE 0 END)) DESC,
GROUP BY i.`product_id_snapshot`
ORDER BY (SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END)
+ SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END)) DESC,
directSaleAmount DESC,
i.`product_id` ASC
i.`product_id_snapshot` ASC
LIMIT #{topN}
</select>
@@ -65,17 +74,22 @@
THEN CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`quantity` ELSE -fi.`quantity` END ELSE 0 END), 0) AS `directQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT'
THEN CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`quantity` ELSE -fi.`quantity` END ELSE 0 END), 0) AS `packageQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT'
THEN CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`base_quantity` ELSE -fi.`base_quantity` END ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT'
THEN CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`base_quantity` ELSE -fi.`base_quantity` END ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`base_quantity` ELSE -fi.`base_quantity` END), 0) AS `baseQuantity`
FROM `gao_order_fulfillment` f
INNER JOIN `gao_order_fulfillment_item` fi ON fi.`fulfillment_id` = f.`id`
INNER JOIN `gao_sales_order_item` i ON i.`id` = fi.`source_order_item_id`
INNER JOIN `gao_sales_order` o ON o.`id` = f.`sales_order_id` AND o.`deleted_at` IS NULL
INNER JOIN `gao_product` p ON p.`id` = fi.`product_id` AND p.`store_id` = f.`store_id`
INNER JOIN `gao_product` p ON p.`id` = fi.`product_id_snapshot` AND p.`store_id` = f.`store_id`
WHERE f.`store_id` = #{storeId}
AND f.`status` = 'VERIFIED'
AND f.`delivered_at` &gt;= #{beginAt}
AND f.`delivered_at` &lt;= #{endAt}
<if test="productId != null and productId != ''">AND fi.`product_id` = #{productId}</if>
<if test="productId != null and productId != ''">AND fi.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND fi.`sku_id` = #{skuId}</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
GROUP BY DATE_FORMAT(FROM_UNIXTIME(f.`delivered_at` / 1000), '%Y%m%d')
@@ -84,21 +98,26 @@
<select id="selectFulfillmentRank" resultType="com.imyeyu.api.modules.gao.vo.GaoProductFulfillmentRankView">
SELECT
i.`product_id` AS `productId`,
i.`product_id_snapshot` AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` ELSE 0 END), 0) AS `directQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` ELSE 0 END), 0) AS `packageQuantity`,
COALESCE(SUM(i.`reserved_quantity`), 0) AS `reservedQuantity`,
COALESCE(SUM(i.`fulfilled_quantity`), 0) AS `fulfilledQuantity`,
COALESCE(SUM(i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`), 0) AS `availableQuantity`
COALESCE(SUM(i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`), 0) AS `availableQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(i.`reserved_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `reservedBaseQuantity`,
COALESCE(SUM(i.`fulfilled_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `fulfilledBaseQuantity`,
COALESCE(SUM((i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`) * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `availableBaseQuantity`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id` AND p.`store_id` = o.`store_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE 1 = 1
<include refid="orderProductFilter"/>
GROUP BY i.`product_id`
ORDER BY `availableQuantity` DESC, `fulfilledQuantity` DESC, i.`product_id` ASC
GROUP BY i.`product_id_snapshot`
ORDER BY `availableBaseQuantity` DESC, `fulfilledBaseQuantity` DESC, i.`product_id_snapshot` ASC
LIMIT #{topN}
</select>
@@ -111,11 +130,12 @@
COALESCE(SUM(CASE WHEN r.`reserved_delta` &gt; 0 THEN r.`reserved_delta` ELSE 0 END), 0) AS `reserveQuantity`,
COALESCE(SUM(CASE WHEN r.`reserved_delta` &lt; 0 THEN -r.`reserved_delta` ELSE 0 END), 0) AS `releaseQuantity`
FROM `gao_product_stock_record` r
INNER JOIN `gao_product` p ON p.`id` = r.`product_id` AND p.`store_id` = r.`store_id`
INNER JOIN `gao_product` p ON p.`id` = r.`product_id_snapshot` AND p.`store_id` = r.`store_id`
WHERE r.`store_id` = #{storeId}
AND r.`occurred_at` &gt;= #{beginAt}
AND r.`occurred_at` &lt;= #{endAt}
<if test="productId != null and productId != ''">AND r.`product_id` = #{productId}</if>
<if test="productId != null and productId != ''">AND r.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND r.`sku_id` = #{skuId}</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
GROUP BY DATE_FORMAT(FROM_UNIXTIME(r.`occurred_at` / 1000), '%Y%m%d')
@@ -129,19 +149,25 @@
p.`category_id` AS `categoryId`,
c.`name` AS `categoryName`,
p.`product_type` AS `productType`,
COALESCE(s.`on_hand_quantity`, 0) AS `onHandQuantity`,
COALESCE(s.`reserved_quantity`, 0) AS `reservedQuantity`,
COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0) AS `availableQuantity`,
p.`min_stock_quantity` AS `minStockQuantity`,
CASE WHEN p.`min_stock_quantity` IS NOT NULL
AND COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0) &lt; p.`min_stock_quantity`
THEN 1 ELSE 0 END AS `lowStock`
COALESCE(SUM(s.`on_hand_quantity`), 0) AS `onHandQuantity`,
COALESCE(SUM(s.`reserved_quantity`), 0) AS `reservedQuantity`,
COALESCE(SUM(s.`on_hand_quantity` - s.`reserved_quantity`), 0) AS `availableQuantity`,
CASE WHEN COUNT(k.`min_stock_quantity`) = 0 THEN NULL ELSE SUM(k.`min_stock_quantity`) END AS `minStockQuantity`,
MAX(CASE WHEN k.`min_stock_quantity` IS NOT NULL
AND COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0) &lt; k.`min_stock_quantity`
THEN 1 ELSE 0 END) AS `lowStock`
, COUNT(k.`id`) AS `skuCount`
, SUM(CASE WHEN k.`min_stock_quantity` IS NOT NULL
AND COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0) &lt; k.`min_stock_quantity`
THEN 1 ELSE 0 END) AS `lowStockSkuCount`
FROM `gao_product` p
LEFT JOIN `gao_product_category` c ON c.`id` = p.`category_id` AND c.`store_id` = p.`store_id` AND c.`deleted_at` IS NULL
LEFT JOIN `gao_product_stock` s ON s.`product_id` = p.`id` AND s.`store_id` = p.`store_id`
INNER JOIN `gao_product_sku` k ON k.`product_id` = p.`id` AND k.`deleted_at` IS NULL
LEFT JOIN `gao_product_stock` s ON s.`sku_id` = k.`id` AND s.`store_id` = p.`store_id`
WHERE p.`store_id` = #{storeId}
AND p.`stock_enabled` = 1
AND k.`stock_enabled` = 1
<include refid="productFilter"/>
GROUP BY p.`id`, p.`name`, p.`category_id`, c.`name`, p.`product_type`, p.`sort`
ORDER BY `lowStock` DESC, `availableQuantity` ASC, p.`sort` ASC, p.`name` ASC
LIMIT #{topN}
</select>
@@ -172,20 +198,26 @@
<select id="selectUnitSalesRank" resultType="com.imyeyu.api.modules.gao.vo.GaoProductUnitSalesRankView">
SELECT
i.`product_id` AS `productId`,
i.`product_id_snapshot` AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
i.`product_unit_id` AS `productUnitId`,
i.`sku_id` AS `skuId`,
MAX(i.`sku_code_snapshot`) AS `skuCode`,
MAX(i.`sku_name_snapshot`) AS `skuName`,
MAX(i.`spec_summary_snapshot`) AS `specSummary`,
i.`sku_unit_id` AS `productUnitId`,
i.`sku_unit_id` AS `skuUnitId`,
MAX(i.`unit_snapshot`) AS `unitName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(i.`quantity`), 0) AS `quantity`,
COALESCE(SUM(i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `baseQuantity`,
COALESCE(SUM(i.`line_amount`), 0) AS `saleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id` AND p.`store_id` = o.`store_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE i.`item_type` = 'DIRECT_PRODUCT'
<include refid="orderProductFilter"/>
GROUP BY i.`product_id`, i.`product_unit_id`
ORDER BY `quantity` DESC, `saleAmount` DESC, i.`product_id` ASC, i.`product_unit_id` ASC
GROUP BY i.`product_id_snapshot`, i.`sku_id`, i.`sku_unit_id`
ORDER BY `baseQuantity` DESC, `saleAmount` DESC, i.`product_id_snapshot` ASC, i.`sku_id` ASC, i.`sku_unit_id` ASC
LIMIT #{topN}
</select>
</mapper>
@@ -0,0 +1,199 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductSkuChartMapper">
<sql id="skuOrderProductFilter">
AND o.`deleted_at` IS NULL
AND i.`deleted_at` IS NULL
AND o.`status` &lt;&gt; 'CANCELLED'
AND o.`store_id` = #{storeId}
<if test="productId != null and productId != ''">AND i.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND i.`sku_id` = #{skuId}</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
AND o.`purchased_at` &gt;= #{beginAt}
AND o.`purchased_at` &lt;= #{endAt}
</sql>
<select id="selectSalesDaily" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuSalesDailyStatView">
SELECT
CAST(DATE_FORMAT(FROM_UNIXTIME(o.`purchased_at` / 1000), '%Y%m%d') AS UNSIGNED) AS `dateValue`,
i.`sku_id` AS `skuId`,
MAX(i.`sku_code_snapshot`) AS `skuCode`,
MAX(i.`sku_name_snapshot`) AS `skuName`,
MAX(i.`spec_summary_snapshot`) AS `specSummary`,
MAX(i.`product_id_snapshot`) AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN COALESCE(i.`line_amount`, 0) ELSE 0 END), 0) AS `directSaleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE 1 = 1
<include refid="skuOrderProductFilter"/>
GROUP BY DATE_FORMAT(FROM_UNIXTIME(o.`purchased_at` / 1000), '%Y%m%d'), i.`sku_id`
ORDER BY `dateValue` ASC, i.`sku_id` ASC
</select>
<select id="selectSalesRank" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuSalesRankView">
SELECT
i.`sku_id` AS `skuId`,
MAX(i.`sku_code_snapshot`) AS `skuCode`,
MAX(i.`sku_name_snapshot`) AS `skuName`,
MAX(i.`spec_summary_snapshot`) AS `specSummary`,
MAX(i.`product_id_snapshot`) AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN COALESCE(i.`line_amount`, 0) ELSE 0 END), 0) AS `directSaleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE 1 = 1
<include refid="skuOrderProductFilter"/>
GROUP BY i.`sku_id`
ORDER BY (SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END)
+ SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END)) DESC,
directSaleAmount DESC, i.`sku_id` ASC
LIMIT #{topN}
</select>
<select id="selectUnitSalesRank" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSalesRankView">
SELECT
i.`sku_id` AS `skuId`,
MAX(i.`sku_code_snapshot`) AS `skuCode`,
MAX(i.`sku_name_snapshot`) AS `skuName`,
MAX(i.`spec_summary_snapshot`) AS `specSummary`,
MAX(i.`product_id_snapshot`) AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
i.`sku_unit_id` AS `skuUnitId`,
MAX(i.`unit_snapshot`) AS `unitName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(i.`quantity`), 0) AS `quantity`,
COALESCE(SUM(i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `baseQuantity`,
COALESCE(SUM(i.`line_amount`), 0) AS `saleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE i.`item_type` = 'DIRECT_PRODUCT'
<include refid="skuOrderProductFilter"/>
GROUP BY i.`sku_id`, i.`sku_unit_id`
ORDER BY `baseQuantity` DESC, `saleAmount` DESC, i.`sku_id` ASC, i.`sku_unit_id` ASC
LIMIT #{topN}
</select>
<select id="selectFulfillmentDaily" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuFulfillmentDailyStatView">
SELECT
CAST(DATE_FORMAT(FROM_UNIXTIME(f.`delivered_at` / 1000), '%Y%m%d') AS UNSIGNED) AS `dateValue`,
fi.`sku_id` AS `skuId`,
MAX(fi.`sku_code_snapshot`) AS `skuCode`,
MAX(fi.`sku_name_snapshot`) AS `skuName`,
MAX(fi.`spec_summary_snapshot`) AS `specSummary`,
MAX(fi.`product_id_snapshot`) AS `productId`,
MAX(fi.`product_name_snapshot`) AS `productName`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT'
THEN CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`base_quantity` ELSE -fi.`base_quantity` END ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT'
THEN CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`base_quantity` ELSE -fi.`base_quantity` END ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(CASE WHEN f.`source_fulfillment_id` IS NULL THEN fi.`base_quantity` ELSE -fi.`base_quantity` END), 0) AS `baseQuantity`
FROM `gao_order_fulfillment` f
INNER JOIN `gao_order_fulfillment_item` fi ON fi.`fulfillment_id` = f.`id`
INNER JOIN `gao_sales_order_item` i ON i.`id` = fi.`source_order_item_id`
INNER JOIN `gao_sales_order` o ON o.`id` = f.`sales_order_id` AND o.`deleted_at` IS NULL
INNER JOIN `gao_product` p ON p.`id` = fi.`product_id_snapshot` AND p.`store_id` = f.`store_id`
WHERE f.`store_id` = #{storeId}
AND f.`status` = 'VERIFIED'
AND i.`deleted_at` IS NULL
AND f.`delivered_at` &gt;= #{beginAt}
AND f.`delivered_at` &lt;= #{endAt}
<if test="productId != null and productId != ''">AND fi.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND fi.`sku_id` = #{skuId}</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
GROUP BY DATE_FORMAT(FROM_UNIXTIME(f.`delivered_at` / 1000), '%Y%m%d'), fi.`sku_id`
ORDER BY `dateValue` ASC, fi.`sku_id` ASC
</select>
<select id="selectFulfillmentRank" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuFulfillmentRankView">
SELECT
i.`sku_id` AS `skuId`,
MAX(i.`sku_code_snapshot`) AS `skuCode`,
MAX(i.`sku_name_snapshot`) AS `skuName`,
MAX(i.`spec_summary_snapshot`) AS `specSummary`,
MAX(i.`product_id_snapshot`) AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(i.`reserved_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `reservedBaseQuantity`,
COALESCE(SUM(i.`fulfilled_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `fulfilledBaseQuantity`,
COALESCE(SUM((i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`) * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `availableBaseQuantity`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE 1 = 1
<include refid="skuOrderProductFilter"/>
GROUP BY i.`sku_id`
ORDER BY `availableBaseQuantity` DESC, `fulfilledBaseQuantity` DESC, i.`sku_id` ASC
LIMIT #{topN}
</select>
<select id="selectStockMovementDaily" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuStockMovementDailyStatView">
SELECT
CAST(DATE_FORMAT(FROM_UNIXTIME(r.`occurred_at` / 1000), '%Y%m%d') AS UNSIGNED) AS `dateValue`,
r.`sku_id` AS `skuId`,
MAX(r.`sku_code_snapshot`) AS `skuCode`,
MAX(r.`sku_name_snapshot`) AS `skuName`,
MAX(r.`spec_summary_snapshot`) AS `specSummary`,
MAX(r.`product_id_snapshot`) AS `productId`,
MAX(r.`product_name_snapshot`) AS `productName`,
COALESCE(SUM(CASE WHEN r.`on_hand_delta` &gt; 0 THEN r.`on_hand_delta` ELSE 0 END), 0) AS `inQuantity`,
COALESCE(SUM(CASE WHEN r.`on_hand_delta` &lt; 0 THEN -r.`on_hand_delta` ELSE 0 END), 0) AS `outQuantity`,
COALESCE(SUM(r.`on_hand_delta`), 0) AS `netOnHandQuantity`,
COALESCE(SUM(CASE WHEN r.`reserved_delta` &gt; 0 THEN r.`reserved_delta` ELSE 0 END), 0) AS `reserveQuantity`,
COALESCE(SUM(CASE WHEN r.`reserved_delta` &lt; 0 THEN -r.`reserved_delta` ELSE 0 END), 0) AS `releaseQuantity`
FROM `gao_product_stock_record` r
WHERE r.`store_id` = #{storeId}
AND r.`occurred_at` &gt;= #{beginAt}
AND r.`occurred_at` &lt;= #{endAt}
<if test="productId != null and productId != ''">AND r.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND r.`sku_id` = #{skuId}</if>
GROUP BY DATE_FORMAT(FROM_UNIXTIME(r.`occurred_at` / 1000), '%Y%m%d'), r.`sku_id`
ORDER BY `dateValue` ASC, r.`sku_id` ASC
</select>
<select id="selectStockHealth" resultType="com.imyeyu.api.modules.gao.vo.GaoProductSkuStockHealthView">
SELECT
k.`id` AS `skuId`,
k.`code` AS `skuCode`,
k.`name` AS `skuName`,
k.`spec_summary` AS `specSummary`,
p.`id` AS `productId`,
p.`name` AS `productName`,
p.`category_id` AS `categoryId`,
c.`name` AS `categoryName`,
p.`product_type` AS `productType`,
COALESCE(s.`on_hand_quantity`, 0) AS `onHandQuantity`,
COALESCE(s.`reserved_quantity`, 0) AS `reservedQuantity`,
COALESCE(s.`on_hand_quantity` - s.`reserved_quantity`, 0) AS `availableQuantity`,
k.`min_stock_quantity` AS `minStockQuantity`,
CASE WHEN k.`min_stock_quantity` IS NOT NULL
AND COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0) &lt; k.`min_stock_quantity`
THEN 1 ELSE 0 END AS `lowStock`
FROM `gao_product_sku` k
INNER JOIN `gao_product` p ON p.`id` = k.`product_id` AND p.`store_id` = k.`store_id` AND p.`deleted_at` IS NULL
LEFT JOIN `gao_product_category` c ON c.`id` = p.`category_id` AND c.`store_id` = p.`store_id` AND c.`deleted_at` IS NULL
LEFT JOIN `gao_product_stock` s ON s.`sku_id` = k.`id` AND s.`store_id` = k.`store_id`
WHERE k.`store_id` = #{storeId}
AND k.`deleted_at` IS NULL
AND k.`stock_enabled` = 1
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND k.`id` = #{skuId}</if>
<if test="categoryId != null and categoryId != ''">AND p.`category_id` = #{categoryId}</if>
<if test="productType != null">AND p.`product_type` = #{productType}</if>
ORDER BY `lowStock` DESC, `availableQuantity` ASC, p.`sort` ASC, k.`sort` ASC, k.`id` ASC
LIMIT #{topN}
</select>
</mapper>
@@ -0,0 +1,24 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductSkuMapper">
<select id="selectByProductId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
SELECT * FROM `gao_product_sku` WHERE `product_id` = #{productId} AND `deleted_at` IS NULL ORDER BY `sort`, `created_at`
</select>
<select id="selectByProductIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
SELECT * FROM `gao_product_sku` WHERE `deleted_at` IS NULL
<choose><when test="productIdList != null and !productIdList.isEmpty()">AND `product_id` IN <foreach collection="productIdList" item="id" open="(" separator="," close=")">#{id}</foreach></when><otherwise>AND FALSE</otherwise></choose>
ORDER BY `product_id`, `sort`, `created_at`
</select>
<select id="selectByStoreIdAndCode" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
SELECT * FROM `gao_product_sku` WHERE `store_id` = #{storeId} AND `code` = #{code} AND `deleted_at` IS NULL <if test="excludeId != null">AND `id` != #{excludeId}</if> LIMIT 1
</select>
<select id="selectByStoreIdAndBarcode" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
SELECT * FROM `gao_product_sku` WHERE `store_id` = #{storeId} AND `barcode` = #{barcode} AND `deleted_at` IS NULL <if test="excludeId != null">AND `id` != #{excludeId}</if> LIMIT 1
</select>
<select id="selectByProductIdAndSpecValueKey" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
SELECT * FROM `gao_product_sku` WHERE `product_id` = #{productId} AND `spec_value_key` = #{specValueKey} AND `deleted_at` IS NULL <if test="excludeId != null">AND `id` != #{excludeId}</if> LIMIT 1
</select>
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSku">
SELECT * FROM `gao_product_sku` WHERE `id` = #{id} AND `deleted_at` IS NULL FOR UPDATE
</select>
</mapper>
@@ -0,0 +1,6 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductSkuSpecValueMapper">
<select id="selectBySkuIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSkuSpecValue">SELECT * FROM `gao_product_sku_spec_value` WHERE 1 = 1 <choose><when test="skuIdList != null and !skuIdList.isEmpty()">AND `sku_id` IN <foreach collection="skuIdList" item="id" open="(" separator="," close=")">#{id}</foreach></when><otherwise>AND FALSE</otherwise></choose></select>
<delete id="deleteBySkuId">DELETE FROM `gao_product_sku_spec_value` WHERE `sku_id`=#{skuId}</delete>
</mapper>
@@ -0,0 +1,16 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductSkuUnitMapper">
<select id="selectBySkuId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit">
SELECT * FROM `gao_product_sku_unit` WHERE `sku_id` = #{skuId} AND `deleted_at` IS NULL ORDER BY `sort`, `created_at`
</select>
<select id="selectBySkuIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit">
SELECT * FROM `gao_product_sku_unit` WHERE `deleted_at` IS NULL
<choose><when test="skuIdList != null and !skuIdList.isEmpty()">AND `sku_id` IN <foreach collection="skuIdList" item="id" open="(" separator="," close=")">#{id}</foreach></when><otherwise>AND FALSE</otherwise></choose>
ORDER BY `sku_id`, `sort`, `created_at`
</select>
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSkuUnit">
SELECT * FROM `gao_product_sku_unit` WHERE `id` = #{id} AND `deleted_at` IS NULL FOR UPDATE
</select>
<update id="updateUnit">UPDATE `gao_product_sku_unit` SET `name`=#{name}, `base_quantity_per_unit`=#{baseQuantityPerUnit}, `sale_price`=#{salePrice}, `is_base`=#{isBase}, `allow_purchase`=#{allowPurchase}, `allow_sale`=#{allowSale}, `sort`=#{sort}, `updated_at`=FLOOR(UNIX_TIMESTAMP(NOW(3))*1000) WHERE `id`=#{id} AND `sku_id`=#{skuId} AND `deleted_at` IS NULL</update>
</mapper>
@@ -0,0 +1,8 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductSpecMapper">
<select id="selectByProductId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSpec">SELECT * FROM `gao_product_spec` WHERE `product_id`=#{productId} AND `deleted_at` IS NULL ORDER BY `sort`, `created_at`</select>
<select id="selectByProductIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSpec">SELECT * FROM `gao_product_spec` WHERE `deleted_at` IS NULL <choose><when test="productIdList != null and !productIdList.isEmpty()">AND `product_id` IN <foreach collection="productIdList" item="id" open="(" separator="," close=")">#{id}</foreach></when><otherwise>AND FALSE</otherwise></choose> ORDER BY `product_id`, `sort`, `created_at`</select>
<select id="selectProductIdBySpecValueId" resultType="string">SELECT `s`.`product_id` FROM `gao_product_spec_value` `v` INNER JOIN `gao_product_spec` `s` ON `s`.`id`=`v`.`spec_id` AND `s`.`deleted_at` IS NULL WHERE `v`.`id`=#{specValueId} AND `v`.`deleted_at` IS NULL</select>
<select id="selectProductIdBySpecId" resultType="string">SELECT `product_id` FROM `gao_product_spec` WHERE `id`=#{specId} AND `deleted_at` IS NULL</select>
</mapper>
@@ -0,0 +1,6 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductSpecValueMapper">
<select id="selectById" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSpecValue">SELECT * FROM `gao_product_spec_value` WHERE `id` = #{id} AND `deleted_at` IS NULL</select>
<select id="selectBySpecIdList" resultType="com.imyeyu.api.modules.gao.entity.GaoProductSpecValue">SELECT * FROM `gao_product_spec_value` WHERE `deleted_at` IS NULL <choose><when test="specIdList != null and !specIdList.isEmpty()">AND `spec_id` IN <foreach collection="specIdList" item="id" open="(" separator="," close=")">#{id}</foreach></when><otherwise>AND FALSE</otherwise></choose> ORDER BY `spec_id`, `sort`, `created_at`</select>
</mapper>
@@ -3,55 +3,92 @@
<mapper namespace="com.imyeyu.api.modules.gao.mapper.GaoProductStockMapper">
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
SELECT * FROM `gao_product_stock`
WHERE `store_id` = #{storeId} AND `product_id` = #{productId}
WHERE `store_id` = #{storeId} AND `sku_id` = #{skuId}
FOR UPDATE
</select>
<select id="selectByStoreIdAndProductId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
<select id="selectByStoreIdAndSkuId" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
SELECT * FROM `gao_product_stock`
WHERE `store_id` = #{storeId} AND `product_id` = #{productId}
WHERE `store_id` = #{storeId} AND `sku_id` = #{skuId}
</select>
<select id="countByQuery" resultType="long">
SELECT COUNT(1)
FROM `gao_product` p
LEFT JOIN `gao_product_stock` s ON s.`product_id` = p.`id`
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` = p.`store_id`</otherwise>
<otherwise>AND s.`store_id` = k.`store_id`</otherwise>
</choose>
WHERE p.`deleted_at` IS NULL
AND p.`stock_enabled` = 1
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 p.`id` = #{productId}</if>
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%'))</if>
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` 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="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
SELECT s.`id`,
p.`store_id`,
p.`id` AS `product_id`,
k.`store_id`,
k.`id` AS `sku_id`,
COALESCE(s.`on_hand_quantity`, 0) AS `on_hand_quantity`,
COALESCE(s.`reserved_quantity`, 0) AS `reserved_quantity`,
s.`updated_by`,
s.`created_at`,
s.`updated_at`
FROM `gao_product` p
LEFT JOIN `gao_product_stock` s ON s.`product_id` = p.`id`
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` = p.`store_id`</otherwise>
<otherwise>AND s.`store_id` = k.`store_id`</otherwise>
</choose>
WHERE p.`deleted_at` IS NULL
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="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` 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`
LIMIT #{offset}, #{limit}
</select>
<select id="countProductByQuery" resultType="long">
SELECT COUNT(DISTINCT p.`id`)
FROM `gao_product_sku` k
JOIN `gao_product` p ON p.`id` = k.`product_id`
WHERE p.`deleted_at` IS NULL AND k.`deleted_at` IS NULL
AND p.`stock_enabled` = 1
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 p.`id` = #{productId}</if>
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%'))</if>
</select>
<select id="selectProductByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoProductStockProductView">
SELECT p.`id` AS `product_id`,
p.`code` AS `product_code`,
p.`name` AS `product_name`,
p.`product_type`,
COUNT(k.`id`) AS `sku_count`,
COALESCE(SUM(COALESCE(s.`on_hand_quantity`, 0)), 0) AS `on_hand_quantity`,
COALESCE(SUM(COALESCE(s.`reserved_quantity`, 0)), 0) AS `reserved_quantity`,
COALESCE(SUM(COALESCE(s.`on_hand_quantity`, 0) - COALESCE(s.`reserved_quantity`, 0)), 0) AS `available_quantity`
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 p.`stock_enabled` = 1
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%'))</if>
GROUP BY p.`id`, p.`code`, p.`name`, p.`product_type`, p.`sort`
ORDER BY p.`sort`, p.`name`, p.`code`
LIMIT #{offset}, #{limit}
</select>
<insert id="insertIgnore">
INSERT IGNORE INTO `gao_product_stock`
(`id`, `store_id`, `product_id`, `on_hand_quantity`, `reserved_quantity`, `updated_by`, `created_at`)
(`id`, `store_id`, `sku_id`, `on_hand_quantity`, `reserved_quantity`, `updated_by`, `created_at`)
VALUES
(#{id}, #{storeId}, #{productId}, #{onHandQuantity}, #{reservedQuantity}, #{updatedBy}, #{createdAt})
(#{id}, #{storeId}, #{skuId}, #{onHandQuantity}, #{reservedQuantity}, #{updatedBy}, #{createdAt})
</insert>
<update id="updateQuantity">
UPDATE `gao_product_stock`
@@ -4,7 +4,7 @@
<select id="selectByRequestNo" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStockRecord">
SELECT * FROM `gao_product_stock_record`
WHERE `store_id` = #{storeId} AND `request_no` = #{requestNo}
ORDER BY `product_id`, `id`
ORDER BY `sku_id`, `id`
</select>
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStockRecord">
SELECT * FROM `gao_product_stock_record`
@@ -21,16 +21,16 @@
WHERE `biz_type` = #{bizType} AND `biz_id` = #{bizId}
ORDER BY `occurred_at`, `id`
</select>
<select id="selectByBizProduct" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStockRecord">
<select id="selectByBizSku" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStockRecord">
SELECT * FROM `gao_product_stock_record`
WHERE `biz_type` = #{bizType} AND `biz_id` = #{bizId} AND `product_id` = #{productId} AND `operation_type` = #{operationType}
WHERE `biz_type` = #{bizType} AND `biz_id` = #{bizId} AND `sku_id` = #{skuId} AND `operation_type` = #{operationType}
ORDER BY `occurred_at`, `id`
LIMIT 1
</select>
<sql id="queryWhere">
1 = 1
<if test="storeId != null and storeId != ''">AND r.`store_id` = #{storeId}</if>
<if test="productId != null and productId != ''">AND r.`product_id` = #{productId}</if>
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
<if test="keyword != null and keyword.trim() != ''">AND (r.`product_name_snapshot` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`code` LIKE CONCAT('%', #{keyword}, '%'))</if>
<if test="bizType != null">AND r.`biz_type` = #{bizType}</if>
<if test="bizId != null and bizId != ''">AND r.`biz_id` = #{bizId}</if>
@@ -43,7 +43,7 @@
WHERE c.`store_id` = r.`store_id`
AND c.`biz_type` = r.`biz_type`
AND c.`biz_id` = r.`biz_id`
AND c.`product_id` = r.`product_id`
AND c.`sku_id` = r.`sku_id`
AND c.`operation_type` IN ('ORDER_RELEASE', 'ORDER_OUT')
)
</if>
@@ -53,10 +53,10 @@
<if test="endAt != null">AND r.`occurred_at` &lt;= #{endAt}</if>
</sql>
<select id="countByQuery" resultType="long">
SELECT COUNT(1) FROM `gao_product_stock_record` r LEFT JOIN `gao_product` p ON p.`id` = r.`product_id` AND p.`store_id` = r.`store_id` WHERE <include refid="queryWhere"/>
SELECT COUNT(1) FROM `gao_product_stock_record` r LEFT JOIN `gao_product_sku` k ON k.`id` = r.`sku_id` AND k.`store_id` = r.`store_id` LEFT JOIN `gao_product` p ON p.`id` = k.`product_id` WHERE <include refid="queryWhere"/>
</select>
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStockRecord">
SELECT r.* FROM `gao_product_stock_record` r LEFT JOIN `gao_product` p ON p.`id` = r.`product_id` AND p.`store_id` = r.`store_id` WHERE <include refid="queryWhere"/>
SELECT r.* FROM `gao_product_stock_record` r LEFT JOIN `gao_product_sku` k ON k.`id` = r.`sku_id` AND k.`store_id` = r.`store_id` LEFT JOIN `gao_product` p ON p.`id` = k.`product_id` WHERE <include refid="queryWhere"/>
ORDER BY r.`occurred_at` DESC, r.`id` DESC
LIMIT #{offset}, #{limit}
</select>
@@ -1,46 +0,0 @@
<?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.imyeyu.api.modules.gao.mapper.GaoProductUnitMapper">
<resultMap id="unitResultMap" type="com.imyeyu.api.modules.gao.entity.GaoProductUnit">
<id column="id" property="id"/>
<result column="product_id" property="productId"/>
<result column="name" property="name"/>
<result column="base_quantity_per_unit" property="baseQuantityPerUnit"/>
<result column="sale_price" property="salePrice"/>
<result column="is_base" property="isBase"/>
<result column="allow_purchase" property="allowPurchase"/>
<result column="allow_sale" property="allowSale"/>
<result column="sort" property="sort"/>
<result column="created_at" property="createdAt"/>
<result column="updated_at" property="updatedAt"/>
<result column="deleted_at" property="deletedAt"/>
</resultMap>
<select id="selectByProductId" resultMap="unitResultMap">
SELECT * FROM `gao_product_unit`
WHERE `product_id` = #{productId} AND `deleted_at` IS NULL
ORDER BY `sort`, `created_at`
</select>
<select id="selectByProductIdList" resultMap="unitResultMap">
SELECT * FROM `gao_product_unit`
WHERE `deleted_at` IS NULL
<choose>
<when test="productIdList != null and !productIdList.isEmpty()">
AND `product_id` IN <foreach collection="productIdList" item="id" open="(" separator="," close=")">#{id}</foreach>
</when>
<otherwise>AND FALSE</otherwise>
</choose>
ORDER BY `product_id`, `sort`, `created_at`
</select>
<select id="selectForUpdate" resultMap="unitResultMap">
SELECT * FROM `gao_product_unit`
WHERE `id` = #{id} AND `deleted_at` IS NULL
FOR UPDATE
</select>
<update id="updateUnit">
UPDATE `gao_product_unit`
SET `name` = #{name}, `base_quantity_per_unit` = #{baseQuantityPerUnit}, `sale_price` = #{salePrice}, `is_base` = #{isBase},
`allow_purchase` = #{allowPurchase}, `allow_sale` = #{allowSale}, `sort` = #{sort},
`updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
WHERE `id` = #{id} AND `product_id` = #{productId} AND `deleted_at` IS NULL
</update>
</mapper>
@@ -81,7 +81,7 @@
<select id="selectCustomerProductRank" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerOrderProductRankView">
SELECT
i.`product_id` AS `productId`,
i.`product_id_snapshot` AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` ELSE 0 END), 0) AS `directQuantity`,
@@ -89,10 +89,15 @@
COALESCE(SUM(i.`reserved_quantity`), 0) AS `reservedQuantity`,
COALESCE(SUM(i.`fulfilled_quantity`), 0) AS `fulfilledQuantity`,
COALESCE(SUM(i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`), 0) AS `availableQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(i.`reserved_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `reservedBaseQuantity`,
COALESCE(SUM(i.`fulfilled_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `fulfilledBaseQuantity`,
COALESCE(SUM((i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`) * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `availableBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN COALESCE(i.`line_amount`, 0) ELSE 0 END), 0) AS `directSaleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id` AND p.`store_id` = o.`store_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE o.`store_id` = #{storeId}
AND o.`customer_id` = #{customerId}
AND o.`deleted_at` IS NULL
@@ -100,11 +105,45 @@
AND o.`status` &lt;&gt; 'CANCELLED'
AND o.`purchased_at` &gt;= #{beginAt}
AND o.`purchased_at` &lt;= #{endAt}
GROUP BY i.`product_id`
ORDER BY (SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` ELSE 0 END)
+ SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` ELSE 0 END)) DESC,
<if test="productId != null and productId != ''">AND i.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND i.`sku_id` = #{skuId}</if>
GROUP BY i.`product_id_snapshot`
ORDER BY (SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END)
+ SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END)) DESC,
directSaleAmount DESC,
i.`product_id` ASC
i.`product_id_snapshot` ASC
LIMIT #{topN}
</select>
<select id="selectCustomerSkuRank" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerOrderSkuRankView">
SELECT
i.`sku_id` AS `skuId`,
MAX(i.`sku_code_snapshot`) AS `skuCode`,
MAX(i.`sku_name_snapshot`) AS `skuName`,
MAX(i.`spec_summary_snapshot`) AS `specSummary`,
i.`product_id_snapshot` AS `productId`,
MAX(i.`product_name_snapshot`) AS `productName`,
COUNT(DISTINCT o.`id`) AS `orderCount`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `directBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'PACKAGE_ENTITLEMENT' THEN i.`quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1) ELSE 0 END), 0) AS `packageBaseQuantity`,
COALESCE(SUM(i.`reserved_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `reservedBaseQuantity`,
COALESCE(SUM(i.`fulfilled_quantity` * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `fulfilledBaseQuantity`,
COALESCE(SUM((i.`quantity` - i.`reserved_quantity` - i.`fulfilled_quantity`) * COALESCE(i.`base_quantity_per_unit_snapshot`, 1)), 0) AS `availableBaseQuantity`,
COALESCE(SUM(CASE WHEN i.`item_type` = 'DIRECT_PRODUCT' THEN COALESCE(i.`line_amount`, 0) ELSE 0 END), 0) AS `directSaleAmount`
FROM `gao_sales_order_item` i
INNER JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
INNER JOIN `gao_product` p ON p.`id` = i.`product_id_snapshot` AND p.`store_id` = o.`store_id`
WHERE o.`store_id` = #{storeId}
AND o.`customer_id` = #{customerId}
AND o.`deleted_at` IS NULL
AND i.`deleted_at` IS NULL
AND o.`status` &lt;&gt; 'CANCELLED'
AND o.`purchased_at` &gt;= #{beginAt}
AND o.`purchased_at` &lt;= #{endAt}
<if test="productId != null and productId != ''">AND i.`product_id_snapshot` = #{productId}</if>
<if test="skuId != null and skuId != ''">AND i.`sku_id` = #{skuId}</if>
GROUP BY i.`sku_id`, i.`product_id_snapshot`
ORDER BY `availableBaseQuantity` DESC, `fulfilledBaseQuantity` DESC, `directSaleAmount` DESC, i.`sku_id` ASC
LIMIT #{topN}
</select>