Skip to content

teibokchyne/JustEat

Repository files navigation

JustEat Application

A comprehensive food delivery platform built with Flask, featuring role-based access for customers and restaurant owners, intelligent menu recommendations, and comprehensive order management.

Table of Contents

Prerequisites

System Requirements

  • Python: 3.8 or higher

Software Dependencies

  • Python 3.8+
  • pip (Python package installer)
  • Git (for version control)

Installation

1. Clone the Repository

git clone <repository-url>
cd Exit_Test

2. Create Virtual Environment

# Create virtual environment
python -m venv venv

# Activate virtual environment
# Windows:
venv\Scripts\activate
# Linux/Mac:
source venv/bin/activate

3. Install Dependencies

# Install required packages
pip install -r requirements.txt

4. Environment Configuration

Create a .env file in the root directory:

# Copy example environment file
copy .env.example .env

Edit .env file with your configuration:

SECRET_KEY=your-secret-key-here
FLASK_ENV=development
FLASK_DEBUG=True

Important: Replace your-secret-key-here with a secure random string.

Database Setup

1. Seed Database with Sample Data

# Run the run.py with "seed" argument for seeding script
python run.py seed

This will:

  • Create all necessary database tables
  • Load sample users, restaurants, menu items, and orders
  • Set up relationships between entities
  • Create log files directory

2. Verify Database Setup

Check that the database file was created:

  • Location: justeat/databases/site.db
  • Size: Should be several MB after seeding

3. Sample Data Overview

The seeded database includes:

Users (5 total)

  • Customers: Alice, Diana
  • Restaurant Owners: Bob, Charlie, Ethan
  • Default Password: password (hashed with bcrypt)

Restaurants (3 total)

  • Bob's Burgers (Owner: Bob)
  • The Masala Mill (Owner: Charlie)
  • Ethan's Eatery (Owner: Ethan)

Menu Items (15+ total)

  • Various cuisines: Italian, Indian, American
  • Different diet types: Vegetarian, Non-Vegetarian, Vegan
  • Price range: $5-$25
  • Special items and discounts

Orders and Reviews

  • Sample order history
  • Customer reviews and ratings
  • Feedback and responses

Running the Application

Development Mode

# Run the Flask development server
python run.py

The application will start on http://localhost:5000

Production Mode

# Set production environment
set FLASK_ENV=production
# Linux/Mac: export FLASK_ENV=production

# Run with production settings
python run.py

Application Features

For Customers

  • Browse restaurants and menu items
  • Add items to cart and checkout
  • View order history
  • Leave reviews and feedback
  • Manage dietary preferences
  • Get personalized recommendations

For Restaurant Owners

  • Register and manage restaurants
  • Add/edit/delete menu items
  • View and manage orders
  • Respond to customer feedback
  • Track restaurant performance

Testing

1. Run All Tests

# Run all tests with verbose output
pytest -v

# Run tests with coverage report
pytest --cov=justeat --cov-report=html

2. Run Specific Test Categories

# Test routes
pytest tests/test_routes.py -v

# Test services
pytest tests/test_services.py -v

# Test ui
pytest tests/test_ui.py -v

Logging

Log Files Location

  • Directory: logs/

Troubleshooting

Common Issues

1. Database Connection Error

# Check if database file exists
ls justeat/databases/site.db

# Recreate database
rm justeat/databases/site.db
python seed_db.py

2. Import Errors

# Ensure virtual environment is activated
venv\Scripts\activate.bat  # Windows
source venv/bin/activate  # Linux/Mac

# Reinstall dependencies
pip install -r requirements.txt

Project Structure

The JustEat application follows a modular Flask architecture with clear separation of concerns:

