diff --git a/api/.gitignore b/api/.gitignore index cc8bf1e..021b40f 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -1 +1,3 @@ -built \ No newline at end of file +built + +!migrations/*.sql \ No newline at end of file diff --git a/api/migrations/20251029012626_init_database.down.sql b/api/migrations/20251029012626_init_database.down.sql new file mode 100644 index 0000000..e69de29 diff --git a/api/migrations/20251029012626_init_database.up.sql b/api/migrations/20251029012626_init_database.up.sql new file mode 100644 index 0000000..b80df9b --- /dev/null +++ b/api/migrations/20251029012626_init_database.up.sql @@ -0,0 +1,609 @@ +-- -------------------------------------------------------- +-- Host: gs.iceberg-gaming.com +-- Server version: 10.6.5-MariaDB - mariadb.org binary distribution +-- Server OS: Win64 +-- HeidiSQL Version: 12.12.0.7122 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!50503 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + + +-- Dumping database structure for ranger_unit_tracker +CREATE DATABASE IF NOT EXISTS `ranger_unit_tracker` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; +USE `ranger_unit_tracker`; + +-- Dumping structure for table ranger_unit_tracker.applications +CREATE TABLE IF NOT EXISTS `applications` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) NOT NULL, + `app_version` int(11) NOT NULL, + `app_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`app_data`)), + `submitted_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT NULL, + `approved_at` datetime DEFAULT NULL, + `denied_at` datetime DEFAULT NULL, + `app_status` varchar(20) GENERATED ALWAYS AS (case when `approved_at` is not null then 'Accepted' when `denied_at` is not null then 'Denied' else 'Pending' end) STORED, + `decision_at` datetime GENERATED ALWAYS AS (coalesce(`approved_at`,`denied_at`)) STORED, + PRIMARY KEY (`id`), + UNIQUE KEY `member_id` (`member_id`), + CONSTRAINT `fk_app_member` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE, + CONSTRAINT `chk_json_valid` CHECK (json_valid(`app_data`)), + CONSTRAINT `chk_app_version` CHECK (`app_version` >= 1), + CONSTRAINT `chk_exclusive_decision` CHECK (`approved_at` is null or `denied_at` is null) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.application_comments +CREATE TABLE IF NOT EXISTS `application_comments` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `post_content` text COLLATE utf8mb4_unicode_ci NOT NULL, + `application_id` int(11) NOT NULL, + `poster_id` int(11) NOT NULL, + `post_time` timestamp NOT NULL DEFAULT current_timestamp(), + `last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + KEY `poster_id` (`poster_id`), + KEY `application_id` (`application_id`), + CONSTRAINT `application_comments_ibfk_1` FOREIGN KEY (`application_id`) REFERENCES `applications` (`id`), + CONSTRAINT `application_comments_ibfk_2` FOREIGN KEY (`poster_id`) REFERENCES `members` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.arma_maps +CREATE TABLE IF NOT EXISTS `arma_maps` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `map` varchar(50) DEFAULT NULL, + `name` text DEFAULT NULL, + `last_used` datetime DEFAULT NULL, + `deleted` tinyint(4) DEFAULT 0, + `workshop_id` varchar(100) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `map` (`map`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='Contains a list of Arma3 Maps'; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.awards +CREATE TABLE IF NOT EXISTS `awards` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` longtext DEFAULT NULL, + `short_name` longtext DEFAULT NULL, + `description` longtext DEFAULT NULL, + `type` longtext DEFAULT NULL, + `footprint` longtext DEFAULT NULL, + `created_at` datetime(3) NOT NULL, + `updated_at` datetime(3) NOT NULL, + `image_url` longtext DEFAULT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `deleted_at` datetime(3) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_awards_deleted` (`deleted`) +) ENGINE=InnoDB AUTO_INCREMENT=81 DEFAULT CHARSET=utf8mb4 COMMENT='Contains a list of Awards for the unit.'; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.calendar_events +CREATE TABLE IF NOT EXISTS `calendar_events` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + `start` datetime NOT NULL, + `end` datetime NOT NULL, + `location` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + `color` char(7) COLLATE utf8mb4_unicode_ci NOT NULL, + `description` text COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `creator` int(11) DEFAULT NULL, + `cancelled` tinyint(1) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `fk_creator` (`creator`), + CONSTRAINT `fk_creator` FOREIGN KEY (`creator`) REFERENCES `members` (`id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.calendar_events_signups +CREATE TABLE IF NOT EXISTS `calendar_events_signups` ( + `member_id` int(11) NOT NULL, + `event_id` int(11) NOT NULL, + `status` enum('not_attending','attending','maybe') COLLATE utf8mb4_unicode_ci NOT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`member_id`,`event_id`), + KEY `fk_signup_event` (`event_id`), + CONSTRAINT `fk_signup_event` FOREIGN KEY (`event_id`) REFERENCES `calendar_events` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_signup_member` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.courses +CREATE TABLE IF NOT EXISTS `courses` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `short_name` varchar(10) NOT NULL, + `category` varchar(100) NOT NULL, + `description` varchar(1000) DEFAULT NULL, + `image_url` varchar(255) DEFAULT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT 0, + `prereq_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + UNIQUE KEY `shortName` (`short_name`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.courses_single +CREATE TABLE IF NOT EXISTS `courses_single` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `short_name` varchar(10) NOT NULL, + `category` varchar(100) NOT NULL, + `description` varchar(1000) DEFAULT NULL, + `image_url` varchar(255) DEFAULT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT 0, + `prereq_id` int(11) DEFAULT NULL, + `require_qual` tinyint(4) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + UNIQUE KEY `shortName` (`short_name`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.courses_sme +CREATE TABLE IF NOT EXISTS `courses_sme` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `course_id` int(11) NOT NULL DEFAULT 0, + `member_id` int(11) NOT NULL DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `fk_course_sme_course_id` (`course_id`), + KEY `fk_course_sme_member_id` (`member_id`), + CONSTRAINT `fk_course_sme_course_id` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_course_sme_member_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.course_attendees +CREATE TABLE IF NOT EXISTS `course_attendees` ( + `passed` tinyint(1) DEFAULT 0, + `attendee_id` int(11) NOT NULL, + `course_event_id` int(11) NOT NULL, + `attendee_role_id` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`attendee_id`,`course_event_id`) USING BTREE, + KEY `courseInstanceId` (`course_event_id`) USING BTREE, + KEY `fk_CourseInstancesMembers_CoureseAttendeeType_id` (`attendee_role_id`) USING BTREE, + CONSTRAINT `fk_course_event_member_coures_attendee_type_id` FOREIGN KEY (`attendee_role_id`) REFERENCES `course_attendee_roles` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_course_event_members_coures_event_id` FOREIGN KEY (`course_event_id`) REFERENCES `course_events` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_course_event_members_members_id` FOREIGN KEY (`attendee_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.course_attendee_roles +CREATE TABLE IF NOT EXISTS `course_attendee_roles` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `type` (`name`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='Changed from course_attendee_type to event_attendee_type'; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.course_category +CREATE TABLE IF NOT EXISTS `course_category` ( + `id` int(11) DEFAULT NULL, + `name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.course_events +CREATE TABLE IF NOT EXISTS `course_events` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `course_id` int(11) DEFAULT NULL, + `event_type` int(11) DEFAULT NULL, + `event_date` datetime NOT NULL, + `guilded_event_id` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT 0, + `report_url` varchar(2048) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fk_course_events_event_type_id` (`event_type`) USING BTREE, + KEY `courseId` (`course_id`) USING BTREE, + CONSTRAINT `fk_coures_events_course_id` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_course_events_event_type_id` FOREIGN KEY (`event_type`) REFERENCES `event_types` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.course_qualified_trainers +CREATE TABLE IF NOT EXISTS `course_qualified_trainers` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) DEFAULT NULL, + `course_id` int(11) DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `qualified` tinyint(4) DEFAULT NULL, + `instance_qualified_id` int(11) DEFAULT NULL, + `deleted` tinyint(4) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `memberId_courseId` (`member_id`,`course_id`) USING BTREE, + KEY `fk_coures_qualified_trainers_coures_id` (`course_id`) USING BTREE, + KEY `fk_CourseTrainers_CourseInstance_id` (`instance_qualified_id`) USING BTREE, + CONSTRAINT `fk_coures_qualified_trainers_coures_events_id` FOREIGN KEY (`instance_qualified_id`) REFERENCES `course_events` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_coures_qualified_trainers_coures_id` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_coures_qualified_trainers_mebers_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='Contains a linked group of qualified trainers'; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.event_types +CREATE TABLE IF NOT EXISTS `event_types` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `event_type` varchar(100) DEFAULT NULL, + `event_category` varchar(100) DEFAULT NULL, + `deleted` tinyint(4) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.guilded_events +CREATE TABLE IF NOT EXISTS `guilded_events` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `channel_id` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `event_id` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `event_type` int(11) DEFAULT NULL, + `event_date` datetime DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` int(11) DEFAULT NULL, + `url` varchar(2048) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `calendar_id_event_id` (`channel_id`,`event_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=3267 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.leave_of_absences +CREATE TABLE IF NOT EXISTS `leave_of_absences` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) DEFAULT NULL, + `filed_date` datetime NOT NULL, + `start_date` datetime NOT NULL, + `end_date` datetime NOT NULL, + `reason` text DEFAULT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `fk_leave_of_absesnse_members_id` (`member_id`) USING BTREE, + CONSTRAINT `fk_leave_of_absesnse_members_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.members +CREATE TABLE IF NOT EXISTS `members` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `timezone` varchar(5) DEFAULT NULL, + `email` varchar(100) DEFAULT NULL, + `website` varchar(240) DEFAULT NULL, + `guilded_id` varchar(10) DEFAULT NULL, + `steam_id_64` varchar(17) DEFAULT NULL, + `teamspeak_uid` varchar(32) DEFAULT NULL, + `steam_profile_name` varchar(32) DEFAULT NULL, + `discord_id` varchar(20) DEFAULT NULL, + `discord_username` varchar(32) DEFAULT NULL, + `aliases` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`aliases`)), + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT NULL, + `remarks` text DEFAULT NULL, + `authentik_sub` varchar(255) DEFAULT NULL, + `authentik_issuer` varchar(255) DEFAULT NULL, + `state` enum('guest','applicant','member','retired','banned','denied') NOT NULL DEFAULT 'guest', + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + UNIQUE KEY `steamId64` (`steam_id_64`) USING BTREE, + UNIQUE KEY `discordId` (`discord_id`) USING BTREE, + UNIQUE KEY `guilded_id` (`guilded_id`), + UNIQUE KEY `uk_authentik_identity` (`authentik_issuer`,`authentik_sub`) +) ENGINE=InnoDB AUTO_INCREMENT=191 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.members_awards +CREATE TABLE IF NOT EXISTS `members_awards` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) DEFAULT NULL, + `awards_id` int(11) DEFAULT NULL, + `event_date` datetime DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `fk_members_awards_membres_id` (`member_id`), + KEY `fk_members_awards_awards_id` (`awards_id`), + CONSTRAINT `fk_members_awards_awards_id` FOREIGN KEY (`awards_id`) REFERENCES `awards` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_members_awards_membres_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.members_qualifications +CREATE TABLE IF NOT EXISTS `members_qualifications` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) DEFAULT 0, + `qualification_id` int(11) DEFAULT 0, + `event_date` datetime DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fk_members_qualifications_member_id` (`member_id`), + KEY `fk_members_qualifications_qualifications_id` (`qualification_id`), + CONSTRAINT `fk_members_qualifications_member_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_members_qualifications_qualifications_id` FOREIGN KEY (`qualification_id`) REFERENCES `qualifications` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.members_ranks +CREATE TABLE IF NOT EXISTS `members_ranks` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) DEFAULT NULL, + `rank_id` int(11) DEFAULT NULL, + `event_date` datetime DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `fk_members_ranks_members_id` (`member_id`), + KEY `fk_members_ranks_rank_id` (`rank_id`), + CONSTRAINT `fk_members_ranks_members_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_members_ranks_rank_id` FOREIGN KEY (`rank_id`) REFERENCES `ranks` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=210 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.members_roles +CREATE TABLE IF NOT EXISTS `members_roles` ( + `member_id` int(11) NOT NULL, + `role_id` int(11) NOT NULL, + PRIMARY KEY (`member_id`,`role_id`), + KEY `role_id` (`role_id`), + CONSTRAINT `members_roles_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON DELETE CASCADE, + CONSTRAINT `members_roles_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.members_statuses +CREATE TABLE IF NOT EXISTS `members_statuses` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `member_id` int(11) DEFAULT NULL, + `status_id` int(11) DEFAULT NULL, + `reason_id` int(11) DEFAULT NULL, + `event_date` datetime DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `fk_members_statuses_status_id` (`status_id`), + KEY `fk_members_statuses_member_id` (`member_id`), + KEY `fk_members_statuses_statuses_reasons_id` (`reason_id`) USING BTREE, + CONSTRAINT `fk_members_statuses_member_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_members_statuses_status_id` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON UPDATE CASCADE, + CONSTRAINT `members_statuses_FK` FOREIGN KEY (`reason_id`) REFERENCES `statuses_reasons` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=207 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.mission_attendee_roles +CREATE TABLE IF NOT EXISTS `mission_attendee_roles` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) DEFAULT NULL, + `short_name` varchar(50) DEFAULT NULL, + `description` text DEFAULT NULL, + `deleted` tinyint(4) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `role_name` (`name`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.mission_events +CREATE TABLE IF NOT EXISTS `mission_events` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `event_type_id` int(11) NOT NULL, + `event_name` varchar(100) NOT NULL, + `description` varchar(100) DEFAULT NULL, + `mission_name` varchar(100) NOT NULL, + `author_id` int(11) DEFAULT NULL, + `map_id` int(11) DEFAULT NULL, + `event_date` datetime NOT NULL, + `guilded_event_id` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `event_name` (`event_name`), + KEY `fk_events_author_member_id` (`author_id`) USING BTREE, + KEY `fk_mission_event_type_id` (`event_type_id`), + KEY `fk_mission_event_map_id` (`map_id`), + CONSTRAINT `fk_events_author_id` FOREIGN KEY (`author_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_mission_event_map_id` FOREIGN KEY (`map_id`) REFERENCES `arma_maps` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_mission_event_type_id` FOREIGN KEY (`event_type_id`) REFERENCES `event_types` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.mission_event_attendees +CREATE TABLE IF NOT EXISTS `mission_event_attendees` ( + `id` int(11) DEFAULT NULL, + `member_id` int(11) NOT NULL, + `event_id` int(11) NOT NULL, + `member_role_id` int(11) DEFAULT NULL, + `event_type` int(11) NOT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`member_id`,`event_id`) USING BTREE, + KEY `fk_mission_event_attendees_role_id` (`member_role_id`), + KEY `fk_mission_event_events_id` (`event_id`), + CONSTRAINT `fk_member_event_member_id` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_mission_event_attendees_role_id` FOREIGN KEY (`member_role_id`) REFERENCES `mission_attendee_roles` (`id`) ON UPDATE CASCADE, + CONSTRAINT `fk_mission_event_events_id` FOREIGN KEY (`event_id`) REFERENCES `mission_events` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.qualifications +CREATE TABLE IF NOT EXISTS `qualifications` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) DEFAULT NULL, + `short_name` varchar(10) DEFAULT NULL, + `description` text DEFAULT NULL, + `type` varchar(100) DEFAULT NULL, + `classification` varchar(100) DEFAULT NULL, + `footprint` varchar(50) DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `image_url` varchar(250) DEFAULT NULL, + `deleted` tinytext DEFAULT '0', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `name` (`name`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=utf8mb4 COMMENT='Contains a list of Member Qualifications for the unit.'; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.ranks +CREATE TABLE IF NOT EXISTS `ranks` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` longtext DEFAULT NULL, + `short_name` varchar(70) NOT NULL, + `category` varchar(100) NOT NULL, + `sort_id` int(11) NOT NULL DEFAULT 0, + `image_url` varchar(240) DEFAULT NULL, + `created_at` datetime(3) NOT NULL, + `updated_at` datetime(3) NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `deleted_at` datetime(3) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `shortName` (`short_name`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.roles +CREATE TABLE IF NOT EXISTS `roles` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, + `color` varchar(9) COLLATE utf8mb4_unicode_ci NOT NULL, + `description` text COLLATE utf8mb4_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.statuses +CREATE TABLE IF NOT EXISTS `statuses` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.statuses_reasons +CREATE TABLE IF NOT EXISTS `statuses_reasons` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `deleted` tinyint(4) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Contains a list of Reasons that a Status Change occured. This helps determine Promotions, Demotions, Transfers, Joins, Leaves.'; + +-- Data exporting was unselected. + +-- Dumping structure for table ranger_unit_tracker.status_change_requests +CREATE TABLE IF NOT EXISTS `status_change_requests` ( + `id` int(11) NOT NULL, + `member_id` int(11) DEFAULT NULL, + `current_status` int(11) DEFAULT NULL, + `next_status` int(11) DEFAULT NULL, + `next_rank` int(11) DEFAULT NULL, + `approval_from` int(11) DEFAULT NULL, + `approval_from_date` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `approval_to` int(11) DEFAULT NULL, + `approval_to_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `request_date` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + KEY `member_id` (`member_id`), + KEY `next_status` (`next_status`), + KEY `next_rank` (`next_rank`), + KEY `approval_from` (`approval_from`), + KEY `approval_to` (`approval_to`), + KEY `current_status` (`current_status`), + CONSTRAINT `status_change_requests_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`), + CONSTRAINT `status_change_requests_ibfk_2` FOREIGN KEY (`next_status`) REFERENCES `statuses` (`id`), + CONSTRAINT `status_change_requests_ibfk_3` FOREIGN KEY (`next_rank`) REFERENCES `ranks` (`id`), + CONSTRAINT `status_change_requests_ibfk_4` FOREIGN KEY (`approval_from`) REFERENCES `members` (`id`), + CONSTRAINT `status_change_requests_ibfk_5` FOREIGN KEY (`approval_to`) REFERENCES `members` (`id`), + CONSTRAINT `status_change_requests_ibfk_6` FOREIGN KEY (`current_status`) REFERENCES `statuses` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Data exporting was unselected. + +-- Dumping structure for view ranger_unit_tracker.view_member_rank_status_all +-- Creating temporary table to overcome VIEW dependency errors +CREATE TABLE `view_member_rank_status_all` ( + `member_id` INT(11) NOT NULL, + `member_name` VARCHAR(1) NOT NULL COLLATE 'utf8mb4_general_ci', + `rank` LONGTEXT NULL COLLATE 'utf8mb4_general_ci', + `rank_date` DATETIME NULL, + `status` VARCHAR(1) NULL COLLATE 'utf8mb4_general_ci', + `status_date` DATETIME NULL +); + +-- Removing temporary table and create final VIEW structure +DROP TABLE IF EXISTS `view_member_rank_status_all`; +CREATE ALGORITHM=UNDEFINED SQL SECURITY DEFINER VIEW `view_member_rank_status_all` AS select `ranger_unit_tracker`.`members`.`id` AS `member_id`,`ranger_unit_tracker`.`members`.`name` AS `member_name`,`ranger_unit_tracker`.`ranks`.`name` AS `rank`,`members_ranks`.`event_date` AS `rank_date`,`ranger_unit_tracker`.`statuses`.`name` AS `status`,`members_statuses`.`event_date` AS `status_date` from ((((`ranger_unit_tracker`.`members` left join (select `mr`.`id` AS `id`,`mr`.`member_id` AS `member_id`,`mr`.`rank_id` AS `rank_id`,`mr`.`event_date` AS `event_date`,`mr`.`created_at` AS `created_at`,`mr`.`updated_at` AS `updated_at` from (`ranger_unit_tracker`.`members_ranks` `mr` join (select `ranger_unit_tracker`.`members_ranks`.`member_id` AS `member_id`,max(`ranger_unit_tracker`.`members_ranks`.`event_date`) AS `max_rank_date` from `ranger_unit_tracker`.`members_ranks` group by `ranger_unit_tracker`.`members_ranks`.`member_id`) `latest_ranks` on(`mr`.`member_id` = `latest_ranks`.`member_id` and `mr`.`event_date` = `latest_ranks`.`max_rank_date`))) `members_ranks` on(`ranger_unit_tracker`.`members`.`id` = `members_ranks`.`member_id`)) left join (select `ms`.`id` AS `id`,`ms`.`member_id` AS `member_id`,`ms`.`status_id` AS `status_id`,`ms`.`event_date` AS `event_date`,`ms`.`created_at` AS `created_at`,`ms`.`updated_at` AS `updated_at` from (`ranger_unit_tracker`.`members_statuses` `ms` join (select `ranger_unit_tracker`.`members_statuses`.`member_id` AS `member_id`,max(`ranger_unit_tracker`.`members_statuses`.`event_date`) AS `max_status_date` from `ranger_unit_tracker`.`members_statuses` group by `ranger_unit_tracker`.`members_statuses`.`member_id`) `latest_statuses` on(`ms`.`member_id` = `latest_statuses`.`member_id` and `ms`.`event_date` = `latest_statuses`.`max_status_date`))) `members_statuses` on(`ranger_unit_tracker`.`members`.`id` = `members_statuses`.`member_id`)) left join `ranger_unit_tracker`.`ranks` on(`members_ranks`.`rank_id` = `ranger_unit_tracker`.`ranks`.`id`)) left join `ranger_unit_tracker`.`statuses` on(`members_statuses`.`status_id` = `ranger_unit_tracker`.`statuses`.`id`)) +; + +/*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */; +/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; +/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */; diff --git a/api/package.json b/api/package.json index ec58d17..b05389f 100644 --- a/api/package.json +++ b/api/package.json @@ -9,7 +9,12 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "tsc && cross-env NODE_ENV=development node ./built/api/src/index.js", - "prod": "tsc && node ./built/api/src/index.js" + "prod": "tsc && node ./built/api/src/index.js", + + "migrate": "node ./scripts/migrate.js", + "migrate:create": "npm run migrate -- create -ext sql -dir /migrations", + "migrate:up": "npm run migrate -- up", + "migrate:down": "npm run migrate -- down 1" }, "dependencies": { "connect-sqlite3": "^0.9.16", @@ -29,8 +34,5 @@ "@types/node": "^24.8.1", "cross-env": "^10.1.0", "typescript": "^5.9.3" - }, - "dotenv": { - "auto": false } } \ No newline at end of file diff --git a/api/scripts/migrate.js b/api/scripts/migrate.js new file mode 100644 index 0000000..7dde6da --- /dev/null +++ b/api/scripts/migrate.js @@ -0,0 +1,30 @@ +const dotenv = require('dotenv'); +const path = require('path'); +const { execSync } = require('child_process'); + +const mode = process.env.NODE_ENV || "development"; +dotenv.config({ path: path.resolve(process.cwd(), `.env.${mode}`) }); + +const db = { + user: process.env.DB_USERNAME, + pass: process.env.DB_PASSWORD, + host: process.env.DB_HOST, + port: process.env.DB_PORT, + name: process.env.DB_DATABASE, +}; +const dbUrl = `mysql://${db.user}:${db.pass}@tcp(host.docker.internal:${db.port})/${db.name}`; + +const args = process.argv.slice(2).join(" "); +const migrations = path.join(process.cwd(), "migrations"); + +const cmd = [ + "docker run --rm", + `-v ${migrations}:/migrations`, + "migrate/migrate", + `-path=/migrations`, + `-database \"${dbUrl}\"`, + args, +].join(" "); + +console.log(cmd); +execSync(cmd, { stdio: "inherit" });