Compare commits
No commits in common. "6f790d65b3e4d3f9b8b14dbc31d50cd0e5125b3e" and "37b8bf8a74cd041822cc7858fb96a315c7d3b5a9" have entirely different histories.
6f790d65b3
...
37b8bf8a74
|
@ -97,6 +97,7 @@ func (repo *KYCRepository) List(ctx context.Context, params repository.KYCQueryP
|
||||||
sort = append(sort, bson.E{Key: "created_at", Value: -1})
|
sort = append(sort, bson.E{Key: "created_at", Value: -1})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var results []*entity.KYC
|
||||||
// 設置排序選項
|
// 設置排序選項
|
||||||
opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize)
|
opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize)
|
||||||
opts.SetSort(bson.D{{Key: "updated_at", Value: -1}})
|
opts.SetSort(bson.D{{Key: "updated_at", Value: -1}})
|
||||||
|
@ -108,7 +109,6 @@ func (repo *KYCRepository) List(ctx context.Context, params repository.KYCQueryP
|
||||||
}
|
}
|
||||||
|
|
||||||
// 執行查詢並獲取結果
|
// 執行查詢並獲取結果
|
||||||
var results []*entity.KYC
|
|
||||||
err = repo.DB.GetClient().Find(ctx, &results, filter, opts)
|
err = repo.DB.GetClient().Find(ctx, &results, filter, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
|
|
|
@ -1,477 +0,0 @@
|
||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
|
|
||||||
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
|
|
||||||
mgo "code.30cm.net/digimon/library-go/mongo"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"github.com/alicebob/miniredis/v2"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
|
||||||
"github.com/zeromicro/go-zero/core/stores/mon"
|
|
||||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SetupTestKYCRepository(db string) (repository.KYCRepository, func(), error) {
|
|
||||||
h, p, tearDown, err := startMongoContainer()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
s, _ := miniredis.Run()
|
|
||||||
|
|
||||||
conf := &mgo.Conf{
|
|
||||||
Schema: Schema,
|
|
||||||
Host: fmt.Sprintf("%s:%s", h, p),
|
|
||||||
Database: db,
|
|
||||||
MaxStaleness: 300,
|
|
||||||
MaxPoolSize: 100,
|
|
||||||
MinPoolSize: 100,
|
|
||||||
MaxConnIdleTime: 300,
|
|
||||||
Compressors: []string{},
|
|
||||||
EnableStandardReadWriteSplitMode: false,
|
|
||||||
ConnectTimeoutMs: 3000,
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheConf := cache.CacheConf{
|
|
||||||
cache.NodeConf{
|
|
||||||
RedisConf: redis.RedisConf{
|
|
||||||
Host: s.Addr(),
|
|
||||||
Type: redis.NodeType,
|
|
||||||
},
|
|
||||||
Weight: 100,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheOpts := []cache.Option{
|
|
||||||
cache.WithExpiry(1000 * time.Microsecond),
|
|
||||||
cache.WithNotFoundExpiry(1000 * time.Microsecond),
|
|
||||||
}
|
|
||||||
|
|
||||||
param := KYCRepositoryParam{
|
|
||||||
Conf: conf,
|
|
||||||
CacheConf: cacheConf,
|
|
||||||
CacheOpts: cacheOpts,
|
|
||||||
DBOpts: []mon.Option{
|
|
||||||
mgo.SetCustomDecimalType(),
|
|
||||||
mgo.InitMongoOptions(*conf),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := NewKYCRepository(param)
|
|
||||||
//_, _ = repo.Index20250317001UP(context.Background())
|
|
||||||
|
|
||||||
return repo, tearDown, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInsertKYC(t *testing.T) {
|
|
||||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
defer tearDown()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// 建立多筆 KYC 資料
|
|
||||||
items := []entity.KYC{
|
|
||||||
{
|
|
||||||
UID: "user-a",
|
|
||||||
CountryRegion: "TW",
|
|
||||||
Name: "王小明",
|
|
||||||
Identification: "A123456789",
|
|
||||||
IdentificationType: "ID_CARD",
|
|
||||||
Address: "台北市信義區",
|
|
||||||
PostalCode: "110",
|
|
||||||
Status: "PENDING",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
UID: "user-b",
|
|
||||||
CountryRegion: "US",
|
|
||||||
Name: "John Smith",
|
|
||||||
Identification: "P987654321",
|
|
||||||
IdentificationType: "PASSPORT",
|
|
||||||
Address: "123 Main St, NY",
|
|
||||||
PostalCode: "10001",
|
|
||||||
Status: "PENDING",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 插入資料
|
|
||||||
for i := range items {
|
|
||||||
err := model.Create(ctx, &items[i])
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, items[i].ID.IsZero(), "ID 應自動產生")
|
|
||||||
assert.NotZero(t, items[i].CreatedAt)
|
|
||||||
assert.NotZero(t, items[i].UpdatedAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 驗證插入資料是否正確
|
|
||||||
for _, item := range items {
|
|
||||||
kyc, err := model.FindByID(ctx, item.ID.Hex())
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, item.UID, kyc.UID)
|
|
||||||
assert.Equal(t, item.Name, kyc.Name)
|
|
||||||
assert.Equal(t, item.CountryRegion, kyc.CountryRegion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindLatestByUID(t *testing.T) {
|
|
||||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
defer tearDown()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
now := time.Now().UnixNano()
|
|
||||||
|
|
||||||
// 測試資料準備
|
|
||||||
testData := []entity.KYC{
|
|
||||||
{
|
|
||||||
UID: "user-multi",
|
|
||||||
Name: "早期資料",
|
|
||||||
Status: "PENDING",
|
|
||||||
CreatedAt: now - 1000,
|
|
||||||
UpdatedAt: now - 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
UID: "user-multi",
|
|
||||||
Name: "最新資料",
|
|
||||||
Status: "APPROVED",
|
|
||||||
CreatedAt: now + 1000,
|
|
||||||
UpdatedAt: now + 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
UID: "user-single",
|
|
||||||
Name: "唯一資料",
|
|
||||||
Status: "PENDING",
|
|
||||||
CreatedAt: now,
|
|
||||||
UpdatedAt: now,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range testData {
|
|
||||||
err := model.Create(ctx, &testData[i])
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// table-driven 測試表
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
uid string
|
|
||||||
expectNil bool
|
|
||||||
expect string // 預期的 Name
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "多筆資料,取最新",
|
|
||||||
uid: "user-multi",
|
|
||||||
expectNil: false,
|
|
||||||
expect: "最新資料",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "單筆資料",
|
|
||||||
uid: "user-single",
|
|
||||||
expectNil: false,
|
|
||||||
expect: "唯一資料",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "查無資料",
|
|
||||||
uid: "user-none",
|
|
||||||
expectNil: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
result, err := model.FindLatestByUID(ctx, tt.uid)
|
|
||||||
if tt.expectNil {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Nil(t, result)
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, result)
|
|
||||||
assert.Equal(t, tt.expect, result.Name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKYCRepository_List(t *testing.T) {
|
|
||||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
defer tearDown()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
now := time.Now().UnixNano()
|
|
||||||
|
|
||||||
seedData := []entity.KYC{
|
|
||||||
{
|
|
||||||
UID: "user-1",
|
|
||||||
CountryRegion: "TW",
|
|
||||||
Status: "PENDING",
|
|
||||||
Name: "Alice",
|
|
||||||
CreatedAt: now,
|
|
||||||
UpdatedAt: now,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
UID: "user-1",
|
|
||||||
CountryRegion: "JP",
|
|
||||||
Status: "APPROVED",
|
|
||||||
Name: "Bob",
|
|
||||||
CreatedAt: now + 1,
|
|
||||||
UpdatedAt: now + 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
UID: "user-2",
|
|
||||||
CountryRegion: "US",
|
|
||||||
Status: "REJECTED",
|
|
||||||
Name: "Charlie",
|
|
||||||
CreatedAt: now + 2,
|
|
||||||
UpdatedAt: now + 2,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range seedData {
|
|
||||||
err := model.Create(ctx, &seedData[i])
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
params repository.KYCQueryParams
|
|
||||||
expectedCount int
|
|
||||||
expectedTotal int64
|
|
||||||
expectedFirst string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Query by UID",
|
|
||||||
params: repository.KYCQueryParams{
|
|
||||||
UID: ptr("user-1"),
|
|
||||||
PageSize: 10,
|
|
||||||
PageIndex: 1,
|
|
||||||
},
|
|
||||||
expectedCount: 2,
|
|
||||||
expectedTotal: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Query by CountryRegion",
|
|
||||||
params: repository.KYCQueryParams{
|
|
||||||
Country: ptr("JP"),
|
|
||||||
PageSize: 10,
|
|
||||||
PageIndex: 1,
|
|
||||||
},
|
|
||||||
expectedCount: 1,
|
|
||||||
expectedTotal: 1,
|
|
||||||
expectedFirst: "Bob",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Query by Status",
|
|
||||||
params: repository.KYCQueryParams{
|
|
||||||
Status: ptr("REJECTED"),
|
|
||||||
PageSize: 10,
|
|
||||||
PageIndex: 1,
|
|
||||||
},
|
|
||||||
expectedCount: 1,
|
|
||||||
expectedTotal: 1,
|
|
||||||
expectedFirst: "Charlie",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Pagination test",
|
|
||||||
params: repository.KYCQueryParams{
|
|
||||||
PageSize: 1,
|
|
||||||
PageIndex: 1,
|
|
||||||
},
|
|
||||||
expectedCount: 1,
|
|
||||||
expectedTotal: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "No match",
|
|
||||||
params: repository.KYCQueryParams{
|
|
||||||
UID: ptr("non-existent"),
|
|
||||||
PageSize: 10,
|
|
||||||
PageIndex: 1,
|
|
||||||
},
|
|
||||||
expectedCount: 0,
|
|
||||||
expectedTotal: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
list, total, err := model.List(ctx, tt.params)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, tt.expectedCount, len(list))
|
|
||||||
assert.Equal(t, tt.expectedTotal, total)
|
|
||||||
if tt.expectedFirst != "" && len(list) > 0 {
|
|
||||||
assert.Equal(t, tt.expectedFirst, list[0].Name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKYCRepository_UpdateStatus(t *testing.T) {
|
|
||||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
defer tearDown()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// 建立一筆 KYC 資料
|
|
||||||
kyc := &entity.KYC{
|
|
||||||
UID: "user-status",
|
|
||||||
Name: "測試用戶",
|
|
||||||
Status: "PENDING",
|
|
||||||
CreatedAt: time.Now().UnixNano(),
|
|
||||||
UpdatedAt: time.Now().UnixNano(),
|
|
||||||
}
|
|
||||||
err = model.Create(ctx, kyc)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
id string
|
|
||||||
newStatus string
|
|
||||||
reason string
|
|
||||||
expectErr bool
|
|
||||||
expectStatus string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "成功更新為 REJECTED",
|
|
||||||
id: kyc.ID.Hex(),
|
|
||||||
newStatus: "REJECTED",
|
|
||||||
reason: "文件不符",
|
|
||||||
expectErr: false,
|
|
||||||
expectStatus: "REJECTED",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "失敗 - 無效 ID 格式",
|
|
||||||
id: "not-a-valid-id",
|
|
||||||
newStatus: "APPROVED",
|
|
||||||
reason: "",
|
|
||||||
expectErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "失敗 - 找不到資料",
|
|
||||||
id: primitive.NewObjectID().Hex(), // 合法但不存在
|
|
||||||
newStatus: "APPROVED",
|
|
||||||
reason: "",
|
|
||||||
expectErr: false, // Mongo 不會報錯,但更新筆數是 0,後面可以補強這邊驗證
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
err := model.UpdateStatus(ctx, tt.id, tt.newStatus, tt.reason)
|
|
||||||
if tt.expectErr {
|
|
||||||
assert.Error(t, err)
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// 如果是第一個 case,檢查資料是否真的被更新
|
|
||||||
if tt.expectStatus != "" {
|
|
||||||
result, err := model.FindByID(ctx, tt.id)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, tt.expectStatus, result.Status)
|
|
||||||
assert.Equal(t, tt.reason, result.RejectReason)
|
|
||||||
assert.NotZero(t, result.UpdatedAt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKYCRepository_UpdateKYCInfo(t *testing.T) {
|
|
||||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
defer tearDown()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
now := time.Now().UnixNano()
|
|
||||||
|
|
||||||
// 建立兩筆資料:一筆 PENDING、一筆 APPROVED
|
|
||||||
pendingKYC := &entity.KYC{
|
|
||||||
UID: "user-pending",
|
|
||||||
Name: "原名",
|
|
||||||
Address: "原地址",
|
|
||||||
Status: "PENDING",
|
|
||||||
CreatedAt: now,
|
|
||||||
UpdatedAt: now,
|
|
||||||
}
|
|
||||||
err = model.Create(ctx, pendingKYC)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
approvedKYC := &entity.KYC{
|
|
||||||
UID: "user-approved",
|
|
||||||
Name: "原名",
|
|
||||||
Address: "原地址",
|
|
||||||
Status: "APPROVED",
|
|
||||||
CreatedAt: now,
|
|
||||||
UpdatedAt: now,
|
|
||||||
}
|
|
||||||
err = model.Create(ctx, approvedKYC)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
name := "新名字"
|
|
||||||
address := "新地址"
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
id string
|
|
||||||
update *repository.KYCUpdateParams
|
|
||||||
expectErr bool
|
|
||||||
expectApply bool // 預期更新是否應成功套用
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "成功更新 PENDING 狀態資料",
|
|
||||||
id: pendingKYC.ID.Hex(),
|
|
||||||
update: &repository.KYCUpdateParams{
|
|
||||||
Name: &name,
|
|
||||||
Address: &address,
|
|
||||||
},
|
|
||||||
expectErr: false,
|
|
||||||
expectApply: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "更新失敗 - 非 PENDING 狀態",
|
|
||||||
id: approvedKYC.ID.Hex(),
|
|
||||||
update: &repository.KYCUpdateParams{
|
|
||||||
Name: &name,
|
|
||||||
Address: &address,
|
|
||||||
},
|
|
||||||
expectErr: false,
|
|
||||||
expectApply: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "更新失敗 - 非法 ID 格式",
|
|
||||||
id: "not-an-id",
|
|
||||||
update: &repository.KYCUpdateParams{
|
|
||||||
Name: &name,
|
|
||||||
},
|
|
||||||
expectErr: true,
|
|
||||||
expectApply: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
err := model.UpdateKYCInfo(ctx, tt.id, tt.update)
|
|
||||||
if tt.expectErr {
|
|
||||||
assert.Error(t, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// 若預期資料已被套用,驗證欄位是否更新
|
|
||||||
if tt.expectApply {
|
|
||||||
got, err := model.FindByID(ctx, tt.id)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, name, got.Name)
|
|
||||||
assert.Equal(t, address, got.Address)
|
|
||||||
} else {
|
|
||||||
got, err := model.FindByID(ctx, tt.id)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotEqual(t, name, got.Name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue