package usecase import ( "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository" "code.30cm.net/digimon/library-go/errs" "context" "errors" "fmt" "github.com/zeromicro/go-zero/core/logx" ) type KYCUseCaseParam struct { KYCRepo repository.KYCRepository } type KYCUseCase struct { KYCUseCaseParam } func MustKYCUseCase(param KYCUseCaseParam) usecase.KYCUseCase { return &KYCUseCase{ param, } } func (use *KYCUseCase) Create(ctx context.Context, data *entity.KYC) error { latest, err := use.KYCRepo.FindLatestByUID(ctx, data.UID) // 發生真正的錯誤(非找不到) if err != nil && !errors.Is(err, repo.ErrNotFound) { return errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "param", Value: data}, {Key: "func", Value: "KYCRepo.FindLatestByUID"}, {Key: "err", Value: err.Error()}, }, "failed to get latest kyc") } // 若查到資料,且不是被駁回的,表示已存在審核中/已通過資料 → 禁止再次建立 if err == nil && latest.Status != kyc.StatusREJECTED { return errs.ForbiddenL(logx.WithContext(ctx), []logx.LogField{ {Key: "param", Value: data}, {Key: "func", Value: "KYCRepo.FindLatestByUID"}, {Key: "reason", Value: "KYC already in progress or approved"}, }, "不能重複送出 KYC 資料") } // ✅ 若查不到資料(ErrNotFound),或前一筆是 REJECTED,允許建立 data.Status = kyc.StatusPending err = use.KYCRepo.Create(ctx, data) if err != nil { return errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "param", Value: data}, {Key: "func", Value: "KYCRepo.Create"}, {Key: "err", Value: err.Error()}, }, "failed to create kyc review") } return nil } func (use *KYCUseCase) FindLatestByUID(ctx context.Context, uid string) (*entity.KYC, error) { latest, err := use.KYCRepo.FindLatestByUID(ctx, uid) if err != nil { return nil, errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "uid", Value: uid}, {Key: "func", Value: "KYCRepo.FindLatestByUID"}, {Key: "err", Value: err.Error()}, }, "failed to get latest kyc") } return latest, nil } func (use *KYCUseCase) FindByID(ctx context.Context, id string) (*entity.KYC, error) { byID, err := use.KYCRepo.FindByID(ctx, id) if err != nil { return nil, errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "id", Value: id}, {Key: "func", Value: "KYCRepo.FindByID"}, {Key: "err", Value: err.Error()}, }, "failed to get kyc") } return byID, nil } func (use *KYCUseCase) List(ctx context.Context, params usecase.KYCQueryParams) ([]*entity.KYC, int64, error) { q := repository.KYCQueryParams{ PageIndex: params.PageIndex, PageSize: params.PageSize, SortByDate: true, } if params.UID != nil { q.UID = params.UID } if params.Country != nil { q.Country = params.Country } if params.Status != nil { q.Status = params.Status } list, i, err := use.KYCRepo.List(ctx, q) if err != nil { return nil, 0, errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "params", Value: params}, {Key: "func", Value: "KYCRepo.List"}, {Key: "err", Value: err.Error()}, }, "failed to list kyc") } return list, i, nil } func (use *KYCUseCase) UpdateStatus(ctx context.Context, id string, status string, reason string) error { err := use.KYCRepo.UpdateStatus(ctx, id, status, reason) if err != nil { return errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "params", Value: fmt.Sprintf("id:%s, status:%s, reason: %s", id, status, reason)}, {Key: "func", Value: "KYCRepo.UpdateStatus"}, {Key: "err", Value: err.Error()}, }, "failed to update kyc status") } return nil } func (use *KYCUseCase) UpdateKYCInfo(ctx context.Context, id string, update *usecase.KYCUpdateParams) error { err := use.KYCRepo.UpdateKYCInfo(ctx, id, &repository.KYCUpdateParams{ Name: update.Name, Identification: update.Identification, IdentificationType: update.IdentificationType, Address: update.Address, PostalCode: update.PostalCode, DateOfBirth: update.DateOfBirth, Gender: update.Gender, IDFrontImage: update.IDFrontImage, IDBackImage: update.IDBackImage, BankStatementImg: update.BankStatementImg, BankCode: update.BankCode, BankName: update.BankName, BranchCode: update.BranchCode, BranchName: update.BranchName, BankAccount: update.BankAccount, }) if err != nil { return errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ {Key: "id", Value: id}, {Key: "params", Value: update}, {Key: "func", Value: "KYCRepo.UpdateKYCInfo"}, {Key: "err", Value: err.Error()}, }, "failed to update kyc") } return nil }