package business import ( "context" "strings" "time" ) type ActivationPoolFilter struct { Sources []string Name, ChannelType, Status, Target string Begin, End *time.Time } type ActivationPoolChannel struct { ID, PromoteID uint64 SourceDB, Name, ChannelType, Status string NoLoginDays *int64 EnteredAt time.Time Rejected bool RejectReason string RejectedAt *time.Time } type ActivationPoolPage struct { Rows []*ActivationPoolChannel Total int64 Available bool } type ActivationBindingOption struct { SourceDB, Account string ID uint64 Level int } type ActivationApplication struct { UserID uint PoolID, BusierID uint64 SourceDB string } type ActivationChurn struct { ID, PromoteID uint64 SourceDB, Name, From, To, Reason, Operator string At time.Time ToPool bool } type ActivationChurnPage struct { Rows []*ActivationChurn Total int64 Available bool } type ActivationPoolRepo interface { Pool(context.Context, ActivationPoolFilter, ...ListOption) (*ActivationPoolPage, error) PoolChannel(context.Context, uint64) (*ActivationPoolChannel, error) BindingOptions(context.Context, uint) ([]*ActivationBindingOption, error) Churn(context.Context, ActivationPoolFilter, ...ListOption) (*ActivationChurnPage, error) } type ActivationGateway interface { Apply(context.Context, ActivationApplication) error } type ActivationPoolUsecase struct { repo ActivationPoolRepo gateway ActivationGateway accounts *AccountUsecase } func NewActivationPoolUsecase(repo ActivationPoolRepo, gateway ActivationGateway, accounts *AccountUsecase) *ActivationPoolUsecase { return &ActivationPoolUsecase{repo: repo, gateway: gateway, accounts: accounts} } func (uc *ActivationPoolUsecase) Pool(ctx context.Context, f ActivationPoolFilter, o ...ListOption) (*ActivationPoolPage, error) { if _, _, err := uc.accounts.actor(ctx); err != nil { return nil, err } return uc.repo.Pool(ctx, f, o...) } func (uc *ActivationPoolUsecase) Options(ctx context.Context) ([]*ActivationBindingOption, error) { a, _, err := uc.accounts.actor(ctx) if err != nil { return nil, err } return uc.repo.BindingOptions(ctx, a.UserID) } func (uc *ActivationPoolUsecase) Apply(ctx context.Context, poolID, busierID uint64, source string) error { a, _, err := uc.accounts.actor(ctx) if err != nil { return err } source, err = NormalizePlatform(source) if err != nil || poolID == 0 || busierID == 0 { return ErrActivationInput } options, err := uc.repo.BindingOptions(ctx, a.UserID) if err != nil { return err } owned := false for _, o := range options { if o.SourceDB == source && o.ID == busierID { owned = true break } } if !owned { return ErrActivationScope } channel, err := uc.repo.PoolChannel(ctx, poolID) if err != nil { return err } if !strings.EqualFold(channel.SourceDB, source) { return ErrActivationInput } return uc.gateway.Apply(ctx, ActivationApplication{UserID: a.UserID, PoolID: poolID, BusierID: busierID, SourceDB: source}) } func (uc *ActivationPoolUsecase) Churn(ctx context.Context, f ActivationPoolFilter, o ...ListOption) (*ActivationChurnPage, error) { if _, _, err := uc.accounts.actor(ctx); err != nil { return nil, err } return uc.repo.Churn(ctx, f, o...) }