fix: harden competitor create and batch kol stats
Backend CI / Backend (push) Failing after 6m48s

This commit is contained in:
2026-05-13 17:31:22 +08:00
parent 7aa786fbf4
commit 18cdbf25f8
5 changed files with 195 additions and 28 deletions
@@ -86,6 +86,7 @@ type KolPromptRepository interface {
Create(ctx context.Context, input CreateKolPromptInput) (*KolPrompt, error)
GetByID(ctx context.Context, tenantID, id int64) (*KolPrompt, error)
ListByPackage(ctx context.Context, tenantID, packageID int64) ([]KolPrompt, error)
CountByPackages(ctx context.Context, tenantID int64, packageIDs []int64) (map[int64]int, error)
ListActiveByPackage(ctx context.Context, tenantID, packageID int64) ([]ActiveKolPrompt, error)
UpdateMetadata(ctx context.Context, input UpdateKolPromptMetadataInput) error
Save(ctx context.Context, input SaveKolPromptInput) error
@@ -269,6 +270,39 @@ ORDER BY sort_order ASC, created_at ASC
return result, nil
}
func (r *kolPromptRepository) CountByPackages(ctx context.Context, tenantID int64, packageIDs []int64) (map[int64]int, error) {
counts := make(map[int64]int, len(packageIDs))
if len(packageIDs) == 0 {
return counts, nil
}
rows, err := r.db.Query(ctx, `
SELECT package_id, COUNT(*)::int
FROM kol_prompts
WHERE tenant_id = $1
AND package_id = ANY($2::bigint[])
AND deleted_at IS NULL
GROUP BY package_id
`, tenantID, packageIDs)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var packageID int64
var count int
if err := rows.Scan(&packageID, &count); err != nil {
return nil, err
}
counts[packageID] = count
}
if err := rows.Err(); err != nil {
return nil, err
}
return counts, nil
}
func (r *kolPromptRepository) ListActiveByPackage(ctx context.Context, tenantID, packageID int64) ([]ActiveKolPrompt, error) {
rows, err := r.q.ListActiveKolPromptsByPackage(ctx, generated.ListActiveKolPromptsByPackageParams{
PackageID: packageID,
@@ -60,8 +60,10 @@ type KolSubscriptionRepository interface {
GetByID(ctx context.Context, tenantID, id int64) (*KolSubscription, error)
GetByIDAny(ctx context.Context, id int64) (*KolSubscription, error)
GetActiveForTenant(ctx context.Context, tenantID, packageID int64) (*KolSubscription, error)
ListActiveForTenantByPackages(ctx context.Context, tenantID int64, packageIDs []int64) (map[int64]KolSubscription, error)
ListByTenant(ctx context.Context, tenantID int64) ([]KolSubscription, error)
ListActiveSubscribersForPackage(ctx context.Context, packageID int64) ([]KolSubscription, error)
CountActiveSubscriberTenantsByPackages(ctx context.Context, packageIDs []int64) (map[int64]int64, error)
Approve(ctx context.Context, id, tenantID, approvedBy int64, endAt *time.Time) error
RevokeByTenant(ctx context.Context, id, tenantID int64) error
CreateAccessRow(ctx context.Context, input CreateAccessRowInput) error
@@ -362,6 +364,41 @@ func (r *kolSubscriptionRepository) GetActiveForTenant(ctx context.Context, tena
return &sub, nil
}
func (r *kolSubscriptionRepository) ListActiveForTenantByPackages(ctx context.Context, tenantID int64, packageIDs []int64) (map[int64]KolSubscription, error) {
result := make(map[int64]KolSubscription, len(packageIDs))
if len(packageIDs) == 0 {
return result, nil
}
rows, err := r.db.Query(ctx, `
SELECT DISTINCT ON (package_id)
id, tenant_id, package_id, status, approved_by, start_at, end_at, created_at, updated_at
FROM kol_subscriptions
WHERE tenant_id = $1
AND package_id = ANY($2::bigint[])
AND status IN ('pending', 'active')
ORDER BY package_id, created_at DESC, id DESC
`, tenantID, packageIDs)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
sub, err := scanKolSubscriptionRaw(rows)
if err != nil {
return nil, err
}
if sub != nil {
result[sub.PackageID] = *sub
}
}
if err := rows.Err(); err != nil {
return nil, err
}
return result, nil
}
func (r *kolSubscriptionRepository) ListByTenant(ctx context.Context, tenantID int64) ([]KolSubscription, error) {
rows, err := r.q.ListKolSubscriptions(ctx, tenantID)
if err != nil {
@@ -386,6 +423,39 @@ func (r *kolSubscriptionRepository) ListActiveSubscribersForPackage(ctx context.
return result, nil
}
func (r *kolSubscriptionRepository) CountActiveSubscriberTenantsByPackages(ctx context.Context, packageIDs []int64) (map[int64]int64, error) {
counts := make(map[int64]int64, len(packageIDs))
if len(packageIDs) == 0 {
return counts, nil
}
rows, err := r.db.Query(ctx, `
SELECT package_id, COUNT(DISTINCT tenant_id)::bigint
FROM kol_subscriptions
WHERE package_id = ANY($1::bigint[])
AND status = 'active'
AND (end_at IS NULL OR end_at > NOW())
GROUP BY package_id
`, packageIDs)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var packageID int64
var count int64
if err := rows.Scan(&packageID, &count); err != nil {
return nil, err
}
counts[packageID] = count
}
if err := rows.Err(); err != nil {
return nil, err
}
return counts, nil
}
func (r *kolSubscriptionRepository) Approve(ctx context.Context, id, tenantID, approvedBy int64, endAt *time.Time) error {
return r.q.ApproveKolSubscription(ctx, generated.ApproveKolSubscriptionParams{
ApprovedBy: pgInt8(&approvedBy),