This commit is contained in:
2026-08-16 16:57:36 +02:00
parent 96f8c1115c
commit 532d439c41
106 changed files with 10147 additions and 494 deletions
@@ -0,0 +1,127 @@
package processing
import (
"context"
"fmt"
"github.com/descrybe/descrybe-v2/apps/api/internal/aiprompts"
"github.com/descrybe/descrybe-v2/apps/api/internal/catalog"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
// FixCompanyCatalogOpts controls optional Fix A1 / catalog hygiene steps.
type FixCompanyCatalogOpts struct {
// BackfillCategories copies mapped_data category unique_ids onto empty
// processed_products.category.
BackfillCategories bool
// ReprocessSampleLimit caps recommended raw_product_ids in the response
// (0 = counts only, no sample ids).
ReprocessSampleLimit int
// AIPrompts optionally re-applies BuiltInDefaults product_enhance per content language.
AIPrompts *aiprompts.Service
}
// FixCompanyCatalogResult is the idempotent admin Fix A1 report.
type FixCompanyCatalogResult struct {
CompanyID uuid.UUID `json:"company_id"`
CompanyName string `json:"company_name"`
A1Cohort bool `json:"a1_cohort"`
CategoryAttributeOrphansRemoved int `json:"category_attribute_orphans_removed"`
CategoryAttributeLinks int `json:"category_attribute_links"`
CategoryPromptsUpdated int `json:"category_prompts_updated"`
CategoryPromptsAlreadyOK int `json:"category_prompts_already_ok"`
CategoryPromptsEmpty int `json:"category_prompts_empty_skipped"`
// Prompts aliases category_prompts_updated for flash.admin.fixA1Success {prompts}.
Prompts int `json:"prompts"`
ProductEnhanceLanguages int `json:"product_enhance_languages"`
WeakHashesCleared int `json:"weak_hashes_cleared"`
CategoriesBackfilled int `json:"categories_backfilled"`
// Hashes / Categories alias the long names for flash.admin.fixA1Success.
Hashes int `json:"hashes"`
Categories int `json:"categories"`
DescriptionsNormalized int `json:"descriptions_normalized"`
DescriptionsBackfilled int `json:"descriptions_backfilled"`
MappedDescriptionsFlat int `json:"mapped_descriptions_flattened"`
MetaBackfilled int `json:"meta_backfilled"`
AttributesSanitized int64 `json:"attributes_sanitized"`
ProductsScanned int `json:"products_scanned"`
ReprocessNeededCount int `json:"reprocess_needed_count"`
ReprocessSampleRawProductIDs []uuid.UUID `json:"reprocess_sample_raw_product_ids,omitempty"`
}
// FixCompanyCatalog runs the admin Fix A1 / catalog hygiene sequence in place.
// Never clears the catalog or uses A1 as a clone destination.
// Step 2 applies RepairCompanyCategoryEnhancePrompts (same repaired map as
// RepairA1DemoCategoryEnhancePrompts / cmd/repair-category-prompts -apply).
// Legacy converters + weak-hash clear live in FixCatalogHygieneWithIDs.
func FixCompanyCatalog(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID, companyName string, a1Cohort bool, opts FixCompanyCatalogOpts) (FixCompanyCatalogResult, error) {
out := FixCompanyCatalogResult{
CompanyID: companyID,
CompanyName: companyName,
A1Cohort: a1Cohort,
}
if pool == nil {
return out, fmt.Errorf("nil pool")
}
orphans, links, err := catalog.EnsureCategoryAttributeLinks(ctx, pool, companyID)
if err != nil {
return out, err
}
out.CategoryAttributeOrphansRemoved = orphans
out.CategoryAttributeLinks = links
updated, alreadyOK, emptySkipped, err := catalog.RepairCompanyCategoryEnhancePrompts(ctx, pool, companyID)
if err != nil {
return out, err
}
out.CategoryPromptsUpdated = updated
out.CategoryPromptsAlreadyOK = alreadyOK
out.CategoryPromptsEmpty = emptySkipped
if opts.AIPrompts != nil {
n, err := opts.AIPrompts.ApplyBuiltInProductEnhance(ctx, companyID)
if err != nil {
return out, fmt.Errorf("product_enhance templates: %w", err)
}
out.ProductEnhanceLanguages = n
}
hygiene, clearedIDs, err := FixCatalogHygieneWithIDs(ctx, pool, companyID, opts.BackfillCategories)
if err != nil {
return out, err
}
out.WeakHashesCleared = hygiene.WeakHashesCleared
out.CategoriesBackfilled = hygiene.CategoriesBackfilled
out.DescriptionsNormalized = hygiene.DescriptionsNormalized
out.DescriptionsBackfilled = hygiene.DescriptionsBackfilled
out.MappedDescriptionsFlat = hygiene.MappedDescriptionsFlat
out.MetaBackfilled = hygiene.MetaBackfilled
out.ProductsScanned = hygiene.ProductsScanned
sanitized, err := BackfillCompanyProcessedAttributes(ctx, pool, companyID)
if err != nil {
return out, fmt.Errorf("sanitize attributes: %w", err)
}
out.AttributesSanitized = sanitized
needed, sample, err := RecommendReprocessRawProductIDs(ctx, pool, companyID, clearedIDs, opts.ReprocessSampleLimit)
if err != nil {
return out, err
}
out.ReprocessNeededCount = needed
out.ReprocessSampleRawProductIDs = sample
// Short keys for flash.admin.fixA1Success {prompts,hashes,categories}.
out.Prompts = out.CategoryPromptsUpdated
out.Hashes = out.WeakHashesCleared
out.Categories = out.CategoriesBackfilled
return out, nil
}