chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.credit.infra.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("credit_flow")
public class CreditFlow {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private String batchNo;
private Integer creditType;
private Integer operationType;
private BigDecimal amount;
private BigDecimal beforeAmount;
private BigDecimal afterAmount;
private String bizNo;
private Date created;
private String remark;
}

View File

@@ -0,0 +1,41 @@
package com.xspaceagi.credit.infra.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("credit_package")
public class CreditPackage {
@TableId(type = IdType.AUTO)
private Long id;
private String packageName;
private BigDecimal creditAmount;
private BigDecimal price;
private Integer sort;
private Integer status;
private Date created;
private Integer period;
private Date modified;
private String remark;
}

View File

@@ -0,0 +1,51 @@
package com.xspaceagi.credit.infra.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("user_credit")
public class UserCredit {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private String batchNo;
private Integer creditType;
private BigDecimal totalAmount;
private BigDecimal usedAmount;
private BigDecimal remainAmount;
private Date expireTime;
private Date created;
private Date modified;
private BigDecimal repaidAmount;
private Integer repayStatus;
private String remark;
private Integer version;
private String extra;
}

View File

@@ -0,0 +1,34 @@
package com.xspaceagi.credit.infra.dao.mapper;
import com.xspaceagi.credit.infra.dao.entity.CreditFlow;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CreditFlowMapper {
int insert(CreditFlow creditFlow);
int batchInsert(@Param("list") List<CreditFlow> list);
/**
* 获取用户指定类型的前N条流水记录按ID降序
*/
List<CreditFlow> selectByUserIdAndType(@Param("userId") Long userId,
@Param("creditType") Integer creditType,
@Param("limit") Integer limit);
/**
* 获取用户指定类型且ID小于指定值的流水记录用于分页
*/
List<CreditFlow> selectByUserIdAndTypeWithOffset(@Param("userId") Long userId,
@Param("creditType") Integer creditType,
@Param("lastId") Long lastId,
@Param("limit") Integer limit);
CreditFlow selectByBizNo(@Param("bizNo") String bizNo, @Param("operationType") Integer operationType);
int countByUserId(@Param("userId") Long userId);
}

View File

@@ -0,0 +1,21 @@
package com.xspaceagi.credit.infra.dao.mapper;
import com.xspaceagi.credit.infra.dao.entity.CreditPackage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CreditPackageMapper {
int insert(CreditPackage creditPackage);
int updateById(CreditPackage creditPackage);
int deleteById(@Param("id") Long id);
CreditPackage selectById(@Param("id") Long id);
List<CreditPackage> selectList(@Param("status") Integer status);
}

View File

@@ -0,0 +1,72 @@
package com.xspaceagi.credit.infra.dao.mapper;
import com.xspaceagi.credit.infra.dao.entity.UserCredit;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Mapper
public interface UserCreditMapper {
int insert(UserCredit userCredit);
int updateById(UserCredit userCredit);
UserCredit selectById(@Param("id") Long id);
UserCredit selectByBatchNo(@Param("batchNo") String batchNo);
List<UserCredit> selectByUserId(@Param("userId") Long userId);
List<UserCredit> selectByUserIdAndType(@Param("userId") Long userId, @Param("creditType") Integer creditType);
List<UserCredit> selectExpiredCredits(@Param("userId") Long userId, @Param("creditType") Integer creditType);
List<UserCredit> selectValidCredits(@Param("userId") Long userId, @Param("creditType") Integer creditType);
List<UserCredit> selectValidCreditsOrderByExpireTime(@Param("userId") Long userId);
BigDecimal sumRemainAmountByUserId(@Param("userId") Long userId);
BigDecimal sumRemainAmountByUserIdAndType(@Param("userId") Long userId, @Param("creditType") Integer creditType);
/**
* 带乐观锁的余额更新使用version字段保证原子性
*/
@Update("UPDATE user_credit " +
"SET remain_amount = remain_amount - #{deductAmount}, " +
" used_amount = used_amount + #{deductAmount}, " +
" version = version + 1, " +
" modified = NOW() " +
"WHERE id = #{id} AND remain_amount >= #{deductAmount} AND version = #{version}")
int updateRemainAmountWithVersion(@Param("id") Long id,
@Param("deductAmount") BigDecimal deductAmount,
@Param("version") Integer version);
List<java.util.Map<String, Object>> selectSummaryList(@Param("userId") Long userId, @Param("offset") Integer offset, @Param("limit") Integer limit);
Long countSummaryList(@Param("userId") Long userId);
List<UserCredit> selectUnpaidLoans(@Param("userId") Long userId);
int updateRepayAmount(@Param("id") Long id,
@Param("repayAmount") BigDecimal repayAmount,
@Param("repayStatus") Integer repayStatus,
@Param("version") Integer version);
/**
* 获取指定时间内即将过期的积分数量
*/
@Select("SELECT COALESCE(SUM(remain_amount), 0) FROM user_credit " +
"WHERE user_id = #{userId} " +
"AND expire_time IS NOT NULL " +
"AND expire_time <= #{expireDate} " +
"AND expire_time > NOW()")
BigDecimal sumExpiringCredits(@Param("userId") Long userId, @Param("expireDate") Date expireDate);
}

