fixes
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
package processing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// CategoryBackfillResult is the outcome of BackfillProcessedCategoriesFromMapped.
|
||||
type CategoryBackfillResult struct {
|
||||
Updated int64 `json:"updated"`
|
||||
}
|
||||
|
||||
// BackfillProcessedCategoriesFromMapped fills empty processed_products.category from
|
||||
// raw_products.mapped_data when a usable unique_id is present. When the company has
|
||||
// categories rows, only known unique_ids are applied (same rule as processOne filter).
|
||||
// Safe for admin "Fix catalog" and migrator reuse. Does not invent categories via vector.
|
||||
func BackfillProcessedCategoriesFromMapped(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID) (CategoryBackfillResult, error) {
|
||||
var out CategoryBackfillResult
|
||||
if pool == nil {
|
||||
return out, fmt.Errorf("category backfill: nil pool")
|
||||
}
|
||||
if companyID == uuid.Nil {
|
||||
return out, fmt.Errorf("category backfill: empty company id")
|
||||
}
|
||||
|
||||
ct, err := pool.Exec(ctx, `
|
||||
WITH src AS (
|
||||
SELECT
|
||||
p.id AS processed_id,
|
||||
BTRIM(COALESCE(
|
||||
CASE
|
||||
WHEN jsonb_typeof(r.mapped_data->'category') IN ('string', 'number')
|
||||
THEN NULLIF(BTRIM(r.mapped_data->>'category'), '')
|
||||
ELSE NULL
|
||||
END,
|
||||
NULLIF(BTRIM(r.mapped_data->>'category_unique_id'), ''),
|
||||
NULLIF(BTRIM(r.mapped_data->'category'->>'unique_id'), ''),
|
||||
NULLIF(BTRIM(r.mapped_data->'category'->>'category_unique_id'), ''),
|
||||
NULLIF(BTRIM(r.mapped_data->'category'->>'#text'), ''),
|
||||
NULLIF(BTRIM(r.mapped_data->'category'->>'id'), ''),
|
||||
NULLIF(BTRIM(r.mapped_data->'category'->>'value'), ''),
|
||||
NULLIF(BTRIM(r.mapped_data->'category'->>'code'), '')
|
||||
)) AS cat_raw
|
||||
FROM processed_products p
|
||||
INNER JOIN raw_products r ON r.id = p.raw_product_id AND r.company_id = p.company_id
|
||||
WHERE p.company_id = $1
|
||||
AND (
|
||||
COALESCE(NULLIF(BTRIM(p.category), ''), '') = ''
|
||||
OR LOWER(BTRIM(p.category)) = 'none'
|
||||
)
|
||||
),
|
||||
mapped AS (
|
||||
SELECT
|
||||
processed_id,
|
||||
CASE
|
||||
WHEN cat_raw IS NULL OR cat_raw = '' OR LOWER(cat_raw) = 'none' THEN NULL
|
||||
ELSE cat_raw
|
||||
END AS cat_uid
|
||||
FROM src
|
||||
),
|
||||
eligible AS (
|
||||
SELECT m.processed_id, m.cat_uid
|
||||
FROM mapped m
|
||||
WHERE m.cat_uid IS NOT NULL
|
||||
AND (
|
||||
NOT EXISTS (SELECT 1 FROM categories c WHERE c.company_id = $1)
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM categories c
|
||||
WHERE c.company_id = $1
|
||||
AND BTRIM(c.unique_id) = m.cat_uid
|
||||
)
|
||||
)
|
||||
)
|
||||
UPDATE processed_products p
|
||||
SET category = e.cat_uid,
|
||||
field_sources = jsonb_set(
|
||||
COALESCE(p.field_sources, '{}'::jsonb),
|
||||
'{category}',
|
||||
'"mapped_backfill"'::jsonb,
|
||||
true
|
||||
),
|
||||
updated_at = now()
|
||||
FROM eligible e
|
||||
WHERE p.id = e.processed_id`, companyID)
|
||||
if err != nil {
|
||||
return out, fmt.Errorf("category backfill: %w", err)
|
||||
}
|
||||
out.Updated = ct.RowsAffected()
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// CountProcessedCategoryCoverage returns how many processed rows for companyID have
|
||||
// a non-empty category vs empty/"none".
|
||||
func CountProcessedCategoryCoverage(ctx context.Context, pool *pgxpool.Pool, companyID uuid.UUID) (withCat, withoutCat int64, err error) {
|
||||
if pool == nil {
|
||||
return 0, 0, fmt.Errorf("category coverage: nil pool")
|
||||
}
|
||||
err = pool.QueryRow(ctx, `
|
||||
SELECT
|
||||
COUNT(*) FILTER (
|
||||
WHERE COALESCE(NULLIF(BTRIM(category), ''), '') <> ''
|
||||
AND LOWER(BTRIM(category)) <> 'none'
|
||||
),
|
||||
COUNT(*) FILTER (
|
||||
WHERE COALESCE(NULLIF(BTRIM(category), ''), '') = ''
|
||||
OR LOWER(BTRIM(category)) = 'none'
|
||||
)
|
||||
FROM processed_products
|
||||
WHERE company_id = $1`, companyID).Scan(&withCat, &withoutCat)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("category coverage: %w", err)
|
||||
}
|
||||
return withCat, withoutCat, nil
|
||||
}
|
||||
Reference in New Issue
Block a user