Exit_Test/                                    # Project root directory
├── justeat/                                  # Main application package
│   ├── __init__.py                          # Flask app factory and initialization
│   ├── config.py                            # Application configuration settings
│   ├── models.py                            # SQLAlchemy database models
│   ├── forms.py                             # WTForms form definitions
│   ├── databases/                           # Database-related modules
│   │   ├── __init__.py
│   │   ├── cursor.py                        # Custom database cursor class
│   │   └── site.db                          # SQLite database file
│   ├── routes/                              # Flask route blueprints
│   │   ├── __init__.py
│   │   ├── user.py                          # Authentication routes (login/logout)
│   │   ├── customer.py                      # Customer-specific routes
│   │   └── restaurant_owner.py              # Restaurant owner routes
│   ├── services/                            # Business logic layer
│   │   ├── __init__.py
│   │   ├── user.py                          # User management services
│   │   ├── customer.py                      # Customer business logic
│   │   └── restaurant_owner.py              # Restaurant owner business logic
│   ├── templates/                           # Jinja2 HTML templates
│   │   ├── layout.html                      # Base template with navigation
│   │   ├── user/                            # Unauthenticated user templates
│   │   │   ├── home.html                    # Landing page
│   │   │   ├── login.html                   # Login form
│   │   │   └── profile.html                 # User profile
│   │   ├── customer/                        # Customer-specific templates
│   │   │   ├── home.html                    # Customer dashboard
│   │   │   ├── display_restaurants.html     # Restaurant listing
│   │   │   ├── display_restaurant.html      # Individual restaurant view
│   │   │   ├── display_cart.html            # Shopping cart
│   │   │   ├── display_orders.html          # Order history
│   │   │   ├── display_order.html           # Individual order details
│   │   │   ├── edit_preferences.html        # User preferences
│   │   │   ├── add_review.html              # Add review form
│   │   │   ├── display_reviews.html         # Reviews listing
│   │   │   ├── add_feedback.html            # Add feedback form
│   │   │   └── display_feedbacks.html       # Feedback listing
│   │   └── restaurant_owner/                # Restaurant owner templates
│   │       ├── home.html                    # Owner dashboard
│   │       ├── register_restaurant.html     # Restaurant registration
│   │       ├── display_restaurant.html      # Restaurant management
│   │       ├── add_item.html                # Add menu item
│   │       ├── display_item.html            # Menu item details
│   │       ├── edit_item.html               # Edit menu item
│   │       ├── display_orders.html          # Order management
│   │       ├── display_order.html           # Individual order details
│   │       ├── display_feedbacks.html       # Customer feedback
│   │       └── reply_feedback.html          # Reply to feedback
│   └── static/                              # Static assets
│       ├── css/
│       │   └── style.css                    # Custom CSS styles
│       ├── js/
│       │   └── scripts.js                   # Custom JavaScript
│       └── seed_data.json                   # Sample data for database seeding
├── logs/                                    # Application log files
│   ├── justeat.log
├── venv/                                    # Python virtual environment
│   ├── Scripts/                             # Windows activation scripts
│   ├── Lib/                                 # Python packages
│   └── pyvenv.cfg                           # Virtual environment config
├── run.py                                   # Application entry point
├── seed_db.py                               # Database seeding script
└── README.md                                # This file

Directory Descriptions

Core Application (justeat/)

  • __init__.py: Flask application factory, extension initialization, and logging setup
  • config.py: Configuration settings including database URI and secret key
  • models.py: SQLAlchemy ORM models for all database entities
  • forms.py: WTForms form classes for data validation and CSRF protection

Database Layer (justeat/databases/)

  • cursor.py: Custom database abstraction layer with CRUD operations
  • site.db: SQLite database file containing all application data

Route Layer (justeat/routes/)

  • user.py: Authentication routes (login, logout, profile management)
  • customer.py: Customer-specific routes (browsing, ordering, reviews)
  • restaurant_owner.py: Restaurant owner routes (management, orders, feedback)

Service Layer (justeat/services/)

  • user.py: User management, authentication, and session handling
  • customer.py: Customer business logic, recommendations, and cart management
  • restaurant_owner.py: Restaurant management and order processing

Template Layer (justeat/templates/)

  • layout.html: Base template with navigation, flash messages, and common elements
  • user/: Templates for unauthenticated users (landing, login, profile)
  • customer/: Customer-specific templates (dashboard, ordering, reviews)
  • restaurant_owner/: Restaurant owner templates (management, orders, feedback)

Static Assets (justeat/static/)

  • css/style.css: Custom CSS for styling and responsive design
  • js/scripts.js: JavaScript for interactive features and form handling
  • seed_data.json: Sample data for database initialization

