Northwind — Semantic Model
1. Overview
The Northwind sample database models the trading operations of a fictional specialty-foods company. It tracks the products the company buys from suppliers and sells to customers, the orders those customers place, the employees who process the orders, and the shippers who deliver them. Sales territories and regions are also modeled, along with which employees are assigned to which territories.
2. Entity summary
| # | Table name | Singular label | Purpose |
|---|---|---|---|
| 1 | regions | Region | Top-level sales regions grouping territories. |
| 2 | categories | Category | Product categorization used across the catalog. |
| 3 | customers | Customer | Companies that place orders. |
| 4 | employees | Employee | Staff who process orders and are assigned to territories. |
| 5 | suppliers | Supplier | Vendors that provide products. |
| 6 | products | Product | Catalog items sold to customers. |
| 7 | shippers | Shipper | Carrier companies that deliver orders. |
| 8 | orders | Order | Customer purchase orders with shipping details. |
| 9 | territories | Territory | Sales territories grouped under regions. |
| 10 | employee_territories | Employee Territory | Junction linking employees to territories (M:N). |
| 11 | order_details | Order Detail | Line items within an order (junction linking orders to products). |
Entity-relationship diagram
flowchart LR
employees -->|reports to| employees
suppliers -->|supplies| products
categories -->|categorizes| products
customers -->|places| orders
employees -->|handles| orders
shippers -->|ships| orders
regions -->|contains| territories
employees --> employee_territories
territories --> employee_territories
orders --> order_details
products --> order_details
3. Entities
3.1 regions — Region
Plural label: Regions
Label column: region_description (the human-identifying field; auto-wired by Semantius)
Description: Sales territories and geographic regions. Serves as the top-level grouping for territories.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
region_description | text | yes | Region | label_column, searchable |
Relationships
- A
regionsrow may have manyterritoriesrecords (1:N, viaterritories.region_id).
3.2 categories — Category
Plural label: Categories
Label column: category_name
Description: Product categories used to group items in the catalog.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
category_name | text | yes | Category | label_column, searchable |
description | text | yes | Description | Description of the product category; searchable |
Relationships
- A
categoriesrow may have manyproductsrecords (1:N, viaproducts.category_id).
3.3 customers — Customer
Plural label: Customers
Label column: company_name
Description: Customer companies that place orders, with contact and address details.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
company_name | text | yes | Customer | label_column, searchable |
customer_id | text | yes | Customer ID | unique, searchable; short code identifying the customer |
contact_name | text | yes | Contact Name | searchable |
contact_title | text | yes | Contact Title | Job title of the primary contact |
address | text | yes | Street Address | |
city | text | yes | City | searchable |
region | text | no | Region | State or province |
postal_code | text | yes | Postal Code | Postal or ZIP code |
country | text | yes | Country | searchable |
phone | text | yes | Phone | Primary phone number |
fax | text | no | Fax |
Relationships
- A
customersrow may have manyordersrecords (1:N, viaorders.customer_id).
3.4 employees — Employee
Plural label: Employees
Label column: last_name
Description: Staff records covering personal, contact, and reporting-structure details.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
last_name | text | yes | Employee | label_column, searchable |
first_name | text | yes | First Name | searchable |
title | text | yes | Title | Job title |
title_of_courtesy | text | no | Title of Courtesy | Courtesy title (Mr., Ms., Dr., etc.) |
birth_date | date | no | Birth Date | |
hire_date | date | yes | Hire Date | defaults to CURRENT_DATE |
address | text | yes | Street Address | |
city | text | yes | City | searchable |
region | text | no | Region | State or province |
postal_code | text | yes | Postal Code | Postal or ZIP code |
country | text | yes | Country | searchable |
home_phone | text | yes | Home Phone | |
extension | text | no | Extension | Phone extension |
notes | text | no | Notes | |
photo_path | text | no | Photo Path | |
reports_to | reference | no | Reports To | → employees (N:1, restrict); self-ref for reporting hierarchy |
Relationships
- An
employeesrow may have an optional manager that is itself anemployeesrow (N:1 self-reference, viareports_to). - An
employeesrow may have manyordersrecords (1:N, viaorders.employee_id). employees↔territoriesis many-to-many through theemployee_territoriesjunction table.
3.5 suppliers — Supplier
Plural label: Suppliers
Label column: company_name
Description: Vendor companies that supply products to the catalog.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
company_name | text | yes | Supplier | label_column, searchable |
contact_name | text | yes | Contact Name | searchable |
contact_title | text | yes | Contact Title | Job title of the primary contact |
address | text | yes | Street Address | |
city | text | yes | City | searchable |
region | text | no | Region | State or province |
postal_code | text | yes | Postal Code | Postal or ZIP code |
country | text | yes | Country | searchable |
phone | text | yes | Phone | Primary phone number |
fax | text | no | Fax | |
homepage | text | no | Homepage | Supplier website URL |
Relationships
- A
suppliersrow may have manyproductsrecords (1:N, viaproducts.supplier_id).
3.6 products — Product
Plural label: Products
Label column: product_name
Description: Catalog items the company sells, including stock levels, pricing, and supplier/category links.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
product_name | text | yes | Product | label_column, searchable |
supplier_id | reference | yes | Supplier | → suppliers (N:1, restrict); supplier providing this product |
category_id | reference | yes | Category | → categories (N:1, restrict); category this product belongs to |
quantity_per_unit | text | yes | Quantity Per Unit | Quantity and unit of measure per package |
unit_price | float | yes | Unit Price | defaults to 0.0 |
units_in_stock | int32 | yes | Units In Stock | defaults to 0; current stock quantity |
units_on_order | int32 | yes | Units On Order | defaults to 0; quantity currently on order from supplier |
reorder_level | int32 | yes | Reorder Level | defaults to 0; minimum stock level before reordering |
discontinued | boolean | yes | Discontinued | defaults to FALSE; whether the product is discontinued |
Relationships
- A
productsrow belongs to onesuppliers(N:1, required, restrict on delete). - A
productsrow belongs to onecategories(N:1, required, restrict on delete). products↔ordersis many-to-many through theorder_detailsjunction table.
3.7 shippers — Shipper
Plural label: Shippers
Label column: company_name
Description: Carrier companies used to deliver orders.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
company_name | text | yes | Shipper | label_column, searchable |
phone | text | yes | Phone |
Relationships
- A
shippersrow may have manyordersrecords (1:N, viaorders.ship_via).
3.8 orders — Order
Plural label: Orders
Label column: ship_name
Description: Customer purchase orders, including who placed and handled each one, shipping address, and delivery dates.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
ship_name | text | yes | Order | label_column, searchable |
customer_id | reference | yes | Customer | → customers (N:1, restrict); customer who placed the order |
employee_id | reference | yes | Employee | → employees (N:1, restrict); employee who handled the order |
ship_via | reference | yes | Shipped Via | → shippers (N:1, restrict); shipper used for this order |
ship_address | text | yes | Ship Address | |
ship_city | text | yes | Ship City | searchable |
ship_region | text | no | Ship Region | State or province for shipment |
ship_postal_code | text | yes | Ship Postal Code | |
ship_country | text | yes | Ship Country | searchable |
freight | float | yes | Freight | defaults to 0.0; freight cost for the order |
order_date | date | yes | Order Date | defaults to CURRENT_DATE |
required_date | date | yes | Required Date | defaults to CURRENT_DATE |
shipped_date | date | no | Shipped Date |
Relationships
- An
ordersrow belongs to onecustomers(N:1, required, restrict on delete). - An
ordersrow belongs to oneemployees(N:1, required, restrict on delete). - An
ordersrow belongs to oneshippers(N:1, required, restrict on delete). - An
ordersrow has manyorder_detailsrecords (1:N, viaorder_details.order_id).
3.9 territories — Territory
Plural label: Territories
Label column: territory_description
Description: Sales territories within regions. Each territory belongs to exactly one region and can be assigned to multiple employees.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
territory_description | text | yes | Territory | label_column, searchable |
territory_id | text | yes | Territory ID | unique, searchable; short code identifying the territory |
region_id | reference | yes | Region | → regions (N:1, restrict); region this territory belongs to |
Relationships
- A
territoriesrow belongs to oneregions(N:1, required, restrict on delete). territories↔employeesis many-to-many through theemployee_territoriesjunction table.
3.10 employee_territories — Employee Territory
Plural label: Employee Territories
Label column: label (auto-generated generic label; no domain-level identifier on this junction)
Description: Links employees to the territories they have been assigned to. Pure M:N junction.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
employee_id | parent | yes | Employee | ↳ employees (N:1, restrict); reference to the employee |
territory_id | parent | yes | Territory | ↳ territories (N:1, restrict); reference to the territory |
Relationships
- A junction row belongs to one
employeesand oneterritories(both parent FKs, required). Together these represent the M:N relationship between employees and territories.
3.11 order_details — Order Detail
Plural label: Order Details
Label column: label (auto-generated generic label; no domain-level identifier on this junction)
Description: Line items within an order — which product was ordered, at what price, quantity, and discount. Junction between orders and products with additional line-level attributes.
Fields
| Field name | Format | Required | Label | Reference / Notes |
|---|---|---|---|---|
order_id | parent | yes | Order | ↳ orders (N:1, restrict); reference to the order |
product_id | parent | yes | Product | ↳ products (N:1, restrict); reference to the product |
unit_price | float | yes | Unit Price | defaults to 0.0; actual price per unit charged on this order |
quantity | int32 | yes | Quantity | defaults to 0; number of units ordered |
discount | float | yes | Discount | defaults to 0.0; discount rate applied to this line item |
Relationships
- An
order_detailsrow belongs to oneorders(N:1, required, restrict on delete). - An
order_detailsrow belongs to oneproducts(N:1, required, restrict on delete). - Together, the pair of parent FKs models the M:N relationship between orders and products, enriched with line-level pricing data.
4. Relationship summary
| From | Field | To | Cardinality | Kind | Delete behavior |
|---|---|---|---|---|---|
employees | reports_to | employees | N:1 | reference (self) | restrict |
products | supplier_id | suppliers | N:1 | reference | restrict |
products | category_id | categories | N:1 | reference | restrict |
orders | customer_id | customers | N:1 | reference | restrict |
orders | employee_id | employees | N:1 | reference | restrict |
orders | ship_via | shippers | N:1 | reference | restrict |
territories | region_id | regions | N:1 | reference | restrict |
employee_territories | employee_id | employees | N:1 | parent (junction) | restrict |
employee_territories | territory_id | territories | N:1 | parent (junction) | restrict |
order_details | order_id | orders | N:1 | parent (junction) | restrict |
order_details | product_id | products | N:1 | parent (junction) | restrict |
5. Enumerations
No enumerations defined.
6. Open questions
6.1 🔴 Decisions needed (blockers)
None.
6.2 🟡 Future considerations (deferred scope)
None.
7. Implementation notes for the downstream agent
- Create one module named
nwindand two baseline permissions (nwind:read,nwind:manage) before any entity. The live module currently usesnwind:view/nwind:manage— align naming with the deployer’s convention or keep the live names, but be explicit at deploy time. - Create entities in the order given in §2 — entities referenced by others first. Creation order that satisfies FK dependencies:
regions,categories,customers,suppliers,shippers,employees(then a second pass foremployees.reports_toself-reference),products,territories,orders,employee_territories,order_details. - For each entity: set
label_columnto the snake_case field marked as label_column in §3, passmodule_id,view_permission,edit_permission. Do not manually createid,created_at,updated_at, or the auto-label field. Foremployee_territoriesandorder_details,label_columndefaults tolabel(the generic auto-label) — no dedicated label field is defined on the junction. - For each field in §3: pass
table_name,field_name,format,title(the Label column),is_nullable(inverse of Required), and forreference/parentfields alsoreference_tableand thereference_delete_modeconsistent with §4 (all currentlyrestrict). - Deduplicate against Semantius built-in tables. This model is self-contained and does not currently reference any Semantius built-in (e.g.
users). All FK targets are nwind entities — no deduplication required. - After creation, spot-check that
label_columnon each entity resolves to a real field and that allreference_tabletargets exist.
External / built-in entities referenced: None. Every reference_table target resolves to an entity declared above.
Self-references: employees.reports_to → employees. Create the field in a second pass after employees exists.
Junctions (create last): employee_territories (parents: employees, territories), order_details (parents: orders, products, plus line-level scalar fields).