fixes
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
package catalog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/descrybe/descrybe-v2/apps/api/internal/company"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
const enhanceInputHashKey = "enhance_input_hash"
|
||||
|
||||
// RepairWeakEnhanceHashesResult is the detailed report for weak-hash clearing.
|
||||
type RepairWeakEnhanceHashesResult struct {
|
||||
Cleared int64
|
||||
Scanned int
|
||||
ClearedRawIDs []uuid.UUID
|
||||
}
|
||||
|
||||
// RepairWeakEnhanceHashes clears enhance_input_hash from field_sources and
|
||||
// localized_content for processed products whose descriptions are weak /
|
||||
// title-echo / filler (so the next enhance cannot hash-skip thin priors).
|
||||
// Returns the number of products updated.
|
||||
func RepairWeakEnhanceHashes(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID) (int64, error) {
|
||||
res, err := RepairWeakEnhanceHashesDetailed(ctx, pool, companyID)
|
||||
return res.Cleared, err
|
||||
}
|
||||
|
||||
// RepairWeakEnhanceHashesDetailed is RepairWeakEnhanceHashes plus scan/raw-id detail
|
||||
// for admin Fix A1 hygiene reporting.
|
||||
func RepairWeakEnhanceHashesDetailed(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID) (RepairWeakEnhanceHashesResult, error) {
|
||||
var out RepairWeakEnhanceHashesResult
|
||||
if pool == nil {
|
||||
return out, fmt.Errorf("catalog pool not configured")
|
||||
}
|
||||
if companyID == uuid.Nil {
|
||||
return out, ClientMsg("company_id is required")
|
||||
}
|
||||
tx, err := pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
out, err = repairWeakEnhanceHashesTx(ctx, tx, companyID)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return out, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// RepairWeakEnhanceHashes clears weak enhance skip hashes for the company.
|
||||
func (s *Service) RepairWeakEnhanceHashes(ctx context.Context, companyID uuid.UUID) (int64, error) {
|
||||
if s == nil || s.Pool == nil {
|
||||
return 0, fmt.Errorf("catalog service not configured")
|
||||
}
|
||||
return RepairWeakEnhanceHashes(ctx, s.Pool, companyID)
|
||||
}
|
||||
|
||||
func repairWeakEnhanceHashesTx(ctx context.Context, tx pgx.Tx, companyID uuid.UUID) (RepairWeakEnhanceHashesResult, error) {
|
||||
var out RepairWeakEnhanceHashesResult
|
||||
rows, err := tx.Query(ctx, `
|
||||
SELECT id, raw_product_id,
|
||||
COALESCE(name, ''),
|
||||
COALESCE(description, ''),
|
||||
COALESCE(processed_name, ''),
|
||||
COALESCE(processed_description, ''),
|
||||
COALESCE(field_sources, '{}'::jsonb),
|
||||
COALESCE(localized_content, '{}'::jsonb)
|
||||
FROM processed_products
|
||||
WHERE company_id = $1`, companyID)
|
||||
if err != nil {
|
||||
return out, fmt.Errorf("list processed products: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
type pending struct {
|
||||
id uuid.UUID
|
||||
rawID uuid.UUID
|
||||
fs []byte
|
||||
loc []byte
|
||||
}
|
||||
var updates []pending
|
||||
|
||||
for rows.Next() {
|
||||
out.Scanned++
|
||||
var (
|
||||
id, rawID uuid.UUID
|
||||
name, desc, processedName, processedDesc string
|
||||
fsRaw, locRaw []byte
|
||||
)
|
||||
if err := rows.Scan(&id, &rawID, &name, &desc, &processedName, &processedDesc, &fsRaw, &locRaw); err != nil {
|
||||
return out, err
|
||||
}
|
||||
fs := map[string]any{}
|
||||
if len(fsRaw) > 0 {
|
||||
if err := json.Unmarshal(fsRaw, &fs); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
if fs == nil {
|
||||
fs = map[string]any{}
|
||||
}
|
||||
loc, err := company.DecodeLocalizedContent(locRaw)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
changed := false
|
||||
primaryDesc := strings.TrimSpace(processedDesc)
|
||||
if primaryDesc == "" {
|
||||
primaryDesc = desc
|
||||
}
|
||||
primaryName := strings.TrimSpace(processedName)
|
||||
if primaryName == "" {
|
||||
primaryName = name
|
||||
}
|
||||
|
||||
if _, has := fs[enhanceInputHashKey]; has {
|
||||
if company.IsWeakPriorEnhanceDescription(primaryDesc, primaryName, name) {
|
||||
delete(fs, enhanceInputHashKey)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
for lang, fields := range loc {
|
||||
d := strings.TrimSpace(fields.ProcessedDescription)
|
||||
n := strings.TrimSpace(fields.ProcessedName)
|
||||
if n == "" {
|
||||
n = primaryName
|
||||
}
|
||||
if strings.TrimSpace(fields.EnhanceInputHash) == "" {
|
||||
continue
|
||||
}
|
||||
if company.IsWeakPriorEnhanceDescription(d, n, primaryName, name) {
|
||||
fields.EnhanceInputHash = ""
|
||||
loc[lang] = fields
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
fsBytes, err := json.Marshal(fs)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
locBytes, err := company.EncodeLocalizedContent(loc)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
updates = append(updates, pending{id: id, rawID: rawID, fs: fsBytes, loc: locBytes})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
seenRaw := map[uuid.UUID]struct{}{}
|
||||
for _, u := range updates {
|
||||
ct, err := tx.Exec(ctx, `
|
||||
UPDATE processed_products
|
||||
SET field_sources = $2::jsonb,
|
||||
localized_content = $3::jsonb,
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND company_id = $4`,
|
||||
u.id, u.fs, u.loc, companyID)
|
||||
if err != nil {
|
||||
return out, fmt.Errorf("clear enhance hashes product=%s: %w", u.id, err)
|
||||
}
|
||||
if ct.RowsAffected() > 0 {
|
||||
out.Cleared++
|
||||
if _, ok := seenRaw[u.rawID]; !ok {
|
||||
seenRaw[u.rawID] = struct{}{}
|
||||
out.ClearedRawIDs = append(out.ClearedRawIDs, u.rawID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
Reference in New Issue
Block a user