The Fini data warehouse uses a classic star schema composed of two dimension tables and one fact table.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/andresshm/fini-marketing-intelligence/llms.txt
Use this file to discover all available pages before exploring further.
dim_products and dim_customers hold the descriptive attributes that give context to each transaction, while fact_sales records every individual sale together with its measured metrics. This design keeps analytical queries simple — most reports need only a single join from the fact table to whichever dimension they need — and makes the schema easy to extend.
Full DDL
The schema is created bysql/create_schema.sql. All three tables are created with IF NOT EXISTS guards so the script is safe to re-run.
dim_products
Holds the catalogue of 20 Fini candy products. Each row describes one SKU with its commercial positioning and unit economics.Surrogate primary key. Unique identifier for each product in the catalogue.
Human-readable product name, e.g.
"Fini Gummy Bears". Never null.Product family. One of:
Gummies, Belts, Seasonal, Marshmallow, Licorice, Foam, Novelty.Seasonal positioning that drives the date-skewing logic in
generate_sales.py. One of: All Year, Halloween, Christmas, Summer, Valentine. Nullable — products without a defined season default to year-round uniform distribution.The date on which the product became available for sale. Sales are never generated before this date. Used as the reference point for
days_since_launch in vw_product_launches.Cost of goods per unit. Used in
generate_sales.py to compute cost = units × unit_cost.Retail price per unit before any discount. Revenue is calculated as
units × unit_price × (1 − discount).dim_customers
Holds 5,000 synthetic customer profiles. Customers are not individually named — they are represented by behavioural and demographic segments to protect analytical generalisability.Surrogate primary key. Referenced by every row in
fact_sales.Age bracket of the customer. One of:
18-24, 25-34, 35-44, 45-54, 55+.Geographic sales region. One of:
North, South, East, West, Center.The sales channel this customer most frequently uses. One of:
Supermarket, E-commerce, Convenience Store, Hypermarket.Behavioural purchase frequency segment. One of:
Low, Medium, High. During sales generation, customers are sampled with weights Low=1, Medium=2, High=4, so high-frequency buyers appear proportionally more often in fact_sales.Average transaction value for this customer segment. Stored as a descriptive attribute; the actual per-transaction revenue is computed and stored in
fact_sales.fact_sales
The central fact table. Each row records one transaction: which customer bought which product, on what date, at what discount, and the resulting financial metrics. The table is designed to grow large —sale_id is a BIGINT — and is populated with 100,000 rows by default.
Sequential surrogate primary key assigned during data generation.
Calendar date of the transaction. Ranges from 2023-01-01 to 2025-12-31. Always ≥ the product’s
launch_date.Foreign key →
dim_customers.customer_id.Foreign key →
dim_products.product_id.Number of units sold in this transaction. Base range is 1–3. Discounted transactions receive an additional 0–2 units to simulate promotional lift.
Fractional discount applied to the unit price. Sampled from
{0.00, 0.10, 0.20, 0.30} with weights 70% / 15% / 10% / 5% respectively. A value of 0.10 represents a 10% discount.Net revenue after discount:
units × unit_price × (1 − discount). Rounded to 2 decimal places.Total cost of goods:
units × unit_cost. Rounded to 2 decimal places.Gross margin:
revenue − cost. Rounded to 2 decimal places. Can be negative when deep discounts push revenue below cost for high-cost products.Foreign Key Relationships
Both foreign keys infact_sales are enforced at the database level.
TRUNCATE … CASCADE pattern used by the ETL loader respects these constraints by truncating fact_sales before the dimension tables, preventing foreign-key violations during reloads.
Domain Value Reference
| Field | Table | Valid Values |
|---|---|---|
category | dim_products | Gummies, Belts, Seasonal, Marshmallow, Licorice, Foam, Novelty |
season | dim_products | All Year, Halloween, Christmas, Summer, Valentine |
region | dim_customers | North, South, East, West, Center |
preferred_channel | dim_customers | Supermarket, E-commerce, Convenience Store, Hypermarket |
purchase_frequency | dim_customers | Low, Medium, High |
age_group | dim_customers | 18-24, 25-34, 35-44, 45-54, 55+ |
discount | fact_sales | 0.00 (70%), 0.10 (15%), 0.20 (10%), 0.30 (5%) |