View File

@@ -0,0 +1,65 @@
<?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.xspaceagi.credit.infra.dao.mapper.CreditFlowMapper">
<resultMap id="BaseResultMap" type="com.xspaceagi.credit.infra.dao.entity.CreditFlow">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="batch_no" property="batchNo"/>
<result column="credit_type" property="creditType"/>
<result column="operation_type" property="operationType"/>
<result column="amount" property="amount"/>
<result column="before_amount" property="beforeAmount"/>
<result column="after_amount" property="afterAmount"/>
<result column="biz_no" property="bizNo"/>
<result column="created" property="created"/>
<result column="remark" property="remark"/>
</resultMap>
<insert id="insert" parameterType="com.xspaceagi.credit.infra.dao.entity.CreditFlow" useGeneratedKeys="true" keyProperty="id">
INSERT INTO credit_flow (user_id, batch_no, credit_type, operation_type, amount, before_amount, after_amount, biz_no, remark)
VALUES (#{userId}, #{batchNo}, #{creditType}, #{operationType}, #{amount}, #{beforeAmount}, #{afterAmount}, #{bizNo}, #{remark})
</insert>
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO credit_flow (user_id, batch_no, credit_type, operation_type, amount, before_amount, after_amount, biz_no, remark)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.userId}, #{item.batchNo}, #{item.creditType}, #{item.operationType}, #{item.amount}, #{item.beforeAmount}, #{item.afterAmount}, #{item.bizNo}, #{item.remark})
</foreach>
</insert>
<select id="selectById" resultMap="BaseResultMap">
SELECT * FROM credit_flow WHERE id = #{id}
</select>
<select id="selectByUserIdAndType" resultMap="BaseResultMap">
SELECT * FROM credit_flow
WHERE user_id = #{userId}
<if test="creditType != null">AND credit_type = #{creditType}</if>
ORDER BY id DESC
LIMIT #{limit}
</select>
<select id="selectByUserIdAndTypeWithOffset" resultMap="BaseResultMap">
SELECT * FROM credit_flow
WHERE user_id = #{userId}
<if test="creditType != null">AND credit_type = #{creditType}</if>
AND id &lt; #{lastId}
ORDER BY id DESC
LIMIT #{limit}
</select>
<select id="selectByBizNo" resultMap="BaseResultMap">
SELECT * FROM credit_flow WHERE biz_no = #{bizNo} AND operation_type = #{operationType} LIMIT 1
</select>
<select id="countByUserId" resultType="int">
SELECT COUNT(*) FROM credit_flow WHERE user_id = #{userId}
</select>
<select id="countByUserIdAndType" resultType="int">
SELECT COUNT(*) FROM credit_flow WHERE user_id = #{userId} AND credit_type = #{creditType}
</select>
</mapper>

View File

