77 lines
2.7 KiB
Go
77 lines
2.7 KiB
Go
package catalog
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
|
||
|
|
"github.com/descrybe/descrybe-v2/apps/api/internal/billing"
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
||
|
|
)
|
||
|
|
|
||
|
|
// EnsureCategoryAttributeLinks removes orphan category_attributes rows (missing
|
||
|
|
// category or attribute) without wiping taxonomy or valid links. Returns orphans
|
||
|
|
// removed and remaining link count.
|
||
|
|
func EnsureCategoryAttributeLinks(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID) (orphansRemoved int, links int, err error) {
|
||
|
|
if pool == nil {
|
||
|
|
return 0, 0, fmt.Errorf("nil pool")
|
||
|
|
}
|
||
|
|
ct, err := pool.Exec(ctx, `
|
||
|
|
DELETE FROM category_attributes ca
|
||
|
|
WHERE ca.company_id = $1
|
||
|
|
AND (
|
||
|
|
NOT EXISTS (
|
||
|
|
SELECT 1 FROM categories c
|
||
|
|
WHERE c.company_id = ca.company_id AND c.unique_id = ca.category_unique_id
|
||
|
|
)
|
||
|
|
OR NOT EXISTS (
|
||
|
|
SELECT 1 FROM attributes a
|
||
|
|
WHERE a.id = ca.attribute_id AND a.company_id = ca.company_id
|
||
|
|
)
|
||
|
|
)`, companyID)
|
||
|
|
if err != nil {
|
||
|
|
return 0, 0, fmt.Errorf("purge orphan category_attributes: %w", err)
|
||
|
|
}
|
||
|
|
orphansRemoved = int(ct.RowsAffected())
|
||
|
|
if err := pool.QueryRow(ctx, `
|
||
|
|
SELECT count(*)::int FROM category_attributes WHERE company_id = $1`, companyID).Scan(&links); err != nil {
|
||
|
|
return orphansRemoved, 0, err
|
||
|
|
}
|
||
|
|
return orphansRemoved, links, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// RepairCompanyCategoryEnhancePrompts is the company-scoped variant of
|
||
|
|
// RepairA1DemoCategoryEnhancePrompts: same repairedCategoryEnhancePromptMap
|
||
|
|
// (sl + "*" with CategoryEnhanceUserTemplate / {{attrs}}), applied to one company.
|
||
|
|
// Idempotent — already-OK categories count as already_ok, not updated.
|
||
|
|
func RepairCompanyCategoryEnhancePrompts(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID) (updated, alreadyOK, emptySkipped int, err error) {
|
||
|
|
if pool == nil {
|
||
|
|
return 0, 0, 0, fmt.Errorf("nil pool")
|
||
|
|
}
|
||
|
|
want, err := repairedCategoryEnhancePromptMap()
|
||
|
|
if err != nil {
|
||
|
|
return 0, 0, 0, err
|
||
|
|
}
|
||
|
|
summary := &RepairCategoryEnhancePromptsResult{ByCompany: map[string]int{}}
|
||
|
|
if _, err := repairCompanyCategoryEnhancePrompts(ctx, pool, companyID, companyID.String(), want, false, summary); err != nil {
|
||
|
|
return 0, 0, 0, err
|
||
|
|
}
|
||
|
|
return summary.Updated, summary.AlreadyOK, summary.EmptySkipped, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ResolvePlatformDemoCompanyID finds the Platform Demo sandbox (never A1 cohort).
|
||
|
|
func ResolvePlatformDemoCompanyID(ctx context.Context, pool *pgxpool.Pool) (uuid.UUID, error) {
|
||
|
|
var id uuid.UUID
|
||
|
|
err := pool.QueryRow(ctx, `
|
||
|
|
SELECT c.id
|
||
|
|
FROM companies c
|
||
|
|
WHERE c.name = $1
|
||
|
|
AND COALESCE(c.legacy_company_id, '') <> $2
|
||
|
|
ORDER BY c.created_at ASC
|
||
|
|
LIMIT 1`, platformDemoCompanyName, billing.A1LegacyCompanyID).Scan(&id)
|
||
|
|
if err != nil {
|
||
|
|
return uuid.Nil, fmt.Errorf("platform demo company not found: %w", err)
|
||
|
|
}
|
||
|
|
return id, nil
|
||
|
|
}
|