Files
mercadodevida/work/artifacts/F-079/architect.md
2026-08-20 05:57:24 +02:00

35 lines
2.0 KiB
Markdown

# F-079 — Architect: Product list /products does not show brand
## Root cause
The admin `/products` page already renders a `Marca` column with `{p.brand?.name ?? '—'}`, and the `Product` TS type already declares an optional `brand: { id, name, slug }`. However, the backend `PgProductRepository` never populates that field: `PRODUCT_COLUMNS` does not LEFT JOIN `brands_brands`, and `toProduct(row)` only emits `brandId: row.brand_id` without a denormalized `brand` object. So every row in the list renders `—` regardless of whether a brand is assigned.
## Design
Single change set in the repository:
1. **`ProductRow` interface** gains optional fields `brand_name: string | null` and `brand_slug: string | null`.
2. **`PRODUCT_COLUMNS`** is replaced with a subquery (`PRODUCT_BASE_COLUMNS`) that LEFT JOINs `brands_brands` and selects `b.name AS brand_name, b.slug AS brand_slug`. Existing queries (`findById`, `findActiveBySlug`, `listAll`) keep their semantics but read the new column set.
3. **`toProduct(row)`** emits `brand` only when `brand_id IS NOT NULL`:
```ts
brand: row.brand_id
? { id: row.brand_id, name: row.brand_name ?? '', slug: row.brand_slug ?? '' }
: undefined,
```
When `brand_id` is null the frontend falls back to the existing `` placeholder.
## No new tables, no API contract change.
Frontend is already prepared (the column, the type and the placeholder all exist). After the change:
- Products with a brand: column shows the brand name.
- Products without a brand: column shows `` (placeholder behavior is unchanged).
## Risk
Low. Pure read-side change. Existing tests on the repository must still pass.
## Acceptance mapping
- "Each row in /products listing shows the brand name" → toProduct now hydrates `brand.name`.
- "Brand column header is present" → already in page.tsx.
- "Empty brand renders as a placeholder" → existing `p.brand?.name ?? '—'` handles it.
- "verify.sh is green" → no test regression expected.