Skip to main content

Data Model

This document describes the key entities in Switchyard and how they relate to each other.

Schema Overview

The Switchyard database contains tables organized into focused domains:
DomainTablesPurpose
Product Catalog10Scraped products, sellable catalog, variants
Inventory4Physical stock, locations, warehouse groups
Orders & Fulfillment9Orders, totes, bags, pick lists
Sweeps & Routes6Retail shopping trips, driver assignments
Partner Brands8Consignment partners, manifests, payouts
Staff & Auth9Users, roles, permissions, service accounts
Equipment Monitoring5Sensors, alerts, temperature readings

Layered Product Architecture

Switchyard uses a layered product architecture that separates scraped data from the curated sellable catalog:
  1. Scraped Products Layer - Raw product data from retailer scrapers (unique by UPC)
  2. Sellable Products Layer - Curated catalog of products we sell (1:1 with scraped products)
  3. Inventory Layer - Physical stock in the RFC warehouse
  4. Order & Fulfillment Layer - Customer orders, bags, totes, and robot delivery

Complete Schema Architecture

Product Domain

scraped_products

The raw product catalog from scrapers. Unique by UPC/barcode.
FieldTypeDescription
iduuidUnique identifier
namestringProduct name
barcodestringUPC/EAN barcode (canonical identifier)
brandstringBrand name
image_urlstringPrimary product image
category_iduuidReference to Category
subcategory_iduuidReference to subcategory
partner_brand_iduuidPartner brand owner (nullable)
descriptiontextProduct description
created_atdatetimeFirst scraped
updated_atdatetimeLast updated

sellable_products

The curated catalog of products we sell. 1:1 relationship with scraped_products.
FieldTypeDescription
iduuidUnique identifier
scraped_product_iduuidReference to scraped_products (UNIQUE)
namestringCurated product name
brandstringBrand
selling_pricedecimalOur price to customers
is_perishablebooleanRequires expiration tracking
temperature_zonestringZone (ambient, chilled, frozen)
is_partner_brandbooleanOwned by partner brand
commission_ratedecimalPartner commission override
statusenumdraft, active, discontinued
is_activebooleanCurrently available for sale

retailer_mappings

Links scraped products to specific retailers and stores. Contains aisle/location data for sweeps.
FieldTypeDescription
iduuidUnique identifier
product_iduuidReference to scraped_products
store_namestringRetailer (heb, walmart, target)
retailer_location_idstringSpecific store ID
store_location_textstringAisle location (e.g., “Aisle 27”)
store_aisleintegerParsed aisle number
is_activebooleanCurrently available
last_seen_atdatetimeLast successful scrape

Pricing Model

Switchyard tracks three types of prices:
TableSourcePurpose
retailer_pricingScrapersOur cost - what we pay retailers
retailer_selling_pricesScrapersRetailer’s price - what retailers charge customers
sellable_products.selling_priceAdminOur price - what we charge customers

Inventory Domain

inventory_items

Tracks physical inventory in the RFC warehouse. Supports FEFO/FIFO picking.
FieldTypeDescription
iduuidUnique identifier
sellable_product_iduuidReference to sellable_products
location_iduuidReference to inventory_locations
quantityintegerTotal quantity
reserved_quantityintegerReserved for orders
received_atdatetimeWhen received (for FIFO)
expiration_datedateExpiration (for FEFO, nullable)
lot_numberstringLot tracking
partner_brand_iduuidConsignment owner (nullable)
is_consignmentbooleanPartner-owned inventory
manifest_item_iduuidReceiving manifest reference
source_sweep_iduuidWhich sweep brought this in
unit_costdecimalAcquisition cost
FEFO/FIFO Picking: Items are picked with expiring soonest first (FEFO), with oldest received as fallback for non-perishables (FIFO).

inventory_locations

Physical location within the RFC warehouse.

inventory_groups

Hierarchical warehouse organization: Zone → Aisle → Bay → Shelf → Slot

Partner Brand Domain

partner_brands

External brand partners who consign inventory.
FieldTypeDescription
iduuidUnique identifier
company_namestringPartner company name
contact_emailstringPrimary contact
approval_statusenumpending, approved, rejected, suspended
default_commission_rate_ambientdecimalDefault commission for ambient (0.15)
default_commission_rate_colddecimalDefault commission for cold (0.20)
retailer_iduuidCreated retailer for sourcing
retailer_location_iduuidCreated location for sourcing
approved_atdatetimeWhen approved
approved_byuuidAdmin who approved

