diff --git a/pom.xml b/pom.xml
index d4e9dd9..07736aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
com.imyeyu.timiserverapi
TimiServerAPI
- 1.0.31
+ 1.0.33
jar
TimiServerAPI
imyeyu.com API
diff --git a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerConsumptionRecordController.java b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerConsumptionRecordController.java
new file mode 100644
index 0000000..d254066
--- /dev/null
+++ b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerConsumptionRecordController.java
@@ -0,0 +1,39 @@
+package com.imyeyu.api.modules.gao.controller;
+
+import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
+import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
+import com.imyeyu.api.modules.gao.service.GaoCustomerConsumptionRecordService;
+import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPage;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPageResult;
+import com.imyeyu.java.bean.timi.TimiException;
+import com.imyeyu.spring.annotation.AOPLog;
+import com.imyeyu.spring.annotation.RequestRateLimit;
+import lombok.RequiredArgsConstructor;
+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;
+
+/// GAO 客户消费事实接口
+///
+/// @author Codex
+/// @since 2026-09-07
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/gao/customer/consumption-record")
+public class GaoCustomerConsumptionRecordController {
+
+ private final GaoCustomerConsumptionRecordService service;
+ private final GaoStoreScopeService storeScopeService;
+
+ @AOPLog
+ @RequestRateLimit
+ @RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
+ @PostMapping("/list")
+ public GaoCustomerConsumptionRecordPageResult list(@RequestBody GaoCustomerConsumptionRecordPage page) {
+ TimiException.required(page, "not found consumption record page");
+ page.setStoreId(storeScopeService.resolveStoreId(page.getStoreId()));
+ return service.pageByQuery(page);
+ }
+}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/entity/GaoCustomerConsumptionRecord.java b/src/main/java/com/imyeyu/api/modules/gao/entity/GaoCustomerConsumptionRecord.java
index 74d3ff0..2c39508 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/entity/GaoCustomerConsumptionRecord.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/entity/GaoCustomerConsumptionRecord.java
@@ -1,6 +1,7 @@
package com.imyeyu.api.modules.gao.entity;
import com.fasterxml.jackson.databind.JsonNode;
+import com.imyeyu.spring.annotation.table.Transient;
import com.imyeyu.spring.entity.UUIDEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -41,4 +42,8 @@ public class GaoCustomerConsumptionRecord extends UUIDEntity {
private Long revokedAt;
private String revokeReason;
private JsonNode sourcePayload;
+
+ /// 客户
+ @Transient
+ private GaoCustomer customer;
}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerConsumptionRecordMapper.java b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerConsumptionRecordMapper.java
index a9c7261..66c3955 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerConsumptionRecordMapper.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerConsumptionRecordMapper.java
@@ -1,6 +1,7 @@
package com.imyeyu.api.modules.gao.mapper;
import com.imyeyu.api.modules.gao.entity.GaoCustomerConsumptionRecord;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPage;
import com.imyeyu.spring.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
@@ -16,5 +17,11 @@ public interface GaoCustomerConsumptionRecordMapper extends BaseMapper selectActiveByWindow(@Param("storeId") String storeId, @Param("customerId") String customerId, @Param("beginAt") long beginAt, @Param("endAt") long endAt);
+ long countByQuery(GaoCustomerConsumptionRecordPage page);
+
+ Long sumAmountByPage(GaoCustomerConsumptionRecordPage page);
+
+ List selectByQuery(GaoCustomerConsumptionRecordPage page);
+
int revokeBySource(@Param("sourceType") GaoCustomerConsumptionRecord.SourceType sourceType, @Param("sourceId") String sourceId, @Param("revokedAt") long revokedAt, @Param("revokeReason") String revokeReason);
}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerConsumptionRecordService.java b/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerConsumptionRecordService.java
index 8ec9e2e..80b420f 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerConsumptionRecordService.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerConsumptionRecordService.java
@@ -1,6 +1,8 @@
package com.imyeyu.api.modules.gao.service;
import com.imyeyu.api.modules.gao.entity.GaoCustomerConsumptionRecord;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPage;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPageResult;
import com.imyeyu.spring.service.BaseService;
import java.util.List;
@@ -11,6 +13,9 @@ import java.util.List;
/// @since 2026-09-04
public interface GaoCustomerConsumptionRecordService extends BaseService {
+ /// 按条件分页查询消费事实
+ GaoCustomerConsumptionRecordPageResult pageByQuery(GaoCustomerConsumptionRecordPage page);
+
/// 写入销售订单消费事实
///
/// 幂等,重复执行返回已有事实
diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerConsumptionRecordServiceImplement.java b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerConsumptionRecordServiceImplement.java
index 73f9917..ca5ca8a 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerConsumptionRecordServiceImplement.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerConsumptionRecordServiceImplement.java
@@ -4,7 +4,10 @@ import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
import com.imyeyu.api.modules.gao.entity.GaoCustomerConsumptionRecord;
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
import com.imyeyu.api.modules.gao.mapper.GaoCustomerConsumptionRecordMapper;
+import com.imyeyu.api.modules.gao.service.GaoCustomerService;
import com.imyeyu.api.modules.gao.service.GaoCustomerConsumptionRecordService;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPage;
+import com.imyeyu.api.modules.gao.vo.GaoCustomerConsumptionRecordPageResult;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
@@ -24,12 +27,28 @@ import java.util.List;
public class GaoCustomerConsumptionRecordServiceImplement extends AbstractEntityService implements GaoCustomerConsumptionRecordService {
private final GaoCustomerConsumptionRecordMapper mapper;
+ private final GaoCustomerService customerService;
@Override
protected BaseMapper mapper() {
return mapper;
}
+ @Override
+ public GaoCustomerConsumptionRecordPageResult pageByQuery(GaoCustomerConsumptionRecordPage page) {
+ TimiException.required(page, "not found consumption record page");
+ GaoCustomerConsumptionRecordPageResult result = new GaoCustomerConsumptionRecordPageResult();
+ result.setTotal(mapper.countByQuery(page));
+ result.setAmountTotal(mapper.sumAmountByPage(page));
+ List list = mapper.selectByQuery(page);
+ result.setList(list);
+ var customerMap = customerService.mapByIdList(list.stream().map(GaoCustomerConsumptionRecord::getCustomerId).toList());
+ for (GaoCustomerConsumptionRecord record : list) {
+ record.setCustomer(customerMap.get(record.getCustomerId()));
+ }
+ return result;
+ }
+
@Transactional(TimiServerDBConfig.ROLLBACKER)
@Override
public GaoCustomerConsumptionRecord createSalesOrder(String salesOrderId, String storeId, String customerId, Long amount, Long effectiveAt, GaoSalesOrder.OrderType orderType) {
diff --git a/src/main/java/com/imyeyu/api/modules/gao/vo/GaoCustomerConsumptionRecordPage.java b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoCustomerConsumptionRecordPage.java
new file mode 100644
index 0000000..ca44f12
--- /dev/null
+++ b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoCustomerConsumptionRecordPage.java
@@ -0,0 +1,33 @@
+package com.imyeyu.api.modules.gao.vo;
+
+import com.imyeyu.api.modules.gao.entity.GaoCustomerConsumptionRecord;
+import com.imyeyu.java.bean.BasePage;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/// GAO 客户消费事实分页请求
+///
+/// @author Codex
+/// @since 2026-09-07
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class GaoCustomerConsumptionRecordPage extends BasePage {
+
+ /// 门店 ID
+ private String storeId;
+
+ /// 客户 ID
+ private String customerId;
+
+ /// 消费来源
+ private GaoCustomerConsumptionRecord.SourceType sourceType;
+
+ /// 消费状态
+ private GaoCustomerConsumptionRecord.Status status;
+
+ /// 起始生效时间
+ private Long beginAt;
+
+ /// 结束生效时间
+ private Long endAt;
+}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/vo/GaoCustomerConsumptionRecordPageResult.java b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoCustomerConsumptionRecordPageResult.java
new file mode 100644
index 0000000..a5a1ce4
--- /dev/null
+++ b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoCustomerConsumptionRecordPageResult.java
@@ -0,0 +1,18 @@
+package com.imyeyu.api.modules.gao.vo;
+
+import com.imyeyu.api.modules.gao.entity.GaoCustomerConsumptionRecord;
+import com.imyeyu.spring.bean.PageResult;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/// GAO 客户消费事实分页查询结果
+///
+/// @author Codex
+/// @since 2026-09-07
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class GaoCustomerConsumptionRecordPageResult extends PageResult {
+
+ /// 当前筛选条件下的消费金额合计,单位分
+ private Long amountTotal;
+}
diff --git a/src/main/resources/mapper/timi-server/gao/GaoCustomerConsumptionRecordMapper.xml b/src/main/resources/mapper/timi-server/gao/GaoCustomerConsumptionRecordMapper.xml
index 79f092c..0ae75ee 100644
--- a/src/main/resources/mapper/timi-server/gao/GaoCustomerConsumptionRecordMapper.xml
+++ b/src/main/resources/mapper/timi-server/gao/GaoCustomerConsumptionRecordMapper.xml
@@ -12,6 +12,26 @@
AND `effective_at` >= #{beginAt} AND `effective_at` <= #{endAt} AND `deleted_at` IS NULL
ORDER BY `effective_at` ASC, `id` ASC
+
+ r.`deleted_at` IS NULL
+ AND r.`store_id` = #{storeId}
+ AND r.`customer_id` = #{customerId}
+ AND r.`source_type` = #{sourceType}
+ AND r.`status` = #{status}
+ AND r.`effective_at` >= #{beginAt}
+ AND r.`effective_at` <= #{endAt}
+
+
+
+
UPDATE `gao_customer_consumption_record`
SET `status` = 'REVOKED', `revoked_at` = #{revokedAt}, `revoke_reason` = #{revokeReason}, `updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)