179 lines
5.9 KiB
Go
179 lines
5.9 KiB
Go
package business
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
"kra/internal/biz/business"
|
|
)
|
|
|
|
// OA 表只读,不由新商务的系统迁移创建或改写。
|
|
type activationPO struct {
|
|
BusierID uint64
|
|
CreatedAt *time.Time
|
|
RelatedChannels string
|
|
ID uint64 `gorm:"primaryKey"`
|
|
PromoteID *uint64
|
|
PlatformName, PromoteAccount, BusierAccount, ApplicantOA, Status string
|
|
AccumAmount *string
|
|
BindAt, UnbindAt, ReachAt, DeletedAt *time.Time
|
|
}
|
|
|
|
func (activationPO) TableName() string { return "sys_promote_active_pool_bind" }
|
|
func toBizActivation(po activationPO) *business.Activation {
|
|
amount := "0.00"
|
|
if po.AccumAmount != nil {
|
|
amount = *po.AccumAmount
|
|
}
|
|
row := &business.Activation{BusierID: po.BusierID, CreatedAt: po.CreatedAt, ID: po.ID, PromoteID: po.PromoteID, PlatformName: po.PlatformName, PromoteAccount: po.PromoteAccount, BusierAccount: po.BusierAccount, ApplicantOA: po.ApplicantOA, Status: po.Status, AccumAmount: amount, BindAt: po.BindAt, UnbindAt: po.UnbindAt, ReachAt: po.ReachAt}
|
|
var channels []struct {
|
|
PlatformName string `json:"platformName"`
|
|
PromoteID uint64 `json:"promoteId"`
|
|
}
|
|
if po.RelatedChannels != "" {
|
|
if json.Unmarshal([]byte(po.RelatedChannels), &channels) != nil {
|
|
return nil
|
|
}
|
|
}
|
|
for _, ch := range channels {
|
|
row.Channels = append(row.Channels, business.ChannelKey{SourceDB: ch.PlatformName, ID: ch.PromoteID})
|
|
}
|
|
return row
|
|
}
|
|
|
|
type activationRepo struct {
|
|
data Provider
|
|
databases PlatformProvider
|
|
}
|
|
|
|
func NewActivationRepo(data Provider, databases PlatformProvider) business.ActivationRepo {
|
|
return &activationRepo{data: data, databases: databases}
|
|
}
|
|
|
|
func (r *activationRepo) OwnAccounts(ctx context.Context, id uint) ([]business.ActivationAccount, error) {
|
|
var rows []struct{ SourceDB, Account string }
|
|
err := r.data.DB().WithContext(ctx).Table("sys_user_bind_platform").Where("user_id = ? AND status = ? AND platform_busier_account IS NOT NULL", id, "0").Distinct("source_db,platform_busier_account AS account").Scan(&rows).Error
|
|
accounts := make([]business.ActivationAccount, 0, len(rows))
|
|
for _, row := range rows {
|
|
accounts = append(accounts, business.ActivationAccount{SourceDB: row.SourceDB, Account: row.Account})
|
|
}
|
|
return accounts, storageError(err)
|
|
}
|
|
|
|
func (r *activationRepo) oa(ctx context.Context) (*gorm.DB, error) {
|
|
db, err := r.databases.Database("oa")
|
|
if err != nil || db == nil {
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
db = db.WithContext(ctx)
|
|
available, err := businessTableAvailable(db, "sys_promote_active_pool_bind")
|
|
if err != nil || !available {
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
return db, nil
|
|
}
|
|
|
|
func (r *activationRepo) List(ctx context.Context, scope business.ActivationScope, filter business.ActivationFilter, options ...business.ListOption) (*business.ActivationPage, error) {
|
|
page := &business.ActivationPage{Rows: []*business.Activation{}, Available: true}
|
|
if !scope.All && len(scope.Accounts) == 0 {
|
|
return page, nil
|
|
}
|
|
db, err := r.oa(ctx)
|
|
if err != nil {
|
|
page.Available = false
|
|
return page, nil
|
|
}
|
|
q := db.Model(&activationPO{}).Where("deleted_at IS NULL")
|
|
if !scope.All {
|
|
accounts := make([][]any, 0, len(scope.Accounts))
|
|
for _, account := range scope.Accounts {
|
|
accounts = append(accounts, []any{strings.ToLower(account.SourceDB), strings.ToLower(account.Account)})
|
|
}
|
|
q = q.Where("(LOWER(platform_name),LOWER(busier_account)) IN ?", accounts)
|
|
}
|
|
if len(filter.PlatformNames) > 0 {
|
|
q = q.Where("platform_name IN ?", filter.PlatformNames)
|
|
}
|
|
if len(filter.Statuses) > 0 {
|
|
q = q.Where("status IN ?", filter.Statuses)
|
|
}
|
|
if filter.PromoteAccount != "" {
|
|
q = q.Where("promote_account LIKE ?", "%"+filter.PromoteAccount+"%")
|
|
}
|
|
if filter.BusierAccount != "" {
|
|
q = q.Where("busier_account LIKE ?", "%"+filter.BusierAccount+"%")
|
|
}
|
|
if err := q.Count(&page.Total).Error; err != nil {
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
o := business.NewListOptions(options...)
|
|
var pos []activationPO
|
|
if err := q.Order("id DESC").Offset(o.Offset).Limit(o.Limit).Find(&pos).Error; err != nil {
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
for _, po := range pos {
|
|
row := toBizActivation(po)
|
|
if row == nil {
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
if row.BindAt != nil {
|
|
if err := r.applyTransferEnd(ctx, row); err != nil {
|
|
return nil, err
|
|
}
|
|
query := activationMetricQuery(row)
|
|
available, err := r.activationMetricsAvailable(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if available {
|
|
items, err := r.Spend(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
amounts := make([]string, 0, len(items))
|
|
for _, item := range items {
|
|
amounts = append(amounts, item.Amount)
|
|
}
|
|
total, err := sumActivationMoney(amounts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
row.AccumAmount = total
|
|
row.MetricsAvailable = true
|
|
}
|
|
row.RegisteredPlayers, err = r.registered(ctx, query, filter.IDCardDedup)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
page.Rows = append(page.Rows, row)
|
|
}
|
|
return page, nil
|
|
}
|
|
|
|
func (r *activationRepo) Find(ctx context.Context, id uint64) (*business.Activation, error) {
|
|
db, err := r.oa(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var po activationPO
|
|
if err := db.Where("id = ? AND deleted_at IS NULL", id).Take(&po).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, business.ErrActivationNotFound
|
|
}
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
row := toBizActivation(po)
|
|
if row == nil {
|
|
return nil, business.ErrActivationSource
|
|
}
|
|
if err := r.applyTransferEnd(ctx, row); err != nil {
|
|
return nil, err
|
|
}
|
|
return row, nil
|
|
}
|