Logging (logs/)

  • justeat.log: Comprehensive application logs (DEBUG, INFO, WARNING, ERROR, CRITICAL)

Root Files

  • run.py: Main application entry point for development server
  • seed_db.py: Database initialization and sample data loading

Database Schema

The JustEat application uses SQLite database with a comprehensive schema designed for a food delivery platform. The database follows normalized design principles with proper relationships and constraints. The detailed diagram is in ER_Diagram.html

Entity Relationship Diagram

┌─────────────┐    ┌──────────────┐    ┌─────────────┐
│    User     │    │  Restaurant  │    │  MenuItem   │
├─────────────┤    ├──────────────┤    ├─────────────┤
│ id (PK)     │◄───┤ id (PK)      │◄───┤ id (PK)     │
│ role        │    │ owner_id (FK)│    │ restaurant_id(FK)│
│ name        │    │ name         │    │ diet_id (FK)│
│ email       │    │ location     │    │ cuisine_id(FK)│
│ password    │    └──────────────┘    │ name        │
└─────────────┘                        │ price       │
       │                               │ description │
       │                               │ is_special  │
       │                               │ discount    │
       │                               │ order_count │
       │                               └─────────────┘
       │                                        │
       │                               ┌─────────────┐
       │                               │ OrderItem   │
       │                               ├─────────────┤
       │                               │ item_id (FK)│
       │                               │ order_id(FK)│
       │                               │ quantity    │
       │                               └─────────────┘
       │                                        │
       │                               ┌─────────────┐
       │                               │   Order     │
       │                               ├─────────────┤
       │                               │ id (PK)     │
       │                               │ restaurant_id(FK)│
       │                               │ customer_id(FK)│
       │                               │ total_cost  │
       │                               │ datetime    │
       │                               │ status      │
       │                               └─────────────┘
       │
       │                               ┌─────────────┐
       │                               │   Review    │
       │                               ├─────────────┤
       │                               │ id (PK)     │
       │                               │ customer_id(FK)│
       │                               │ restaurant_id(FK)│
       │                               │ cuisine_id(FK)│
       │                               │ rating      │
       │                               │ review      │
       │                               └─────────────┘
       │
       │                               ┌─────────────┐
       │                               │  Feedback   │
       │                               ├─────────────┤
       │                               │ id (PK)     │
       │                               │ customer_id(FK)│
       │                               │ restaurant_id(FK)│
       │                               │ feedback    │
       │                               │ reply       │
       │                               └─────────────┘
       │
       │                               ┌─────────────┐
       │                               │    Diet     │
       │                               ├─────────────┤
       │                               │ id (PK)     │
       │                               │ name        │
       │                               └─────────────┘
       │
       │                               ┌─────────────┐
       │                               │   Cuisine   │
       │                               ├─────────────┤
       │                               │ id (PK)     │
       │                               │ name        │
       │                               └─────────────┘

Table Definitions

1. User Table

Purpose: Stores user account information for both customers and restaurant owners.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique user identifier
role INTEGER NOT NULL User role (0=Customer, 1=Restaurant Owner)
name VARCHAR(20) NOT NULL User's display name
email VARCHAR(50) NOT NULL User's email address (unique)
password VARCHAR(60) NOT NULL Bcrypt hashed password

Relationships:

  • One-to-Many with Restaurant (restaurant owners)
  • One-to-Many with Order (customers)
  • Many-to-Many with Diet (diet preferences)
  • Many-to-Many with Cuisine (cuisine preferences)
  • Many-to-Many with Restaurant (favorite restaurants)

2. Restaurant Table

Purpose: Stores restaurant information and links to owners.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique restaurant identifier
owner_id INTEGER NOT NULL, FOREIGN KEY Reference to User table
name VARCHAR(20) NOT NULL Restaurant name
location INTEGER NOT NULL Location code/zip code

Relationships:

  • Many-to-One with User (restaurant owner)
  • One-to-Many with MenuItem (menu items)
  • One-to-Many with Order (orders placed)
  • Many-to-Many with User (favorite restaurants)

3. Diet Table

Purpose: Stores dietary preference categories.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique diet identifier
name VARCHAR(20) NOT NULL Diet type name (e.g., Vegetarian, Vegan)

