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

@@ -3,6 +3,7 @@ package services
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"testing"
@@ -78,13 +79,13 @@ func (s *OrderTestSuite) seedPublishedContent(ctx context.Context, tenantID, own
func (s *OrderTestSuite) seedContentPrice(ctx context.Context, tenantID, contentID, priceAmount int64) {
p := &models.ContentPrice{
TenantID: tenantID,
UserID: 1,
ContentID: contentID,
Currency: consts.CurrencyCNY,
PriceAmount: priceAmount,
DiscountType: consts.DiscountTypeNone,
DiscountValue: 0,
TenantID: tenantID,
UserID: 1,
ContentID: contentID,
Currency: consts.CurrencyCNY,
PriceAmount: priceAmount,
DiscountType: consts.DiscountTypeNone,
DiscountValue: 0,
DiscountStartAt: time.Time{},
DiscountEndAt: time.Time{},
}
@@ -141,6 +142,12 @@ func (s *OrderTestSuite) Test_AdminTopupUser() {
So(orderModel.Status, ShouldEqual, consts.OrderStatusPaid)
So(orderModel.AmountPaid, ShouldEqual, 300)
var snap map[string]any
So(json.Unmarshal([]byte(orderModel.Snapshot), &snap), ShouldBeNil)
So(snap["operator_user_id"], ShouldEqual, float64(operatorUserID))
So(snap["target_user_id"], ShouldEqual, float64(targetUserID))
So(snap["amount"], ShouldEqual, float64(300))
var tu models.TenantUser
So(_db.WithContext(ctx).Where("tenant_id = ? AND user_id = ?", tenantID, targetUserID).First(&tu).Error, ShouldBeNil)
So(tu.Balance, ShouldEqual, 300)
@@ -360,14 +367,14 @@ func (s *OrderTestSuite) Test_AdminRefundOrder() {
So(item.Create(ctx), ShouldBeNil)
access := &models.ContentAccess{
TenantID: tenantID,
UserID: buyerUserID,
ContentID: contentID,
OrderID: orderModel.ID,
Status: consts.ContentAccessStatusActive,
CreatedAt: now,
UpdatedAt: now,
RevokedAt: time.Time{},
TenantID: tenantID,
UserID: buyerUserID,
ContentID: contentID,
OrderID: orderModel.ID,
Status: consts.ContentAccessStatusActive,
CreatedAt: now,
UpdatedAt: now,
RevokedAt: time.Time{},
}
So(access.Create(ctx), ShouldBeNil)
@@ -477,6 +484,12 @@ func (s *OrderTestSuite) Test_PurchaseContent() {
So(res1.Access, ShouldNotBeNil)
So(res1.Access.Status, ShouldEqual, consts.ContentAccessStatusActive)
var snap map[string]any
So(json.Unmarshal([]byte(res1.Order.Snapshot), &snap), ShouldBeNil)
So(snap["content_id"], ShouldEqual, float64(content.ID))
So(snap["content_title"], ShouldEqual, content.Title)
So(snap["amount_paid"], ShouldEqual, float64(0))
res2, err := Order.PurchaseContent(ctx, &PurchaseContentParams{
TenantID: tenantID,
UserID: buyerUserID,
@@ -518,6 +531,17 @@ func (s *OrderTestSuite) Test_PurchaseContent() {
So(res1.Access, ShouldNotBeNil)
So(res1.Access.Status, ShouldEqual, consts.ContentAccessStatusActive)
var snap map[string]any
So(json.Unmarshal([]byte(res1.Order.Snapshot), &snap), ShouldBeNil)
So(snap["content_id"], ShouldEqual, float64(content.ID))
So(snap["amount_paid"], ShouldEqual, float64(300))
So(snap["amount_original"], ShouldEqual, float64(300))
var itemSnap map[string]any
So(json.Unmarshal([]byte(res1.OrderItem.Snapshot), &itemSnap), ShouldBeNil)
So(itemSnap["content_id"], ShouldEqual, float64(content.ID))
So(itemSnap["amount_paid"], ShouldEqual, float64(300))
var tu models.TenantUser
So(_db.WithContext(ctx).Where("tenant_id = ? AND user_id = ?", tenantID, buyerUserID).First(&tu).Error, ShouldBeNil)
So(tu.Balance, ShouldEqual, 700)