← back to Greenland China

QA-REPORT.md

72 lines

# Greenland Wallcoverings — Staging Catalog QA

_Read-only audit of `staging/greenland.jsonl` · 800 SKUs · generated 2026-07-01_

## Summary

800 staged products — **795 Wallcovering + 5 Engineering wallpaper**. Structural
capture is strong (image + core spec coverage all ≥96%), but three things **block a
DW import today**: no real pricing, `repeat` never captured, and a handful of
identity/image gaps. None are fatal; all are fixable at the scraper or enrichment step.

## Field coverage (non-null / non-empty, of 800)

| Field | Coverage | Notes |
|---|---|---|
| id, sku, code, pattern, name, category, weight, unit_price, url | 100% | see caveats below |
| cover_image / images | 99.1% | 7 products have none |
| sub_categories | 99.5% | |
| use | 98.9% | |
| backing | 97.9% | |
| width | 97.8% | |
| fire_rating | 96.6% | mostly `ASTM E84 Class A` |
| minimum_order | 95.9% | e.g. `5.5 meters / 6 yards` |
| wall_class (material) | 91.5% | 20 distinct materials |
| **wall_type** | **50.3%** | half the catalog has no book/type |
| **composition** | **21.1%** | enrichment gap |
| **colorways** | **18.4%** | most rows carry no colorway array |
| **repeat** | **0.0%** | **never captured — field is always null** |

## Blockers (fix before any DW onboarding)

1. **No real pricing.** `unit_price` is the literal value `2` for **all 800** rows — a
   placeholder, not a price. Greenland is a China-direct vendor, so cost is
   quote/negotiated. Per the standing rule (every scraper confirms **cost + discount**
   before import), onboarding is blocked until a real cost basis exists. Retail would
   then follow the DW formula `cost / 0.65 / 0.85`.
2. **`repeat` = 0% captured.** The scraper (`scripts/scrape.js`) never populates repeat.
   Repeat is a required spec for wallcovering PDPs — needs a scraper fix + re-pull.
3. **7 products with no image** — ids `651, 525, 493, 748, 678, 675, 668`. Cannot
   merchandise without a cover image; re-scrape or drop.

## Data-quality issues (fix at normalize step)

4. **SKU identity is ~98% clean, not 100%.** The alphanumeric manufacturer code lives in
   `sku`/`code` for **786/800** rows (e.g. `V020P1455`). ~14 outliers instead carry a
   **color name** in `sku` (e.g. `Warm White`, `JUNGLE PULSE`) with the real code in
   `pattern`. The only **duplicate SKU** is `"JUNGLE PULSE"` (ids `260` + `262`).
   → The stable unique key is **`id`**; treat `sku` as mfr-code only after normalizing
   those ~14 rows.
5. **Field-role note.** `pattern` = human pattern name; `code`/`sku` = mfr code;
   `name` mirrors `pattern` (or the code on the outliers). `sku === code` for all 800.
6. **`weight` units unconfirmed** — bare integers (e.g. `270`). Confirm g/m² vs g/roll
   before trusting it as a spec.
7. **Enrichment gaps** — `wall_type` 50%, `composition` 21%, `colorways` 18%. Fine for a
   preview; incomplete for a customer-facing PDP.

## What's good

- Material taxonomy is rich and usable now: Sisal 139, Vinyl 100, PE-Weave 98, Cork 95,
  Wood 72, Hemp 41, Abaca 40, Linen 39, Paper-Weave 26, Suede 21, Silk 16 … (20 total).
- Images, width, backing, fire rating, MOQ all ≥95% — enough to preview + spec-sheet.

## Recommended next steps

- [ ] Patch `scripts/scrape.js` to capture **repeat** (+ colorways/composition where present), re-pull.
- [ ] Get a real **cost basis** from Greenland (quote) → unblock pricing.
- [ ] Normalize the ~14 color-name-as-SKU outliers; de-dupe `JUNGLE PULSE`.
- [ ] Re-scrape or drop the 7 image-less ids.
- [ ] Confirm `weight` units.
- [ ] **Decide private-label vs. named** (see `ONBOARDING-MAP.md`) — a China-direct line
      may need relabeling like WallQuest→Malibu / Command54→Phillipe Romano.