feat: add balance and ledger endpoints for tenant

- Implemented MyBalance and MyLedgerPage methods in the ledger service to retrieve current user balance and transaction history for a specified tenant.
- Added corresponding test cases for MyBalance and MyLedgerPage methods in the ledger test suite.
- Created DTOs for balance response and ledger items to structure the response data.
- Updated Swagger documentation to include new endpoints for retrieving tenant balance and ledgers.
- Added HTTP tests for the new endpoints to ensure proper functionality.
This commit is contained in:
2025-12-18 16:24:37 +08:00
parent 435e541dbe
commit 3249e405ac
13 changed files with 990 additions and 33 deletions

View File

@@ -1078,6 +1078,80 @@ const docTemplate = `{
}
}
},
"/t/{tenantCode}/v1/me/balance": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "当前租户余额信息",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.MeBalanceResponse"
}
}
}
}
},
"/t/{tenantCode}/v1/me/ledgers": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "当前租户余额流水(分页)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/requests.Pager"
},
{
"type": "object",
"properties": {
"items": {
"$ref": "#/definitions/dto.MyLedgerItem"
}
}
}
]
}
}
}
}
},
"/t/{tenantCode}/v1/orders": {
"get": {
"consumes": [
@@ -1345,6 +1419,25 @@ const docTemplate = `{
"RoleSuperAdmin"
]
},
"consts.TenantLedgerType": {
"type": "string",
"enum": [
"credit_topup",
"debit_purchase",
"credit_refund",
"freeze",
"unfreeze",
"adjustment"
],
"x-enum-varnames": [
"TenantLedgerTypeCreditTopup",
"TenantLedgerTypeDebitPurchase",
"TenantLedgerTypeCreditRefund",
"TenantLedgerTypeFreeze",
"TenantLedgerTypeUnfreeze",
"TenantLedgerTypeAdjustment"
]
},
"consts.TenantStatus": {
"type": "string",
"enum": [
@@ -1638,6 +1731,31 @@ const docTemplate = `{
}
}
},
"dto.MeBalanceResponse": {
"type": "object",
"properties": {
"balance": {
"description": "Balance 可用余额:可用于购买/消费。",
"type": "integer"
},
"balance_frozen": {
"description": "BalanceFrozen 冻结余额:用于下单冻结/争议期等。",
"type": "integer"
},
"currency": {
"description": "Currency 币种:当前固定 CNY金额单位为分。",
"allOf": [
{
"$ref": "#/definitions/consts.Currency"
}
]
},
"updated_at": {
"description": "UpdatedAt 更新时间:余额变更时更新。",
"type": "string"
}
}
},
"dto.MeResponse": {
"type": "object",
"properties": {
@@ -1667,6 +1785,23 @@ const docTemplate = `{
}
}
},
"dto.MyLedgerItem": {
"type": "object",
"properties": {
"ledger": {
"description": "Ledger 流水记录(租户内隔离)。",
"allOf": [
{
"$ref": "#/definitions/models.TenantLedger"
}
]
},
"type_description": {
"description": "TypeDescription 流水类型中文说明(用于前端展示)。",
"type": "string"
}
}
},
"dto.PurchaseContentForm": {
"type": "object",
"properties": {
@@ -2381,6 +2516,74 @@ const docTemplate = `{
}
}
},
"models.TenantLedger": {
"type": "object",
"properties": {
"amount": {
"description": "流水金额:分/最小货币单位;通常为正数,方向由 type 决定(由业务层约束)",
"type": "integer"
},
"balance_after": {
"description": "变更后可用余额:用于审计与对账回放",
"type": "integer"
},
"balance_before": {
"description": "变更前可用余额:用于审计与对账回放",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now()",
"type": "string"
},
"frozen_after": {
"description": "变更后冻结余额:用于审计与对账回放",
"type": "integer"
},
"frozen_before": {
"description": "变更前冻结余额:用于审计与对账回放",
"type": "integer"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"idempotency_key": {
"description": "幂等键:同一租户同一用户同一业务操作固定;用于防止重复落账(建议由业务层生成)",
"type": "string"
},
"order": {
"$ref": "#/definitions/models.Order"
},
"order_id": {
"description": "关联订单ID购买/退款类流水应关联 orders.id非订单类可为空",
"type": "integer"
},
"remark": {
"description": "备注:业务说明/后台操作原因等;用于审计",
"type": "string"
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段必须与 tenant_users.tenant_id 一致",
"type": "integer"
},
"type": {
"description": "流水类型credit_topup/debit_purchase/credit_refund/freeze/unfreeze/adjustment不同类型决定余额/冻结余额的变更方向",
"allOf": [
{
"$ref": "#/definitions/consts.TenantLedgerType"
}
]
},
"updated_at": {
"description": "更新时间:默认 now()",
"type": "string"
},
"user_id": {
"description": "用户ID余额账户归属用户对应 tenant_users.user_id",
"type": "integer"
}
}
},
"models.TenantUser": {
"type": "object",
"properties": {

View File

@@ -1072,6 +1072,80 @@
}
}
},
"/t/{tenantCode}/v1/me/balance": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "当前租户余额信息",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.MeBalanceResponse"
}
}
}
}
},
"/t/{tenantCode}/v1/me/ledgers": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "当前租户余额流水(分页)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/requests.Pager"
},
{
"type": "object",
"properties": {
"items": {
"$ref": "#/definitions/dto.MyLedgerItem"
}
}
}
]
}
}
}
}
},
"/t/{tenantCode}/v1/orders": {
"get": {
"consumes": [
@@ -1339,6 +1413,25 @@
"RoleSuperAdmin"
]
},
"consts.TenantLedgerType": {
"type": "string",
"enum": [
"credit_topup",
"debit_purchase",
"credit_refund",
"freeze",
"unfreeze",
"adjustment"
],
"x-enum-varnames": [
"TenantLedgerTypeCreditTopup",
"TenantLedgerTypeDebitPurchase",
"TenantLedgerTypeCreditRefund",
"TenantLedgerTypeFreeze",
"TenantLedgerTypeUnfreeze",
"TenantLedgerTypeAdjustment"
]
},
"consts.TenantStatus": {
"type": "string",
"enum": [
@@ -1632,6 +1725,31 @@
}
}
},
"dto.MeBalanceResponse": {
"type": "object",
"properties": {
"balance": {
"description": "Balance 可用余额:可用于购买/消费。",
"type": "integer"
},
"balance_frozen": {
"description": "BalanceFrozen 冻结余额:用于下单冻结/争议期等。",
"type": "integer"
},
"currency": {
"description": "Currency 币种:当前固定 CNY金额单位为分。",
"allOf": [
{
"$ref": "#/definitions/consts.Currency"
}
]
},
"updated_at": {
"description": "UpdatedAt 更新时间:余额变更时更新。",
"type": "string"
}
}
},
"dto.MeResponse": {
"type": "object",
"properties": {
@@ -1661,6 +1779,23 @@
}
}
},
"dto.MyLedgerItem": {
"type": "object",
"properties": {
"ledger": {
"description": "Ledger 流水记录(租户内隔离)。",
"allOf": [
{
"$ref": "#/definitions/models.TenantLedger"
}
]
},
"type_description": {
"description": "TypeDescription 流水类型中文说明(用于前端展示)。",
"type": "string"
}
}
},
"dto.PurchaseContentForm": {
"type": "object",
"properties": {
@@ -2375,6 +2510,74 @@
}
}
},
"models.TenantLedger": {
"type": "object",
"properties": {
"amount": {
"description": "流水金额:分/最小货币单位;通常为正数,方向由 type 决定(由业务层约束)",
"type": "integer"
},
"balance_after": {
"description": "变更后可用余额:用于审计与对账回放",
"type": "integer"
},
"balance_before": {
"description": "变更前可用余额:用于审计与对账回放",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now()",
"type": "string"
},
"frozen_after": {
"description": "变更后冻结余额:用于审计与对账回放",
"type": "integer"
},
"frozen_before": {
"description": "变更前冻结余额:用于审计与对账回放",
"type": "integer"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"idempotency_key": {
"description": "幂等键:同一租户同一用户同一业务操作固定;用于防止重复落账(建议由业务层生成)",
"type": "string"
},
"order": {
"$ref": "#/definitions/models.Order"
},
"order_id": {
"description": "关联订单ID购买/退款类流水应关联 orders.id非订单类可为空",
"type": "integer"
},
"remark": {
"description": "备注:业务说明/后台操作原因等;用于审计",
"type": "string"
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段必须与 tenant_users.tenant_id 一致",
"type": "integer"
},
"type": {
"description": "流水类型credit_topup/debit_purchase/credit_refund/freeze/unfreeze/adjustment不同类型决定余额/冻结余额的变更方向",
"allOf": [
{
"$ref": "#/definitions/consts.TenantLedgerType"
}
]
},
"updated_at": {
"description": "更新时间:默认 now()",
"type": "string"
},
"user_id": {
"description": "用户ID余额账户归属用户对应 tenant_users.user_id",
"type": "integer"
}
}
},
"models.TenantUser": {
"type": "object",
"properties": {

View File

@@ -116,6 +116,22 @@ definitions:
x-enum-varnames:
- RoleUser
- RoleSuperAdmin
consts.TenantLedgerType:
enum:
- credit_topup
- debit_purchase
- credit_refund
- freeze
- unfreeze
- adjustment
type: string
x-enum-varnames:
- TenantLedgerTypeCreditTopup
- TenantLedgerTypeDebitPurchase
- TenantLedgerTypeCreditRefund
- TenantLedgerTypeFreeze
- TenantLedgerTypeUnfreeze
- TenantLedgerTypeAdjustment
consts.TenantStatus:
enum:
- pending_verify
@@ -317,6 +333,22 @@ definitions:
token:
type: string
type: object
dto.MeBalanceResponse:
properties:
balance:
description: Balance 可用余额:可用于购买/消费。
type: integer
balance_frozen:
description: BalanceFrozen 冻结余额:用于下单冻结/争议期等。
type: integer
currency:
allOf:
- $ref: '#/definitions/consts.Currency'
description: Currency 币种:当前固定 CNY金额单位为分
updated_at:
description: UpdatedAt 更新时间:余额变更时更新。
type: string
type: object
dto.MeResponse:
properties:
tenant:
@@ -333,6 +365,16 @@ definitions:
- $ref: '#/definitions/models.User'
description: User is the authenticated user derived from JWT `user_id`.
type: object
dto.MyLedgerItem:
properties:
ledger:
allOf:
- $ref: '#/definitions/models.TenantLedger'
description: Ledger 流水记录(租户内隔离)。
type_description:
description: TypeDescription 流水类型中文说明(用于前端展示)。
type: string
type: object
dto.PurchaseContentForm:
properties:
idempotency_key:
@@ -809,6 +851,54 @@ definitions:
uuid:
type: string
type: object
models.TenantLedger:
properties:
amount:
description: 流水金额:分/最小货币单位;通常为正数,方向由 type 决定(由业务层约束)
type: integer
balance_after:
description: 变更后可用余额:用于审计与对账回放
type: integer
balance_before:
description: 变更前可用余额:用于审计与对账回放
type: integer
created_at:
description: 创建时间:默认 now()
type: string
frozen_after:
description: 变更后冻结余额:用于审计与对账回放
type: integer
frozen_before:
description: 变更前冻结余额:用于审计与对账回放
type: integer
id:
description: 主键ID自增
type: integer
idempotency_key:
description: 幂等键:同一租户同一用户同一业务操作固定;用于防止重复落账(建议由业务层生成)
type: string
order:
$ref: '#/definitions/models.Order'
order_id:
description: 关联订单ID购买/退款类流水应关联 orders.id非订单类可为空
type: integer
remark:
description: 备注:业务说明/后台操作原因等;用于审计
type: string
tenant_id:
description: 租户ID多租户隔离关键字段必须与 tenant_users.tenant_id 一致
type: integer
type:
allOf:
- $ref: '#/definitions/consts.TenantLedgerType'
description: 流水类型credit_topup/debit_purchase/credit_refund/freeze/unfreeze/adjustment不同类型决定余额/冻结余额的变更方向
updated_at:
description: 更新时间:默认 now()
type: string
user_id:
description: 用户ID余额账户归属用户对应 tenant_users.user_id
type: integer
type: object
models.TenantUser:
properties:
balance:
@@ -1600,6 +1690,51 @@ paths:
summary: 当前租户上下文信息
tags:
- Tenant
/t/{tenantCode}/v1/me/balance:
get:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/dto.MeBalanceResponse'
summary: 当前租户余额信息
tags:
- Tenant
/t/{tenantCode}/v1/me/ledgers:
get:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/requests.Pager'
- properties:
items:
$ref: '#/definitions/dto.MyLedgerItem'
type: object
summary: 当前租户余额流水(分页)
tags:
- Tenant
/t/{tenantCode}/v1/orders:
get:
consumes: