v1.0.51 #63

Merged
timi merged 3 commits from dev into master 2026-09-18 17:27:14 +00:00
12 changed files with 415 additions and 1 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
<groupId>com.imyeyu.timiserverapi</groupId> <groupId>com.imyeyu.timiserverapi</groupId>
<artifactId>TimiServerAPI</artifactId> <artifactId>TimiServerAPI</artifactId>
<version>1.0.50</version> <version>1.0.51</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>TimiServerAPI</name> <name>TimiServerAPI</name>
<description>imyeyu.com API</description> <description>imyeyu.com API</description>
@@ -9,6 +9,8 @@ import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
import com.imyeyu.api.modules.gao.service.GaoSalesOrderService; import com.imyeyu.api.modules.gao.service.GaoSalesOrderService;
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService; import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
import com.imyeyu.api.modules.gao.vo.GaoDirectProductOrderCreateRequest; import com.imyeyu.api.modules.gao.vo.GaoDirectProductOrderCreateRequest;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductPage;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductCustomerView;
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentActionRequest; import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentActionRequest;
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentNoRefundRequest; import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentNoRefundRequest;
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentReceiveRequest; import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentReceiveRequest;
@@ -16,6 +18,7 @@ import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRefundRequest;
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest; import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderReceivableStatView;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
import com.imyeyu.api.modules.user.service.UserService; import com.imyeyu.api.modules.user.service.UserService;
import com.imyeyu.java.TimiJava; import com.imyeyu.java.TimiJava;
@@ -54,6 +57,26 @@ public class GaoSalesOrderController {
return service.pageByQuery(page); return service.pageByQuery(page);
} }
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
@PostMapping("/summary")
public GaoSalesOrderReceivableStatView summary(@RequestBody GaoSalesOrderPage page) {
TimiException.required(page, "not found sales order summary page");
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
return service.summary(page);
}
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
@PostMapping("/customer-product/list")
public PageResult<GaoCustomerProductCustomerView> customerProductList(@RequestBody GaoCustomerProductPage page) {
TimiException.required(page, "not found customer product page");
page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
return service.pageCustomerProduct(page);
}
@AOPLog @AOPLog
@RequestRateLimit @RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ) @RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
@@ -1,7 +1,11 @@
package com.imyeyu.api.modules.gao.mapper; package com.imyeyu.api.modules.gao.mapper;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder; import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductPage;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductCustomerRow;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductView;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderReceivableStatView;
import com.imyeyu.spring.mapper.BaseMapper; import com.imyeyu.spring.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@@ -29,6 +33,18 @@ public interface GaoSalesOrderMapper extends BaseMapper<GaoSalesOrder, String> {
/// 按条件查询订单 /// 按条件查询订单
List<GaoSalesOrder> selectByQuery(GaoSalesOrderPage page); List<GaoSalesOrder> selectByQuery(GaoSalesOrderPage page);
/// 按条件汇总订单金额
GaoSalesOrderReceivableStatView selectSummaryByQuery(GaoSalesOrderPage page);
/// 按条件统计客户产品客户
long countCustomerProductCustomerByQuery(GaoCustomerProductPage page);
/// 按条件查询客户产品客户
List<GaoCustomerProductCustomerRow> selectCustomerProductCustomerByQuery(GaoCustomerProductPage page);
/// 按条件查询客户产品明细
List<GaoCustomerProductView> selectCustomerProductByQuery(GaoCustomerProductPage page);
/// 更新订单付款汇总 /// 更新订单付款汇总
int updatePayment(@Param("id") String id, @Param("pendingPaidAmount") Long pendingPaidAmount, @Param("paidAmount") Long paidAmount, int updatePayment(@Param("id") String id, @Param("pendingPaidAmount") Long pendingPaidAmount, @Param("paidAmount") Long paidAmount,
@Param("paidAt") Long paidAt, @Param("refundedAmount") Long refundedAmount, @Param("paymentStatus") GaoSalesOrder.PaymentStatus paymentStatus, @Param("paidAt") Long paidAt, @Param("refundedAmount") Long refundedAmount, @Param("paymentStatus") GaoSalesOrder.PaymentStatus paymentStatus,
@@ -3,9 +3,12 @@ package com.imyeyu.api.modules.gao.service;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder; import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem; import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem;
import com.imyeyu.api.modules.gao.vo.GaoDirectProductOrderCreateRequest; import com.imyeyu.api.modules.gao.vo.GaoDirectProductOrderCreateRequest;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductPage;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductCustomerView;
import com.imyeyu.api.modules.gao.vo.GaoPackageOrderCreateData; import com.imyeyu.api.modules.gao.vo.GaoPackageOrderCreateData;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderReceivableStatView;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
import com.imyeyu.spring.bean.PageResult; import com.imyeyu.spring.bean.PageResult;
import com.imyeyu.spring.service.BaseService; import com.imyeyu.spring.service.BaseService;
@@ -24,6 +27,12 @@ public interface GaoSalesOrderService extends BaseService<GaoSalesOrder, String>
/// 按条件分页查询订单 /// 按条件分页查询订单
PageResult<GaoSalesOrder> pageByQuery(GaoSalesOrderPage page); PageResult<GaoSalesOrder> pageByQuery(GaoSalesOrderPage page);
/// 按条件汇总订单金额
GaoSalesOrderReceivableStatView summary(GaoSalesOrderPage page);
/// 按条件分页查询客户产品
PageResult<GaoCustomerProductCustomerView> pageCustomerProduct(GaoCustomerProductPage page);
/// 查询订单详情 /// 查询订单详情
GaoSalesOrder detail(String id); GaoSalesOrder detail(String id);
@@ -30,10 +30,16 @@ import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
import com.imyeyu.api.modules.gao.service.GaoStoreService; import com.imyeyu.api.modules.gao.service.GaoStoreService;
import com.imyeyu.api.modules.gao.vo.GaoDirectProductOrderCreateRequest; import com.imyeyu.api.modules.gao.vo.GaoDirectProductOrderCreateRequest;
import com.imyeyu.api.modules.gao.vo.GaoPackageOrderCreateData; import com.imyeyu.api.modules.gao.vo.GaoPackageOrderCreateData;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductCustomerRow;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductCustomerView;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductPage;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductSummaryView;
import com.imyeyu.api.modules.gao.vo.GaoCustomerProductView;
import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection; import com.imyeyu.api.modules.gao.vo.GaoProductSkuUnitSelection;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderItemRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderItemRequest;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderReceivableStatView;
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest; import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
import com.imyeyu.api.modules.system.audit.AuditOperation; import com.imyeyu.api.modules.system.audit.AuditOperation;
import com.imyeyu.api.modules.system.audit.OperationAudit; import com.imyeyu.api.modules.system.audit.OperationAudit;
@@ -59,6 +65,7 @@ import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -111,6 +118,80 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
return result; return result;
} }
@Override
public GaoSalesOrderReceivableStatView summary(GaoSalesOrderPage page) {
TimiException.required(page, "not found sales order summary page");
return mapper.selectSummaryByQuery(page);
}
@Override
public PageResult<GaoCustomerProductCustomerView> pageCustomerProduct(GaoCustomerProductPage page) {
TimiException.required(page, "not found customer product page");
PageResult<GaoCustomerProductCustomerView> result = new PageResult<>();
result.setTotal(mapper.countCustomerProductCustomerByQuery(page));
List<GaoCustomerProductCustomerRow> customerRows = mapper.selectCustomerProductCustomerByQuery(page);
if (customerRows.isEmpty()) {
result.setList(List.of());
return result;
}
List<String> customerIdList = customerRows.stream().map(GaoCustomerProductCustomerRow::getCustomerId).toList();
page.setCustomerIdList(customerIdList);
List<GaoCustomerProductView> itemList = mapper.selectCustomerProductByQuery(page);
Map<String, GaoCustomerProductCustomerView> customerMap = new LinkedHashMap<>();
Map<String, Map<String, GaoCustomerProductSummaryView>> purchasedProductMap = new HashMap<>();
Map<String, Map<String, GaoCustomerProductSummaryView>> availableProductMap = new HashMap<>();
for (GaoCustomerProductCustomerRow row : customerRows) {
GaoCustomerProductCustomerView customerView = new GaoCustomerProductCustomerView();
GaoCustomer customer = new GaoCustomer();
customer.setId(row.getCustomerId());
customer.setCode(row.getCustomerCode());
customer.setName(row.getCustomerName());
customerView.setCustomer(customer);
customerView.setOrderCount(row.getOrderCount());
customerView.setPurchasedProducts(new ArrayList<>());
customerView.setAvailableProducts(new ArrayList<>());
customerMap.put(row.getCustomerId(), customerView);
}
for (GaoCustomerProductView item : itemList) {
if (!customerMap.containsKey(item.getCustomerId())) {
continue;
}
mergeCustomerProduct(purchasedProductMap, item, item.getBaseQuantity());
if (decimal(item.getAvailableBaseQuantity()).compareTo(ZERO) > 0) {
mergeCustomerProduct(availableProductMap, item, item.getAvailableBaseQuantity());
}
}
for (GaoCustomerProductCustomerRow row : customerRows) {
GaoCustomerProductCustomerView customerView = customerMap.get(row.getCustomerId());
customerView.setPurchasedProducts(new ArrayList<>(purchasedProductMap.getOrDefault(row.getCustomerId(), Map.of()).values()));
customerView.setAvailableProducts(new ArrayList<>(availableProductMap.getOrDefault(row.getCustomerId(), Map.of()).values()));
}
result.setList(new ArrayList<>(customerMap.values()));
return result;
}
private void mergeCustomerProduct(Map<String, Map<String, GaoCustomerProductSummaryView>> productMap,
GaoCustomerProductView item, BigDecimal quantity) {
String customerId = item.getCustomerId();
String productName = item.getProductNameSnapshot() == null ? "未命名产品" : item.getProductNameSnapshot();
String unit = item.getBaseUnitName() == null ? item.getUnitSnapshot() : item.getBaseUnitName();
unit = unit == null ? "基础单位" : unit;
String productKey = (item.getProductIdSnapshot() == null ? productName : item.getProductIdSnapshot()) + "::" + unit;
Map<String, GaoCustomerProductSummaryView> customerProducts = productMap.computeIfAbsent(customerId, key -> new LinkedHashMap<>());
GaoCustomerProductSummaryView product = customerProducts.get(productKey);
if (product == null) {
product = new GaoCustomerProductSummaryView();
product.setProductIdSnapshot(item.getProductIdSnapshot());
product.setProductName(productName);
product.setQuantity(decimal(quantity));
product.setUnit(unit);
customerProducts.put(productKey, product);
return;
}
product.setQuantity(decimal(product.getQuantity()).add(decimal(quantity)));
}
@Override @Override
public GaoSalesOrder detail(String id) { public GaoSalesOrder detail(String id) {
GaoSalesOrder order = get(id); GaoSalesOrder order = get(id);
@@ -0,0 +1,23 @@
package com.imyeyu.api.modules.gao.vo;
import lombok.Data;
/// GAO 客户产品客户分页行
///
/// @author Codex
/// @since 2026-09-18
@Data
public class GaoCustomerProductCustomerRow {
/// 客户 ID
private String customerId;
/// 客户编码
private String customerCode;
/// 客户姓名
private String customerName;
/// 相关订单数
private Long orderCount;
}
@@ -0,0 +1,26 @@
package com.imyeyu.api.modules.gao.vo;
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
import lombok.Data;
import java.util.List;
/// GAO 客户产品客户视图
///
/// @author Codex
/// @since 2026-09-18
@Data
public class GaoCustomerProductCustomerView {
/// 客户
private GaoCustomer customer;
/// 相关订单数
private Long orderCount;
/// 已购买产品
private List<GaoCustomerProductSummaryView> purchasedProducts;
/// 当前可履约产品
private List<GaoCustomerProductSummaryView> availableProducts;
}
@@ -0,0 +1,32 @@
package com.imyeyu.api.modules.gao.vo;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem;
import com.imyeyu.java.bean.BasePage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/// GAO 客户产品分页请求
///
/// @author Codex
/// @since 2026-09-18
@Data
@EqualsAndHashCode(callSuper = true)
public class GaoCustomerProductPage extends BasePage {
/// 门店 ID
private String storeId;
/// 客户 ID
private String customerId;
/// 客户、订单或产品关键词
private String keyword;
/// 产品来源
private GaoSalesOrderItem.ItemType itemType;
/// 内部批量查询客户 ID
private List<String> customerIdList;
}
@@ -0,0 +1,25 @@
package com.imyeyu.api.modules.gao.vo;
import lombok.Data;
import java.math.BigDecimal;
/// GAO 客户产品汇总视图
///
/// @author Codex
/// @since 2026-09-18
@Data
public class GaoCustomerProductSummaryView {
/// 产品 ID 快照
private String productIdSnapshot;
/// 产品名称
private String productName;
/// 产品数量,使用基础单位
private BigDecimal quantity;
/// 基础单位名称
private String unit;
}
@@ -0,0 +1,98 @@
package com.imyeyu.api.modules.gao.vo;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem;
import lombok.Data;
import java.math.BigDecimal;
/// GAO 客户产品明细视图
///
/// 每一行对应一个订单明细,数量使用基础单位,便于汇总客户产品。
///
/// @author Codex
/// @since 2026-09-18
@Data
public class GaoCustomerProductView {
/// 订单明细 ID
private String id;
/// 销售订单 ID
private String salesOrderId;
/// 客户 ID
private String customerId;
/// 客户编码
private String customerCode;
/// 客户姓名
private String customerName;
/// 订单号
private String orderNo;
/// 订单类型
private GaoSalesOrder.OrderType orderType;
/// 订单状态
private GaoSalesOrder.Status orderStatus;
/// 下单时间
private Long purchasedAt;
/// 订单项类型
private GaoSalesOrderItem.ItemType itemType;
/// 是否赠送权益
private Boolean gifted;
/// SKU ID
private String skuId;
/// SKU 单位 ID
private String skuUnitId;
/// 产品名称快照
private String productNameSnapshot;
/// 产品 ID 快照
private String productIdSnapshot;
/// SKU 编码快照
private String skuCodeSnapshot;
/// SKU 名称快照
private String skuNameSnapshot;
/// 规格摘要快照
private String specSummarySnapshot;
/// 单位快照
private String unitSnapshot;
/// 当前基础单位名称
private String baseUnitName;
/// 基础单位数量系数快照
private BigDecimal baseQuantityPerUnitSnapshot;
/// 购买数量
private BigDecimal quantity;
/// 购买基础单位数量
private BigDecimal baseQuantity;
/// 待履约基础单位数量
private BigDecimal reservedBaseQuantity;
/// 已履约基础单位数量
private BigDecimal fulfilledBaseQuantity;
/// 剩余权益基础单位数量
private BigDecimal remainingBaseQuantity;
/// 当前可立即履约基础单位数量
private BigDecimal availableBaseQuantity;
}
@@ -19,6 +19,9 @@ public class GaoSalesOrderPage extends BasePage {
/// 客户 ID /// 客户 ID
private String customerId; private String customerId;
/// 套餐配置 ID
private String packageConfigId;
/// 订单类型 /// 订单类型
private GaoSalesOrder.OrderType orderType; private GaoSalesOrder.OrderType orderType;
@@ -23,6 +23,14 @@
o.`deleted_at` IS NULL o.`deleted_at` IS NULL
<if test="storeId != null and storeId != ''">AND o.`store_id` = #{storeId}</if> <if test="storeId != null and storeId != ''">AND o.`store_id` = #{storeId}</if>
<if test="customerId != null and customerId != ''">AND o.`customer_id` = #{customerId}</if> <if test="customerId != null and customerId != ''">AND o.`customer_id` = #{customerId}</if>
<if test="packageConfigId != null and packageConfigId != ''">
AND EXISTS (
SELECT 1 FROM `gao_customer_package` cp
WHERE cp.`sales_order_id` = o.`id`
AND cp.`package_config_id` = #{packageConfigId}
AND cp.`deleted_at` IS NULL
)
</if>
<if test="orderType != null">AND o.`order_type` = #{orderType}</if> <if test="orderType != null">AND o.`order_type` = #{orderType}</if>
<if test="status != null">AND o.`status` = #{status}</if> <if test="status != null">AND o.`status` = #{status}</if>
<if test="paymentStatus != null">AND o.`payment_status` = #{paymentStatus}</if> <if test="paymentStatus != null">AND o.`payment_status` = #{paymentStatus}</if>
@@ -41,6 +49,76 @@
ORDER BY o.`purchased_at` DESC, o.`created_at` DESC ORDER BY o.`purchased_at` DESC, o.`created_at` DESC
LIMIT #{offset}, #{limit} LIMIT #{offset}, #{limit}
</select> </select>
<select id="selectSummaryByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoSalesOrderReceivableStatView">
SELECT
COUNT(1) AS `orderCount`,
COALESCE(SUM(o.`sale_amount`), 0) AS `saleAmount`,
COALESCE(SUM(o.`paid_amount`), 0) AS `paidAmount`,
COALESCE(SUM(o.`pending_paid_amount`), 0) AS `pendingPaidAmount`,
COALESCE(SUM(o.`sale_amount` - o.`paid_amount`), 0) AS `unpaidAmount`,
COALESCE(SUM(o.`refunded_amount`), 0) AS `refundedAmount`,
COALESCE(SUM(o.`paid_amount` - o.`refunded_amount`), 0) AS `netPaidAmount`
FROM `gao_sales_order` o LEFT JOIN `gao_customer` c ON c.`id` = o.`customer_id`
WHERE <include refid="queryWhere"/>
</select>
<sql id="customerProductWhere">
i.`deleted_at` IS NULL
AND o.`deleted_at` IS NULL
AND o.`store_id` = #{storeId}
AND o.`status` &lt;&gt; 'CANCELLED'
<if test="customerId != null and customerId != ''">AND o.`customer_id` = #{customerId}</if>
<if test="customerIdList != null and customerIdList.size() &gt; 0">
AND o.`customer_id` IN
<foreach collection="customerIdList" item="customerIdItem" open="(" separator="," close=")">
#{customerIdItem}
</foreach>
</if>
<if test="itemType != null">AND i.`item_type` = #{itemType}</if>
<if test="keyword != null and keyword.trim() != ''">
AND (
c.`name` LIKE CONCAT('%', #{keyword}, '%')
OR c.`code` LIKE CONCAT('%', #{keyword}, '%')
OR o.`order_no` LIKE CONCAT('%', #{keyword}, '%')
OR i.`product_name_snapshot` LIKE CONCAT('%', #{keyword}, '%')
OR i.`sku_name_snapshot` LIKE CONCAT('%', #{keyword}, '%')
OR i.`sku_code_snapshot` LIKE CONCAT('%', #{keyword}, '%')
OR i.`spec_summary_snapshot` LIKE CONCAT('%', #{keyword}, '%')
)
</if>
</sql>
<select id="countCustomerProductCustomerByQuery" resultType="long">
SELECT COUNT(DISTINCT o.`customer_id`)
FROM `gao_sales_order_item` i
JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
LEFT JOIN `gao_customer` c ON c.`id` = o.`customer_id`
WHERE <include refid="customerProductWhere"/>
</select>
<select id="selectCustomerProductCustomerByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerProductCustomerRow">
SELECT o.`customer_id`, c.`code` AS `customer_code`, c.`name` AS `customer_name`, COUNT(DISTINCT o.`id`) AS `order_count`
FROM `gao_sales_order_item` i
JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
LEFT JOIN `gao_customer` c ON c.`id` = o.`customer_id`
WHERE <include refid="customerProductWhere"/>
GROUP BY o.`customer_id`, c.`code`, c.`name`
ORDER BY c.`name` ASC, c.`code` ASC, o.`customer_id` ASC
LIMIT #{offset}, #{limit}
</select>
<select id="selectCustomerProductByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerProductView">
SELECT i.`id`, i.`sales_order_id`, o.`customer_id`, c.`code` AS `customer_code`, c.`name` AS `customer_name`,
o.`order_no`, o.`order_type`, o.`status` AS `order_status`, o.`purchased_at`,
i.`item_type`, i.`gifted`, i.`sku_id`, i.`sku_unit_id`, i.`product_name_snapshot`, i.`product_id_snapshot`,
i.`sku_code_snapshot`, i.`sku_name_snapshot`, i.`spec_summary_snapshot`, i.`unit_snapshot`, base_unit.`name` AS `base_unit_name`,
i.`base_quantity_per_unit_snapshot`, i.`quantity`, i.`base_quantity`, i.`reserved_base_quantity`,
i.`fulfilled_base_quantity`,
COALESCE(i.`base_quantity`, 0) - COALESCE(i.`fulfilled_base_quantity`, 0) AS `remaining_base_quantity`,
COALESCE(i.`base_quantity`, 0) - COALESCE(i.`reserved_base_quantity`, 0) - COALESCE(i.`fulfilled_base_quantity`, 0) AS `available_base_quantity`
FROM `gao_sales_order_item` i
JOIN `gao_sales_order` o ON o.`id` = i.`sales_order_id`
LEFT JOIN `gao_customer` c ON c.`id` = o.`customer_id`
LEFT JOIN `gao_product_sku_unit` base_unit ON base_unit.`sku_id` = i.`sku_id` AND base_unit.`is_base` = 1 AND base_unit.`deleted_at` IS NULL
WHERE <include refid="customerProductWhere"/>
ORDER BY o.`purchased_at` DESC, o.`created_at` DESC, i.`sort` ASC, i.`created_at` ASC
</select>
<update id="updatePayment"> <update id="updatePayment">
UPDATE `gao_sales_order` UPDATE `gao_sales_order`
SET `pending_paid_amount` = #{pendingPaidAmount}, `paid_amount` = #{paidAmount}, `paid_at` = #{paidAt}, `refunded_amount` = #{refundedAmount}, SET `pending_paid_amount` = #{pendingPaidAmount}, `paid_amount` = #{paidAmount}, `paid_at` = #{paidAt}, `refunded_amount` = #{refundedAmount},