← 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.