first commit
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
-- Fitness Tracking App - Production Database Schema
|
||||
-- Database: fitness_app
|
||||
-- Created: 2026-04-21
|
||||
|
||||
-- Create Database
|
||||
CREATE DATABASE IF NOT EXISTS fitness_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
USE fitness_app;
|
||||
|
||||
-- Users Table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid CHAR(36) UNIQUE NOT NULL COMMENT 'Unique identifier for the user',
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
email VARCHAR(100) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL COMMENT 'bcrypt hash',
|
||||
api_key VARCHAR(64) UNIQUE NOT NULL COMMENT 'API key for client authentication',
|
||||
api_secret VARCHAR(64) NOT NULL COMMENT 'Secret for HMAC signature',
|
||||
full_name VARCHAR(100),
|
||||
avatar_url VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_uuid (uuid),
|
||||
INDEX idx_api_key (api_key),
|
||||
INDEX idx_created_at (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Workouts Table
|
||||
CREATE TABLE IF NOT EXISTS workouts (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
workout_uuid CHAR(36) UNIQUE NOT NULL COMMENT 'Unique identifier for the workout',
|
||||
user_id INT NOT NULL,
|
||||
workout_type ENUM('running', 'walking') NOT NULL,
|
||||
distance_meters INT NOT NULL COMMENT 'Total distance in meters',
|
||||
duration_seconds INT NOT NULL COMMENT 'Total duration in seconds',
|
||||
elevation_gain_meters INT DEFAULT 0 COMMENT 'Elevation gain in meters',
|
||||
elevation_loss_meters INT DEFAULT 0 COMMENT 'Elevation loss in meters',
|
||||
calories_burned FLOAT DEFAULT 0,
|
||||
average_pace_mps FLOAT COMMENT 'Average pace in meters per second',
|
||||
max_speed_mps FLOAT DEFAULT 0 COMMENT 'Max speed in meters per second',
|
||||
route_polyline LONGTEXT NOT NULL COMMENT 'Encoded polyline format (Google Maps Polyline Algorithm)',
|
||||
coordinate_count INT NOT NULL COMMENT 'Total number of GPS coordinates recorded',
|
||||
start_lat DECIMAL(10, 8) NOT NULL,
|
||||
start_lng DECIMAL(11, 8) NOT NULL,
|
||||
end_lat DECIMAL(10, 8) NOT NULL,
|
||||
end_lng DECIMAL(11, 8) NOT NULL,
|
||||
start_time DATETIME NOT NULL COMMENT 'ISO 8601 datetime when workout started',
|
||||
end_time DATETIME NOT NULL COMMENT 'ISO 8601 datetime when workout ended',
|
||||
weather_condition VARCHAR(50),
|
||||
temperature_celsius FLOAT,
|
||||
notes TEXT,
|
||||
is_public BOOLEAN DEFAULT FALSE,
|
||||
synced_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
INDEX idx_workout_uuid (workout_uuid),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_workout_type (workout_type),
|
||||
INDEX idx_synced_at (synced_at),
|
||||
INDEX idx_created_at (created_at),
|
||||
INDEX idx_user_created (user_id, created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Workout Segments Table (for detailed route tracking if needed)
|
||||
CREATE TABLE IF NOT EXISTS workout_segments (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
workout_id INT NOT NULL,
|
||||
segment_order INT NOT NULL COMMENT 'Order of segment in workout',
|
||||
duration_seconds INT,
|
||||
distance_meters INT,
|
||||
average_pace_mps FLOAT,
|
||||
index_in_polyline INT COMMENT 'Start index in polyline',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (workout_id) REFERENCES workouts(id) ON DELETE CASCADE,
|
||||
INDEX idx_workout_id (workout_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- API Logs Table (for debugging and analytics)
|
||||
CREATE TABLE IF NOT EXISTS api_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT,
|
||||
endpoint VARCHAR(255),
|
||||
method VARCHAR(10),
|
||||
status_code INT,
|
||||
request_hash VARCHAR(64) COMMENT 'Hash of request for deduplication',
|
||||
ip_address VARCHAR(45),
|
||||
user_agent VARCHAR(255),
|
||||
response_time_ms INT,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_created_at (created_at),
|
||||
INDEX idx_endpoint (endpoint),
|
||||
INDEX idx_request_hash (request_hash)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Statistics Cache Table (for performance optimization)
|
||||
CREATE TABLE IF NOT EXISTS user_stats_cache (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT UNIQUE NOT NULL,
|
||||
total_workouts INT DEFAULT 0,
|
||||
total_distance_meters INT DEFAULT 0,
|
||||
total_duration_seconds INT DEFAULT 0,
|
||||
total_calories_burned FLOAT DEFAULT 0,
|
||||
average_pace_mps FLOAT,
|
||||
last_workout_date DATETIME,
|
||||
streak_days INT DEFAULT 0,
|
||||
cached_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_cached_at (cached_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Create Triggers for audit trail
|
||||
DELIMITER $$
|
||||
|
||||
CREATE TRIGGER workout_audit_insert AFTER INSERT ON workouts
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO api_logs (endpoint, method, status_code, error_message, created_at)
|
||||
VALUES ('workouts', 'INSERT', 201, NULL, NOW());
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
-- Stored Procedure to get user workout statistics
|
||||
DELIMITER $$
|
||||
|
||||
CREATE PROCEDURE GetUserStats(IN p_user_id INT)
|
||||
BEGIN
|
||||
SELECT
|
||||
COUNT(*) as total_workouts,
|
||||
SUM(distance_meters) as total_distance,
|
||||
SUM(duration_seconds) as total_duration,
|
||||
SUM(calories_burned) as total_calories,
|
||||
AVG(average_pace_mps) as avg_pace,
|
||||
MAX(created_at) as last_workout,
|
||||
workout_type
|
||||
FROM workouts
|
||||
WHERE user_id = p_user_id
|
||||
GROUP BY workout_type
|
||||
ORDER BY created_at DESC;
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
-- Initial indexes for optimal query performance
|
||||
CREATE INDEX idx_workouts_stats ON workouts(user_id, workout_type, created_at);
|
||||
CREATE INDEX idx_users_active ON users(is_active, created_at);
|
||||
Reference in New Issue
Block a user