Relationships:

  • One-to-Many with MenuItem (menu items with this diet)
  • Many-to-Many with User (user diet preferences)

4. Cuisine Table

Purpose: Stores cuisine type categories.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique cuisine identifier
name VARCHAR(20) NOT NULL Cuisine type name (e.g., Italian, Indian)

Relationships:

  • One-to-Many with MenuItem (menu items of this cuisine)
  • Many-to-Many with User (user cuisine preferences)

5. MenuItem Table

Purpose: Stores individual menu items with pricing and categorization.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique menu item identifier
restaurant_id INTEGER NOT NULL, FOREIGN KEY Reference to Restaurant table
diet_id INTEGER NOT NULL, FOREIGN KEY Reference to Diet table
cuisine_id INTEGER NOT NULL, FOREIGN KEY Reference to Cuisine table
name VARCHAR(20) NOT NULL Menu item name
price INTEGER NOT NULL Price in cents
description TEXT NOT NULL, DEFAULT "No description" Item description
is_special BOOLEAN NOT NULL, DEFAULT FALSE Special item flag
discount INTEGER NOT NULL, DEFAULT 0 Discount percentage (0-100)
order_count INTEGER NOT NULL, DEFAULT 0 Number of times ordered

Constraints:

  • discount >= 0 AND discount <= 100

Relationships:

  • Many-to-One with Restaurant (belongs to restaurant)
  • Many-to-One with Diet (diet type)
  • Many-to-One with Cuisine (cuisine type)
  • One-to-Many with OrderItem (ordered items)

6. Order Table

Purpose: Stores order information and status.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique order identifier
restaurant_id INTEGER NOT NULL, FOREIGN KEY Reference to Restaurant table
customer_id INTEGER NOT NULL, FOREIGN KEY Reference to User table
total_cost INTEGER NOT NULL Total order cost in cents
datetime DATETIME NOT NULL, DEFAULT NOW() Order timestamp
status ENUM NOT NULL Order status (CART, ORDERED, READY, DELIVERED, CANCELLED, REJECTED)

Order Status Values:

  • CART: Items in shopping cart
  • ORDERED: Order placed, awaiting confirmation
  • READY: Order ready for pickup/delivery
  • DELIVERED: Order completed
  • CANCELLED: Order cancelled by customer
  • REJECTED: Order rejected by restaurant

Relationships:

  • Many-to-One with Restaurant (order from restaurant)
  • Many-to-One with User (customer who placed order)
  • One-to-Many with OrderItem (items in order)

7. OrderItem Table

Purpose: Junction table for order-item relationships with quantities.

Column Type Constraints Description
item_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to MenuItem table
order_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to Order table
quantity INTEGER NOT NULL, DEFAULT 0 Quantity of item in order

Relationships:

  • Many-to-One with MenuItem (menu item)
  • Many-to-One with Order (order containing item)

8. Review Table

Purpose: Stores customer reviews for restaurants or cuisines.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique review identifier
customer_id INTEGER NOT NULL, FOREIGN KEY Reference to User table
restaurant_id INTEGER NULL, FOREIGN KEY Reference to Restaurant table
cuisine_id INTEGER NULL, FOREIGN KEY Reference to Cuisine table
rating INTEGER NOT NULL Rating (1-5 stars)
review TEXT NULL Review text

Constraints:

  • rating > 0 AND rating <= 5
  • Either restaurant_id or cuisine_id must be provided

Relationships:

  • Many-to-One with User (reviewer)
  • Many-to-One with Restaurant (restaurant being reviewed)
  • Many-to-One with Cuisine (cuisine being reviewed)

9. Feedback Table

Purpose: Stores customer feedback and restaurant owner replies.

Column Type Constraints Description
id INTEGER PRIMARY KEY, AUTO_INCREMENT Unique feedback identifier
customer_id INTEGER NOT NULL, FOREIGN KEY Reference to User table
restaurant_id INTEGER NOT NULL, FOREIGN KEY Reference to Restaurant table
feedback TEXT NOT NULL Customer feedback text
reply TEXT NULL Restaurant owner reply

Relationships:

  • Many-to-One with User (feedback author)
  • Many-to-One with Restaurant (restaurant receiving feedback)

