Add Importing // Mapping Overview
@@ -0,0 +1,239 @@
|
||||
# Battl Builder – Import & Mapping Flow Overview
|
||||
|
||||
This document explains the entire data ingestion, normalization, and builder-level mapping process used in Battl Builder — from raw AvantLink feed → normalized Battl Builder product → categorized builder slot.
|
||||
|
||||
---
|
||||
|
||||
## 1. Big Picture Architecture
|
||||
|
||||
Battl Builder’s data flow breaks into three layers:
|
||||
|
||||
1. **Import Layer**
|
||||
_“What did the merchant send us?”_
|
||||
|
||||
2. **Domain Layer**
|
||||
_“What is this part in Battl Builder language?”_
|
||||
|
||||
3. **Builder Layer**
|
||||
_“Where does this part appear in the UI, and what slot does it fill?”_
|
||||
|
||||
This doc walks through each step in plain English.
|
||||
|
||||
---
|
||||
|
||||
## 2. Import Layer (AvantLink → Battl Builder database)
|
||||
|
||||
### 2.1 Merchants
|
||||
|
||||
Table: `merchants`
|
||||
|
||||
Each row stores:
|
||||
|
||||
- Merchant name (“Primary Arms”, “Brownells”, etc.)
|
||||
- AvantLink MID
|
||||
- Feed URLs
|
||||
- Active flags
|
||||
- Timestamps
|
||||
|
||||
**Purpose:**
|
||||
Tell the importer *which* feeds exist and how to read them.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 AvantLink Product & Offer Feeds
|
||||
|
||||
Every merchant provides two key feeds:
|
||||
|
||||
#### Product Feed
|
||||
- brand name
|
||||
- product name
|
||||
- description
|
||||
- merchant’s category
|
||||
- MPN, UPC, SKU
|
||||
- main image
|
||||
- etc.
|
||||
|
||||
#### Offer Feed
|
||||
- price
|
||||
- original MSRP
|
||||
- availability
|
||||
- buy URL
|
||||
- merchant id
|
||||
- AvantLink product id
|
||||
- timestamps
|
||||
|
||||
The importer loops over these feeds continuously.
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Normalizing Merchant Categories (merchant_category_mappings)
|
||||
|
||||
Table: `merchant_category_mappings`
|
||||
|
||||
Each row answers this question:
|
||||
|
||||
> “When Merchant X says category string Y, what does that mean in our taxonomy?”
|
||||
|
||||
Columns include:
|
||||
|
||||
- `merchant_id`
|
||||
- `raw_category` (merchant’s text)
|
||||
- `mapped_part_role`
|
||||
- `mapped_configuration`
|
||||
- timestamps
|
||||
|
||||
This is the **first** normalization hop:
|
||||
|
||||
**Merchant category → internal part_role**
|
||||
|
||||
---
|
||||
|
||||
### 2.4 Brands
|
||||
|
||||
Table: `brands`
|
||||
|
||||
Import logic:
|
||||
|
||||
1. Try to find a case-insensitive match.
|
||||
2. If found: reuse it.
|
||||
3. If not found: create a new brand row.
|
||||
|
||||
---
|
||||
|
||||
### 2.5 Products
|
||||
|
||||
Table: `products`
|
||||
|
||||
Represents Battl Builder’s canonical catalog — not merchant-specific.
|
||||
|
||||
Columns include:
|
||||
|
||||
- `brand_id`
|
||||
- `name`
|
||||
- `part_role`
|
||||
- `platform`
|
||||
- `slug`
|
||||
- `mpn`, `upc`
|
||||
- descriptions
|
||||
- main image
|
||||
- `raw_category_key`
|
||||
- timestamps
|
||||
|
||||
**Import behavior:**
|
||||
|
||||
1. Sync brand
|
||||
2. Normalize category → part_role
|
||||
3. Determine platform
|
||||
4. Upsert product (insert or update)
|
||||
|
||||
---
|
||||
|
||||
### 2.6 Product Offers
|
||||
|
||||
Table: `product_offers`
|
||||
|
||||
Represents merchant-specific availability and pricing.
|
||||
|
||||
Columns:
|
||||
|
||||
- `product_id`
|
||||
- `merchant_id`
|
||||
- `price`, `original_price`
|
||||
- `currency`
|
||||
- `in_stock`
|
||||
- `buy_url`
|
||||
- timestamps
|
||||
|
||||
---
|
||||
|
||||
## 3. Domain Layer (Mapping Into Builder Categories)
|
||||
|
||||
### 3.1 Part Categories
|
||||
|
||||
Table: `part_categories`
|
||||
|
||||
Represents categories used in the builder UI such as:
|
||||
|
||||
- lower
|
||||
- upper
|
||||
- barrel
|
||||
- optic
|
||||
- trigger
|
||||
|
||||
These map directly to the builder’s UI slots.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Part Role Mappings
|
||||
|
||||
Table: `part_role_mappings`
|
||||
|
||||
Maps from:
|
||||
|
||||
> **platform + part_role → builder category**
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
AR-15 + LOWER_RECEIVER_STRIPPED → lower
|
||||
AR-15 + OPTIC_LPVO → optic
|
||||
```
|
||||
|
||||
This is the glue between raw import data and builder UI categories.
|
||||
|
||||
---
|
||||
|
||||
## 4. Builder Layer (Frontend Consumption)
|
||||
|
||||
### How `/builder` loads parts
|
||||
|
||||
Frontend calls:
|
||||
|
||||
```
|
||||
GET /api/gunbuilder/products?platform=AR-15&partRoles=optic
|
||||
```
|
||||
|
||||
Backend:
|
||||
|
||||
1. Query products
|
||||
2. Load offers
|
||||
3. Map to DTOs
|
||||
4. Return JSON
|
||||
5. Frontend groups by category via part_role_mappings
|
||||
|
||||
---
|
||||
|
||||
## 5. Relationship Between Mapping Systems
|
||||
|
||||
| Layer | Table | Purpose |
|
||||
|-------|--------|----------|
|
||||
| Import | `merchant_category_mappings` | Convert merchant category → part_role |
|
||||
| Builder | `part_role_mappings` | Convert part_role → builder category slot |
|
||||
|
||||
Flow:
|
||||
|
||||
```
|
||||
Merchant raw category
|
||||
↓
|
||||
merchant_category_mappings
|
||||
↓
|
||||
products.part_role
|
||||
↓
|
||||
part_role_mappings
|
||||
↓
|
||||
part_categories.slug
|
||||
↓
|
||||
Builder slot (frontend)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. `/builds` Page
|
||||
|
||||
Currently placeholder-only. Later it will store real builds composed from imported & mapped products.
|
||||
|
||||
---
|
||||
|
||||
## 7. Summary
|
||||
|
||||
AvantLink feeds → merchant category mapping → products + offers → part_role_mappings → builder UI → user builds.
|
||||
Reference in New Issue
Block a user