add gao point

This commit is contained in:
Timi
2026-08-11 23:57:59 +08:00
parent 39ac73dc66
commit c6157db0de
26 changed files with 1534 additions and 1 deletions
@@ -0,0 +1,72 @@
CREATE TABLE IF NOT EXISTS `gao_point_account` (
`id` VARCHAR(36) NOT NULL,
`store_id` VARCHAR(36) NOT NULL COMMENT '门店 ID',
`customer_id` VARCHAR(36) NOT NULL COMMENT '客户 ID',
`active_customer_id` VARCHAR(36) GENERATED ALWAYS AS (
CASE WHEN `deleted_at` IS NULL THEN `customer_id` END
) STORED COMMENT '未删除客户 ID' INVISIBLE,
`balance` BIGINT NOT NULL DEFAULT 0 COMMENT '当前可用积分余额',
`total_earned` BIGINT NOT NULL DEFAULT 0 COMMENT '累计获得积分',
`total_revoked` BIGINT NOT NULL DEFAULT 0 COMMENT '累计撤销积分',
`total_adjusted` BIGINT NOT NULL DEFAULT 0 COMMENT '累计人工调整积分',
`version` BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
`created_at` BIGINT NOT NULL,
`updated_at` BIGINT NULL,
`deleted_at` BIGINT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_gao_point_account_customer` (`store_id`, `active_customer_id`),
KEY `idx_gao_point_account_customer_id` (`customer_id`),
KEY `idx_gao_point_account_store_balance` (`store_id`, `deleted_at`, `balance`)
) COMMENT='GAO 客户积分账户';
CREATE TABLE IF NOT EXISTS `gao_point_rule` (
`id` VARCHAR(36) NOT NULL,
`store_id` VARCHAR(36) NOT NULL COMMENT '门店 ID',
`event_id` VARCHAR(36) NOT NULL COMMENT '登记事件 ID',
`name` VARCHAR(64) NOT NULL COMMENT '规则名称',
`status` VARCHAR(32) NOT NULL COMMENT '规则状态',
`trigger_type` VARCHAR(32) NOT NULL COMMENT '触发类型',
`point_mode` VARCHAR(32) NOT NULL COMMENT '积分值模式',
`point_value` BIGINT NULL COMMENT '固定积分值',
`condition_json` JSON NULL COMMENT '条件配置',
`begin_at` BIGINT NULL COMMENT '生效开始时间戳,毫秒',
`end_at` BIGINT NULL COMMENT '生效结束时间戳,毫秒',
`priority` INT NOT NULL DEFAULT 0 COMMENT '优先级,数值小优先',
`exclusive` BIT(1) NOT NULL DEFAULT b'0' COMMENT 'true 为命中后停止继续匹配后续规则',
`remark` TEXT NULL COMMENT '备注',
`created_at` BIGINT NOT NULL,
`updated_at` BIGINT NULL,
`deleted_at` BIGINT NULL,
PRIMARY KEY (`id`),
KEY `idx_gao_point_rule_match` (`store_id`, `event_id`, `status`, `deleted_at`, `priority`),
KEY `idx_gao_point_rule_type` (`trigger_type`, `point_mode`)
) COMMENT='GAO 客户积分规则';
CREATE TABLE IF NOT EXISTS `gao_point_ledger` (
`id` VARCHAR(36) NOT NULL,
`account_id` VARCHAR(36) NOT NULL COMMENT '客户积分账户 ID',
`store_id` VARCHAR(36) NOT NULL COMMENT '门店 ID',
`customer_id` VARCHAR(36) NOT NULL COMMENT '客户 ID',
`change_type` VARCHAR(32) NOT NULL COMMENT '变化类型',
`direction` VARCHAR(16) NOT NULL COMMENT '方向',
`point_delta` BIGINT NOT NULL COMMENT '本次变化积分,增加为正,减少为负',
`balance_before` BIGINT NOT NULL COMMENT '变化前余额',
`balance_after` BIGINT NOT NULL COMMENT '变化后余额',
`rule_id` VARCHAR(36) NULL COMMENT '积分规则 ID',
`event_id` VARCHAR(36) NULL COMMENT '登记事件 ID',
`event_record_id` VARCHAR(36) NULL COMMENT '登记记录 ID',
`source_payload` JSON NULL COMMENT '来源快照',
`idempotency_key` VARCHAR(128) NOT NULL COMMENT '幂等键',
`remark` TEXT NULL COMMENT '备注',
`operator_user_id` VARCHAR(36) NULL COMMENT '操作用户 ID',
`occurred_at` BIGINT NOT NULL COMMENT '发生时间',
`created_at` BIGINT NOT NULL,
`updated_at` BIGINT NULL,
`deleted_at` BIGINT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_gao_point_ledger_idempotency` (`idempotency_key`),
KEY `idx_gao_point_ledger_account_time` (`account_id`, `deleted_at`, `occurred_at`),
KEY `idx_gao_point_ledger_customer_time` (`store_id`, `customer_id`, `deleted_at`, `occurred_at`),
KEY `idx_gao_point_ledger_event_record` (`event_record_id`, `change_type`),
KEY `idx_gao_point_ledger_rule_time` (`rule_id`, `occurred_at`)
) COMMENT='GAO 客户积分流水';
@@ -0,0 +1,44 @@
<?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.GaoPointAccountMapper">
<select id="selectByStoreIdAndCustomerId" resultType="com.imyeyu.api.modules.gao.entity.GaoPointAccount">
SELECT *
FROM `gao_point_account`
WHERE `store_id` = #{storeId}
AND `customer_id` = #{customerId}
AND `deleted_at` IS NULL
LIMIT 1
</select>
<insert id="insertIfAbsent">
INSERT INTO `gao_point_account` (
`id`, `store_id`, `customer_id`, `balance`, `total_earned`, `total_revoked`, `total_adjusted`, `version`, `created_at`, `updated_at`, `deleted_at`
) VALUES (
#{account.id}, #{account.storeId}, #{account.customerId}, #{account.balance}, #{account.totalEarned}, #{account.totalRevoked}, #{account.totalAdjusted}, #{account.version}, #{account.createdAt}, #{account.updatedAt}, #{account.deletedAt}
)
ON DUPLICATE KEY UPDATE `id` = `id`
</insert>
<select id="selectForUpdate" resultType="com.imyeyu.api.modules.gao.entity.GaoPointAccount">
SELECT *
FROM `gao_point_account`
WHERE `id` = #{id}
AND `deleted_at` IS NULL
LIMIT 1
FOR UPDATE
</select>
<update id="updateBalance">
UPDATE `gao_point_account`
SET
`balance` = `balance` + #{delta},
`total_earned` = `total_earned` + #{totalEarnedDelta},
`total_revoked` = `total_revoked` + #{totalRevokedDelta},
`total_adjusted` = `total_adjusted` + #{totalAdjustedDelta},
`version` = `version` + 1,
`updated_at` = #{updatedAt}
WHERE `id` = #{id}
AND `balance` + #{delta} &gt;= 0
AND `deleted_at` IS NULL
</update>
</mapper>
@@ -0,0 +1,68 @@
<?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.GaoPointLedgerMapper">
<select id="selectByIdempotencyKey" resultType="com.imyeyu.api.modules.gao.entity.GaoPointLedger">
SELECT *
FROM `gao_point_ledger`
WHERE `idempotency_key` = #{idempotencyKey}
AND `deleted_at` IS NULL
LIMIT 1
</select>
<select id="selectEarnByEventRecordId" resultType="com.imyeyu.api.modules.gao.entity.GaoPointLedger">
SELECT *
FROM `gao_point_ledger`
WHERE `event_record_id` = #{eventRecordId}
AND `change_type` = 'EARN'
AND `deleted_at` IS NULL
ORDER BY `created_at` ASC, `id` ASC
</select>
<select id="selectByIdempotencyKeyList" resultType="com.imyeyu.api.modules.gao.entity.GaoPointLedger">
SELECT *
FROM `gao_point_ledger`
WHERE `deleted_at` IS NULL
AND `idempotency_key` IN
<foreach collection="idempotencyKeyList" item="idempotencyKey" open="(" separator="," close=")">
#{idempotencyKey}
</foreach>
</select>
<sql id="queryWhere">
`deleted_at` IS NULL
<if test="storeId != null and storeId != ''">
AND `store_id` = #{storeId}
</if>
<if test="customerId != null and customerId != ''">
AND `customer_id` = #{customerId}
</if>
<if test="accountId != null and accountId != ''">
AND `account_id` = #{accountId}
</if>
<if test="changeType != null">
AND `change_type` = #{changeType}
</if>
<if test="beginAt != null">
AND `occurred_at` &gt;= #{beginAt}
</if>
<if test="endAt != null">
AND `occurred_at` &lt;= #{endAt}
</if>
</sql>
<select id="countByQuery" resultType="long">
SELECT COUNT(1)
FROM `gao_point_ledger`
WHERE
<include refid="queryWhere"/>
</select>
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoPointLedger">
SELECT *
FROM `gao_point_ledger`
WHERE
<include refid="queryWhere"/>
ORDER BY `occurred_at` DESC, `created_at` DESC
LIMIT #{offset}, #{limit}
</select>
</mapper>
@@ -0,0 +1,15 @@
<?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.GaoPointRuleMapper">
<select id="selectActiveByStoreIdAndEventId" resultType="com.imyeyu.api.modules.gao.entity.GaoPointRule">
SELECT *
FROM `gao_point_rule`
WHERE `store_id` = #{storeId}
AND `event_id` = #{eventId}
AND `status` = 'ACTIVE'
AND (`begin_at` IS NULL OR `begin_at` &lt;= #{now})
AND (`end_at` IS NULL OR #{now} &lt;= `end_at`)
AND `deleted_at` IS NULL
ORDER BY `priority` ASC, `created_at` ASC, `id` ASC
</select>
</mapper>