Freshly Baked • Deliciously Served • Always with Love

Sign In to Eniceberny

Order faster & track deliveries

Sign In →
Eniceberny Bakery and Catering Enterprise

Relational Database Schema & Entity Architecture

This document details the relational database architecture, entity relationships, schema migrations, indexing strategies, and transactional locking mechanisms powering Eniceberny Bakery and Culinary Hub.


1. Entity Relationship Diagram (ERD)

erDiagram
    users ||--o{ orders : places
    users ||--o{ addresses : has
    users ||--o| customer_profiles : has
    categories ||--o{ products : contains
    categories ||--o{ categories : "parent / children"
    products ||--o{ product_variants : has
    products ||--o{ product_options : has
    products ||--o{ product_images : has
    products ||--o{ inventory_movements : tracks
    orders ||--o{ order_items : contains
    orders ||--o{ order_status_histories : logs
    orders ||--o{ payment_transactions : records
    carts ||--o{ cart_items : contains
    catering_services ||--o{ catering_packages : includes
    catering_inquiries ||--o| quotes : generates
    quotes ||--o{ quote_items : contains
    quotes ||--o| orders : converts_to

2. Table Specifications & Column Definitions

2.1 Identity, Access & Customers

  • users:
    • id (bigint, PK)
    • name (string)
    • email (string, unique, index)
    • phone (string, nullable, index)
    • password (string, Bcrypt hash)
    • role (string, default: 'customer', index)
    • email_verified_at (timestamp, nullable)
    • otp_code (string, nullable)
    • otp_expires_at (timestamp, nullable)
    • is_active (boolean, default: true, index)
    • permissions (json, nullable)
  • customer_profiles:
    • id (bigint, PK)
    • user_id (bigint, FK -> users.id, unique)
    • total_spent (decimal 10,2, default: 0.00)
    • total_orders (integer, default: 0)
    • notes (text, nullable)
  • addresses:
    • id (bigint, PK)
    • user_id (bigint, FK -> users.id)
    • recipient_name (string)
    • phone (string)
    • street (string)
    • city (string)
    • region (string)
    • landmark (string, nullable)
    • digital_address (string, nullable, GhanaPostGPS code)
    • is_default (boolean, default: false)

2.2 Catalog & Inventory

  • categories:
    • id (bigint, PK)
    • name (string)
    • slug (string, unique, index)
    • description (text, nullable)
    • image_path (string, nullable)
    • parent_id (bigint, nullable, FK -> categories.id)
    • sort_order (integer, default: 0)
    • is_active (boolean, default: true, index)
  • products:
    • id (bigint, PK)
    • category_id (bigint, FK -> categories.id, index)
    • name (string)
    • slug (string, unique, index)
    • sku (string, unique, index)
    • description (text, nullable)
    • price (decimal 10,2)
    • sale_price (decimal 10,2, nullable)
    • track_inventory (boolean, default: false)
    • stock_quantity (integer, default: 0)
    • is_available (boolean, default: true, index)
    • is_featured (boolean, default: false, index)
    • is_bestseller (boolean, default: false, index)
    • prep_time_minutes (integer, default: 15)
  • product_variants:
    • id (bigint, PK)
    • product_id (bigint, FK -> products.id, cascade delete)
    • name (string, e.g. "8-inch", "Party Pan")
    • price (decimal 10,2)
    • sku (string, nullable)
    • stock_quantity (integer, default: 0)
  • inventory_movements:
    • id (bigint, PK)
    • product_id (bigint, FK -> products.id)
    • user_id (bigint, nullable, FK -> users.id)
    • movement_type (string, 'sale', 'pos_sale', 'restock', 'adjustment')
    • quantity_change (integer, positive or negative)
    • quantity_after (integer)
    • reason (string, nullable)

2.3 Orders & Commerce Ledger

  • orders:
    • id (bigint, PK)
    • order_number (string, unique, index, e.g. EB-20260927-1402)
    • user_id (bigint, nullable, FK -> users.id, index)
    • customer_name (string)
    • customer_email (string)
    • customer_phone (string, index)
    • source (string, 'storefront', 'pos', 'catering', index)
    • order_type (string, 'delivery', 'pickup', 'dine_in', 'takeaway')
    • status (string, 'pending', 'confirmed', 'preparing', 'ready_for_pickup', 'out_for_delivery', 'delivered', 'cancelled', index)
    • payment_status (string, 'pending', 'paid', 'failed', 'refunded', index)
    • payment_method (string, 'cash', 'momo', 'paystack')
    • subtotal (decimal 10,2)
    • delivery_fee (decimal 10,2, default: 0.00)
    • discount_amount (decimal 10,2, default: 0.00)
    • tax_amount (decimal 10,2, default: 0.00)
    • total (decimal 10,2)
    • delivery_address_json (json, nullable)
  • order_items:
    • id (bigint, PK)
    • order_id (bigint, FK -> orders.id, cascade delete)
    • product_id (bigint, nullable, FK -> products.id)
    • product_name (string)
    • variant_name (string, nullable)
    • unit_price (decimal 10,2)
    • quantity (integer)
    • subtotal (decimal 10,2)
    • custom_options (json, nullable)
  • payment_transactions:
    • id (bigint, PK)
    • order_id (bigint, FK -> orders.id)
    • gateway (string, 'cash', 'momo', 'paystack', index)
    • reference (string, unique, index)
    • amount (decimal 10,2)
    • currency (string, default: 'GHS')
    • status (string, 'pending', 'success', 'failed')
    • provider_response (json, nullable)

2.4 Catering & Quotation Subsystem

  • catering_inquiries:
    • id (bigint, PK)
    • name (string)
    • email (string)
    • phone (string)
    • event_type (string)
    • event_date (date)
    • guest_count (integer)
    • budget (decimal 10,2, nullable)
    • message (text, nullable)
    • status (string, 'pending', 'under_review', 'quoted', 'confirmed', 'declined', index)
  • quotes:
    • id (bigint, PK)
    • quote_number (string, unique, index, e.g. QT-260927-4401)
    • catering_inquiry_id (bigint, nullable, FK -> catering_inquiries.id)
    • customer_name (string)
    • customer_email (string)
    • customer_phone (string)
    • event_date (date)
    • headcount (integer)
    • subtotal (decimal 10,2)
    • discount_amount (decimal 10,2, default: 0.00)
    • tax_amount (decimal 10,2, default: 0.00)
    • total (decimal 10,2)
    • status (string, 'draft', 'sent', 'accepted', 'converted', 'expired', index)
    • terms (text, nullable)
  • quote_items:
    • id (bigint, PK)
    • quote_id (bigint, FK -> quotes.id, cascade delete)
    • description (string)
    • quantity (integer)
    • unit_price (decimal 10,2)
    • subtotal (decimal 10,2)

3. Database Indexes & Performance Optimizations

  1. Composite & Foreign Indexes:
    • orders(status, created_at): Powers the executive dashboard live orders table and daily aggregation metrics.
    • products(category_id, is_available): Optimizes public storefront shop filtering and category page rendering.
  2. Transaction Isolation:
    • Critical checkout and stock deduction routines are locked within DB::transaction() to eliminate race conditions and overselling during simultaneous online and counter POS sales.

Your Bakery Basket

Subtotal:

Fresh orders prepared promptly upon checkout