Association Tables

1. favourite_restaurant

Purpose: Many-to-many relationship between users and their favorite restaurants.

Column Type Constraints Description
customer_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to User table
restaurant_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to Restaurant table

2. favourite_cuisine

Purpose: Many-to-many relationship between users and their favorite cuisines.

Column Type Constraints Description
customer_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to User table
cuisine_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to Cuisine table

3. diet_preference

Purpose: Many-to-many relationship between users and their dietary preferences.

Column Type Constraints Description
customer_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to User table
diet_id INTEGER PRIMARY KEY, FOREIGN KEY Reference to Diet table

Database Constraints

Primary Keys

  • All tables have auto-incrementing integer primary keys
  • Composite primary keys for association tables

Foreign Keys

  • All foreign key relationships have proper referential integrity
  • Cascade delete for order items when orders are deleted
  • Foreign key constraints enabled via SQLite PRAGMA

Check Constraints

  • MenuItem.discount: Must be between 0 and 100
  • Review.rating: Must be between 1 and 5

Unique Constraints

  • User email addresses are unique
  • Composite unique constraints on association tables

Development

Database Migrations

# Create migration
flask db migrate -m "Description of changes"

# Apply migration
flask db upgrade

System Assumptions

This document outlines all the assumptions made in the JustEat application design and implementation.

Business Logic Assumptions

User Management

  • User Roles: Only two user roles exist - Customer (role=0) and Restaurant Owner (role=1)
  • Authentication: All users must be authenticated to access application features
  • Password Security: Default passwords are 'password' or 'password2' for all seed users
  • User Names: User names are limited to 20 characters maximum
  • Email Validation: Email addresses are limited to 50 characters maximum
  • Password Storage: Passwords are hashed using bcrypt with 60-character storage limit

Recommendation System

  • New Item Recommendations: There will always be items that the customer has not tried
  • Recommendation Limit: Maximum 10 items are recommended to users
  • Preference Scoring: Items are scored based on user's favorite restaurants, cuisines, and diets
  • Random Fallback: If no preferences exist, 10 random items are selected
  • Item Availability: All menu items are always available for recommendation

Order Management

  • Order Status: Orders have predefined statuses defined in OrderStatus class from justeat.models.py
  • Cart Initialization: Every customer gets a cart order automatically created upon login
  • Order Items: Order items are linked to specific menu items and quantities
  • Order Totals: Order totals are calculated based on item prices and quantities
  • Order History: All orders are permanently stored and accessible

Restaurant Management

  • Restaurant Ownership: Each restaurant has exactly one owner
  • Menu Items: Restaurants can have multiple menu items
  • Item Categories: Every menu item must have a diet type and cuisine type
  • Price Storage: Prices are stored as integers (assuming cents or fixed decimal places)
  • Discount Range: Discounts must be between 0-100%
  • Special Items: Items can be marked as special (boolean flag)

Data Model Assumptions

Database Structure

  • Database Type: SQLite database is used for all environments
  • Foreign Keys: Foreign key constraints are enabled via PRAGMA
  • Table Relationships: Many-to-many relationships use association tables
  • Data Integrity: All required fields are non-nullable
  • ID Generation: All primary keys are auto-incrementing integers

Field Constraints

  • String Lengths:
    • User names: 20 characters max
    • Email addresses: 50 characters max
    • Menu item names: 20 characters max
    • Restaurant names: 20 characters max
    • Diet names: 20 characters max
    • Cuisine names: 20 characters max
  • Numeric Ranges:
    • Discounts: 0-100%
    • Prices: Positive integers
    • Order counts: Non-negative integers

Data Relationships

  • User-Restaurant: One-to-many (one owner, many restaurants)
  • User-Orders: One-to-many (one user, many orders)
  • Restaurant-MenuItems: One-to-many (one restaurant, many items)
  • Order-OrderItems: One-to-many (one order, many items)
  • User Preferences: Many-to-many (users can have multiple favorites)

About

Full-stack food delivery app – restaurant discovery, online ordering, real-time tracking, reviews. Technology: Unit Tests, Python Flask, SQLAlchemy, Jinja2, SQLite

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors