package app import ( "context" "time" "github.com/geo-platform/tenant-api/internal/shared/auth" "github.com/geo-platform/tenant-api/internal/shared/objectstorage" "github.com/geo-platform/tenant-api/internal/shared/response" "github.com/geo-platform/tenant-api/internal/tenant/repository" ) var ErrNotActiveKol = response.ErrForbidden(40341, "kol_not_active", "user is not an active KOL") type KolProfileService struct { repo repository.KolProfileRepository objectStorage objectstorage.Client } type UpdateKolProfileServiceInput struct { DisplayName string Bio *string AvatarURL *string } type KolProfileResponse struct { ID int64 `json:"id"` TenantID int64 `json:"tenant_id"` UserID int64 `json:"user_id"` DisplayName string `json:"display_name"` Bio *string `json:"bio"` AvatarURL *string `json:"avatar_url"` MarketEnabled bool `json:"market_enabled"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func NewKolProfileService(repo repository.KolProfileRepository) *KolProfileService { return &KolProfileService{repo: repo} } func (s *KolProfileService) WithObjectStorage(client objectstorage.Client) *KolProfileService { s.objectStorage = client return s } func (s *KolProfileService) RequireActiveKol(ctx context.Context, actor auth.Actor) (*repository.KolProfile, error) { profile, err := s.repo.GetByUser(ctx, actor.TenantID, actor.UserID) if err != nil { return nil, response.ErrInternal(50061, "kol_profile_query_failed", err.Error()) } if profile == nil || profile.Status != "active" { return nil, ErrNotActiveKol } return profile, nil } func (s *KolProfileService) UpdateProfile(ctx context.Context, actor auth.Actor, input UpdateKolProfileServiceInput) (*repository.KolProfile, error) { profile, err := s.RequireActiveKol(ctx, actor) if err != nil { return nil, err } displayName, err := validateKolDisplayName(input.DisplayName) if err != nil { return nil, err } bio, err := validateKolBio(input.Bio) if err != nil { return nil, err } avatarURL, err := validateKolAvatarURL(input.AvatarURL) if err != nil { return nil, err } if err := s.repo.Update(ctx, actor.TenantID, repository.UpdateKolProfileInput{ ID: profile.ID, DisplayName: displayName, Bio: bio, AvatarURL: avatarURL, }); err != nil { return nil, response.ErrInternal(50062, "kol_profile_update_failed", err.Error()) } updated, err := s.repo.GetByID(ctx, profile.ID) if err != nil { return nil, response.ErrInternal(50061, "kol_profile_query_failed", err.Error()) } if updated == nil { return nil, ErrNotActiveKol } return updated, nil } func NewKolProfileResponse(profile *repository.KolProfile) *KolProfileResponse { if profile == nil { return nil } return &KolProfileResponse{ ID: profile.ID, TenantID: profile.TenantID, UserID: profile.UserID, DisplayName: profile.DisplayName, Bio: profile.Bio, AvatarURL: profile.AvatarURL, MarketEnabled: profile.MarketEnabled, Status: profile.Status, CreatedAt: profile.CreatedAt, UpdatedAt: profile.UpdatedAt, } }