@@ -0,0 +1,53 @@
<?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.xspaceagi.credit.infra.dao.mapper.CreditPackageMapper">
<resultMap id="BaseResultMap" type="com.xspaceagi.credit.infra.dao.entity.CreditPackage">
<id column="id" property="id"/>
<result column="package_name" property="packageName"/>
<result column="credit_amount" property="creditAmount"/>
<result column="price" property="price"/>
<result column="sort" property="sort"/>
<result column="status" property="status"/>
<result column="period" property="period"/>
<result column="created" property="created"/>
<result column="modified" property="modified"/>
<result column="remark" property="remark"/>
</resultMap>
<insert id="insert" parameterType="com.xspaceagi.credit.infra.dao.entity.CreditPackage" useGeneratedKeys="true" keyProperty="id">
INSERT INTO credit_package (package_name, credit_amount, price, sort, status, period, remark)
VALUES (#{packageName}, #{creditAmount}, #{price}, #{sort}, #{status}, #{period}, #{remark})
</insert>
<update id="updateById" parameterType="com.xspaceagi.credit.infra.dao.entity.CreditPackage">
UPDATE credit_package
<set>
<if test="packageName != null">package_name = #{packageName},</if>
<if test="creditAmount != null">credit_amount = #{creditAmount},</if>
<if test="price != null">price = #{price},</if>
<if test="sort != null">sort = #{sort},</if>
<if test="status != null">status = #{status},</if>
<if test="period != null">period = #{period},</if>
<if test="remark != null">remark = #{remark},</if>
</set>
WHERE id = #{id}
</update>
<delete id="deleteById">
DELETE FROM credit_package WHERE id = #{id}
</delete>
<select id="selectById" resultMap="BaseResultMap">
SELECT * FROM credit_package WHERE id = #{id}
</select>
<select id="selectList" resultMap="BaseResultMap">
SELECT * FROM credit_package
<where>
<if test="status != null">AND status = #{status}</if>
</where>
ORDER BY sort ASC, id DESC
</select>
</mapper>

View File

@@ -0,0 +1,153 @@
<?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.xspaceagi.credit.infra.dao.mapper.UserCreditMapper">
<resultMap id="BaseResultMap" type="com.xspaceagi.credit.infra.dao.entity.UserCredit">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="batch_no" property="batchNo"/>
<result column="credit_type" property="creditType"/>
<result column="total_amount" property="totalAmount"/>
<result column="used_amount" property="usedAmount"/>
<result column="remain_amount" property="remainAmount"/>
<result column="expire_time" property="expireTime"/>
<result column="created" property="created"/>
<result column="modified" property="modified"/>
<result column="version" property="version"/>
<result column="repaid_amount" property="repaidAmount"/>
<result column="repay_status" property="repayStatus"/>
<result column="remark" property="remark"/>
<result column="extra" property="extra"/>
</resultMap>
<insert id="insert" parameterType="com.xspaceagi.credit.infra.dao.entity.UserCredit" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user_credit (user_id, batch_no, credit_type, total_amount, used_amount, remain_amount, expire_time, repaid_amount, repay_status, version, remark, extra)
VALUES (#{userId}, #{batchNo}, #{creditType}, #{totalAmount}, #{usedAmount}, #{remainAmount}, #{expireTime}, #{repaidAmount}, #{repayStatus}, 1, #{remark}, #{extra})
</insert>
<update id="updateById" parameterType="com.xspaceagi.credit.infra.dao.entity.UserCredit">
UPDATE user_credit
<set>
<if test="usedAmount != null">used_amount = #{usedAmount},</if>
<if test="remainAmount != null">remain_amount = #{remainAmount},</if>
<if test="remark != null">remark = #{remark},</if>
</set>
WHERE id = #{id}
</update>
<update id="updateRemainAmount">
UPDATE user_credit
SET used_amount = used_amount + #{deductAmount},
remain_amount = remain_amount - #{deductAmount}
WHERE id = #{id} AND remain_amount >= #{deductAmount}
</update>
<select id="selectById" resultMap="BaseResultMap">
SELECT * FROM user_credit WHERE id = #{id}
</select>
<select id="selectByBatchNo" resultMap="BaseResultMap">
SELECT * FROM user_credit WHERE batch_no = #{batchNo} LIMIT 1
</select>
<select id="selectByUserId" resultMap="BaseResultMap">
SELECT * FROM user_credit WHERE user_id = #{userId} ORDER BY created DESC
</select>
<select id="selectByUserIdAndType" resultMap="BaseResultMap">
SELECT * FROM user_credit WHERE user_id = #{userId} AND credit_type = #{creditType} ORDER BY created DESC
</select>
<select id="selectExpiredCredits" resultMap="BaseResultMap">
SELECT * FROM user_credit
WHERE user_id = #{userId}
<if test="creditType != null">AND credit_type = #{creditType}</if>
AND expire_time IS NOT NULL
AND expire_time &lt; NOW()
AND remain_amount &gt; 0
ORDER BY expire_time ASC
</select>
<select id="selectValidCredits" resultMap="BaseResultMap">
SELECT * FROM user_credit
WHERE user_id = #{userId}
<if test="creditType != null">AND credit_type = #{creditType}</if>
AND remain_amount &gt; 0
AND (expire_time IS NULL OR expire_time &gt; NOW())
ORDER BY
CASE WHEN expire_time IS NULL THEN 1 ELSE 0 END,
expire_time ASC
</select>
<select id="selectValidCreditsOrderByExpireTime" resultMap="BaseResultMap">
SELECT * FROM user_credit
WHERE user_id = #{userId}
AND (expire_time IS NULL OR expire_time &gt; NOW())
AND remain_amount &gt; 0
ORDER BY
CASE WHEN expire_time IS NULL THEN 0 ELSE 1 END,
expire_time ASC,
created ASC
</select>
<select id="sumRemainAmountByUserId" resultType="java.math.BigDecimal">
SELECT COALESCE(SUM(remain_amount), 0) + COALESCE(SUM(CASE WHEN credit_type = 5 THEN repaid_amount - total_amount ELSE 0 END), 0)
FROM user_credit
WHERE user_id = #{userId}
AND (remain_amount &gt; 0 OR (credit_type = 5 AND repaid_amount &lt; total_amount))
AND (expire_time IS NULL OR expire_time &gt; NOW())
</select>
<select id="sumRemainAmountByUserIdAndType" resultType="java.math.BigDecimal">
SELECT COALESCE(SUM(remain_amount), 0)
FROM user_credit
WHERE user_id = #{userId}
AND credit_type = #{creditType}
AND remain_amount &gt; 0
AND (expire_time IS NULL OR expire_time &gt; NOW())
</select>
<select id="selectSummaryList" resultType="java.util.HashMap">
SELECT
user_id,
COALESCE(SUM(remain_amount), 0) + COALESCE(SUM(CASE WHEN credit_type = 5 THEN repaid_amount - total_amount ELSE 0 END), 0) AS totalCredit,
COALESCE(SUM(CASE WHEN credit_type = 1 THEN remain_amount ELSE 0 END), 0) AS subscriptionCredit,
COALESCE(SUM(CASE WHEN credit_type = 2 THEN remain_amount ELSE 0 END), 0) AS purchaseCredit,
COALESCE(SUM(CASE WHEN credit_type = 3 THEN remain_amount ELSE 0 END), 0) AS activityCredit,
COALESCE(SUM(CASE WHEN credit_type = 4 THEN remain_amount ELSE 0 END), 0) AS manualCredit
FROM user_credit
WHERE (remain_amount &gt; 0 OR (credit_type = 5 AND repaid_amount &lt; total_amount))
AND (expire_time IS NULL OR expire_time &gt; NOW())
<if test="userId != null">AND user_id = #{userId}</if>
GROUP BY user_id
ORDER BY user_id ASC
LIMIT #{offset}, #{limit}
</select>
<select id="countSummaryList" resultType="java.lang.Long">
SELECT COUNT(DISTINCT user_id)
FROM user_credit
WHERE (remain_amount &gt; 0 OR (credit_type = 5 AND repaid_amount &lt; total_amount))
AND (expire_time IS NULL OR expire_time &gt; NOW())
<if test="userId != null">AND user_id = #{userId}</if>
</select>
<select id="selectUnpaidLoans" resultMap="BaseResultMap">
SELECT * FROM user_credit
WHERE user_id = #{userId}
AND credit_type = 5
AND total_amount &gt; repaid_amount
AND repay_status = 0
ORDER BY created ASC
</select>
<update id="updateRepayAmount">
UPDATE user_credit
SET repaid_amount = repaid_amount + #{repayAmount},
repay_status = #{repayStatus},
version = version + 1,
modified = NOW()
WHERE id = #{id} AND version = #{version}
</update>
</mapper>