-- AlterTable ALTER TABLE `bookings` ADD COLUMN `origin_assessment_id` VARCHAR(191) NULL; ALTER TABLE `progress_photos` ADD COLUMN `angle` VARCHAR(16) NULL, ADD COLUMN `session_id` VARCHAR(191) NULL; -- CreateTable CREATE TABLE `body_portrait_visits` ( `id` VARCHAR(191) NOT NULL, `token_hash` VARCHAR(64) NOT NULL, `source` VARCHAR(32) NOT NULL DEFAULT 'organic', `campaign_id` VARCHAR(40) NULL, `referral_code` VARCHAR(12) NULL, `referrer_user_id` VARCHAR(191) NULL, `landing_path` VARCHAR(120) NOT NULL DEFAULT '', `user_id` VARCHAR(191) NULL, `first_seen_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `last_seen_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), UNIQUE INDEX `body_portrait_visits_token_hash_key`(`token_hash`), INDEX `body_portrait_visits_source_created_at_idx`(`source`, `created_at`), INDEX `body_portrait_visits_user_id_idx`(`user_id`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `body_portrait_assessments` ( `id` VARCHAR(191) NOT NULL, `visit_id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NULL, `token_hash` VARCHAR(64) NOT NULL, `questionnaire_version` VARCHAR(32) NOT NULL, `rules_version` VARCHAR(32) NOT NULL, `status` VARCHAR(16) NOT NULL DEFAULT 'DRAFT', `answers` JSON NOT NULL, `safety_flagged` BOOLEAN NOT NULL DEFAULT false, `report` JSON NULL, `completed_at` DATETIME(3) NULL, `claimed_at` DATETIME(3) NULL, `expires_at` DATETIME(3) NOT NULL, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL, UNIQUE INDEX `body_portrait_assessments_token_hash_key`(`token_hash`), INDEX `body_portrait_assessments_visit_id_idx`(`visit_id`), INDEX `body_portrait_assessments_user_id_created_at_idx`(`user_id`, `created_at`), INDEX `body_portrait_assessments_status_expires_at_idx`(`status`, `expires_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `growth_leads` ( `id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `latest_assessment_id` VARCHAR(191) NULL, `stage` VARCHAR(32) NOT NULL DEFAULT 'CLAIMED', `source` VARCHAR(32) NULL, `campaign_id` VARCHAR(40) NULL, `last_active_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `coach_note` VARCHAR(500) NOT NULL DEFAULT '', `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL, UNIQUE INDEX `growth_leads_user_id_key`(`user_id`), INDEX `growth_leads_stage_last_active_at_idx`(`stage`, `last_active_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `growth_events` ( `id` VARCHAR(191) NOT NULL, `name` VARCHAR(40) NOT NULL, `idempotency_key` VARCHAR(120) NOT NULL, `visit_id` VARCHAR(191) NULL, `assessment_id` VARCHAR(191) NULL, `user_id` VARCHAR(191) NULL, `properties` JSON NOT NULL, `occurred_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), UNIQUE INDEX `growth_events_idempotency_key_key`(`idempotency_key`), INDEX `growth_events_name_occurred_at_idx`(`name`, `occurred_at`), INDEX `growth_events_user_id_occurred_at_idx`(`user_id`, `occurred_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `professional_assessment_sessions` ( `id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `kind` VARCHAR(16) NOT NULL, `protocol_version` VARCHAR(32) NOT NULL DEFAULT 'offline-v1', `recorded_at` DATE NOT NULL, `booking_id` VARCHAR(191) NULL, `origin_assessment_id` VARCHAR(191) NULL, `observations` JSON NOT NULL, `subjective_tension` DOUBLE NULL, `coach_summary` VARCHAR(1000) NOT NULL DEFAULT '', `training_focus` VARCHAR(500) NOT NULL DEFAULT '', `phase_goal` VARCHAR(500) NOT NULL DEFAULT '', `photo_angle` VARCHAR(16) NULL, `operator_id` VARCHAR(191) NOT NULL, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), INDEX `professional_assessment_sessions_user_id_recorded_at_idx`(`user_id`, `recorded_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `training_plans` ( `id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `session_id` VARCHAR(191) NULL, `title` VARCHAR(80) NOT NULL, `status` VARCHAR(16) NOT NULL DEFAULT 'ACTIVE', `weeks` INTEGER NOT NULL DEFAULT 12, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL, INDEX `training_plans_user_id_created_at_idx`(`user_id`, `created_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `training_plan_phases` ( `id` VARCHAR(191) NOT NULL, `plan_id` VARCHAR(191) NOT NULL, `name` VARCHAR(40) NOT NULL, `lesson_start` INTEGER NOT NULL, `lesson_end` INTEGER NOT NULL, `focus` JSON NOT NULL, `summary` VARCHAR(300) NOT NULL DEFAULT '', `sort_order` INTEGER NOT NULL DEFAULT 0, INDEX `training_plan_phases_plan_id_idx`(`plan_id`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `reassessment_todos` ( `id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `plan_id` VARCHAR(191) NOT NULL, `lesson_checkpoint` INTEGER NOT NULL, `due_at` DATETIME(3) NOT NULL, `completed_at` DATETIME(3) NULL, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), UNIQUE INDEX `reassessment_todos_plan_id_lesson_checkpoint_key`(`plan_id`, `lesson_checkpoint`), INDEX `reassessment_todos_user_id_completed_at_idx`(`user_id`, `completed_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `growth_share_cards` ( `id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `plan_id` VARCHAR(191) NULL, `share_code` VARCHAR(12) NOT NULL, `title` VARCHAR(80) NOT NULL, `caption` VARCHAR(200) NOT NULL, `completed_count` INTEGER NOT NULL, `weeks` INTEGER NOT NULL DEFAULT 12, `rows` JSON NOT NULL, `include_photos` BOOLEAN NOT NULL DEFAULT false, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), UNIQUE INDEX `growth_share_cards_share_code_key`(`share_code`), INDEX `growth_share_cards_user_id_created_at_idx`(`user_id`, `created_at`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX `bookings_origin_assessment_id_idx` ON `bookings`(`origin_assessment_id`); CREATE INDEX `progress_photos_session_id_idx` ON `progress_photos`(`session_id`); -- AddForeignKey ALTER TABLE `body_portrait_visits` ADD CONSTRAINT `body_portrait_visits_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `body_portrait_visits` ADD CONSTRAINT `body_portrait_visits_referrer_user_id_fkey` FOREIGN KEY (`referrer_user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `body_portrait_assessments` ADD CONSTRAINT `body_portrait_assessments_visit_id_fkey` FOREIGN KEY (`visit_id`) REFERENCES `body_portrait_visits`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE `body_portrait_assessments` ADD CONSTRAINT `body_portrait_assessments_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `growth_leads` ADD CONSTRAINT `growth_leads_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE `growth_leads` ADD CONSTRAINT `growth_leads_latest_assessment_id_fkey` FOREIGN KEY (`latest_assessment_id`) REFERENCES `body_portrait_assessments`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `growth_events` ADD CONSTRAINT `growth_events_visit_id_fkey` FOREIGN KEY (`visit_id`) REFERENCES `body_portrait_visits`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `growth_events` ADD CONSTRAINT `growth_events_assessment_id_fkey` FOREIGN KEY (`assessment_id`) REFERENCES `body_portrait_assessments`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `growth_events` ADD CONSTRAINT `growth_events_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `bookings` ADD CONSTRAINT `bookings_origin_assessment_id_fkey` FOREIGN KEY (`origin_assessment_id`) REFERENCES `body_portrait_assessments`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `professional_assessment_sessions` ADD CONSTRAINT `professional_assessment_sessions_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE `professional_assessment_sessions` ADD CONSTRAINT `professional_assessment_sessions_booking_id_fkey` FOREIGN KEY (`booking_id`) REFERENCES `bookings`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `professional_assessment_sessions` ADD CONSTRAINT `professional_assessment_sessions_origin_assessment_id_fkey` FOREIGN KEY (`origin_assessment_id`) REFERENCES `body_portrait_assessments`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `progress_photos` ADD CONSTRAINT `progress_photos_session_id_fkey` FOREIGN KEY (`session_id`) REFERENCES `professional_assessment_sessions`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `training_plans` ADD CONSTRAINT `training_plans_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE `training_plans` ADD CONSTRAINT `training_plans_session_id_fkey` FOREIGN KEY (`session_id`) REFERENCES `professional_assessment_sessions`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE `training_plan_phases` ADD CONSTRAINT `training_plan_phases_plan_id_fkey` FOREIGN KEY (`plan_id`) REFERENCES `training_plans`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `reassessment_todos` ADD CONSTRAINT `reassessment_todos_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE `reassessment_todos` ADD CONSTRAINT `reassessment_todos_plan_id_fkey` FOREIGN KEY (`plan_id`) REFERENCES `training_plans`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `growth_share_cards` ADD CONSTRAINT `growth_share_cards_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE `growth_share_cards` ADD CONSTRAINT `growth_share_cards_plan_id_fkey` FOREIGN KEY (`plan_id`) REFERENCES `training_plans`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;