Commit 910ebbc5 by luoqi

chore(db): consolidate 14 migrations into single 20260526000000_init

合并 W3 之前所有增量 migration 为单文件 init,便于 fresh deploy。
旧 migration 已在 dev 环境跑过;prod 首次部署直接走 init。
parent 7758f537
-- Remove deprecated Platform.field_mapping column.
-- AssemblerEngine + per-host assembler.yaml(`apps/pac-service/data/<host>/assemblers/*.yaml`)
-- 已完全替代该字段;保留它只会让 v1 / v2 模型混淆。
ALTER TABLE "platforms" DROP COLUMN IF EXISTS "field_mapping";
-- Plan 模型重构:patient-级 plan + scenario-级 plan_reasons 子表
-- 对应 db-review-confirm §1:plan 1:N reason
--
-- 旧:followup_plans 含 scenario / inclusion_reason / evidence 字段,
-- partial UNIQUE on (platform_id, tenant_id, patient_id, scenario) WHERE status active/assigned
-- 新:followup_plans 只剩触达决策字段,scenario 维度移到 plan_reasons,
-- partial UNIQUE on (platform_id, tenant_id, patient_id) WHERE status active/assigned
-- 1) FollowupPlan: 移除字段 + 改 UNIQUE
ALTER TABLE "followup_plans"
DROP COLUMN IF EXISTS "scenario",
DROP COLUMN IF EXISTS "inclusion_reason",
DROP COLUMN IF EXISTS "evidence",
ADD COLUMN IF NOT EXISTS "contact_attempts" INT NOT NULL DEFAULT 0;
-- 删旧 UNIQUE/索引(若存在),换新 UNIQUE 不含 scenario
DROP INDEX IF EXISTS "followup_plans_platform_id_tenant_id_patient_id_scenario_ver_key";
DROP INDEX IF EXISTS "followup_plans_scenario_status_idx";
DROP INDEX IF EXISTS "followup_plans_active_per_patient_scenario_idx";
-- 新 UNIQUE: (platform_id, tenant_id, patient_id, version)
ALTER TABLE "followup_plans"
ADD CONSTRAINT "followup_plans_platform_id_tenant_id_patient_id_version_key"
UNIQUE ("platform_id", "tenant_id", "patient_id", "version");
-- 新 partial UNIQUE:patient 级 single-active(不再含 scenario)
CREATE UNIQUE INDEX IF NOT EXISTS "followup_plans_active_per_patient_idx"
ON "followup_plans" ("platform_id", "tenant_id", "patient_id")
WHERE "status" IN ('active', 'assigned');
-- 2) PlanReason 子表
CREATE TABLE IF NOT EXISTS "plan_reasons" (
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"plan_id" UUID NOT NULL REFERENCES "followup_plans"("id") ON DELETE CASCADE,
"scenario" TEXT NOT NULL,
"priority_score" DOUBLE PRECISION NOT NULL,
"reason" TEXT NOT NULL,
"evidence_fact_ids" UUID[] NOT NULL DEFAULT '{}',
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT now(),
"updated_at" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "plan_reasons_plan_id_scenario_key" UNIQUE ("plan_id", "scenario")
);
CREATE INDEX IF NOT EXISTS "plan_reasons_scenario_idx" ON "plan_reasons" ("scenario");
CREATE INDEX IF NOT EXISTS "plan_reasons_evidence_gin_idx" ON "plan_reasons" USING GIN ("evidence_fact_ids");
-- 产品收集字段(回访中心信息字段.docx 吸收)
-- 1) Patient: tags + primary_contact_type
-- 2) PlanReason: lifecycle / source / source_actor_id / campaign_id / closed_reason / closed_at + index
-- 3) PlanExecution: invalid_reason
-- 1) Patient
ALTER TABLE "patients"
ADD COLUMN IF NOT EXISTS "tags" TEXT[] NOT NULL DEFAULT '{}',
ADD COLUMN IF NOT EXISTS "primary_contact_type" TEXT;
-- 2) PlanReason
ALTER TABLE "plan_reasons"
ADD COLUMN IF NOT EXISTS "lifecycle" TEXT NOT NULL DEFAULT 'one_shot',
ADD COLUMN IF NOT EXISTS "source" TEXT NOT NULL DEFAULT 'algorithm',
ADD COLUMN IF NOT EXISTS "source_actor_id" TEXT,
ADD COLUMN IF NOT EXISTS "campaign_id" TEXT,
ADD COLUMN IF NOT EXISTS "closed_reason" TEXT,
ADD COLUMN IF NOT EXISTS "closed_at" TIMESTAMPTZ(3);
CREATE INDEX IF NOT EXISTS "plan_reasons_campaign_id_idx" ON "plan_reasons" ("campaign_id");
-- 3) PlanExecution
ALTER TABLE "plan_executions"
ADD COLUMN IF NOT EXISTS "invalid_reason" TEXT;
-- 大重命名:platform → host(表 + 列)+ Patient 重构 + PatientProfile 副表 + fact_type 清理
-- 1) 重命名 platforms 表
ALTER TABLE "platforms" RENAME TO "hosts";
-- 2) 重命名 platform_id 列 → host_id(子表 12 个)
ALTER TABLE "patients" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "patient_transactions" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "patient_facts" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "personas" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "persona_recompute_logs" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "followup_plans" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "plan_scripts" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "plan_summaries" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "plan_executions" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "plan_generation_logs" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "agent_invocations" RENAME COLUMN "platform_id" TO "host_id";
ALTER TABLE "sync_logs" RENAME COLUMN "platform_id" TO "host_id";
-- 3) Patient 重构:删 status/合规/标签/merge 字段,加 active
ALTER TABLE "patients"
DROP COLUMN IF EXISTS "status",
DROP COLUMN IF EXISTS "merged_into_id",
DROP COLUMN IF EXISTS "do_not_contact",
DROP COLUMN IF EXISTS "do_not_contact_reason",
DROP COLUMN IF EXISTS "do_not_contact_at",
DROP COLUMN IF EXISTS "deceased",
DROP COLUMN IF EXISTS "deceased_at",
DROP COLUMN IF EXISTS "tags",
DROP COLUMN IF EXISTS "primary_contact_type",
ADD COLUMN IF NOT EXISTS "active" BOOLEAN NOT NULL DEFAULT TRUE;
-- 旧召回池索引含已删字段,重建
DROP INDEX IF EXISTS "patients_platform_id_tenant_id_status_do_not_contact_deceas_idx";
DROP INDEX IF EXISTS "patients_host_id_tenant_id_status_do_not_contact_deceased_idx";
CREATE INDEX IF NOT EXISTS "patients_host_id_tenant_id_active_idx"
ON "patients" ("host_id", "tenant_id", "active");
-- 4) PatientProfile 副表(1:1)
CREATE TABLE IF NOT EXISTS "patient_profiles" (
"patient_id" UUID PRIMARY KEY REFERENCES "patients"("id") ON DELETE CASCADE,
"do_not_contact" BOOLEAN NOT NULL DEFAULT FALSE,
"do_not_contact_reason" TEXT,
"do_not_contact_at" TIMESTAMPTZ(3),
"deceased" BOOLEAN NOT NULL DEFAULT FALSE,
"deceased_at" TIMESTAMPTZ(3),
"tags" TEXT[] NOT NULL DEFAULT '{}',
"notes" TEXT,
"primary_contact_type" TEXT,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT now(),
"updated_at" TIMESTAMPTZ(3) NOT NULL
);
CREATE INDEX IF NOT EXISTS "patient_profiles_do_not_contact_idx" ON "patient_profiles" ("do_not_contact");
CREATE INDEX IF NOT EXISTS "patient_profiles_deceased_idx" ON "patient_profiles" ("deceased");
-- 5) fact_type 清理:删 6 个衍生类 + 重命名 charge_order_record → order_record + appointment_plan → appointment_record
-- 由于 dev mock 数据,直接删 fact 行而非 transform
DELETE FROM "patient_facts"
WHERE "type" IN ('diagnosis_record', 'treatment_record', 'treatment_plan',
'review_plan', 'payment_plan');
UPDATE "patient_facts" SET "type" = 'order_record' WHERE "type" = 'charge_order_record';
UPDATE "patient_facts" SET "type" = 'appointment_record' WHERE "type" = 'appointment_plan';
-- 6) action / subjectType 重命名
UPDATE "patient_transactions" SET "action" = 'order_submitted' WHERE "action" = 'charge_order_submitted';
UPDATE "patient_transactions" SET "subject_type" = 'order' WHERE "subject_type" = 'charge_order';
/*
Warnings:
- You are about to drop the column `triggered_by` on the `personas` table. All the data in the column will be lost.
- Added the required column `source` to the `personas` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "patient_profiles" DROP CONSTRAINT "patient_profiles_patient_id_fkey";
-- DropForeignKey
ALTER TABLE "plan_reasons" DROP CONSTRAINT "plan_reasons_plan_id_fkey";
-- DropIndex
DROP INDEX "patient_facts_transaction_ids_gin";
-- DropIndex
DROP INDEX "plan_reasons_evidence_gin_idx";
-- AlterTable
ALTER TABLE "hosts" RENAME CONSTRAINT "platforms_pkey" TO "hosts_pkey";
-- AlterTable
ALTER TABLE "personas" DROP COLUMN "triggered_by",
ADD COLUMN "source" TEXT NOT NULL;
-- AlterTable
ALTER TABLE "plan_reasons" ALTER COLUMN "id" DROP DEFAULT,
ALTER COLUMN "evidence_fact_ids" DROP DEFAULT;
-- RenameForeignKey
ALTER TABLE "agent_invocations" RENAME CONSTRAINT "agent_invocations_platform_id_fkey" TO "agent_invocations_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "followup_plans" RENAME CONSTRAINT "followup_plans_platform_id_fkey" TO "followup_plans_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "patient_facts" RENAME CONSTRAINT "patient_facts_platform_id_fkey" TO "patient_facts_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "patient_transactions" RENAME CONSTRAINT "patient_transactions_platform_id_fkey" TO "patient_transactions_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "patients" RENAME CONSTRAINT "patients_platform_id_fkey" TO "patients_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "persona_recompute_logs" RENAME CONSTRAINT "persona_recompute_logs_platform_id_fkey" TO "persona_recompute_logs_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "personas" RENAME CONSTRAINT "personas_platform_id_fkey" TO "personas_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "plan_executions" RENAME CONSTRAINT "plan_executions_platform_id_fkey" TO "plan_executions_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "plan_generation_logs" RENAME CONSTRAINT "plan_generation_logs_platform_id_fkey" TO "plan_generation_logs_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "plan_scripts" RENAME CONSTRAINT "plan_scripts_platform_id_fkey" TO "plan_scripts_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "plan_summaries" RENAME CONSTRAINT "plan_summaries_platform_id_fkey" TO "plan_summaries_host_id_fkey";
-- RenameForeignKey
ALTER TABLE "sync_logs" RENAME CONSTRAINT "sync_logs_platform_id_fkey" TO "sync_logs_host_id_fkey";
-- AddForeignKey
ALTER TABLE "patient_profiles" ADD CONSTRAINT "patient_profiles_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "plan_reasons" ADD CONSTRAINT "plan_reasons_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- RenameIndex
ALTER INDEX "agent_invocations_platform_id_tenant_id_idx" RENAME TO "agent_invocations_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "followup_plans_platform_id_tenant_id_idx" RENAME TO "followup_plans_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "followup_plans_platform_id_tenant_id_patient_id_version_key" RENAME TO "followup_plans_host_id_tenant_id_patient_id_version_key";
-- RenameIndex
ALTER INDEX "followup_plans_platform_id_tenant_id_target_clinic_id_idx" RENAME TO "followup_plans_host_id_tenant_id_target_clinic_id_idx";
-- RenameIndex
ALTER INDEX "platforms_app_id_key" RENAME TO "hosts_app_id_key";
-- RenameIndex
ALTER INDEX "platforms_name_key" RENAME TO "hosts_name_key";
-- RenameIndex
ALTER INDEX "patient_facts_platform_id_tenant_id_idx" RENAME TO "patient_facts_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "patient_facts_platform_id_tenant_id_subject_id_version_key" RENAME TO "patient_facts_host_id_tenant_id_subject_id_version_key";
-- RenameIndex
ALTER INDEX "patient_transactions_platform_id_tenant_id_clinic_id_idx" RENAME TO "patient_transactions_host_id_tenant_id_clinic_id_idx";
-- RenameIndex
ALTER INDEX "patients_platform_id_tenant_id_external_id_key" RENAME TO "patients_host_id_tenant_id_external_id_key";
-- RenameIndex
ALTER INDEX "patients_platform_id_tenant_id_idx" RENAME TO "patients_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "persona_recompute_logs_platform_id_tenant_id_idx" RENAME TO "persona_recompute_logs_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "personas_platform_id_tenant_id_idx" RENAME TO "personas_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "plan_executions_platform_id_tenant_id_executor_clinic_id_idx" RENAME TO "plan_executions_host_id_tenant_id_executor_clinic_id_idx";
-- RenameIndex
ALTER INDEX "plan_generation_logs_platform_id_tenant_id_idx" RENAME TO "plan_generation_logs_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "plan_scripts_platform_id_tenant_id_idx" RENAME TO "plan_scripts_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "plan_summaries_platform_id_tenant_id_idx" RENAME TO "plan_summaries_host_id_tenant_id_idx";
-- RenameIndex
ALTER INDEX "sync_logs_platform_id_tenant_id_resource_idx" RENAME TO "sync_logs_host_id_tenant_id_resource_idx";
/*
Warnings:
- You are about to drop the column `agent_version` on the `agent_invocations` table. All the data in the column will be lost.
- You are about to drop the column `gateway_provider` on the `agent_invocations` table. All the data in the column will be lost.
- You are about to drop the column `workflow_id` on the `agent_invocations` table. All the data in the column will be lost.
- Added the required column `input_hash` to the `agent_invocations` table without a default value. This is not possible if the table is not empty.
- Added the required column `model_provider` to the `agent_invocations` table without a default value. This is not possible if the table is not empty.
- Added the required column `prompt_version` to the `agent_invocations` table without a default value. This is not possible if the table is not empty.
- Added the required column `skill_key` to the `agent_invocations` table without a default value. This is not possible if the table is not empty.
- Added the required column `workflow_run_id` to the `agent_invocations` table without a default value. This is not possible if the table is not empty.
- Made the column `model_name` on table `agent_invocations` required. This step will fail if there are existing NULL values in that column.
*/
-- AlterTable
ALTER TABLE "agent_invocations" DROP COLUMN "agent_version",
DROP COLUMN "gateway_provider",
DROP COLUMN "workflow_id",
ADD COLUMN "cache_hit" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "eval_mode" TEXT NOT NULL DEFAULT 'production',
ADD COLUMN "golden_set_case_id" TEXT,
ADD COLUMN "input_hash" TEXT NOT NULL,
ADD COLUMN "judge_rubric" JSONB,
ADD COLUMN "judge_score" DECIMAL(3,2),
ADD COLUMN "model_provider" TEXT NOT NULL,
ADD COLUMN "parent_invocation_id" UUID,
ADD COLUMN "prompt_version" TEXT NOT NULL,
ADD COLUMN "skill_key" TEXT NOT NULL,
ADD COLUMN "workflow_run_id" UUID NOT NULL,
ALTER COLUMN "model_name" SET NOT NULL;
-- CreateIndex
CREATE INDEX "agent_invocations_skill_key_prompt_version_started_at_idx" ON "agent_invocations"("skill_key", "prompt_version", "started_at");
-- CreateIndex
CREATE INDEX "agent_invocations_workflow_run_id_idx" ON "agent_invocations"("workflow_run_id");
-- CreateIndex
CREATE INDEX "agent_invocations_parent_invocation_id_idx" ON "agent_invocations"("parent_invocation_id");
-- CreateIndex
CREATE INDEX "agent_invocations_input_hash_idx" ON "agent_invocations"("input_hash");
-- CreateIndex
CREATE INDEX "agent_invocations_eval_mode_skill_key_idx" ON "agent_invocations"("eval_mode", "skill_key");
-- Rename agent_invocations.skill_key -> call_key
-- (词义对齐:Anthropic Agent Skills 是另一回事 — md 文件 + 渐进式披露;
-- 我们这里只是"一次 LLM 调用配方",改名 call_key 避免混淆。)
-- Drop old indexes that reference skill_key
DROP INDEX IF EXISTS "agent_invocations_skill_key_prompt_version_started_at_idx";
DROP INDEX IF EXISTS "agent_invocations_eval_mode_skill_key_idx";
-- Rename column
ALTER TABLE "agent_invocations" RENAME COLUMN "skill_key" TO "call_key";
-- Recreate indexes with new column name
CREATE INDEX "agent_invocations_call_key_prompt_version_started_at_idx"
ON "agent_invocations"("call_key", "prompt_version", "started_at");
CREATE INDEX "agent_invocations_eval_mode_call_key_idx"
ON "agent_invocations"("eval_mode", "call_key");
-- agent_invocations.cost_cents (Int 分) → cost_yuan (Decimal 元 6 位小数)
-- 原因:单次 LLM 调用成本常 <0.01 分(如 ¥0.0034),Int 分粒度全归零,仪表盘看不出差异。
ALTER TABLE "agent_invocations"
ADD COLUMN "cost_yuan" NUMERIC(12, 6) NOT NULL DEFAULT 0;
-- 历史数据搬迁:cost_cents (Int 分) → cost_yuan (¥) = cost_cents / 100
UPDATE "agent_invocations" SET "cost_yuan" = "cost_cents"::numeric / 100;
ALTER TABLE "agent_invocations" DROP COLUMN "cost_cents";
-- AlterTable
ALTER TABLE "agent_invocations" ADD COLUMN "cached_input_tokens" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "reasoning_tokens" INTEGER NOT NULL DEFAULT 0;
-- AlterTable
ALTER TABLE "patient_transactions" ADD COLUMN "canonical_payload" JSONB;
-- AlterTable
ALTER TABLE "plan_reasons" ADD COLUMN "breakdown" JSONB;
-- AlterTable
ALTER TABLE "followup_plans" ADD COLUMN "goal" TEXT;
-- AlterTable
ALTER TABLE "patients" ADD COLUMN "medical_record_number" TEXT;
-- CreateSchema
CREATE SCHEMA IF NOT EXISTS "public";
-- CreateTable -- CreateTable
CREATE TABLE "platforms" ( CREATE TABLE "hosts" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"name" TEXT NOT NULL, "name" TEXT NOT NULL,
"app_id" TEXT NOT NULL, "app_id" TEXT NOT NULL,
"app_secret_hash" TEXT NOT NULL, "app_secret_hash" TEXT NOT NULL,
"pull_config" JSONB, "pull_config" JSONB,
"push_secret_hashes" TEXT[], "push_secret_hashes" TEXT[],
"field_mapping" JSONB NOT NULL DEFAULT '{}',
"action_urls" JSONB NOT NULL DEFAULT '{}', "action_urls" JSONB NOT NULL DEFAULT '{}',
"active" BOOLEAN NOT NULL DEFAULT true, "active" BOOLEAN NOT NULL DEFAULT true,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(3) NOT NULL, "updated_at" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "platforms_pkey" PRIMARY KEY ("id") CONSTRAINT "hosts_pkey" PRIMARY KEY ("id")
); );
-- CreateTable -- CreateTable
CREATE TABLE "patients" ( CREATE TABLE "patients" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"external_id" TEXT NOT NULL, "external_id" TEXT NOT NULL,
"name" TEXT, "name" TEXT,
"phone" TEXT, "phone" TEXT,
"gender" TEXT, "gender" TEXT,
"birth_date" DATE, "birth_date" DATE,
"medical_record_number" TEXT,
"preferences" JSONB, "preferences" JSONB,
"active" BOOLEAN NOT NULL DEFAULT true,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "patients_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "patient_profiles" (
"patient_id" UUID NOT NULL,
"do_not_contact" BOOLEAN NOT NULL DEFAULT false, "do_not_contact" BOOLEAN NOT NULL DEFAULT false,
"do_not_contact_reason" TEXT, "do_not_contact_reason" TEXT,
"do_not_contact_at" TIMESTAMPTZ(3), "do_not_contact_at" TIMESTAMPTZ(3),
"deceased" BOOLEAN NOT NULL DEFAULT false, "deceased" BOOLEAN NOT NULL DEFAULT false,
"deceased_at" TIMESTAMPTZ(3), "deceased_at" TIMESTAMPTZ(3),
"status" TEXT NOT NULL DEFAULT 'active', "tags" TEXT[] DEFAULT ARRAY[]::TEXT[],
"merged_into_id" UUID, "notes" TEXT,
"primary_contact_type" TEXT,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(3) NOT NULL, "updated_at" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "patients_pkey" PRIMARY KEY ("id") CONSTRAINT "patient_profiles_pkey" PRIMARY KEY ("patient_id")
); );
-- CreateTable -- CreateTable
CREATE TABLE "patient_transactions" ( CREATE TABLE "patient_transactions" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"event_seq" BIGSERIAL NOT NULL, "event_seq" BIGSERIAL NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID, "patient_id" UUID,
"source_event_id" TEXT, "source_event_id" TEXT,
...@@ -52,6 +66,7 @@ CREATE TABLE "patient_transactions" ( ...@@ -52,6 +66,7 @@ CREATE TABLE "patient_transactions" (
"subject_type" TEXT NOT NULL, "subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL, "subject_id" TEXT NOT NULL,
"raw_payload" JSONB NOT NULL, "raw_payload" JSONB NOT NULL,
"canonical_payload" JSONB,
"payload_hash" TEXT NOT NULL, "payload_hash" TEXT NOT NULL,
"occurred_at" TIMESTAMPTZ(3) NOT NULL, "occurred_at" TIMESTAMPTZ(3) NOT NULL,
"received_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "received_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
...@@ -64,7 +79,7 @@ CREATE TABLE "patient_transactions" ( ...@@ -64,7 +79,7 @@ CREATE TABLE "patient_transactions" (
-- CreateTable -- CreateTable
CREATE TABLE "patient_facts" ( CREATE TABLE "patient_facts" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID NOT NULL, "patient_id" UUID NOT NULL,
"subject_id" TEXT NOT NULL, "subject_id" TEXT NOT NULL,
...@@ -91,11 +106,11 @@ CREATE TABLE "patient_facts" ( ...@@ -91,11 +106,11 @@ CREATE TABLE "patient_facts" (
-- CreateTable -- CreateTable
CREATE TABLE "personas" ( CREATE TABLE "personas" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID NOT NULL, "patient_id" UUID NOT NULL,
"version" INTEGER NOT NULL, "version" INTEGER NOT NULL,
"triggered_by" TEXT NOT NULL, "source" TEXT NOT NULL,
"computed_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "computed_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"superseded_at" TIMESTAMPTZ(3), "superseded_at" TIMESTAMPTZ(3),
"event_watermark" BIGINT, "event_watermark" BIGINT,
...@@ -119,7 +134,7 @@ CREATE TABLE "persona_features" ( ...@@ -119,7 +134,7 @@ CREATE TABLE "persona_features" (
-- CreateTable -- CreateTable
CREATE TABLE "persona_recompute_logs" ( CREATE TABLE "persona_recompute_logs" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID NOT NULL, "patient_id" UUID NOT NULL,
"triggered_by" TEXT NOT NULL, "triggered_by" TEXT NOT NULL,
...@@ -140,19 +155,18 @@ CREATE TABLE "persona_recompute_logs" ( ...@@ -140,19 +155,18 @@ CREATE TABLE "persona_recompute_logs" (
-- CreateTable -- CreateTable
CREATE TABLE "followup_plans" ( CREATE TABLE "followup_plans" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID NOT NULL, "patient_id" UUID NOT NULL,
"persona_id" UUID, "persona_id" UUID,
"target_clinic_id" TEXT, "target_clinic_id" TEXT,
"scenario" TEXT NOT NULL,
"version" INTEGER NOT NULL, "version" INTEGER NOT NULL,
"priority_score" DOUBLE PRECISION NOT NULL, "priority_score" DOUBLE PRECISION NOT NULL,
"inclusion_reason" TEXT NOT NULL, "goal" TEXT,
"recommended_at" TIMESTAMPTZ(3), "recommended_at" TIMESTAMPTZ(3),
"recommended_role" TEXT, "recommended_role" TEXT,
"recommended_channel" TEXT, "recommended_channel" TEXT,
"evidence" JSONB NOT NULL, "contact_attempts" INTEGER NOT NULL DEFAULT 0,
"status" TEXT NOT NULL, "status" TEXT NOT NULL,
"recycle_at" TIMESTAMPTZ(3), "recycle_at" TIMESTAMPTZ(3),
"assignee_user_id" TEXT, "assignee_user_id" TEXT,
...@@ -165,9 +179,32 @@ CREATE TABLE "followup_plans" ( ...@@ -165,9 +179,32 @@ CREATE TABLE "followup_plans" (
); );
-- CreateTable -- CreateTable
CREATE TABLE "plan_reasons" (
"id" UUID NOT NULL,
"plan_id" UUID NOT NULL,
"scenario" TEXT NOT NULL,
"sub_key" TEXT,
"priority_score" DOUBLE PRECISION NOT NULL,
"reason" TEXT NOT NULL,
"evidence" JSONB NOT NULL,
"breakdown" JSONB,
"signals" JSONB,
"lifecycle" TEXT NOT NULL DEFAULT 'one_shot',
"source" TEXT NOT NULL DEFAULT 'algorithm',
"source_actor_id" TEXT,
"campaign_id" TEXT,
"closed_reason" TEXT,
"closed_at" TIMESTAMPTZ(3),
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "plan_reasons_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "plan_scripts" ( CREATE TABLE "plan_scripts" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"plan_id" UUID NOT NULL, "plan_id" UUID NOT NULL,
"content" TEXT, "content" TEXT,
...@@ -183,7 +220,7 @@ CREATE TABLE "plan_scripts" ( ...@@ -183,7 +220,7 @@ CREATE TABLE "plan_scripts" (
-- CreateTable -- CreateTable
CREATE TABLE "plan_summaries" ( CREATE TABLE "plan_summaries" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"plan_id" UUID NOT NULL, "plan_id" UUID NOT NULL,
"type" TEXT NOT NULL, "type" TEXT NOT NULL,
...@@ -200,7 +237,7 @@ CREATE TABLE "plan_summaries" ( ...@@ -200,7 +237,7 @@ CREATE TABLE "plan_summaries" (
-- CreateTable -- CreateTable
CREATE TABLE "plan_executions" ( CREATE TABLE "plan_executions" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"executor_clinic_id" TEXT NOT NULL, "executor_clinic_id" TEXT NOT NULL,
"plan_id" UUID NOT NULL, "plan_id" UUID NOT NULL,
...@@ -208,6 +245,7 @@ CREATE TABLE "plan_executions" ( ...@@ -208,6 +245,7 @@ CREATE TABLE "plan_executions" (
"channel" TEXT NOT NULL, "channel" TEXT NOT NULL,
"outcome" TEXT NOT NULL, "outcome" TEXT NOT NULL,
"notes" TEXT, "notes" TEXT,
"invalid_reason" TEXT,
"abandon_reasons" TEXT[], "abandon_reasons" TEXT[],
"abandon_other" TEXT, "abandon_other" TEXT,
"scheduled_next_at" TIMESTAMPTZ(3), "scheduled_next_at" TIMESTAMPTZ(3),
...@@ -219,7 +257,7 @@ CREATE TABLE "plan_executions" ( ...@@ -219,7 +257,7 @@ CREATE TABLE "plan_executions" (
-- CreateTable -- CreateTable
CREATE TABLE "plan_generation_logs" ( CREATE TABLE "plan_generation_logs" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID NOT NULL, "patient_id" UUID NOT NULL,
"triggered_by" TEXT NOT NULL, "triggered_by" TEXT NOT NULL,
...@@ -240,13 +278,24 @@ CREATE TABLE "plan_generation_logs" ( ...@@ -240,13 +278,24 @@ CREATE TABLE "plan_generation_logs" (
-- CreateTable -- CreateTable
CREATE TABLE "agent_invocations" ( CREATE TABLE "agent_invocations" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"kind" TEXT NOT NULL, "kind" TEXT NOT NULL,
"agent_version" TEXT, "call_key" TEXT NOT NULL,
"model_name" TEXT, "prompt_version" TEXT NOT NULL,
"gateway_provider" TEXT NOT NULL, "model_provider" TEXT NOT NULL,
"workflow_id" TEXT, "model_name" TEXT NOT NULL,
"workflow_run_id" UUID NOT NULL,
"parent_invocation_id" UUID,
"input_hash" TEXT NOT NULL,
"cache_hit" BOOLEAN NOT NULL DEFAULT false,
"eval_mode" TEXT NOT NULL DEFAULT 'production',
"golden_set_case_id" TEXT,
"judge_score" DECIMAL(3,2),
"judge_rubric" JSONB,
"user_feedback" TEXT,
"user_feedback_at" TIMESTAMPTZ(3),
"user_feedback_by" TEXT,
"input_snapshot" JSONB NOT NULL, "input_snapshot" JSONB NOT NULL,
"prompt_template" TEXT, "prompt_template" TEXT,
"output" JSONB, "output" JSONB,
...@@ -257,7 +306,9 @@ CREATE TABLE "agent_invocations" ( ...@@ -257,7 +306,9 @@ CREATE TABLE "agent_invocations" (
"prompt_tokens" INTEGER NOT NULL DEFAULT 0, "prompt_tokens" INTEGER NOT NULL DEFAULT 0,
"completion_tokens" INTEGER NOT NULL DEFAULT 0, "completion_tokens" INTEGER NOT NULL DEFAULT 0,
"total_tokens" INTEGER NOT NULL DEFAULT 0, "total_tokens" INTEGER NOT NULL DEFAULT 0,
"cost_cents" INTEGER NOT NULL DEFAULT 0, "cached_input_tokens" INTEGER NOT NULL DEFAULT 0,
"reasoning_tokens" INTEGER NOT NULL DEFAULT 0,
"cost_yuan" DECIMAL(12,6) NOT NULL DEFAULT 0,
"status" TEXT NOT NULL, "status" TEXT NOT NULL,
"error_message" TEXT, "error_message" TEXT,
"started_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "started_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
...@@ -270,7 +321,7 @@ CREATE TABLE "agent_invocations" ( ...@@ -270,7 +321,7 @@ CREATE TABLE "agent_invocations" (
-- CreateTable -- CreateTable
CREATE TABLE "sync_logs" ( CREATE TABLE "sync_logs" (
"id" UUID NOT NULL, "id" UUID NOT NULL,
"platform_id" UUID NOT NULL, "host_id" UUID NOT NULL,
"tenant_id" TEXT NOT NULL, "tenant_id" TEXT NOT NULL,
"patient_id" UUID, "patient_id" UUID,
"direction" TEXT NOT NULL, "direction" TEXT NOT NULL,
...@@ -292,25 +343,31 @@ CREATE TABLE "sync_logs" ( ...@@ -292,25 +343,31 @@ CREATE TABLE "sync_logs" (
); );
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "platforms_name_key" ON "platforms"("name"); CREATE UNIQUE INDEX "hosts_name_key" ON "hosts"("name");
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "platforms_app_id_key" ON "platforms"("app_id"); CREATE UNIQUE INDEX "hosts_app_id_key" ON "hosts"("app_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "patients_platform_id_tenant_id_idx" ON "patients"("platform_id", "tenant_id"); CREATE INDEX "patients_host_id_tenant_id_idx" ON "patients"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "patients_phone_idx" ON "patients"("phone"); CREATE INDEX "patients_phone_idx" ON "patients"("phone");
-- CreateIndex -- CreateIndex
CREATE INDEX "patients_platform_id_tenant_id_status_do_not_contact_deceas_idx" ON "patients"("platform_id", "tenant_id", "status", "do_not_contact", "deceased"); CREATE INDEX "patients_host_id_tenant_id_active_idx" ON "patients"("host_id", "tenant_id", "active");
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "patients_platform_id_tenant_id_external_id_key" ON "patients"("platform_id", "tenant_id", "external_id"); CREATE UNIQUE INDEX "patients_host_id_tenant_id_external_id_key" ON "patients"("host_id", "tenant_id", "external_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "patient_transactions_platform_id_tenant_id_clinic_id_idx" ON "patient_transactions"("platform_id", "tenant_id", "clinic_id"); CREATE INDEX "patient_profiles_do_not_contact_idx" ON "patient_profiles"("do_not_contact");
-- CreateIndex
CREATE INDEX "patient_profiles_deceased_idx" ON "patient_profiles"("deceased");
-- CreateIndex
CREATE INDEX "patient_transactions_host_id_tenant_id_clinic_id_idx" ON "patient_transactions"("host_id", "tenant_id", "clinic_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "patient_transactions_patient_id_occurred_at_idx" ON "patient_transactions"("patient_id", "occurred_at"); CREATE INDEX "patient_transactions_patient_id_occurred_at_idx" ON "patient_transactions"("patient_id", "occurred_at");
...@@ -328,7 +385,7 @@ CREATE INDEX "patient_transactions_received_at_idx" ON "patient_transactions"("r ...@@ -328,7 +385,7 @@ CREATE INDEX "patient_transactions_received_at_idx" ON "patient_transactions"("r
CREATE INDEX "patient_transactions_event_seq_idx" ON "patient_transactions"("event_seq"); CREATE INDEX "patient_transactions_event_seq_idx" ON "patient_transactions"("event_seq");
-- CreateIndex -- CreateIndex
CREATE INDEX "patient_facts_platform_id_tenant_id_idx" ON "patient_facts"("platform_id", "tenant_id"); CREATE INDEX "patient_facts_host_id_tenant_id_idx" ON "patient_facts"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "patient_facts_patient_id_status_idx" ON "patient_facts"("patient_id", "status"); CREATE INDEX "patient_facts_patient_id_status_idx" ON "patient_facts"("patient_id", "status");
...@@ -343,10 +400,10 @@ CREATE INDEX "patient_facts_patient_id_planned_for_idx" ON "patient_facts"("pati ...@@ -343,10 +400,10 @@ CREATE INDEX "patient_facts_patient_id_planned_for_idx" ON "patient_facts"("pati
CREATE INDEX "patient_facts_type_status_valid_until_idx" ON "patient_facts"("type", "status", "valid_until"); CREATE INDEX "patient_facts_type_status_valid_until_idx" ON "patient_facts"("type", "status", "valid_until");
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "patient_facts_platform_id_tenant_id_subject_id_version_key" ON "patient_facts"("platform_id", "tenant_id", "subject_id", "version"); CREATE UNIQUE INDEX "patient_facts_host_id_tenant_id_subject_id_version_key" ON "patient_facts"("host_id", "tenant_id", "subject_id", "version");
-- CreateIndex -- CreateIndex
CREATE INDEX "personas_platform_id_tenant_id_idx" ON "personas"("platform_id", "tenant_id"); CREATE INDEX "personas_host_id_tenant_id_idx" ON "personas"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "personas_patient_id_superseded_at_idx" ON "personas"("patient_id", "superseded_at"); CREATE INDEX "personas_patient_id_superseded_at_idx" ON "personas"("patient_id", "superseded_at");
...@@ -364,19 +421,16 @@ CREATE UNIQUE INDEX "persona_features_persona_id_key_key" ON "persona_features"( ...@@ -364,19 +421,16 @@ CREATE UNIQUE INDEX "persona_features_persona_id_key_key" ON "persona_features"(
CREATE INDEX "persona_recompute_logs_patient_id_started_at_idx" ON "persona_recompute_logs"("patient_id", "started_at"); CREATE INDEX "persona_recompute_logs_patient_id_started_at_idx" ON "persona_recompute_logs"("patient_id", "started_at");
-- CreateIndex -- CreateIndex
CREATE INDEX "persona_recompute_logs_platform_id_tenant_id_idx" ON "persona_recompute_logs"("platform_id", "tenant_id"); CREATE INDEX "persona_recompute_logs_host_id_tenant_id_idx" ON "persona_recompute_logs"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "persona_recompute_logs_status_idx" ON "persona_recompute_logs"("status"); CREATE INDEX "persona_recompute_logs_status_idx" ON "persona_recompute_logs"("status");
-- CreateIndex -- CreateIndex
CREATE INDEX "followup_plans_platform_id_tenant_id_idx" ON "followup_plans"("platform_id", "tenant_id"); CREATE INDEX "followup_plans_host_id_tenant_id_idx" ON "followup_plans"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "followup_plans_platform_id_tenant_id_target_clinic_id_idx" ON "followup_plans"("platform_id", "tenant_id", "target_clinic_id"); CREATE INDEX "followup_plans_host_id_tenant_id_target_clinic_id_idx" ON "followup_plans"("host_id", "tenant_id", "target_clinic_id");
-- CreateIndex
CREATE INDEX "followup_plans_scenario_status_idx" ON "followup_plans"("scenario", "status");
-- CreateIndex -- CreateIndex
CREATE INDEX "followup_plans_assignee_user_id_idx" ON "followup_plans"("assignee_user_id"); CREATE INDEX "followup_plans_assignee_user_id_idx" ON "followup_plans"("assignee_user_id");
...@@ -385,22 +439,31 @@ CREATE INDEX "followup_plans_assignee_user_id_idx" ON "followup_plans"("assignee ...@@ -385,22 +439,31 @@ CREATE INDEX "followup_plans_assignee_user_id_idx" ON "followup_plans"("assignee
CREATE INDEX "followup_plans_status_assignee_user_id_priority_score_idx" ON "followup_plans"("status", "assignee_user_id", "priority_score"); CREATE INDEX "followup_plans_status_assignee_user_id_priority_score_idx" ON "followup_plans"("status", "assignee_user_id", "priority_score");
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "followup_plans_platform_id_tenant_id_patient_id_scenario_ve_key" ON "followup_plans"("platform_id", "tenant_id", "patient_id", "scenario", "version"); CREATE UNIQUE INDEX "followup_plans_host_id_tenant_id_patient_id_version_key" ON "followup_plans"("host_id", "tenant_id", "patient_id", "version");
-- CreateIndex
CREATE INDEX "plan_reasons_scenario_idx" ON "plan_reasons"("scenario");
-- CreateIndex
CREATE INDEX "plan_reasons_campaign_id_idx" ON "plan_reasons"("campaign_id");
-- CreateIndex
CREATE UNIQUE INDEX "plan_reasons_plan_id_scenario_sub_key_key" ON "plan_reasons"("plan_id", "scenario", "sub_key");
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "plan_scripts_plan_id_key" ON "plan_scripts"("plan_id"); CREATE UNIQUE INDEX "plan_scripts_plan_id_key" ON "plan_scripts"("plan_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "plan_scripts_platform_id_tenant_id_idx" ON "plan_scripts"("platform_id", "tenant_id"); CREATE INDEX "plan_scripts_host_id_tenant_id_idx" ON "plan_scripts"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "plan_summaries_platform_id_tenant_id_idx" ON "plan_summaries"("platform_id", "tenant_id"); CREATE INDEX "plan_summaries_host_id_tenant_id_idx" ON "plan_summaries"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE UNIQUE INDEX "plan_summaries_plan_id_type_key" ON "plan_summaries"("plan_id", "type"); CREATE UNIQUE INDEX "plan_summaries_plan_id_type_key" ON "plan_summaries"("plan_id", "type");
-- CreateIndex -- CreateIndex
CREATE INDEX "plan_executions_platform_id_tenant_id_executor_clinic_id_idx" ON "plan_executions"("platform_id", "tenant_id", "executor_clinic_id"); CREATE INDEX "plan_executions_host_id_tenant_id_executor_clinic_id_idx" ON "plan_executions"("host_id", "tenant_id", "executor_clinic_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "plan_executions_plan_id_created_at_idx" ON "plan_executions"("plan_id", "created_at"); CREATE INDEX "plan_executions_plan_id_created_at_idx" ON "plan_executions"("plan_id", "created_at");
...@@ -412,18 +475,33 @@ CREATE INDEX "plan_executions_operator_user_id_created_at_idx" ON "plan_executio ...@@ -412,18 +475,33 @@ CREATE INDEX "plan_executions_operator_user_id_created_at_idx" ON "plan_executio
CREATE INDEX "plan_generation_logs_patient_id_started_at_idx" ON "plan_generation_logs"("patient_id", "started_at"); CREATE INDEX "plan_generation_logs_patient_id_started_at_idx" ON "plan_generation_logs"("patient_id", "started_at");
-- CreateIndex -- CreateIndex
CREATE INDEX "plan_generation_logs_platform_id_tenant_id_idx" ON "plan_generation_logs"("platform_id", "tenant_id"); CREATE INDEX "plan_generation_logs_host_id_tenant_id_idx" ON "plan_generation_logs"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "plan_generation_logs_status_idx" ON "plan_generation_logs"("status"); CREATE INDEX "plan_generation_logs_status_idx" ON "plan_generation_logs"("status");
-- CreateIndex -- CreateIndex
CREATE INDEX "agent_invocations_platform_id_tenant_id_idx" ON "agent_invocations"("platform_id", "tenant_id"); CREATE INDEX "agent_invocations_host_id_tenant_id_idx" ON "agent_invocations"("host_id", "tenant_id");
-- CreateIndex -- CreateIndex
CREATE INDEX "agent_invocations_kind_idx" ON "agent_invocations"("kind"); CREATE INDEX "agent_invocations_kind_idx" ON "agent_invocations"("kind");
-- CreateIndex -- CreateIndex
CREATE INDEX "agent_invocations_call_key_prompt_version_started_at_idx" ON "agent_invocations"("call_key", "prompt_version", "started_at");
-- CreateIndex
CREATE INDEX "agent_invocations_workflow_run_id_idx" ON "agent_invocations"("workflow_run_id");
-- CreateIndex
CREATE INDEX "agent_invocations_parent_invocation_id_idx" ON "agent_invocations"("parent_invocation_id");
-- CreateIndex
CREATE INDEX "agent_invocations_input_hash_idx" ON "agent_invocations"("input_hash");
-- CreateIndex
CREATE INDEX "agent_invocations_eval_mode_call_key_idx" ON "agent_invocations"("eval_mode", "call_key");
-- CreateIndex
CREATE INDEX "agent_invocations_linked_patient_id_idx" ON "agent_invocations"("linked_patient_id"); CREATE INDEX "agent_invocations_linked_patient_id_idx" ON "agent_invocations"("linked_patient_id");
-- CreateIndex -- CreateIndex
...@@ -436,7 +514,7 @@ CREATE INDEX "agent_invocations_linked_plan_id_idx" ON "agent_invocations"("link ...@@ -436,7 +514,7 @@ CREATE INDEX "agent_invocations_linked_plan_id_idx" ON "agent_invocations"("link
CREATE INDEX "agent_invocations_started_at_idx" ON "agent_invocations"("started_at"); CREATE INDEX "agent_invocations_started_at_idx" ON "agent_invocations"("started_at");
-- CreateIndex -- CreateIndex
CREATE INDEX "sync_logs_platform_id_tenant_id_resource_idx" ON "sync_logs"("platform_id", "tenant_id", "resource"); CREATE INDEX "sync_logs_host_id_tenant_id_resource_idx" ON "sync_logs"("host_id", "tenant_id", "resource");
-- CreateIndex -- CreateIndex
CREATE INDEX "sync_logs_started_at_idx" ON "sync_logs"("started_at"); CREATE INDEX "sync_logs_started_at_idx" ON "sync_logs"("started_at");
...@@ -448,13 +526,13 @@ CREATE INDEX "sync_logs_status_idx" ON "sync_logs"("status"); ...@@ -448,13 +526,13 @@ CREATE INDEX "sync_logs_status_idx" ON "sync_logs"("status");
CREATE INDEX "sync_logs_patient_id_started_at_idx" ON "sync_logs"("patient_id", "started_at"); CREATE INDEX "sync_logs_patient_id_started_at_idx" ON "sync_logs"("patient_id", "started_at");
-- AddForeignKey -- AddForeignKey
ALTER TABLE "patients" ADD CONSTRAINT "patients_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "patients" ADD CONSTRAINT "patients_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "patients" ADD CONSTRAINT "patients_merged_into_id_fkey" FOREIGN KEY ("merged_into_id") REFERENCES "patients"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "patient_profiles" ADD CONSTRAINT "patient_profiles_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE SET NULL ON UPDATE CASCADE;
...@@ -463,13 +541,13 @@ ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_patient_ ...@@ -463,13 +541,13 @@ ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_patient_
ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_sync_log_id_fkey" FOREIGN KEY ("sync_log_id") REFERENCES "sync_logs"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "patient_transactions" ADD CONSTRAINT "patient_transactions_sync_log_id_fkey" FOREIGN KEY ("sync_log_id") REFERENCES "sync_logs"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "patient_facts" ADD CONSTRAINT "patient_facts_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "patient_facts" ADD CONSTRAINT "patient_facts_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "patient_facts" ADD CONSTRAINT "patient_facts_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "patient_facts" ADD CONSTRAINT "patient_facts_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "personas" ADD CONSTRAINT "personas_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "personas" ADD CONSTRAINT "personas_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "personas" ADD CONSTRAINT "personas_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "personas" ADD CONSTRAINT "personas_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
...@@ -478,10 +556,10 @@ ALTER TABLE "personas" ADD CONSTRAINT "personas_patient_id_fkey" FOREIGN KEY ("p ...@@ -478,10 +556,10 @@ ALTER TABLE "personas" ADD CONSTRAINT "personas_patient_id_fkey" FOREIGN KEY ("p
ALTER TABLE "persona_features" ADD CONSTRAINT "persona_features_persona_id_fkey" FOREIGN KEY ("persona_id") REFERENCES "personas"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "persona_features" ADD CONSTRAINT "persona_features_persona_id_fkey" FOREIGN KEY ("persona_id") REFERENCES "personas"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "persona_recompute_logs" ADD CONSTRAINT "persona_recompute_logs_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "persona_recompute_logs" ADD CONSTRAINT "persona_recompute_logs_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "patients"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
...@@ -490,52 +568,32 @@ ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_patient_id_fkey" FOR ...@@ -490,52 +568,32 @@ ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_patient_id_fkey" FOR
ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_persona_id_fkey" FOREIGN KEY ("persona_id") REFERENCES "personas"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "followup_plans" ADD CONSTRAINT "followup_plans_persona_id_fkey" FOREIGN KEY ("persona_id") REFERENCES "personas"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_scripts" ADD CONSTRAINT "plan_scripts_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "plan_reasons" ADD CONSTRAINT "plan_reasons_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "plan_scripts" ADD CONSTRAINT "plan_scripts_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_scripts" ADD CONSTRAINT "plan_scripts_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "plan_scripts" ADD CONSTRAINT "plan_scripts_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_summaries" ADD CONSTRAINT "plan_summaries_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "plan_summaries" ADD CONSTRAINT "plan_summaries_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_summaries" ADD CONSTRAINT "plan_summaries_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "plan_summaries" ADD CONSTRAINT "plan_summaries_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_executions" ADD CONSTRAINT "plan_executions_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "plan_executions" ADD CONSTRAINT "plan_executions_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_executions" ADD CONSTRAINT "plan_executions_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "plan_executions" ADD CONSTRAINT "plan_executions_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "followup_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "plan_generation_logs" ADD CONSTRAINT "plan_generation_logs_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "plan_generation_logs" ADD CONSTRAINT "plan_generation_logs_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "agent_invocations" ADD CONSTRAINT "agent_invocations_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "agent_invocations" ADD CONSTRAINT "agent_invocations_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey -- AddForeignKey
ALTER TABLE "sync_logs" ADD CONSTRAINT "sync_logs_platform_id_fkey" FOREIGN KEY ("platform_id") REFERENCES "platforms"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "sync_logs" ADD CONSTRAINT "sync_logs_host_id_fkey" FOREIGN KEY ("host_id") REFERENCES "hosts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- ============================================================================
-- 以下 4 项 Prisma schema 表达不了,这里用 raw SQL 补齐(对应 schema.prisma 头部 MIGRATION 注释)
-- ============================================================================
-- 1) patient_transactions 幂等键:partial UNIQUE on source_event_id (WHERE NOT NULL)
CREATE UNIQUE INDEX "patient_transactions_idempotency"
ON "patient_transactions" ("platform_id", "tenant_id", "source_event_id")
WHERE "source_event_id" IS NOT NULL;
-- 2) patient_facts 单一活跃版本:partial UNIQUE on subject_id (WHERE status='active')
CREATE UNIQUE INDEX "patient_facts_single_active_version"
ON "patient_facts" ("platform_id", "tenant_id", "subject_id")
WHERE "status" = 'active';
-- 3) patient_facts 证据链反查:GIN on transaction_ids 数组
CREATE INDEX "patient_facts_transaction_ids_gin"
ON "patient_facts" USING GIN ("transaction_ids");
-- 4) followup_plans 单一活跃计划:partial UNIQUE per (patient, scenario)
-- WHERE status IN ('active','assigned') — 同 patient × scenario 只能有一个未结案 plan
CREATE UNIQUE INDEX "followup_plans_one_open_per_scenario"
ON "followup_plans" ("platform_id", "tenant_id", "patient_id", "scenario")
WHERE "status" IN ('active', 'assigned');
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment