Skip to main content

EU hierarchy: district-to-area fallback and the France & Benelux merge

**Shipped.** 19 of the 72 European stores carried no district in the retail roster, so they appeared nowhere in the hierarchy drill-down. The region read 72 while its groups summed to 53, and nothing anywhere indicated that 19 were missing. ## What was wrong Germany and Austria were entirely absent. Italy & Switzerland showed 1 store when it should have shown 10. This was a roster data gap rather than an application defect, but the app was silently dropping stores while its own totals disagreed. Two findings shaped the fix: - **Italy & Switzerland already had a district code** (TPR_IT_CH_D1), assigned to exactly one store: 42421 Landquart, which opened April 2026. The other nine were never given it. - **Germany has no district code at all.** Neither TPR_DE_A1 nor TPR_DE_AT_A1 has one, so there was nothing to assign. ## The rule A store's group resolves as: **district → area → country → raise (never hide)**. Then a display-group mapping merges group keys that should render as one row. Safe by inspection, not assumption: area is populated on all 72 EU stores, and on the 49 that carry a district, district and area names are identical. So the fallback cannot move a store into a different group from the one it was already in. Every North American store carries a district, so the fallback never fires there and NA is unchanged. Group by the **code**, take the label from the **name**, add nothing. ## The merge Belgium, France and Netherlands render as one group: **France & Benelux**. The roster already had all three reporting to the same area manager and the same district manager, so this reflects how they are actually run rather than imposing a new structure. The mapping covers both the district codes and the area codes, so a group cannot split across the fallback boundary. That mattered: Italy & Switzerland had nine stores resolving via area and one via district, and without mapping both it would have rendered as two rows with the same name. Germany and Germany & Austria stay as **two separate rows** — different area codes, different area managers. Merging them would be a management change, not a display one. ## Result: seven groups, 72 stores | Group | Stores | Source | |---|---|---| | France & Benelux | 11 | Merged display group | | Germany | 5 | Area fallback (was invisible) | | Germany & Austria | 5 | Area fallback (was invisible) | | Italy & Switzerland | 10 | Area fallback (was showing 1) | | Spain & Portugal | 21 | District, unchanged | | UK North & Ireland | 10 | District, unchanged | | UK South | 10 | District, unchanged | ## Applied to Analytics too Analytics had its own district resolution in SQL and could not call the shared rule — the rule lived in a TypeScript file and the analytics compute is plain JS, which cannot import it. The rule now lives in a .mjs with a typed facade over it, and all three surfaces import one file. Analytics resolves stores in JS and hands SQL a store-to-label lookup to join against. Verified against prod: 57 statements, zero query failures, unassigned bucket empty across all 859 stores. ## The guardrail that matters **The merged group key is a value no database column holds**, so it cannot reach an access decision even by accident. Scope still resolves from each store's real district, area, region and country. A manager scoped to Belgium still sees Belgium only. ## Still with Tapestry - Populate the existing code TPR_IT_CH_D1 onto the other nine Italy & Switzerland stores - Create district codes for the two German areas and assign them - Attach a district manager to store 42421, which carries a district code today with no manager against it The fallback is a safety net, not a substitute for the roster being right. As each of these lands, the fallback stops firing for those stores and the hierarchy is unchanged — which is the proof the two agree. --- Docs: *EU Hierarchy Resolution v1* and *Analytics Hierarchy Resolution v1* (FutureProof, 27 Aug 2026).
Status: Completed And Live In Production

Log in to comment and vote

No comments yet

Be the first to share your thoughts.