把 3 分钟身体状态评估做成独立获客链路,匿名测评后登录认领完整报告,并接入体验预约与今日待办。 Co-authored-by: Cursor <cursoragent@cursor.com>
197 lines
11 KiB
SQL
197 lines
11 KiB
SQL
-- 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;
|