-- Fociz MariaDB Databaseschema -- UTF-8 / utf8mb4 ondersteuning voor emoticons, sticky notes en internationale tekens CREATE TABLE IF NOT EXISTS `users` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(120) NOT NULL, `email` VARCHAR(191) NOT NULL UNIQUE, `password_hash` VARCHAR(255) NOT NULL, `role` ENUM('ADMIN', 'MEMBER') NOT NULL DEFAULT 'MEMBER', `two_factor_secret` VARCHAR(120) NULL, `two_factor_enabled` TINYINT(1) NOT NULL DEFAULT 0, `backup_codes` TEXT NULL, `remember_token` VARCHAR(64) NULL, `remember_token_expires_at` DATETIME NULL, `notification_settings` TEXT NULL, `avatar_url` VARCHAR(255) NULL, `default_jira_filter_code` VARCHAR(50) NULL, `fociz_widget_layout` TEXT NULL, `last_mail_check_at` DATETIME NULL, `last_jira_check_at` DATETIME NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `invites` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `token` VARCHAR(64) NOT NULL UNIQUE, `email` VARCHAR(191) NOT NULL, `role` ENUM('ADMIN', 'MEMBER') NOT NULL DEFAULT 'MEMBER', `expires_at` DATETIME NOT NULL, `used_at` DATETIME NULL, `created_by_id` INT NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX (`token`), CONSTRAINT `fk_invites_user` FOREIGN KEY (`created_by_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `password_resets` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `email` VARCHAR(191) NOT NULL, `token` VARCHAR(64) NOT NULL UNIQUE, `expires_at` DATETIME NOT NULL, `used_at` DATETIME NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX (`email`), INDEX (`token`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `daily_plans` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `plan_date` DATE NOT NULL, `focus_goal` TEXT NULL, `secondary_goals` TEXT NULL, `notes` TEXT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `uk_user_date` (`user_id`, `plan_date`), CONSTRAINT `fk_dailyplans_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `tasks` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `daily_plan_id` INT NULL, `title` VARCHAR(255) NOT NULL, `description` TEXT NULL, `status` ENUM('TODO', 'IN_PROGRESS', 'DONE', 'CANCELLED') NOT NULL DEFAULT 'TODO', `priority` ENUM('P1', 'P2', 'P3') NOT NULL DEFAULT 'P2', `time_block_start` VARCHAR(10) NULL, `time_block_end` VARCHAR(10) NULL, `duration_minutes` INT NULL DEFAULT 30, `is_completed` TINYINT(1) NOT NULL DEFAULT 0, `source` VARCHAR(50) NOT NULL DEFAULT 'FOCIZ', `external_id` VARCHAR(255) NULL, `external_url` TEXT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`user_id`), CONSTRAINT `fk_tasks_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_tasks_plan` FOREIGN KEY (`daily_plan_id`) REFERENCES `daily_plans` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `brainstorm_sessions` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `title` VARCHAR(255) NOT NULL, `description` TEXT NULL, `theme` VARCHAR(100) NOT NULL DEFAULT 'Algemeen', `created_by_id` INT NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`created_by_id`), CONSTRAINT `fk_brainstorm_user` FOREIGN KEY (`created_by_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `brainstorm_cards` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `session_id` INT NOT NULL, `content` TEXT NOT NULL, `category` VARCHAR(100) NOT NULL DEFAULT 'Ideeën', `color` VARCHAR(20) NOT NULL DEFAULT 'amber', `votes` INT NOT NULL DEFAULT 0, `author_name` VARCHAR(120) NULL, `converted_to_roadmap_item_id` INT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`session_id`), CONSTRAINT `fk_cards_session` FOREIGN KEY (`session_id`) REFERENCES `brainstorm_sessions` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `roadmap_items` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `title` VARCHAR(255) NOT NULL, `description` TEXT NULL, `type` VARCHAR(50) NOT NULL DEFAULT 'FEATURE', `status` VARCHAR(50) NOT NULL DEFAULT 'PLANNED', `quarter` VARCHAR(20) NOT NULL DEFAULT 'Q3', `priority` VARCHAR(20) NOT NULL DEFAULT 'MEDIUM', `progress` INT NOT NULL DEFAULT 0, `start_date` DATE NULL, `due_date` DATE NULL, `jira_issue_key` VARCHAR(50) NULL, `origin_brainstorm_card_id` INT NULL, `created_by_id` INT NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`created_by_id`), CONSTRAINT `fk_roadmap_user` FOREIGN KEY (`created_by_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `integrations` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `provider` ENUM('OUTLOOK', 'TEAMS', 'JIRA') NOT NULL, `is_enabled` TINYINT(1) NOT NULL DEFAULT 1, `is_demo_mode` TINYINT(1) NOT NULL DEFAULT 1, `access_token` TEXT NULL, `refresh_token` TEXT NULL, `settings` TEXT NULL, `last_sync_at` DATETIME NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `uk_user_provider` (`user_id`, `provider`), CONSTRAINT `fk_integrations_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `system_settings` ( `setting_key` VARCHAR(64) PRIMARY KEY, `setting_value` TEXT NULL, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- Fociz Kanban / Trello Borden, Lanes, Kaarten & Tijdspadkoppelingen CREATE TABLE IF NOT EXISTS `boards` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `title` VARCHAR(255) NOT NULL, `description` TEXT NULL, `created_by_id` INT NOT NULL, `is_archived` TINYINT(1) NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`created_by_id`), CONSTRAINT `fk_boards_creator` FOREIGN KEY (`created_by_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `board_members` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `board_id` INT NOT NULL, `user_id` INT NOT NULL, `role` ENUM('ADMIN', 'MEMBER', 'VIEWER') NOT NULL DEFAULT 'MEMBER', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `uk_board_user` (`board_id`, `user_id`), CONSTRAINT `fk_bmembers_board` FOREIGN KEY (`board_id`) REFERENCES `boards` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_bmembers_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `board_lanes` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `board_id` INT NOT NULL, `title` VARCHAR(100) NOT NULL, `color` VARCHAR(30) NOT NULL DEFAULT 'slate', `position` INT NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`board_id`, `position`), CONSTRAINT `fk_blanes_board` FOREIGN KEY (`board_id`) REFERENCES `boards` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `board_cards` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `board_id` INT NOT NULL, `lane_id` INT NOT NULL, `title` VARCHAR(255) NOT NULL, `description` TEXT NULL, `assignee_id` INT NULL, `priority` ENUM('P1', 'P2', 'P3') NOT NULL DEFAULT 'P2', `color` VARCHAR(30) NOT NULL DEFAULT 'yellow', `position` INT NOT NULL DEFAULT 0, `created_by_id` INT NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`board_id`, `lane_id`, `position`), INDEX (`assignee_id`), CONSTRAINT `fk_bcards_board` FOREIGN KEY (`board_id`) REFERENCES `boards` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_bcards_lane` FOREIGN KEY (`lane_id`) REFERENCES `board_lanes` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_bcards_assignee` FOREIGN KEY (`assignee_id`) REFERENCES `users` (`id`) ON DELETE SET NULL, CONSTRAINT `fk_bcards_creator` FOREIGN KEY (`created_by_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `board_card_schedules` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `card_id` INT NOT NULL, `schedule_type` ENUM('SINGLE', 'DAILY_RANGE') NOT NULL DEFAULT 'SINGLE', `start_date` DATE NOT NULL, `end_date` DATE NOT NULL, `start_time` VARCHAR(10) NOT NULL DEFAULT '14:00', `end_time` VARCHAR(10) NOT NULL DEFAULT '15:00', `days_of_week` VARCHAR(50) NULL DEFAULT '1,2,3,4,5', `outlook_event_id` VARCHAR(255) NULL, `outlook_synced_at` DATETIME NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `uk_sched_card` (`card_id`), CONSTRAINT `fk_bsched_card` FOREIGN KEY (`card_id`) REFERENCES `board_cards` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `jira_queue_filters` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `filter_code` VARCHAR(50) NOT NULL UNIQUE, `filter_name` VARCHAR(120) NOT NULL, `project_key` VARCHAR(50) NULL, `jql_clause` TEXT NOT NULL, `description` VARCHAR(255) NULL, `is_active` TINYINT(1) NOT NULL DEFAULT 1, `sort_order` INT NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `app_cache` ( `cache_key` VARCHAR(128) NOT NULL PRIMARY KEY, `cache_value` MEDIUMTEXT NOT NULL, `expires_at` INT UNSIGNED NOT NULL, INDEX `idx_app_cache_expires` (`expires_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- Fociz V2.0: Subtaken & Checklists per taak CREATE TABLE IF NOT EXISTS `task_subtasks` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `task_id` INT NOT NULL, `user_id` INT NOT NULL, `title` VARCHAR(255) NOT NULL, `is_completed` TINYINT(1) NOT NULL DEFAULT 0, `position` INT NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX (`task_id`, `position`), CONSTRAINT `fk_subtasks_task` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_subtasks_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;