partner_manifests

Shipments from partner brands to RFC.
FieldTypeDescription
iduuidUnique identifier
partner_brand_iduuidReference to partner_brands
taxonomy_idstring18-digit QR code ID (TYPE 27)
manifest_numberintegerSequential per brand
statusenumdraft, pending_brand_approval, approved, in_transit, received, partially_received, cancelled
tracking_numberstringShipping tracking
carrierstringShipping carrier
expected_delivery_datedateExpected arrival

partner_manifest_items

Line items on a manifest with expected and received quantities.
FieldTypeDescription
manifest_iduuidReference to partner_manifests
sellable_product_iduuidProduct being shipped
expected_quantityintegerQuantity expected
received_quantityintegerQuantity received
lot_numberstringLot tracking
expiration_datedateProduct expiration
discrepancy_notestextNotes on quantity differences

partner_reorder_requests

Admin-initiated requests for partner inventory.
FieldTypeDescription
iduuidUnique identifier
partner_brand_iduuidReference to partner_brands
statusenumpending, accepted, rejected, expired, cancelled
expires_atdatetime7 days from creation
manifest_iduuidCreated manifest on acceptance
is_auto_generatedbooleanFrom auto-reorder system

consignment_sales

Records sales of consigned inventory for payout calculation.
FieldTypeDescription
iduuidUnique identifier
inventory_item_iduuidSold inventory item
order_item_iduuidCustomer order item
partner_brand_iduuidPartner to pay
quantity_soldintegerUnits sold
sale_pricedecimalPrice per unit
commission_ratedecimalRate at time of sale
commission_amountdecimalOur commission
net_to_partnerdecimalAmount due to partner
payout_statusenumpending, included, paid
payout_periodstringSettlement period (YYYY-MM)

shopify_sync

Per-product Shopify sync configuration.
FieldTypeDescription
sellable_product_iduuidProduct to sync
partner_brand_iduuidPartner brand
shopify_product_idstringShopify product ID
sync_namebooleanSync product name
sync_descriptionbooleanSync description
sync_imagesbooleanSync images
sync_retail_pricebooleanSync price
last_sync_atdatetimeLast sync time
last_sync_statusenumsuccess, failed
locally_modified_fieldsarrayFields with local edits

Staff Domain

staff

Employees who can be pickers, drivers, or both. Replaces the old drivers table.
FieldTypeDescription
iduuidUnique identifier
user_idstringLink to admin user account
emailstringStaff email
is_pickerbooleanCan pick orders
is_driverbooleanCan perform sweeps
is_activebooleanCurrently active
Staff members can have both picker and driver roles, but not perform both simultaneously.

Order & Fulfillment Domain

orders

Customer orders from app or admin dashboard.
FieldTypeDescription
iduuidUnique identifier
customer_iduuidReference to customers
sourceenum’app’ or ‘admin’
statusenumpending, processing, sweep_in_progress, intake, picking, staged, delivering, delivered

order_items

Line items referencing sellable_products.
FieldTypeDescription
sellable_product_iduuidReference to sellable_products
fulfillment_sourceenum’inventory’ or ‘sweep’
allocated_atdatetimeWhen allocation was made

totes, bags, bag_items

Physical containers for robot delivery:
  • Order → has many Totes
  • Tote → has many Bags (one robot per tote)
  • Bag → has many Bag Items (temperature-separated)
  • Bag Item → fulfills an Order Item

Operations Domain

routes

Groups multiple sweeps together for a single driver trip.

sweeps

Shopping trips to retailers. Supports order sweeps and inventory sweeps.
FieldTypeDescription
sweep_typeenum’order’ or ‘inventory’
driver_iduuidReference to staff
route_iduuidReference to routes

sweep_economics_settings

Configuration for sweep profitability calculations.
FieldTypeDescription
in_store_breakeven_itemsintegerMin items for profitable in-store sweep
curbside_breakeven_itemsintegerMin items for profitable curbside sweep
labor_rate_hourlydecimalDriver hourly cost
new_sweep_marginal_costdecimalCost to add another sweep

pick_lists

RFC picking assignments assigned to staff (pickers).

Write Separation

To protect product data integrity, scrapers and admin have different write permissions:
TableScrapersAdmin
scraped_productsCreate new onlyFull control
retailer_mappingsFull controlRead only
retailer_pricingFull controlRead only
sellable_productsNeverFull control
inventory_itemsNeverFull control
Once a product exists, scrapers only update retailer-specific tables (pricing, availability), never core product attributes.