chore: squash migrations into initial schema
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,932 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddContentNavigationAndTenantConfiguration : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("Npgsql:PostgresExtension:citext", ",,")
|
||||
.Annotation("Npgsql:PostgresExtension:ltree", ",,")
|
||||
.OldAnnotation("Npgsql:PostgresExtension:citext", ",,");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "content_node_id",
|
||||
table: "questions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "entry_id",
|
||||
table: "questions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "exam_markers",
|
||||
table: "questions",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "primary_collection_id",
|
||||
table: "questions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "blueprint_id",
|
||||
table: "practice_sessions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "collection_id",
|
||||
table: "practice_sessions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "content_node_id",
|
||||
table: "practice_sessions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "duration_minutes",
|
||||
table: "practice_sessions",
|
||||
type: "integer",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "entry_id",
|
||||
table: "practice_sessions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "expires_at",
|
||||
table: "practice_sessions",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "question_count",
|
||||
table: "practice_sessions",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "question_ids",
|
||||
table: "practice_sessions",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'[]'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "total_score",
|
||||
table: "practice_sessions",
|
||||
type: "numeric(8,2)",
|
||||
precision: 8,
|
||||
scale: 2,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_entries",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
entry_key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
entry_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
icon = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
route = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
description = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
|
||||
visibility = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
access_rules = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
layout_config = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_entries", x => x.id);
|
||||
table.UniqueConstraint("ak_content_entries_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_content_entries_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_entries_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_entries_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_entries_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_branding",
|
||||
columns: table => new
|
||||
{
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
brand_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
short_name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
slogan = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
organization_name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
logo_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
favicon_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
service_wechat = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
service_account_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
theme = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
public_assets = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_branding", x => x.tenant_id);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_branding_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_domains",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
host = table.Column<string>(type: "citext", maxLength: 253, nullable: false),
|
||||
domain_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
is_primary = table.Column<bool>(type: "boolean", nullable: false),
|
||||
verification_token = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||
verified_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_domains", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_domains_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_domains_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_settings",
|
||||
columns: table => new
|
||||
{
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
feature_flags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
admin_feature_flags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
public_config = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_settings", x => x.tenant_id);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_settings_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_nodes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
parent_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
node_key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
node_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
marker_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
marker_config = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
path = table.Column<string>(type: "ltree", nullable: true),
|
||||
depth = table.Column<int>(type: "integer", nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
is_selectable = table.Column<bool>(type: "boolean", nullable: false),
|
||||
is_leaf = table.Column<bool>(type: "boolean", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_nodes", x => x.id);
|
||||
table.UniqueConstraint("ak_content_nodes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_content_nodes_depth", "depth >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_content_nodes_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_nodes_content_nodes_tenant_id_parent_id",
|
||||
columns: x => new { x.tenant_id, x.parent_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_nodes_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_nodes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_nodes_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_nodes_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "question_collections",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
subject_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
category_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
question_bank_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
collection_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
filters = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
question_count = table.Column<int>(type: "integer", nullable: false),
|
||||
total_score = table.Column<decimal>(type: "numeric(8,2)", precision: 8, scale: 2, nullable: true),
|
||||
duration_minutes = table.Column<int>(type: "integer", nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_question_collections", x => x.id);
|
||||
table.UniqueConstraint("ak_question_collections_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_question_collections_duration", "duration_minutes is null or duration_minutes > 0");
|
||||
table.CheckConstraint("ck_question_collections_question_count", "question_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_categories_tenant_id_category_id",
|
||||
columns: x => new { x.tenant_id, x.category_id },
|
||||
principalTable: "categories",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_content_nodes_tenant_id_node_id",
|
||||
columns: x => new { x.tenant_id, x.node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_question_banks_tenant_id_question_bank~",
|
||||
columns: x => new { x.tenant_id, x.question_bank_id },
|
||||
principalTable: "question_banks",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_subjects_tenant_id_subject_id",
|
||||
columns: x => new { x.tenant_id, x.subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collections_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "practice_blueprints",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
collection_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
assembly_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
question_limit = table.Column<int>(type: "integer", nullable: true),
|
||||
duration_minutes = table.Column<int>(type: "integer", nullable: true),
|
||||
total_score = table.Column<decimal>(type: "numeric(8,2)", precision: 8, scale: 2, nullable: true),
|
||||
pass_score = table.Column<decimal>(type: "numeric(8,2)", precision: 8, scale: 2, nullable: true),
|
||||
sections = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
rules = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_practice_blueprints", x => x.id);
|
||||
table.UniqueConstraint("ak_practice_blueprints_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_practice_blueprints_duration", "duration_minutes is null or duration_minutes > 0");
|
||||
table.CheckConstraint("ck_practice_blueprints_question_limit", "question_limit is null or question_limit > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_content_nodes_tenant_id_node_id",
|
||||
columns: x => new { x.tenant_id, x.node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_question_collections_tenant_id_collecti~",
|
||||
columns: x => new { x.tenant_id, x.collection_id },
|
||||
principalTable: "question_collections",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_blueprints_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "question_collection_items",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
collection_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
question_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
section_key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
score = table.Column<decimal>(type: "numeric(8,2)", precision: 8, scale: 2, nullable: true),
|
||||
required = table.Column<bool>(type: "boolean", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_question_collection_items", x => x.id);
|
||||
table.UniqueConstraint("ak_question_collection_items_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collection_items_question_collections_tenant_id_co~",
|
||||
columns: x => new { x.tenant_id, x.collection_id },
|
||||
principalTable: "question_collections",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collection_items_questions_tenant_id_question_id",
|
||||
columns: x => new { x.tenant_id, x.question_id },
|
||||
principalTable: "questions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_collection_items_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_questions_tenant_id_content_node_id",
|
||||
table: "questions",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_questions_tenant_id_entry_id",
|
||||
table: "questions",
|
||||
columns: new[] { "tenant_id", "entry_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_questions_tenant_id_primary_collection_id",
|
||||
table: "questions",
|
||||
columns: new[] { "tenant_id", "primary_collection_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_sessions_tenant_id_blueprint_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "blueprint_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_sessions_tenant_id_collection_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "collection_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_sessions_tenant_id_content_node_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_sessions_tenant_id_entry_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "entry_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_entries_created_by",
|
||||
table: "content_entries",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_entries_tenant_id_entry_key",
|
||||
table: "content_entries",
|
||||
columns: new[] { "tenant_id", "entry_key" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_entries_tenant_id_legacy_id",
|
||||
table: "content_entries",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_entries_tenant_id_region_id_entry_type_is_active_so~",
|
||||
table: "content_entries",
|
||||
columns: new[] { "tenant_id", "region_id", "entry_type", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_entries_updated_by",
|
||||
table: "content_entries",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_created_by",
|
||||
table: "content_nodes",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_path",
|
||||
table: "content_nodes",
|
||||
column: "path")
|
||||
.Annotation("Npgsql:IndexMethod", "gist");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_tenant_id_entry_id_node_key",
|
||||
table: "content_nodes",
|
||||
columns: new[] { "tenant_id", "entry_id", "node_key" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_tenant_id_entry_id_parent_id_sort_order",
|
||||
table: "content_nodes",
|
||||
columns: new[] { "tenant_id", "entry_id", "parent_id", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_tenant_id_legacy_id",
|
||||
table: "content_nodes",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_tenant_id_marker_type",
|
||||
table: "content_nodes",
|
||||
columns: new[] { "tenant_id", "marker_type" },
|
||||
filter: "marker_type is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_tenant_id_parent_id",
|
||||
table: "content_nodes",
|
||||
columns: new[] { "tenant_id", "parent_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_tenant_id_region_id",
|
||||
table: "content_nodes",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_nodes_updated_by",
|
||||
table: "content_nodes",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_created_by",
|
||||
table: "practice_blueprints",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_tenant_id_collection_id",
|
||||
table: "practice_blueprints",
|
||||
columns: new[] { "tenant_id", "collection_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_tenant_id_entry_id",
|
||||
table: "practice_blueprints",
|
||||
columns: new[] { "tenant_id", "entry_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_tenant_id_legacy_id",
|
||||
table: "practice_blueprints",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_tenant_id_node_id_collection_id_mode_st~",
|
||||
table: "practice_blueprints",
|
||||
columns: new[] { "tenant_id", "node_id", "collection_id", "mode", "status", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_tenant_id_region_id",
|
||||
table: "practice_blueprints",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_blueprints_updated_by",
|
||||
table: "practice_blueprints",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collection_items_tenant_id_collection_id_question_~",
|
||||
table: "question_collection_items",
|
||||
columns: new[] { "tenant_id", "collection_id", "question_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collection_items_tenant_id_collection_id_section_k~",
|
||||
table: "question_collection_items",
|
||||
columns: new[] { "tenant_id", "collection_id", "section_key", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collection_items_tenant_id_question_id",
|
||||
table: "question_collection_items",
|
||||
columns: new[] { "tenant_id", "question_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_created_by",
|
||||
table: "question_collections",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_category_id",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "category_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_entry_id",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "entry_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_legacy_id",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_node_id_status_sort_order",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "node_id", "status", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_question_bank_id",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "question_bank_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_region_id",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_tenant_id_subject_id",
|
||||
table: "question_collections",
|
||||
columns: new[] { "tenant_id", "subject_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_collections_updated_by",
|
||||
table: "question_collections",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_domains_host",
|
||||
table: "tenant_domains",
|
||||
column: "host",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_domains_tenant_id_is_primary",
|
||||
table: "tenant_domains",
|
||||
columns: new[] { "tenant_id", "is_primary" },
|
||||
unique: true,
|
||||
filter: "is_primary");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_practice_sessions_content_entries_tenant_id_entry_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "entry_id" },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_practice_sessions_content_nodes_tenant_id_content_node_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "content_node_id" },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_practice_sessions_practice_blueprints_tenant_id_blueprint_id",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "blueprint_id" },
|
||||
principalTable: "practice_blueprints",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_practice_sessions_question_collections_tenant_id_collection~",
|
||||
table: "practice_sessions",
|
||||
columns: new[] { "tenant_id", "collection_id" },
|
||||
principalTable: "question_collections",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_questions_content_entries_tenant_id_entry_id",
|
||||
table: "questions",
|
||||
columns: new[] { "tenant_id", "entry_id" },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_questions_content_nodes_tenant_id_content_node_id",
|
||||
table: "questions",
|
||||
columns: new[] { "tenant_id", "content_node_id" },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_questions_question_collections_tenant_id_primary_collection~",
|
||||
table: "questions",
|
||||
columns: new[] { "tenant_id", "primary_collection_id" },
|
||||
principalTable: "question_collections",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_practice_sessions_content_entries_tenant_id_entry_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_practice_sessions_content_nodes_tenant_id_content_node_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_practice_sessions_practice_blueprints_tenant_id_blueprint_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_practice_sessions_question_collections_tenant_id_collection~",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_questions_content_entries_tenant_id_entry_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_questions_content_nodes_tenant_id_content_node_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_questions_question_collections_tenant_id_primary_collection~",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "practice_blueprints");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "question_collection_items");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_branding");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_domains");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_settings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "question_collections");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_nodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_entries");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_questions_tenant_id_content_node_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_questions_tenant_id_entry_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_questions_tenant_id_primary_collection_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_practice_sessions_tenant_id_blueprint_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_practice_sessions_tenant_id_collection_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_practice_sessions_tenant_id_content_node_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_practice_sessions_tenant_id_entry_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "content_node_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "entry_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "exam_markers",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "primary_collection_id",
|
||||
table: "questions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "blueprint_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "collection_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "content_node_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "duration_minutes",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "entry_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "expires_at",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "question_count",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "question_ids",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "total_score",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("Npgsql:PostgresExtension:citext", ",,")
|
||||
.OldAnnotation("Npgsql:PostgresExtension:citext", ",,")
|
||||
.OldAnnotation("Npgsql:PostgresExtension:ltree", ",,");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,648 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddVocabularyAndHandbookPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "handbook_subjects",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
school_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
major_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
icon = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
color = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
major_legacy_ids = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_handbook_subjects", x => x.id);
|
||||
table.UniqueConstraint("ak_handbook_subjects_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_subjects_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_subjects_content_nodes_tenant_id_content_node_id",
|
||||
columns: x => new { x.tenant_id, x.content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_subjects_majors_tenant_id_major_id",
|
||||
columns: x => new { x.tenant_id, x.major_id },
|
||||
principalTable: "majors",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_subjects_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_subjects_schools_tenant_id_school_id",
|
||||
columns: x => new { x.tenant_id, x.school_id },
|
||||
principalTable: "schools",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_subjects_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "question_type_groups",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
subject_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
display_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
types = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_question_type_groups", x => x.id);
|
||||
table.UniqueConstraint("ak_question_type_groups_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_question_type_groups_subjects_tenant_id_subject_id",
|
||||
columns: x => new { x.tenant_id, x.subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_type_groups_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "subject_shares",
|
||||
columns: table => new
|
||||
{
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
source_subject_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
target_subject_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
legacy_id = table.Column<string>(type: "text", nullable: true),
|
||||
legacy_source_subject_id = table.Column<string>(type: "text", nullable: true),
|
||||
legacy_target_subject_id = table.Column<string>(type: "text", nullable: true),
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_subject_shares", x => new { x.tenant_id, x.source_subject_id, x.target_subject_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_subject_shares_subjects_tenant_id_source_subject_id",
|
||||
columns: x => new { x.tenant_id, x.source_subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_subject_shares_subjects_tenant_id_target_subject_id",
|
||||
columns: x => new { x.tenant_id, x.target_subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_subject_shares_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "vocabulary_units",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
word_count = table.Column<int>(type: "integer", nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_vocabulary_units", x => x.id);
|
||||
table.UniqueConstraint("ak_vocabulary_units_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_units_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_units_content_nodes_tenant_id_content_node_id",
|
||||
columns: x => new { x.tenant_id, x.content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_units_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_units_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "handbook_chapters",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
subject_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_handbook_chapters", x => x.id);
|
||||
table.UniqueConstraint("ak_handbook_chapters_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_chapters_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_chapters_content_nodes_tenant_id_content_node_id",
|
||||
columns: x => new { x.tenant_id, x.content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_chapters_handbook_subjects_tenant_id_subject_id",
|
||||
columns: x => new { x.tenant_id, x.subject_id },
|
||||
principalTable: "handbook_subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_chapters_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "vocabulary_words",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
unit_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
word = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
phonetic = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
meaning = table.Column<string>(type: "text", nullable: true),
|
||||
example = table.Column<string>(type: "text", nullable: true),
|
||||
example_translation = table.Column<string>(type: "text", nullable: true),
|
||||
difficulty = table.Column<int>(type: "integer", nullable: true),
|
||||
tags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_vocabulary_words", x => x.id);
|
||||
table.UniqueConstraint("ak_vocabulary_words_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_words_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_words_content_nodes_tenant_id_content_node_id",
|
||||
columns: x => new { x.tenant_id, x.content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_words_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_vocabulary_words_vocabulary_units_tenant_id_unit_id",
|
||||
columns: x => new { x.tenant_id, x.unit_id },
|
||||
principalTable: "vocabulary_units",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "handbook_entries",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
chapter_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: false),
|
||||
summary = table.Column<string>(type: "text", nullable: true),
|
||||
content = table.Column<string>(type: "text", nullable: true),
|
||||
tags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_handbook_entries", x => x.id);
|
||||
table.UniqueConstraint("ak_handbook_entries_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_entries_content_entries_tenant_id_entry_id",
|
||||
columns: x => new { x.tenant_id, x.entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_entries_content_nodes_tenant_id_content_node_id",
|
||||
columns: x => new { x.tenant_id, x.content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_entries_handbook_chapters_tenant_id_chapter_id",
|
||||
columns: x => new { x.tenant_id, x.chapter_id },
|
||||
principalTable: "handbook_chapters",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_handbook_entries_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_word_favorites",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
word_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
legacy_id = table.Column<string>(type: "text", nullable: true),
|
||||
legacy_user_id = table.Column<string>(type: "text", nullable: true),
|
||||
legacy_word_id = table.Column<string>(type: "text", nullable: true),
|
||||
note = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
favorited_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_word_favorites", x => x.id);
|
||||
table.UniqueConstraint("ak_user_word_favorites_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_user_word_favorites_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_word_favorites_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_word_favorites_vocabulary_words_tenant_id_word_id",
|
||||
columns: x => new { x.tenant_id, x.word_id },
|
||||
principalTable: "vocabulary_words",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_word_progress",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
word_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
legacy_id = table.Column<string>(type: "text", nullable: true),
|
||||
legacy_user_id = table.Column<string>(type: "text", nullable: true),
|
||||
legacy_word_id = table.Column<string>(type: "text", nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
correct_count = table.Column<int>(type: "integer", nullable: false),
|
||||
wrong_count = table.Column<int>(type: "integer", nullable: false),
|
||||
last_review_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
next_review_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
review_count = table.Column<int>(type: "integer", nullable: false),
|
||||
correct_streak = table.Column<int>(type: "integer", nullable: false),
|
||||
ease_factor = table.Column<decimal>(type: "numeric(4,2)", precision: 4, scale: 2, nullable: false, defaultValue: 2.50m),
|
||||
last_result = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
due_level = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_word_progress", x => x.id);
|
||||
table.UniqueConstraint("ak_user_word_progress_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_user_word_progress_correct_streak", "correct_streak >= 0");
|
||||
table.CheckConstraint("ck_user_word_progress_ease_factor", "ease_factor >= 1.30 and ease_factor <= 3.00");
|
||||
table.CheckConstraint("ck_user_word_progress_review_count", "review_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_user_word_progress_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_word_progress_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_word_progress_vocabulary_words_tenant_id_word_id",
|
||||
columns: x => new { x.tenant_id, x.word_id },
|
||||
principalTable: "vocabulary_words",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_chapters_tenant_id_content_node_id",
|
||||
table: "handbook_chapters",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_chapters_tenant_id_entry_id_content_node_id_subjec~",
|
||||
table: "handbook_chapters",
|
||||
columns: new[] { "tenant_id", "entry_id", "content_node_id", "subject_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_chapters_tenant_id_legacy_id",
|
||||
table: "handbook_chapters",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_chapters_tenant_id_subject_id",
|
||||
table: "handbook_chapters",
|
||||
columns: new[] { "tenant_id", "subject_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_entries_tenant_id_chapter_id",
|
||||
table: "handbook_entries",
|
||||
columns: new[] { "tenant_id", "chapter_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_entries_tenant_id_content_node_id",
|
||||
table: "handbook_entries",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_entries_tenant_id_entry_id_content_node_id_chapter~",
|
||||
table: "handbook_entries",
|
||||
columns: new[] { "tenant_id", "entry_id", "content_node_id", "chapter_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_entries_tenant_id_legacy_id",
|
||||
table: "handbook_entries",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_subjects_tenant_id_content_node_id",
|
||||
table: "handbook_subjects",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_subjects_tenant_id_entry_id_content_node_id_region~",
|
||||
table: "handbook_subjects",
|
||||
columns: new[] { "tenant_id", "entry_id", "content_node_id", "region_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_subjects_tenant_id_legacy_id",
|
||||
table: "handbook_subjects",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_subjects_tenant_id_major_id",
|
||||
table: "handbook_subjects",
|
||||
columns: new[] { "tenant_id", "major_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_subjects_tenant_id_region_id",
|
||||
table: "handbook_subjects",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_handbook_subjects_tenant_id_school_id",
|
||||
table: "handbook_subjects",
|
||||
columns: new[] { "tenant_id", "school_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_type_groups_tenant_id_legacy_id",
|
||||
table: "question_type_groups",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_type_groups_tenant_id_subject_id_is_active_sort_or~",
|
||||
table: "question_type_groups",
|
||||
columns: new[] { "tenant_id", "subject_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_subject_shares_tenant_id_target_subject_id",
|
||||
table: "subject_shares",
|
||||
columns: new[] { "tenant_id", "target_subject_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_favorites_tenant_id_user_id_word_id",
|
||||
table: "user_word_favorites",
|
||||
columns: new[] { "tenant_id", "user_id", "word_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_favorites_tenant_id_word_id",
|
||||
table: "user_word_favorites",
|
||||
columns: new[] { "tenant_id", "word_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_favorites_user_id",
|
||||
table: "user_word_favorites",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_progress_tenant_id_user_id_next_review_at_status_~",
|
||||
table: "user_word_progress",
|
||||
columns: new[] { "tenant_id", "user_id", "next_review_at", "status", "due_level" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_progress_tenant_id_user_id_word_id",
|
||||
table: "user_word_progress",
|
||||
columns: new[] { "tenant_id", "user_id", "word_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_progress_tenant_id_word_id",
|
||||
table: "user_word_progress",
|
||||
columns: new[] { "tenant_id", "word_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_word_progress_user_id",
|
||||
table: "user_word_progress",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_units_tenant_id_content_node_id",
|
||||
table: "vocabulary_units",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_units_tenant_id_entry_id_content_node_id_region_~",
|
||||
table: "vocabulary_units",
|
||||
columns: new[] { "tenant_id", "entry_id", "content_node_id", "region_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_units_tenant_id_legacy_id",
|
||||
table: "vocabulary_units",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_units_tenant_id_region_id",
|
||||
table: "vocabulary_units",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_words_tenant_id_content_node_id",
|
||||
table: "vocabulary_words",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_words_tenant_id_entry_id_content_node_id_unit_id~",
|
||||
table: "vocabulary_words",
|
||||
columns: new[] { "tenant_id", "entry_id", "content_node_id", "unit_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_words_tenant_id_legacy_id",
|
||||
table: "vocabulary_words",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_vocabulary_words_tenant_id_unit_id_is_active_sort_order_cre~",
|
||||
table: "vocabulary_words",
|
||||
columns: new[] { "tenant_id", "unit_id", "is_active", "sort_order", "created_at" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "handbook_entries");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "question_type_groups");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "subject_shares");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_word_favorites");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_word_progress");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "handbook_chapters");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "vocabulary_words");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "handbook_subjects");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "vocabulary_units");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,630 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddContentAssetsAndImportPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "app_assets",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
asset_key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
file_name = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_app_assets", x => x.id);
|
||||
table.UniqueConstraint("ak_app_assets_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_app_assets_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_assets",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
subject_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
category_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
verified_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
asset_key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
category = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
file_name = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
cdn_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
is_public = table.Column<bool>(type: "boolean", nullable: false),
|
||||
asset_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
storage_provider = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
bucket = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
object_key = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
mime_type = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
file_size_bytes = table.Column<long>(type: "bigint", nullable: true),
|
||||
checksum_sha256 = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
visibility = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
preview_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
access_rules = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
source = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
download_count = table.Column<int>(type: "integer", nullable: false),
|
||||
upload_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
verified_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
verified_size_bytes = table.Column<long>(type: "bigint", nullable: true),
|
||||
verified_checksum_sha256 = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
verification_details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
preview_object_key = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
preview_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
security_flags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_assets", x => x.id);
|
||||
table.UniqueConstraint("ak_content_assets_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_content_assets_download_count", "download_count >= 0");
|
||||
table.CheckConstraint("ck_content_assets_file_size", "file_size_bytes is null or file_size_bytes >= 0");
|
||||
table.CheckConstraint("ck_content_assets_verified_checksum", "verified_checksum_sha256 is null or verified_checksum_sha256 ~ '^[a-f0-9]{64}$'");
|
||||
table.CheckConstraint("ck_content_assets_verified_size", "verified_size_bytes is null or verified_size_bytes >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_categories_tenant_id_category_id",
|
||||
columns: x => new { x.tenant_id, x.category_id },
|
||||
principalTable: "categories",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_content_nodes_tenant_id_content_node_id",
|
||||
columns: x => new { x.tenant_id, x.content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_subjects_tenant_id_subject_id",
|
||||
columns: x => new { x.tenant_id, x.subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_assets_users_verified_by",
|
||||
column: x => x.verified_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_import_jobs",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_subject_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_category_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_content_node_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_question_bank_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
import_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source_format = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source_name = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
dry_run = table.Column<bool>(type: "boolean", nullable: false),
|
||||
total_count = table.Column<int>(type: "integer", nullable: false),
|
||||
valid_count = table.Column<int>(type: "integer", nullable: false),
|
||||
error_count = table.Column<int>(type: "integer", nullable: false),
|
||||
warning_count = table.Column<int>(type: "integer", nullable: false),
|
||||
inserted_count = table.Column<int>(type: "integer", nullable: false),
|
||||
updated_count = table.Column<int>(type: "integer", nullable: false),
|
||||
skipped_count = table.Column<int>(type: "integer", nullable: false),
|
||||
summary = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
raw_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
normalized_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
error_message = table.Column<string>(type: "text", nullable: true),
|
||||
started_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
finished_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_import_jobs", x => x.id);
|
||||
table.UniqueConstraint("ak_content_import_jobs_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_content_import_jobs_counts", "total_count >= 0 and valid_count >= 0 and error_count >= 0 and warning_count >= 0 and inserted_count >= 0 and updated_count >= 0 and skipped_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_categories_tenant_id_target_category_id",
|
||||
columns: x => new { x.tenant_id, x.target_category_id },
|
||||
principalTable: "categories",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_content_nodes_tenant_id_target_content_~",
|
||||
columns: x => new { x.tenant_id, x.target_content_node_id },
|
||||
principalTable: "content_nodes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_question_banks_tenant_id_target_questio~",
|
||||
columns: x => new { x.tenant_id, x.target_question_bank_id },
|
||||
principalTable: "question_banks",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_regions_tenant_id_target_region_id",
|
||||
columns: x => new { x.tenant_id, x.target_region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_subjects_tenant_id_target_subject_id",
|
||||
columns: x => new { x.tenant_id, x.target_subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_jobs_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "images",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
category = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
file_name = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
is_public = table.Column<bool>(type: "boolean", nullable: false),
|
||||
cdn_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_images", x => x.id);
|
||||
table.UniqueConstraint("ak_images_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_images_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "video_explanations",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
subject_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_subject_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
video_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
thumbnail_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
duration_seconds = table.Column<int>(type: "integer", nullable: true),
|
||||
knowledge_tags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
is_general = table.Column<bool>(type: "boolean", nullable: false),
|
||||
difficulty = table.Column<int>(type: "integer", nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
source_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_video_explanations", x => x.id);
|
||||
table.UniqueConstraint("ak_video_explanations_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_video_explanations_subjects_tenant_id_subject_id",
|
||||
columns: x => new { x.tenant_id, x.subject_id },
|
||||
principalTable: "subjects",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_video_explanations_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_import_items",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
job_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
row_no = table.Column<int>(type: "integer", nullable: false),
|
||||
external_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
target_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
target_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
source_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
normalized_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
content_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
issues_count = table.Column<int>(type: "integer", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_import_items", x => x.id);
|
||||
table.UniqueConstraint("ak_content_import_items_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_content_import_items_issues_count", "issues_count >= 0");
|
||||
table.CheckConstraint("ck_content_import_items_row_no", "row_no >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_items_content_import_jobs_tenant_id_job_id",
|
||||
columns: x => new { x.tenant_id, x.job_id },
|
||||
principalTable: "content_import_jobs",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_items_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "question_videos",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
question_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
video_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_question_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_video_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
video_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_question_videos", x => x.id);
|
||||
table.UniqueConstraint("ak_question_videos_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_question_videos_questions_tenant_id_question_id",
|
||||
columns: x => new { x.tenant_id, x.question_id },
|
||||
principalTable: "questions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_videos_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_videos_video_explanations_tenant_id_video_id",
|
||||
columns: x => new { x.tenant_id, x.video_id },
|
||||
principalTable: "video_explanations",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_import_issues",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
job_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
item_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
row_no = table.Column<int>(type: "integer", nullable: true),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
field_path = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
message = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_import_issues", x => x.id);
|
||||
table.UniqueConstraint("ak_content_import_issues_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_issues_content_import_items_tenant_id_item_id",
|
||||
columns: x => new { x.tenant_id, x.item_id },
|
||||
principalTable: "content_import_items",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_issues_content_import_jobs_tenant_id_job_id",
|
||||
columns: x => new { x.tenant_id, x.job_id },
|
||||
principalTable: "content_import_jobs",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_import_issues_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_app_assets_tenant_id_asset_key",
|
||||
table: "app_assets",
|
||||
columns: new[] { "tenant_id", "asset_key" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_app_assets_tenant_id_legacy_id",
|
||||
table: "app_assets",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_created_by",
|
||||
table: "content_assets",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_category_id",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "category_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_checksum_sha256",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "checksum_sha256" },
|
||||
filter: "checksum_sha256 is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_content_node_id",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_legacy_id",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_preview_status",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "preview_status" },
|
||||
filter: "preview_status <> 'none'");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_region_id",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_status_visibility_asset_type_regio~",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "status", "visibility", "asset_type", "region_id", "subject_id", "category_id", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_storage_provider_bucket_object_key",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "storage_provider", "bucket", "object_key" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_subject_id",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "subject_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_upload_status_status_updated_at",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "upload_status", "status", "updated_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_updated_by",
|
||||
table: "content_assets",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_verified_by",
|
||||
table: "content_assets",
|
||||
column: "verified_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_issues_tenant_id_item_id",
|
||||
table: "content_import_issues",
|
||||
columns: new[] { "tenant_id", "item_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_issues_tenant_id_job_id_severity_row_no",
|
||||
table: "content_import_issues",
|
||||
columns: new[] { "tenant_id", "job_id", "severity", "row_no" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_items_job_id_row_no",
|
||||
table: "content_import_items",
|
||||
columns: new[] { "job_id", "row_no" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_items_tenant_id_job_id_status_row_no",
|
||||
table: "content_import_items",
|
||||
columns: new[] { "tenant_id", "job_id", "status", "row_no" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_created_by",
|
||||
table: "content_import_jobs",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_tenant_id_import_type_status_created_at",
|
||||
table: "content_import_jobs",
|
||||
columns: new[] { "tenant_id", "import_type", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_tenant_id_target_category_id",
|
||||
table: "content_import_jobs",
|
||||
columns: new[] { "tenant_id", "target_category_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_tenant_id_target_content_node_id",
|
||||
table: "content_import_jobs",
|
||||
columns: new[] { "tenant_id", "target_content_node_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_tenant_id_target_question_bank_id",
|
||||
table: "content_import_jobs",
|
||||
columns: new[] { "tenant_id", "target_question_bank_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_tenant_id_target_region_id",
|
||||
table: "content_import_jobs",
|
||||
columns: new[] { "tenant_id", "target_region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_import_jobs_tenant_id_target_subject_id",
|
||||
table: "content_import_jobs",
|
||||
columns: new[] { "tenant_id", "target_subject_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_images_tenant_id_category_is_public",
|
||||
table: "images",
|
||||
columns: new[] { "tenant_id", "category", "is_public" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_images_tenant_id_legacy_id",
|
||||
table: "images",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_videos_tenant_id_legacy_id",
|
||||
table: "question_videos",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_videos_tenant_id_question_id_video_id_video_type",
|
||||
table: "question_videos",
|
||||
columns: new[] { "tenant_id", "question_id", "video_id", "video_type" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_videos_tenant_id_video_id",
|
||||
table: "question_videos",
|
||||
columns: new[] { "tenant_id", "video_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_explanations_tenant_id_legacy_id",
|
||||
table: "video_explanations",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_explanations_tenant_id_source_hash",
|
||||
table: "video_explanations",
|
||||
columns: new[] { "tenant_id", "source_hash" },
|
||||
filter: "source_hash is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_explanations_tenant_id_subject_id_is_active_sort_order",
|
||||
table: "video_explanations",
|
||||
columns: new[] { "tenant_id", "subject_id", "is_active", "sort_order" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "app_assets");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_assets");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_import_issues");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "images");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "question_videos");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_import_items");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "video_explanations");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_import_jobs");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,764 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddLearningReportsAndPracticeAccessPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "access_rules",
|
||||
table: "question_collections",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "access_entitlement_id",
|
||||
table: "practice_sessions",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "access_mode",
|
||||
table: "practice_sessions",
|
||||
type: "character varying(32)",
|
||||
maxLength: 32,
|
||||
nullable: false,
|
||||
defaultValue: "free");
|
||||
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "access_snapshot",
|
||||
table: "practice_sessions",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "consumed_free_quota",
|
||||
table: "practice_sessions",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "access_rules",
|
||||
table: "practice_blueprints",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "access_rules",
|
||||
table: "content_nodes",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "dashboard_daily_stats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_region_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
stat_date = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
new_users = table.Column<int>(type: "integer", nullable: false),
|
||||
new_questions = table.Column<int>(type: "integer", nullable: false),
|
||||
new_orders = table.Column<int>(type: "integer", nullable: false),
|
||||
new_revenue_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
active_users = table.Column<int>(type: "integer", nullable: false),
|
||||
rebuilt_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_dashboard_daily_stats", x => x.id);
|
||||
table.UniqueConstraint("ak_dashboard_daily_stats_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_dashboard_daily_stats_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_dashboard_daily_stats_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "exam_dates",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
school_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
exam_name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
exam_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
exam_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_exam_dates", x => x.id);
|
||||
table.UniqueConstraint("ak_exam_dates_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_exam_dates_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_exam_dates_schools_tenant_id_school_id",
|
||||
columns: x => new { x.tenant_id, x.school_id },
|
||||
principalTable: "schools",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_exam_dates_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "practice_access_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
practice_session_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
event_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
access_mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
requested_count = table.Column<int>(type: "integer", nullable: false),
|
||||
granted_count = table.Column<int>(type: "integer", nullable: false),
|
||||
consumed_free_quota = table.Column<int>(type: "integer", nullable: false),
|
||||
reason = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
scope_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
scope_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
entitlement_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_practice_access_events", x => x.id);
|
||||
table.UniqueConstraint("ak_practice_access_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_practice_access_events_consumed_free_quota", "consumed_free_quota >= 0");
|
||||
table.CheckConstraint("ck_practice_access_events_granted_count", "granted_count >= 0");
|
||||
table.CheckConstraint("ck_practice_access_events_requested_count", "requested_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_access_events_practice_sessions_tenant_id_practice~",
|
||||
columns: x => new { x.tenant_id, x.practice_session_id },
|
||||
principalTable: "practice_sessions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_access_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_access_events_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "practice_daily_usage",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
usage_date = table.Column<DateOnly>(type: "date", nullable: false, defaultValueSql: "current_date"),
|
||||
scope_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
scope_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
free_limit = table.Column<int>(type: "integer", nullable: false),
|
||||
used_count = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_practice_daily_usage", x => x.id);
|
||||
table.UniqueConstraint("ak_practice_daily_usage_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_practice_daily_usage_free_limit", "free_limit >= 0");
|
||||
table.CheckConstraint("ck_practice_daily_usage_used_count", "used_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_daily_usage_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_daily_usage_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "practice_session_reports",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
practice_session_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
blueprint_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
collection_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
mode = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
total_questions = table.Column<int>(type: "integer", nullable: false),
|
||||
answered_count = table.Column<int>(type: "integer", nullable: false),
|
||||
correct_count = table.Column<int>(type: "integer", nullable: false),
|
||||
wrong_count = table.Column<int>(type: "integer", nullable: false),
|
||||
unanswered_count = table.Column<int>(type: "integer", nullable: false),
|
||||
score = table.Column<decimal>(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false),
|
||||
total_score = table.Column<decimal>(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false),
|
||||
accuracy = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: false),
|
||||
duration_seconds = table.Column<int>(type: "integer", nullable: false),
|
||||
started_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
submitted_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
section_stats = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
question_results = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
wrong_question_ids = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_practice_session_reports", x => x.id);
|
||||
table.UniqueConstraint("ak_practice_session_reports_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_practice_session_reports_accuracy", "accuracy >= 0 and accuracy <= 1");
|
||||
table.CheckConstraint("ck_practice_session_reports_counts", "total_questions >= 0 and answered_count >= 0 and correct_count >= 0 and wrong_count >= 0 and unanswered_count >= 0");
|
||||
table.CheckConstraint("ck_practice_session_reports_duration", "duration_seconds >= 0");
|
||||
table.CheckConstraint("ck_practice_session_reports_scores", "score >= 0 and total_score >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_reports_practice_blueprints_tenant_id_blue~",
|
||||
columns: x => new { x.tenant_id, x.blueprint_id },
|
||||
principalTable: "practice_blueprints",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_reports_practice_sessions_tenant_id_practi~",
|
||||
columns: x => new { x.tenant_id, x.practice_session_id },
|
||||
principalTable: "practice_sessions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_reports_question_collections_tenant_id_col~",
|
||||
columns: x => new { x.tenant_id, x.collection_id },
|
||||
principalTable: "question_collections",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_reports_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_reports_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reports",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
question_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
handled_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
category = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
priority = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
handled_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
resolution = table.Column<string>(type: "text", nullable: true),
|
||||
contact = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
attachments = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reports", x => x.id);
|
||||
table.UniqueConstraint("ak_reports_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_reports_questions_tenant_id_question_id",
|
||||
columns: x => new { x.tenant_id, x.question_id },
|
||||
principalTable: "questions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_reports_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_reports_users_handled_by",
|
||||
column: x => x.handled_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_reports_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "revenue_daily_stats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_region_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
stat_date = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
sale_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
real_revenue_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
order_count = table.Column<int>(type: "integer", nullable: false),
|
||||
code_count = table.Column<int>(type: "integer", nullable: false),
|
||||
code_used = table.Column<int>(type: "integer", nullable: false),
|
||||
code_estimated = table.Column<int>(type: "integer", nullable: false),
|
||||
estimated_revenue_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
rebuilt_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_revenue_daily_stats", x => x.id);
|
||||
table.UniqueConstraint("ak_revenue_daily_stats_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_revenue_daily_stats_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_revenue_daily_stats_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_score_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
event_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
points = table.Column<int>(type: "integer", nullable: false),
|
||||
balance_after = table.Column<int>(type: "integer", nullable: false),
|
||||
source_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
source_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
idempotency_key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_score_events", x => x.id);
|
||||
table.UniqueConstraint("ak_user_score_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_user_score_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_score_events_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "practice_session_report_sections",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
report_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
practice_session_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
section_key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
section_name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
question_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
question_count = table.Column<int>(type: "integer", nullable: false),
|
||||
answered_count = table.Column<int>(type: "integer", nullable: false),
|
||||
correct_count = table.Column<int>(type: "integer", nullable: false),
|
||||
wrong_count = table.Column<int>(type: "integer", nullable: false),
|
||||
unanswered_count = table.Column<int>(type: "integer", nullable: false),
|
||||
score = table.Column<decimal>(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false),
|
||||
total_score = table.Column<decimal>(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false),
|
||||
accuracy = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_practice_session_report_sections", x => x.id);
|
||||
table.UniqueConstraint("ak_practice_session_report_sections_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_practice_session_report_sections_accuracy", "accuracy >= 0 and accuracy <= 1");
|
||||
table.CheckConstraint("ck_practice_session_report_sections_counts", "question_count >= 0 and answered_count >= 0 and correct_count >= 0 and wrong_count >= 0 and unanswered_count >= 0");
|
||||
table.CheckConstraint("ck_practice_session_report_sections_scores", "score >= 0 and total_score >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_report_sections_practice_session_reports_t~",
|
||||
columns: x => new { x.tenant_id, x.report_id },
|
||||
principalTable: "practice_session_reports",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_report_sections_practice_sessions_tenant_i~",
|
||||
columns: x => new { x.tenant_id, x.practice_session_id },
|
||||
principalTable: "practice_sessions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_practice_session_report_sections_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "report_status_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
report_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
from_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
to_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
note = table.Column<string>(type: "text", nullable: true),
|
||||
actor_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_report_status_events", x => x.id);
|
||||
table.UniqueConstraint("ak_report_status_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_report_status_events_reports_tenant_id_report_id",
|
||||
columns: x => new { x.tenant_id, x.report_id },
|
||||
principalTable: "reports",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_report_status_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_report_status_events_users_actor_user_id",
|
||||
column: x => x.actor_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.AddCheckConstraint(
|
||||
name: "ck_practice_sessions_consumed_free_quota",
|
||||
table: "practice_sessions",
|
||||
sql: "consumed_free_quota >= 0");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_dashboard_daily_stats_tenant_id_legacy_id",
|
||||
table: "dashboard_daily_stats",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_dashboard_daily_stats_tenant_id_region_id",
|
||||
table: "dashboard_daily_stats",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_dashboard_daily_stats_tenant_id_stat_date_region_id",
|
||||
table: "dashboard_daily_stats",
|
||||
columns: new[] { "tenant_id", "stat_date", "region_id" },
|
||||
unique: true)
|
||||
.Annotation("Npgsql:NullsDistinct", false);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_exam_dates_tenant_id_legacy_id",
|
||||
table: "exam_dates",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_exam_dates_tenant_id_region_id",
|
||||
table: "exam_dates",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_exam_dates_tenant_id_school_id_exam_at",
|
||||
table: "exam_dates",
|
||||
columns: new[] { "tenant_id", "school_id", "exam_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_access_events_tenant_id_practice_session_id",
|
||||
table: "practice_access_events",
|
||||
columns: new[] { "tenant_id", "practice_session_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_access_events_tenant_id_user_id_created_at",
|
||||
table: "practice_access_events",
|
||||
columns: new[] { "tenant_id", "user_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_access_events_user_id",
|
||||
table: "practice_access_events",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_daily_usage_tenant_id_user_id_usage_date",
|
||||
table: "practice_daily_usage",
|
||||
columns: new[] { "tenant_id", "user_id", "usage_date" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_daily_usage_tenant_id_user_id_usage_date_scope_typ~",
|
||||
table: "practice_daily_usage",
|
||||
columns: new[] { "tenant_id", "user_id", "usage_date", "scope_type", "scope_id" },
|
||||
unique: true)
|
||||
.Annotation("Npgsql:NullsDistinct", false);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_daily_usage_user_id",
|
||||
table: "practice_daily_usage",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_report_sections_tenant_id_practice_session~",
|
||||
table: "practice_session_report_sections",
|
||||
columns: new[] { "tenant_id", "practice_session_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_report_sections_tenant_id_report_id_sectio~",
|
||||
table: "practice_session_report_sections",
|
||||
columns: new[] { "tenant_id", "report_id", "section_key" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_report_sections_tenant_id_report_id_sort_o~",
|
||||
table: "practice_session_report_sections",
|
||||
columns: new[] { "tenant_id", "report_id", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_reports_tenant_id_blueprint_id_submitted_at",
|
||||
table: "practice_session_reports",
|
||||
columns: new[] { "tenant_id", "blueprint_id", "submitted_at" },
|
||||
filter: "blueprint_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_reports_tenant_id_collection_id",
|
||||
table: "practice_session_reports",
|
||||
columns: new[] { "tenant_id", "collection_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_reports_tenant_id_practice_session_id",
|
||||
table: "practice_session_reports",
|
||||
columns: new[] { "tenant_id", "practice_session_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_reports_tenant_id_user_id_submitted_at",
|
||||
table: "practice_session_reports",
|
||||
columns: new[] { "tenant_id", "user_id", "submitted_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_practice_session_reports_user_id",
|
||||
table: "practice_session_reports",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_report_status_events_actor_user_id",
|
||||
table: "report_status_events",
|
||||
column: "actor_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_report_status_events_tenant_id_report_id_created_at",
|
||||
table: "report_status_events",
|
||||
columns: new[] { "tenant_id", "report_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reports_handled_by",
|
||||
table: "reports",
|
||||
column: "handled_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reports_tenant_id_legacy_id",
|
||||
table: "reports",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reports_tenant_id_question_id_created_at",
|
||||
table: "reports",
|
||||
columns: new[] { "tenant_id", "question_id", "created_at" },
|
||||
filter: "question_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reports_tenant_id_status_created_at",
|
||||
table: "reports",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reports_user_id",
|
||||
table: "reports",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_revenue_daily_stats_tenant_id_legacy_id",
|
||||
table: "revenue_daily_stats",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_revenue_daily_stats_tenant_id_region_id",
|
||||
table: "revenue_daily_stats",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_revenue_daily_stats_tenant_id_stat_date_region_id_sale_type",
|
||||
table: "revenue_daily_stats",
|
||||
columns: new[] { "tenant_id", "stat_date", "region_id", "sale_type" },
|
||||
unique: true)
|
||||
.Annotation("Npgsql:NullsDistinct", false);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_score_events_tenant_id_idempotency_key",
|
||||
table: "user_score_events",
|
||||
columns: new[] { "tenant_id", "idempotency_key" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_score_events_tenant_id_user_id_created_at",
|
||||
table: "user_score_events",
|
||||
columns: new[] { "tenant_id", "user_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_score_events_user_id",
|
||||
table: "user_score_events",
|
||||
column: "user_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "dashboard_daily_stats");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "exam_dates");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "practice_access_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "practice_daily_usage");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "practice_session_report_sections");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "report_status_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "revenue_daily_stats");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_score_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "practice_session_reports");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "reports");
|
||||
|
||||
migrationBuilder.DropCheckConstraint(
|
||||
name: "ck_practice_sessions_consumed_free_quota",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "access_rules",
|
||||
table: "question_collections");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "access_entitlement_id",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "access_mode",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "access_snapshot",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "consumed_free_quota",
|
||||
table: "practice_sessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "access_rules",
|
||||
table: "practice_blueprints");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "access_rules",
|
||||
table: "content_nodes");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,669 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddAuthAndTenantOperationsPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "role_template_id",
|
||||
table: "tenant_memberships",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "auth_login_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
identifier = table.Column<string>(type: "character varying(320)", maxLength: 320, nullable: true),
|
||||
result = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
failure_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_auth_login_events", x => x.id);
|
||||
table.UniqueConstraint("ak_auth_login_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_login_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_login_events_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "auth_sessions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
token_hash = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
revoked_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_auth_sessions", x => x.id);
|
||||
table.UniqueConstraint("ak_auth_sessions_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_sessions_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_sessions_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "sms_send_rate_limits",
|
||||
columns: table => new
|
||||
{
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
dimension = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
scope_hash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
||||
bucket_start = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
request_count = table.Column<int>(type: "integer", nullable: false, defaultValue: 0),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_sms_send_rate_limits", x => new { x.tenant_id, x.dimension, x.scope_hash, x.bucket_start });
|
||||
table.CheckConstraint("ck_sms_send_rate_limits_request_count", "request_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_sms_send_rate_limits_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "sms_verification_codes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
phone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
purpose = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
code_hash = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
attempts = table.Column<int>(type: "integer", nullable: false),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
consumed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_sms_verification_codes", x => x.id);
|
||||
table.UniqueConstraint("ak_sms_verification_codes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_sms_verification_codes_attempts", "attempts >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_sms_verification_codes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_auth_providers",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
display_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
config_public = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_auth_providers", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_auth_providers_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_auth_providers_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_classes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_classes", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_classes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_classes_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_classes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_classes_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_classes_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_role_templates",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
base_role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
menu_permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
module_permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
field_permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
data_scope = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
is_system = table.Column<bool>(type: "boolean", nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_role_templates", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_role_templates_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_role_templates_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_role_templates_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_role_templates_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_student_notes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
student_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
note_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
content = table.Column<string>(type: "text", nullable: false),
|
||||
visibility = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
is_pinned = table.Column<bool>(type: "boolean", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_student_notes", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_student_notes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_notes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_notes_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_notes_users_student_user_id",
|
||||
column: x => x.student_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_notes_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_class_members",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
class_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
member_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
joined_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
left_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_class_members", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_class_members_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_class_members_tenant_classes_tenant_id_class_id",
|
||||
columns: x => new { x.tenant_id, x.class_id },
|
||||
principalTable: "tenant_classes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_class_members_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_class_members_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_student_followups",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
student_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
assigned_to_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
class_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
followup_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
priority = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
due_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
completed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
completed_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_student_followups", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_student_followups_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_followups_tenant_classes_tenant_id_class_id",
|
||||
columns: x => new { x.tenant_id, x.class_id },
|
||||
principalTable: "tenant_classes",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_followups_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_followups_users_assigned_to_user_id",
|
||||
column: x => x.assigned_to_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_followups_users_completed_by",
|
||||
column: x => x.completed_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_student_followups_users_student_user_id",
|
||||
column: x => x.student_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_memberships_tenant_id_role_template_id",
|
||||
table: "tenant_memberships",
|
||||
columns: new[] { "tenant_id", "role_template_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_login_events_tenant_id_user_id_created_at",
|
||||
table: "auth_login_events",
|
||||
columns: new[] { "tenant_id", "user_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_login_events_user_id",
|
||||
table: "auth_login_events",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_tenant_id_user_id_expires_at",
|
||||
table: "auth_sessions",
|
||||
columns: new[] { "tenant_id", "user_id", "expires_at" },
|
||||
filter: "revoked_at is null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_token_hash",
|
||||
table: "auth_sessions",
|
||||
column: "token_hash",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_user_id",
|
||||
table: "auth_sessions",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_sms_send_rate_limits_updated_at",
|
||||
table: "sms_send_rate_limits",
|
||||
column: "updated_at");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_sms_verification_codes_tenant_id_phone_purpose",
|
||||
table: "sms_verification_codes",
|
||||
columns: new[] { "tenant_id", "phone", "purpose" },
|
||||
unique: true,
|
||||
filter: "consumed_at is null and status in ('pending', 'sent')");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_sms_verification_codes_tenant_id_phone_purpose_created_at",
|
||||
table: "sms_verification_codes",
|
||||
columns: new[] { "tenant_id", "phone", "purpose", "created_at" },
|
||||
filter: "consumed_at is null and status in ('pending', 'sent')");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_sms_verification_codes_tenant_id_phone_purpose_expires_at",
|
||||
table: "sms_verification_codes",
|
||||
columns: new[] { "tenant_id", "phone", "purpose", "expires_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_auth_providers_tenant_id_provider",
|
||||
table: "tenant_auth_providers",
|
||||
columns: new[] { "tenant_id", "provider" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_auth_providers_tenant_id_provider_status",
|
||||
table: "tenant_auth_providers",
|
||||
columns: new[] { "tenant_id", "provider", "status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_class_members_tenant_id_class_id_status_member_type",
|
||||
table: "tenant_class_members",
|
||||
columns: new[] { "tenant_id", "class_id", "status", "member_type" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_class_members_tenant_id_class_id_user_id_member_type",
|
||||
table: "tenant_class_members",
|
||||
columns: new[] { "tenant_id", "class_id", "user_id", "member_type" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_class_members_tenant_id_user_id_status_member_type",
|
||||
table: "tenant_class_members",
|
||||
columns: new[] { "tenant_id", "user_id", "status", "member_type" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_class_members_user_id",
|
||||
table: "tenant_class_members",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_classes_created_by",
|
||||
table: "tenant_classes",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_classes_tenant_id_code",
|
||||
table: "tenant_classes",
|
||||
columns: new[] { "tenant_id", "code" },
|
||||
unique: true,
|
||||
filter: "code is not null and code <> ''");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_classes_tenant_id_legacy_id",
|
||||
table: "tenant_classes",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_classes_tenant_id_region_id",
|
||||
table: "tenant_classes",
|
||||
columns: new[] { "tenant_id", "region_id" },
|
||||
filter: "region_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_classes_tenant_id_status_sort_order_created_at",
|
||||
table: "tenant_classes",
|
||||
columns: new[] { "tenant_id", "status", "sort_order", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_classes_updated_by",
|
||||
table: "tenant_classes",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_created_by",
|
||||
table: "tenant_role_templates",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_tenant_id_code",
|
||||
table: "tenant_role_templates",
|
||||
columns: new[] { "tenant_id", "code" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_tenant_id_status_sort_order",
|
||||
table: "tenant_role_templates",
|
||||
columns: new[] { "tenant_id", "status", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_updated_by",
|
||||
table: "tenant_role_templates",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_followups_assigned_to_user_id",
|
||||
table: "tenant_student_followups",
|
||||
column: "assigned_to_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_followups_completed_by",
|
||||
table: "tenant_student_followups",
|
||||
column: "completed_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_followups_student_user_id",
|
||||
table: "tenant_student_followups",
|
||||
column: "student_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_followups_tenant_id_assigned_to_user_id_stat~",
|
||||
table: "tenant_student_followups",
|
||||
columns: new[] { "tenant_id", "assigned_to_user_id", "status", "due_at" },
|
||||
filter: "assigned_to_user_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_followups_tenant_id_class_id_status_due_at",
|
||||
table: "tenant_student_followups",
|
||||
columns: new[] { "tenant_id", "class_id", "status", "due_at" },
|
||||
filter: "class_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_followups_tenant_id_student_user_id_status_d~",
|
||||
table: "tenant_student_followups",
|
||||
columns: new[] { "tenant_id", "student_user_id", "status", "due_at", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_notes_created_by",
|
||||
table: "tenant_student_notes",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_notes_student_user_id",
|
||||
table: "tenant_student_notes",
|
||||
column: "student_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_notes_tenant_id_created_by_created_at",
|
||||
table: "tenant_student_notes",
|
||||
columns: new[] { "tenant_id", "created_by", "created_at" },
|
||||
filter: "created_by is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_notes_tenant_id_student_user_id_is_pinned_cr~",
|
||||
table: "tenant_student_notes",
|
||||
columns: new[] { "tenant_id", "student_user_id", "is_pinned", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_student_notes_updated_by",
|
||||
table: "tenant_student_notes",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_tenant_memberships_tenant_role_templates_tenant_id_role_tem~",
|
||||
table: "tenant_memberships",
|
||||
columns: new[] { "tenant_id", "role_template_id" },
|
||||
principalTable: "tenant_role_templates",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_tenant_memberships_tenant_role_templates_tenant_id_role_tem~",
|
||||
table: "tenant_memberships");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "auth_login_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "auth_sessions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "sms_send_rate_limits");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "sms_verification_codes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_auth_providers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_class_members");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_role_templates");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_student_followups");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_student_notes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_classes");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_tenant_memberships_tenant_id_role_template_id",
|
||||
table: "tenant_memberships");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "role_template_id",
|
||||
table: "tenant_memberships");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,853 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddCommercePersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "code_batches",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
sale_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
channel = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
campaign_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
default_unit_price_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
cost_price_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
total_count = table.Column<int>(type: "integer", nullable: false),
|
||||
days = table.Column<int>(type: "integer", nullable: true),
|
||||
legacy_region_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
issued_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
remark = table.Column<string>(type: "text", nullable: true),
|
||||
commission_rate = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_code_batches", x => x.id);
|
||||
table.UniqueConstraint("ak_code_batches_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_code_batches_amounts", "default_unit_price_cents >= 0 and cost_price_cents >= 0");
|
||||
table.CheckConstraint("ck_code_batches_counts", "total_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_code_batches_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "entitlements",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
entitlement_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
scope_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
scope_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
source_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
source_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_source_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
starts_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_entitlements", x => x.id);
|
||||
table.UniqueConstraint("ak_entitlements_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_entitlements_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_entitlements_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "products",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
legacy_price_text = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
link = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
tags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
cover = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
preview_iframe = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
detail_images = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_products", x => x.id);
|
||||
table.UniqueConstraint("ak_products_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_products_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_products_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "svip_plans",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
price_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
original_price_cents = table.Column<int>(type: "integer", nullable: true),
|
||||
days = table.Column<int>(type: "integer", nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
per_day_label = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
badge = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
recommended = table.Column<bool>(type: "boolean", nullable: false),
|
||||
coupon_only = table.Column<bool>(type: "boolean", nullable: false),
|
||||
vp_product_id = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
vp_enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_svip_plans", x => x.id);
|
||||
table.UniqueConstraint("ak_svip_plans_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_svip_plans_days", "days >= 0");
|
||||
table.CheckConstraint("ck_svip_plans_price", "price_cents >= 0 and (original_price_cents is null or original_price_cents >= 0)");
|
||||
table.ForeignKey(
|
||||
name: "fk_svip_plans_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_svip_plans_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_payment_accounts",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
display_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
config_public = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_payment_accounts", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_payment_accounts_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_payment_accounts_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_subscriptions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
plan_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
starts_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
billing_cycle = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_subscriptions", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_subscriptions_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_subscriptions_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_usage_records",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
metric_key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
metric_value = table.Column<decimal>(type: "numeric(18,4)", precision: 18, scale: 4, nullable: false),
|
||||
period_start = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
period_end = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_usage_records", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_usage_records_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_usage_records_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "coupons",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
plan_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
code = table.Column<string>(type: "citext", maxLength: 100, nullable: false),
|
||||
discount_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
discount_value = table.Column<decimal>(type: "numeric(10,2)", precision: 10, scale: 2, nullable: true),
|
||||
valid_from = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
valid_to = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
max_uses = table.Column<int>(type: "integer", nullable: true),
|
||||
used_count = table.Column<int>(type: "integer", nullable: false),
|
||||
source = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
remark = table.Column<string>(type: "text", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_coupons", x => x.id);
|
||||
table.UniqueConstraint("ak_coupons_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_coupons_svip_plans_tenant_id_plan_id",
|
||||
columns: x => new { x.tenant_id, x.plan_id },
|
||||
principalTable: "svip_plans",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_coupons_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "orders",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
plan_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_user_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_plan_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_region_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
order_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
product_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
product_name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
pay_method = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
pay_provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
trade_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
days = table.Column<int>(type: "integer", nullable: true),
|
||||
paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
raw_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_orders", x => x.id);
|
||||
table.UniqueConstraint("ak_orders_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_orders_amount", "amount_cents >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_orders_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_orders_svip_plans_tenant_id_plan_id",
|
||||
columns: x => new { x.tenant_id, x.plan_id },
|
||||
principalTable: "svip_plans",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_orders_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_orders_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "coupon_redemptions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
coupon_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
plan_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
coupon_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
discount_applied_cents = table.Column<int>(type: "integer", nullable: true),
|
||||
source = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
remark = table.Column<string>(type: "text", nullable: true),
|
||||
claimed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
used_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_coupon_redemptions", x => x.id);
|
||||
table.UniqueConstraint("ak_coupon_redemptions_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_coupon_redemptions_coupons_tenant_id_coupon_id",
|
||||
columns: x => new { x.tenant_id, x.coupon_id },
|
||||
principalTable: "coupons",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_coupon_redemptions_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_coupon_redemptions_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_coupon_redemptions_svip_plans_tenant_id_plan_id",
|
||||
columns: x => new { x.tenant_id, x.plan_id },
|
||||
principalTable: "svip_plans",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_coupon_redemptions_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_coupon_redemptions_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "order_items",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
item_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
item_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
quantity = table.Column<int>(type: "integer", nullable: false),
|
||||
unit_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
total_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_order_items", x => x.id);
|
||||
table.UniqueConstraint("ak_order_items_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_order_items_amounts", "unit_amount_cents >= 0 and total_amount_cents >= 0");
|
||||
table.CheckConstraint("ck_order_items_quantity", "quantity > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_order_items_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_order_items_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "payments",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
legacy_order_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
method = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_trade_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
raw_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_payments", x => x.id);
|
||||
table.UniqueConstraint("ak_payments_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_payments_amount", "amount_cents >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_payments_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_payments_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "activation_codes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
used_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
agent_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
batch_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
used_region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
coupon_redemption_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
code = table.Column<string>(type: "citext", maxLength: 100, nullable: false),
|
||||
days = table.Column<int>(type: "integer", nullable: false),
|
||||
is_used = table.Column<bool>(type: "boolean", nullable: false),
|
||||
used_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
sale_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
unit_price_cents = table.Column<int>(type: "integer", nullable: true),
|
||||
sold_to = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
coupon_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
remark = table.Column<string>(type: "text", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_activation_codes", x => x.id);
|
||||
table.UniqueConstraint("ak_activation_codes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_activation_codes_code_batches_tenant_id_batch_id",
|
||||
columns: x => new { x.tenant_id, x.batch_id },
|
||||
principalTable: "code_batches",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_activation_codes_coupon_redemptions_tenant_id_coupon_redemp~",
|
||||
columns: x => new { x.tenant_id, x.coupon_redemption_id },
|
||||
principalTable: "coupon_redemptions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_activation_codes_regions_tenant_id_used_region_id",
|
||||
columns: x => new { x.tenant_id, x.used_region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_activation_codes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_activation_codes_users_agent_user_id",
|
||||
column: x => x.agent_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_activation_codes_users_used_by",
|
||||
column: x => x.used_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "payment_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
payment_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
event_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
event_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
signature_valid = table.Column<bool>(type: "boolean", nullable: true),
|
||||
payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
processed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
error = table.Column<string>(type: "text", nullable: true),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_payment_events", x => x.id);
|
||||
table.UniqueConstraint("ak_payment_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_payment_events_payments_tenant_id_payment_id",
|
||||
columns: x => new { x.tenant_id, x.payment_id },
|
||||
principalTable: "payments",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_payment_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_agent_user_id",
|
||||
table: "activation_codes",
|
||||
column: "agent_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_tenant_id_batch_id",
|
||||
table: "activation_codes",
|
||||
columns: new[] { "tenant_id", "batch_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_tenant_id_code",
|
||||
table: "activation_codes",
|
||||
columns: new[] { "tenant_id", "code" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_tenant_id_coupon_redemption_id",
|
||||
table: "activation_codes",
|
||||
columns: new[] { "tenant_id", "coupon_redemption_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_tenant_id_legacy_id",
|
||||
table: "activation_codes",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_tenant_id_used_region_id",
|
||||
table: "activation_codes",
|
||||
columns: new[] { "tenant_id", "used_region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_activation_codes_used_by",
|
||||
table: "activation_codes",
|
||||
column: "used_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_code_batches_tenant_id_legacy_id",
|
||||
table: "code_batches",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_tenant_id_coupon_id",
|
||||
table: "coupon_redemptions",
|
||||
columns: new[] { "tenant_id", "coupon_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_tenant_id_legacy_id",
|
||||
table: "coupon_redemptions",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_tenant_id_order_id_user_id",
|
||||
table: "coupon_redemptions",
|
||||
columns: new[] { "tenant_id", "order_id", "user_id" },
|
||||
filter: "order_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_tenant_id_plan_id",
|
||||
table: "coupon_redemptions",
|
||||
columns: new[] { "tenant_id", "plan_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_tenant_id_region_id",
|
||||
table: "coupon_redemptions",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_tenant_id_user_id_coupon_id",
|
||||
table: "coupon_redemptions",
|
||||
columns: new[] { "tenant_id", "user_id", "coupon_id" },
|
||||
unique: true,
|
||||
filter: "coupon_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupon_redemptions_user_id",
|
||||
table: "coupon_redemptions",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupons_tenant_id_code",
|
||||
table: "coupons",
|
||||
columns: new[] { "tenant_id", "code" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupons_tenant_id_legacy_id",
|
||||
table: "coupons",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_coupons_tenant_id_plan_id",
|
||||
table: "coupons",
|
||||
columns: new[] { "tenant_id", "plan_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_entitlements_tenant_id_user_id_status_expires_at",
|
||||
table: "entitlements",
|
||||
columns: new[] { "tenant_id", "user_id", "status", "expires_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_entitlements_user_id",
|
||||
table: "entitlements",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_order_items_tenant_id_legacy_id",
|
||||
table: "order_items",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_order_items_tenant_id_order_id",
|
||||
table: "order_items",
|
||||
columns: new[] { "tenant_id", "order_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_orders_tenant_id_legacy_id",
|
||||
table: "orders",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_orders_tenant_id_order_no",
|
||||
table: "orders",
|
||||
columns: new[] { "tenant_id", "order_no" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_orders_tenant_id_plan_id",
|
||||
table: "orders",
|
||||
columns: new[] { "tenant_id", "plan_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_orders_tenant_id_region_id",
|
||||
table: "orders",
|
||||
columns: new[] { "tenant_id", "region_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_orders_tenant_id_user_id_created_at",
|
||||
table: "orders",
|
||||
columns: new[] { "tenant_id", "user_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_orders_user_id",
|
||||
table: "orders",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_payment_events_provider_event_id",
|
||||
table: "payment_events",
|
||||
columns: new[] { "provider", "event_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_payment_events_tenant_id_payment_id",
|
||||
table: "payment_events",
|
||||
columns: new[] { "tenant_id", "payment_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_payments_provider_provider_trade_no",
|
||||
table: "payments",
|
||||
columns: new[] { "provider", "provider_trade_no" },
|
||||
unique: true,
|
||||
filter: "provider_trade_no is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_payments_tenant_id_legacy_id",
|
||||
table: "payments",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_payments_tenant_id_order_id_updated_at",
|
||||
table: "payments",
|
||||
columns: new[] { "tenant_id", "order_id", "updated_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_products_tenant_id_legacy_id",
|
||||
table: "products",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_products_tenant_id_region_id_type_sort_order",
|
||||
table: "products",
|
||||
columns: new[] { "tenant_id", "region_id", "type", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_svip_plans_tenant_id_legacy_id",
|
||||
table: "svip_plans",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_svip_plans_tenant_id_region_id_is_active_sort_order",
|
||||
table: "svip_plans",
|
||||
columns: new[] { "tenant_id", "region_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_payment_accounts_tenant_id_provider",
|
||||
table: "tenant_payment_accounts",
|
||||
columns: new[] { "tenant_id", "provider" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_subscriptions_tenant_id_status_expires_at",
|
||||
table: "tenant_subscriptions",
|
||||
columns: new[] { "tenant_id", "status", "expires_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_usage_records_tenant_id_metric_key_period_start_peri~",
|
||||
table: "tenant_usage_records",
|
||||
columns: new[] { "tenant_id", "metric_key", "period_start", "period_end" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "activation_codes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "entitlements");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "order_items");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "payment_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "products");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_payment_accounts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_subscriptions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_usage_records");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "code_batches");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "coupon_redemptions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "payments");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "coupons");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "orders");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "svip_plans");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,799 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddReferralCrmAndCommissionPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commission_settlements",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
referrer_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
generated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
reviewed_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
paid_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
settlement_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
period_start = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
period_end = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
source_count = table.Column<int>(type: "integer", nullable: false),
|
||||
paid_user_count = table.Column<int>(type: "integer", nullable: false),
|
||||
gross_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
commission_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
default_rate = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: false),
|
||||
effective_rate = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: true),
|
||||
reviewed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
payment_method = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
payment_account = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
remark = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commission_settlements", x => x.id);
|
||||
table.UniqueConstraint("ak_commission_settlements_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commission_settlements_amounts", "gross_amount_cents >= 0 and commission_amount_cents >= 0");
|
||||
table.CheckConstraint("ck_commission_settlements_counts", "source_count >= 0 and paid_user_count >= 0");
|
||||
table.CheckConstraint("ck_commission_settlements_period", "period_end >= period_start");
|
||||
table.CheckConstraint("ck_commission_settlements_rates", "default_rate >= 0 and default_rate <= 1 and (effective_rate is null or (effective_rate >= 0 and effective_rate <= 1))");
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlements_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlements_users_generated_by",
|
||||
column: x => x.generated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlements_users_paid_by",
|
||||
column: x => x.paid_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlements_users_referrer_user_id",
|
||||
column: x => x.referrer_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlements_users_reviewed_by",
|
||||
column: x => x.reviewed_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "crm_config",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
secret_ref = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
form_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
exam_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
timeout_seconds = table.Column<int>(type: "integer", nullable: true),
|
||||
delay_seconds = table.Column<int>(type: "integer", nullable: true),
|
||||
assignment_mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
assignment_pool = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
assignment_cursor = table.Column<int>(type: "integer", nullable: false),
|
||||
assignment_config = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_crm_config", x => x.id);
|
||||
table.UniqueConstraint("ak_crm_config_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_crm_config_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "crm_webhook_log",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
record_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
lead_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
http_code = table.Column<int>(type: "integer", nullable: true),
|
||||
outcome = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
error_message = table.Column<string>(type: "text", nullable: true),
|
||||
request_body = table.Column<string>(type: "text", nullable: true),
|
||||
request_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
response_summary = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
|
||||
signed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
attempt = table.Column<int>(type: "integer", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_crm_webhook_log", x => x.id);
|
||||
table.UniqueConstraint("ak_crm_webhook_log_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_crm_webhook_log_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "crm_webhook_queue",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
record_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
lead_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
source = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
provider = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
scheduled_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
attempts = table.Column<int>(type: "integer", nullable: false),
|
||||
next_attempt_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
last_attempt_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
last_error = table.Column<string>(type: "text", nullable: true),
|
||||
last_http_code = table.Column<int>(type: "integer", nullable: true),
|
||||
last_response_summary = table.Column<string>(type: "text", nullable: true),
|
||||
sent_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
idempotency_key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
target_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_crm_webhook_queue", x => x.id);
|
||||
table.UniqueConstraint("ak_crm_webhook_queue_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_crm_webhook_queue_attempts", "attempts >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_crm_webhook_queue_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "referral_codes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
code = table.Column<string>(type: "citext", maxLength: 100, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
channel = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
landing_path = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_referral_codes", x => x.id);
|
||||
table.UniqueConstraint("ak_referral_codes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_codes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_codes_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "referral_qrcodes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
ref_code = table.Column<string>(type: "citext", maxLength: 100, nullable: false),
|
||||
scene = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
page = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
qrcode_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
error_message = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_referral_qrcodes", x => x.id);
|
||||
table.UniqueConstraint("ak_referral_qrcodes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_qrcodes_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_qrcodes_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "referral_team_edges",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
member_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
leader_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
relation_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_referral_team_edges", x => x.id);
|
||||
table.UniqueConstraint("ak_referral_team_edges_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_team_edges_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_team_edges_users_leader_user_id",
|
||||
column: x => x.leader_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_team_edges_users_member_user_id",
|
||||
column: x => x.member_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_commission_settings",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
default_rate = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: false),
|
||||
min_settlement_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
settlement_cycle = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
config = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_commission_settings", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_commission_settings_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_tenant_commission_settings_default_rate", "default_rate >= 0 and default_rate <= 1");
|
||||
table.CheckConstraint("ck_tenant_commission_settings_min_settlement", "min_settlement_cents >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_commission_settings_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_commission_settings_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commission_settlement_items",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
settlement_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
referrer_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
student_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
source_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
source_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
source_paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
gross_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
commission_rate = table.Column<decimal>(type: "numeric(6,4)", precision: 6, scale: 4, nullable: false),
|
||||
commission_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
rate_source = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
attribution_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commission_settlement_items", x => x.id);
|
||||
table.UniqueConstraint("ak_commission_settlement_items_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commission_settlement_items_amounts", "gross_amount_cents >= 0 and commission_amount_cents >= 0");
|
||||
table.CheckConstraint("ck_commission_settlement_items_rate", "commission_rate >= 0 and commission_rate <= 1");
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlement_items_commission_settlements_tenant_i~",
|
||||
columns: x => new { x.tenant_id, x.settlement_id },
|
||||
principalTable: "commission_settlements",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlement_items_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlement_items_users_referrer_user_id",
|
||||
column: x => x.referrer_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commission_settlement_items_users_student_user_id",
|
||||
column: x => x.student_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "referral_leads",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
student_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
referrer_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
first_track_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
assigned_to_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
assigned_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
ref_code = table.Column<string>(type: "citext", maxLength: 100, nullable: true),
|
||||
source = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
bind_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
protected_until = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
assignment_mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
assigned_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
bound_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_referral_leads", x => x.id);
|
||||
table.UniqueConstraint("ak_referral_leads_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_leads_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_leads_users_assigned_by",
|
||||
column: x => x.assigned_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_leads_users_assigned_to_user_id",
|
||||
column: x => x.assigned_to_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_leads_users_referrer_user_id",
|
||||
column: x => x.referrer_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_leads_users_student_user_id",
|
||||
column: x => x.student_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "referral_tracks",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
lead_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
referrer_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
event_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
ref_code = table.Column<string>(type: "citext", maxLength: 100, nullable: true),
|
||||
source = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_referral_tracks", x => x.id);
|
||||
table.UniqueConstraint("ak_referral_tracks_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_tracks_referral_leads_tenant_id_lead_id",
|
||||
columns: x => new { x.tenant_id, x.lead_id },
|
||||
principalTable: "referral_leads",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_tracks_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_tracks_users_referrer_user_id",
|
||||
column: x => x.referrer_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_referral_tracks_users_target_user_id",
|
||||
column: x => x.target_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlement_items_referrer_user_id",
|
||||
table: "commission_settlement_items",
|
||||
column: "referrer_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlement_items_student_user_id",
|
||||
table: "commission_settlement_items",
|
||||
column: "student_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlement_items_tenant_id_referrer_user_id_sour~",
|
||||
table: "commission_settlement_items",
|
||||
columns: new[] { "tenant_id", "referrer_user_id", "source_paid_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlement_items_tenant_id_settlement_id",
|
||||
table: "commission_settlement_items",
|
||||
columns: new[] { "tenant_id", "settlement_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlement_items_tenant_id_source_type_source_id",
|
||||
table: "commission_settlement_items",
|
||||
columns: new[] { "tenant_id", "source_type", "source_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlements_generated_by",
|
||||
table: "commission_settlements",
|
||||
column: "generated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlements_paid_by",
|
||||
table: "commission_settlements",
|
||||
column: "paid_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlements_referrer_start",
|
||||
table: "commission_settlements",
|
||||
columns: new[] { "tenant_id", "referrer_user_id", "period_start" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlements_referrer_user_id",
|
||||
table: "commission_settlements",
|
||||
column: "referrer_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlements_reviewed_by",
|
||||
table: "commission_settlements",
|
||||
column: "reviewed_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commission_settlements_tenant_id_settlement_no",
|
||||
table: "commission_settlements",
|
||||
columns: new[] { "tenant_id", "settlement_no" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ux_commission_settlements_referrer_period",
|
||||
table: "commission_settlements",
|
||||
columns: new[] { "tenant_id", "referrer_user_id", "period_start", "period_end" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_config_tenant_id",
|
||||
table: "crm_config",
|
||||
column: "tenant_id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_config_tenant_id_assignment_mode",
|
||||
table: "crm_config",
|
||||
columns: new[] { "tenant_id", "assignment_mode" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_log_tenant_id_legacy_id",
|
||||
table: "crm_webhook_log",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_log_tenant_id_record_id_created_at",
|
||||
table: "crm_webhook_log",
|
||||
columns: new[] { "tenant_id", "record_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_queue_tenant_id_idempotency_key",
|
||||
table: "crm_webhook_queue",
|
||||
columns: new[] { "tenant_id", "idempotency_key" },
|
||||
unique: true,
|
||||
filter: "idempotency_key is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_queue_tenant_id_legacy_id",
|
||||
table: "crm_webhook_queue",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_queue_tenant_id_record_id",
|
||||
table: "crm_webhook_queue",
|
||||
columns: new[] { "tenant_id", "record_id" },
|
||||
unique: true,
|
||||
filter: "record_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_queue_tenant_id_record_id_created_at",
|
||||
table: "crm_webhook_queue",
|
||||
columns: new[] { "tenant_id", "record_id", "created_at" },
|
||||
filter: "record_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_queue_tenant_id_source_created_at",
|
||||
table: "crm_webhook_queue",
|
||||
columns: new[] { "tenant_id", "source", "created_at" },
|
||||
filter: "source = 'tenant.student.crm_push'");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_crm_webhook_queue_tenant_id_status_scheduled_at_next_attemp~",
|
||||
table: "crm_webhook_queue",
|
||||
columns: new[] { "tenant_id", "status", "scheduled_at", "next_attempt_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_codes_tenant_id_code",
|
||||
table: "referral_codes",
|
||||
columns: new[] { "tenant_id", "code" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_codes_tenant_id_code_status",
|
||||
table: "referral_codes",
|
||||
columns: new[] { "tenant_id", "code", "status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_codes_tenant_id_user_id",
|
||||
table: "referral_codes",
|
||||
columns: new[] { "tenant_id", "user_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_codes_user_id",
|
||||
table: "referral_codes",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_assigned_by",
|
||||
table: "referral_leads",
|
||||
column: "assigned_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_assigned_to_user_id",
|
||||
table: "referral_leads",
|
||||
column: "assigned_to_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_referrer_user_id",
|
||||
table: "referral_leads",
|
||||
column: "referrer_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_student_user_id",
|
||||
table: "referral_leads",
|
||||
column: "student_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_tenant_id_assigned_to_user_id_status_bound_at",
|
||||
table: "referral_leads",
|
||||
columns: new[] { "tenant_id", "assigned_to_user_id", "status", "bound_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_tenant_id_first_track_id",
|
||||
table: "referral_leads",
|
||||
columns: new[] { "tenant_id", "first_track_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_tenant_id_referrer_user_id_bound_at",
|
||||
table: "referral_leads",
|
||||
columns: new[] { "tenant_id", "referrer_user_id", "bound_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_leads_tenant_id_student_user_id",
|
||||
table: "referral_leads",
|
||||
columns: new[] { "tenant_id", "student_user_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_qrcodes_tenant_id_provider_scene_page",
|
||||
table: "referral_qrcodes",
|
||||
columns: new[] { "tenant_id", "provider", "scene", "page" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_qrcodes_tenant_id_ref_code_status",
|
||||
table: "referral_qrcodes",
|
||||
columns: new[] { "tenant_id", "ref_code", "status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_qrcodes_user_id",
|
||||
table: "referral_qrcodes",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_team_edges_leader_user_id",
|
||||
table: "referral_team_edges",
|
||||
column: "leader_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_team_edges_member_user_id",
|
||||
table: "referral_team_edges",
|
||||
column: "member_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_team_edges_tenant_id_leader_user_id_status",
|
||||
table: "referral_team_edges",
|
||||
columns: new[] { "tenant_id", "leader_user_id", "status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_team_edges_tenant_id_member_user_id_relation_type",
|
||||
table: "referral_team_edges",
|
||||
columns: new[] { "tenant_id", "member_user_id", "relation_type" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_tracks_referrer_user_id",
|
||||
table: "referral_tracks",
|
||||
column: "referrer_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_tracks_target_user_id",
|
||||
table: "referral_tracks",
|
||||
column: "target_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_tracks_tenant_id_lead_id_created_at",
|
||||
table: "referral_tracks",
|
||||
columns: new[] { "tenant_id", "lead_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_tracks_tenant_id_legacy_id",
|
||||
table: "referral_tracks",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_referral_tracks_tenant_id_ref_code_event_type_created_at",
|
||||
table: "referral_tracks",
|
||||
columns: new[] { "tenant_id", "ref_code", "event_type", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_commission_settings_tenant_id",
|
||||
table: "tenant_commission_settings",
|
||||
column: "tenant_id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_commission_settings_updated_by",
|
||||
table: "tenant_commission_settings",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_referral_leads_referral_tracks_tenant_id_first_track_id",
|
||||
table: "referral_leads",
|
||||
columns: new[] { "tenant_id", "first_track_id" },
|
||||
principalTable: "referral_tracks",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_referral_leads_referral_tracks_tenant_id_first_track_id",
|
||||
table: "referral_leads");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commission_settlement_items");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "crm_config");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "crm_webhook_log");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "crm_webhook_queue");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "referral_codes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "referral_qrcodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "referral_team_edges");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_commission_settings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commission_settlements");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "referral_tracks");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "referral_leads");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,619 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddOperationsContentAndAuditPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "announcements",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
content = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
background_color = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_announcements", x => x.id);
|
||||
table.UniqueConstraint("ak_announcements_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_announcements_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "audit_logs",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
actor_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
action = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
target_type = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
target_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
ip_address = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_audit_logs", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_audit_logs_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_audit_logs_users_actor_user_id",
|
||||
column: x => x.actor_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "badges",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
category = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
icon_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
level = table.Column<int>(type: "integer", nullable: true),
|
||||
unlock_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
condition_field = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
condition_operator = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
condition_value = table.Column<decimal>(type: "numeric(18,4)", precision: 18, scale: 4, nullable: true),
|
||||
condition_extra = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_badges", x => x.id);
|
||||
table.UniqueConstraint("ak_badges_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_badges_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "banners",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
subtitle = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
content = table.Column<string>(type: "text", nullable: true),
|
||||
button_text = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
button_link = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
background_color = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
border_color = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_banners", x => x.id);
|
||||
table.UniqueConstraint("ak_banners_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_banners_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_banners_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "faqs",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
question = table.Column<string>(type: "text", nullable: true),
|
||||
answer = table.Column<string>(type: "text", nullable: true),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
is_active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_faqs", x => x.id);
|
||||
table.UniqueConstraint("ak_faqs_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_faqs_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_faqs_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_content_notifications",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
adoption_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
source_question_bank_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
read_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
notification_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
message = table.Column<string>(type: "text", nullable: false),
|
||||
action_label = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
action_path = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
dedupe_key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
read_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
resolved_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_content_notifications", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_content_notifications_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_content_notifications_question_banks_tenant_id_sourc~",
|
||||
columns: x => new { x.tenant_id, x.source_question_bank_id },
|
||||
principalTable: "question_banks",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_content_notifications_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_content_notifications_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_content_notifications_users_read_by",
|
||||
column: x => x.read_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_theme_templates",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
preview_image_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
theme = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
public_assets = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_theme_templates", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_theme_templates_code", x => x.code);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_notifications",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
source_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
notification_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
message = table.Column<string>(type: "text", nullable: false),
|
||||
action_label = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
action_path = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
source_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
dedupe_key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
read_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_notifications", x => x.id);
|
||||
table.UniqueConstraint("ak_user_notifications_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_user_notifications_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_notifications_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_notifications_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_badges",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
badge_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
granted_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
note = table.Column<string>(type: "text", nullable: true),
|
||||
granted_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_badges", x => x.id);
|
||||
table.UniqueConstraint("ak_user_badges_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_user_badges_badges_tenant_id_badge_id",
|
||||
columns: x => new { x.tenant_id, x.badge_id },
|
||||
principalTable: "badges",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_badges_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_badges_users_granted_by",
|
||||
column: x => x.granted_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_badges_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_theme_configs",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
active_template_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
active_theme = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
active_public_assets = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
draft_template_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
draft_theme = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
draft_public_assets = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
published_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
published_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
draft_updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_theme_configs", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_theme_configs_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_theme_configs_tenant_theme_templates_active_template~",
|
||||
column: x => x.active_template_code,
|
||||
principalTable: "tenant_theme_templates",
|
||||
principalColumn: "code",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_theme_configs_tenant_theme_templates_draft_template_~",
|
||||
column: x => x.draft_template_code,
|
||||
principalTable: "tenant_theme_templates",
|
||||
principalColumn: "code",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_theme_configs_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_theme_configs_users_draft_updated_by",
|
||||
column: x => x.draft_updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_theme_configs_users_published_by",
|
||||
column: x => x.published_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_announcements_tenant_id_is_active_sort_order",
|
||||
table: "announcements",
|
||||
columns: new[] { "tenant_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_announcements_tenant_id_legacy_id",
|
||||
table: "announcements",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_audit_logs_actor_user_id",
|
||||
table: "audit_logs",
|
||||
column: "actor_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_audit_logs_tenant_id_created_at",
|
||||
table: "audit_logs",
|
||||
columns: new[] { "tenant_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_audit_logs_tenant_id_target_type_target_id_created_at",
|
||||
table: "audit_logs",
|
||||
columns: new[] { "tenant_id", "target_type", "target_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_badges_tenant_id_category_is_active_sort_order",
|
||||
table: "badges",
|
||||
columns: new[] { "tenant_id", "category", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_badges_tenant_id_legacy_id",
|
||||
table: "badges",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_banners_tenant_id_legacy_id",
|
||||
table: "banners",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_banners_tenant_id_region_id_is_active_sort_order",
|
||||
table: "banners",
|
||||
columns: new[] { "tenant_id", "region_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_faqs_tenant_id_legacy_id",
|
||||
table: "faqs",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_faqs_tenant_id_region_id_is_active_sort_order",
|
||||
table: "faqs",
|
||||
columns: new[] { "tenant_id", "region_id", "is_active", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_content_notifications_created_by",
|
||||
table: "tenant_content_notifications",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_content_notifications_read_by",
|
||||
table: "tenant_content_notifications",
|
||||
column: "read_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_content_notifications_tenant_id_adoption_id_notifica~",
|
||||
table: "tenant_content_notifications",
|
||||
columns: new[] { "tenant_id", "adoption_id", "notification_type", "status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_content_notifications_tenant_id_notification_type_de~",
|
||||
table: "tenant_content_notifications",
|
||||
columns: new[] { "tenant_id", "notification_type", "dedupe_key" },
|
||||
unique: true,
|
||||
filter: "dedupe_key is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_content_notifications_tenant_id_source_question_bank~",
|
||||
table: "tenant_content_notifications",
|
||||
columns: new[] { "tenant_id", "source_question_bank_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_content_notifications_tenant_id_status_created_at",
|
||||
table: "tenant_content_notifications",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_configs_active_template_code",
|
||||
table: "tenant_theme_configs",
|
||||
column: "active_template_code");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_configs_draft_template_code",
|
||||
table: "tenant_theme_configs",
|
||||
column: "draft_template_code");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_configs_draft_updated_by",
|
||||
table: "tenant_theme_configs",
|
||||
column: "draft_updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_configs_published_by",
|
||||
table: "tenant_theme_configs",
|
||||
column: "published_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_configs_tenant_id",
|
||||
table: "tenant_theme_configs",
|
||||
column: "tenant_id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_templates_code",
|
||||
table: "tenant_theme_templates",
|
||||
column: "code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_theme_templates_status_sort_order_code",
|
||||
table: "tenant_theme_templates",
|
||||
columns: new[] { "status", "sort_order", "code" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_badges_granted_by",
|
||||
table: "user_badges",
|
||||
column: "granted_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_badges_tenant_id_badge_id",
|
||||
table: "user_badges",
|
||||
columns: new[] { "tenant_id", "badge_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_badges_tenant_id_legacy_id",
|
||||
table: "user_badges",
|
||||
columns: new[] { "tenant_id", "legacy_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_badges_tenant_id_user_id_badge_id",
|
||||
table: "user_badges",
|
||||
columns: new[] { "tenant_id", "user_id", "badge_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_badges_user_id",
|
||||
table: "user_badges",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_notifications_created_by",
|
||||
table: "user_notifications",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_notifications_tenant_id_source_type_source_id",
|
||||
table: "user_notifications",
|
||||
columns: new[] { "tenant_id", "source_type", "source_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_notifications_tenant_id_user_id_notification_type_dedu~",
|
||||
table: "user_notifications",
|
||||
columns: new[] { "tenant_id", "user_id", "notification_type", "dedupe_key" },
|
||||
unique: true,
|
||||
filter: "dedupe_key is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_notifications_tenant_id_user_id_status_created_at",
|
||||
table: "user_notifications",
|
||||
columns: new[] { "tenant_id", "user_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_notifications_user_id",
|
||||
table: "user_notifications",
|
||||
column: "user_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "announcements");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "audit_logs");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "banners");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "faqs");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_content_notifications");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_theme_configs");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_badges");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_notifications");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_theme_templates");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "badges");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,669 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddCommerceRefundAndReconciliationPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "refunded_amount_cents",
|
||||
table: "payments",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "refunded_amount_cents",
|
||||
table: "orders",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "revoked_at",
|
||||
table: "entitlements",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "revoked_by",
|
||||
table: "entitlements",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "revoked_reason",
|
||||
table: "entitlements",
|
||||
type: "character varying(1000)",
|
||||
maxLength: 1000,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_reconciliation_batches",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
bill_date = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
bill_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source_name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
source_hash = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
total_count = table.Column<int>(type: "integer", nullable: false),
|
||||
matched_count = table.Column<int>(type: "integer", nullable: false),
|
||||
mismatch_count = table.Column<int>(type: "integer", nullable: false),
|
||||
missing_local_count = table.Column<int>(type: "integer", nullable: false),
|
||||
missing_provider_count = table.Column<int>(type: "integer", nullable: false),
|
||||
duplicate_count = table.Column<int>(type: "integer", nullable: false),
|
||||
ignored_count = table.Column<int>(type: "integer", nullable: false),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
refund_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
fee_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
completed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
error = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_reconciliation_batches", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_reconciliation_batches_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commerce_reconciliation_batches_amounts", "amount_cents >= 0 and refund_amount_cents >= 0");
|
||||
table.CheckConstraint("ck_commerce_reconciliation_batches_counts", "total_count >= 0 and matched_count >= 0 and mismatch_count >= 0 and missing_local_count >= 0 and missing_provider_count >= 0 and duplicate_count >= 0 and ignored_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_batches_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_batches_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_refund_requests",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
payment_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
requested_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
reviewed_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
processed_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
refund_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
provider_refund_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
reason = table.Column<string>(type: "text", nullable: true),
|
||||
entitlement_action = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
requested_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
reviewed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
processed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
succeeded_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
failed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
cancelled_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
failure_reason = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_refund_requests", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_refund_requests_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commerce_refund_requests_amount", "amount_cents > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_requests_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_requests_payments_tenant_id_payment_id",
|
||||
columns: x => new { x.tenant_id, x.payment_id },
|
||||
principalTable: "payments",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_requests_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_requests_users_processed_by",
|
||||
column: x => x.processed_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_requests_users_requested_by",
|
||||
column: x => x.requested_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_requests_users_reviewed_by",
|
||||
column: x => x.reviewed_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_reconciliation_items",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
batch_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
payment_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
refund_request_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
row_no = table.Column<int>(type: "integer", nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
transaction_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
provider_trade_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
provider_refund_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
order_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
refund_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
refund_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
fee_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
refunded_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
provider_status = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
local_status = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
match_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
issue_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_reconciliation_items", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_reconciliation_items_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commerce_reconciliation_items_amounts", "amount_cents >= 0 and refund_amount_cents >= 0");
|
||||
table.CheckConstraint("ck_commerce_reconciliation_items_row", "row_no > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_items_commerce_reconciliation_batch~",
|
||||
columns: x => new { x.tenant_id, x.batch_id },
|
||||
principalTable: "commerce_reconciliation_batches",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_items_commerce_refund_requests_tena~",
|
||||
columns: x => new { x.tenant_id, x.refund_request_id },
|
||||
principalTable: "commerce_refund_requests",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_items_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_items_payments_tenant_id_payment_id",
|
||||
columns: x => new { x.tenant_id, x.payment_id },
|
||||
principalTable: "payments",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_items_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_refund_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
refund_request_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
from_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
to_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
event_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
actor_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_refund_events", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_refund_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_events_commerce_refund_requests_tenant_id_r~",
|
||||
columns: x => new { x.tenant_id, x.refund_request_id },
|
||||
principalTable: "commerce_refund_requests",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_refund_events_users_actor_user_id",
|
||||
column: x => x.actor_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_reconciliation_issues",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
batch_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
item_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
payment_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
refund_request_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
assigned_to = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
resolved_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
issue_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
transaction_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
issue_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
match_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
resolution_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
order_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
refund_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
provider_trade_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
provider_refund_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
refund_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
resolved_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
due_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
summary = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
resolution_note = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_reconciliation_issues", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_reconciliation_issues_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commerce_reconciliation_issues_amounts", "amount_cents >= 0 and refund_amount_cents >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_commerce_reconciliation_batc~",
|
||||
columns: x => new { x.tenant_id, x.batch_id },
|
||||
principalTable: "commerce_reconciliation_batches",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_commerce_reconciliation_item~",
|
||||
columns: x => new { x.tenant_id, x.item_id },
|
||||
principalTable: "commerce_reconciliation_items",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_commerce_refund_requests_ten~",
|
||||
columns: x => new { x.tenant_id, x.refund_request_id },
|
||||
principalTable: "commerce_refund_requests",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_payments_tenant_id_payment_id",
|
||||
columns: x => new { x.tenant_id, x.payment_id },
|
||||
principalTable: "payments",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_users_assigned_to",
|
||||
column: x => x.assigned_to,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issues_users_resolved_by",
|
||||
column: x => x.resolved_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_reconciliation_issue_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
issue_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
from_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
to_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
event_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
actor_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
note = table.Column<string>(type: "text", nullable: true),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_reconciliation_issue_events", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_reconciliation_issue_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issue_events_commerce_reconciliatio~",
|
||||
columns: x => new { x.tenant_id, x.issue_id },
|
||||
principalTable: "commerce_reconciliation_issues",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issue_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_reconciliation_issue_events_users_actor_user_id",
|
||||
column: x => x.actor_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.AddCheckConstraint(
|
||||
name: "ck_payments_refunded_amount",
|
||||
table: "payments",
|
||||
sql: "refunded_amount_cents >= 0");
|
||||
|
||||
migrationBuilder.AddCheckConstraint(
|
||||
name: "ck_orders_refunded_amount",
|
||||
table: "orders",
|
||||
sql: "refunded_amount_cents >= 0");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_entitlements_revoked_by",
|
||||
table: "entitlements",
|
||||
column: "revoked_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_batches_created_by",
|
||||
table: "commerce_reconciliation_batches",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_batches_tenant_id_provider_bill_dat~",
|
||||
table: "commerce_reconciliation_batches",
|
||||
columns: new[] { "tenant_id", "provider", "bill_date", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_batches_tenant_id_status_created_at",
|
||||
table: "commerce_reconciliation_batches",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issue_events_actor_user_id",
|
||||
table: "commerce_reconciliation_issue_events",
|
||||
column: "actor_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issue_events_tenant_id_issue_id_cre~",
|
||||
table: "commerce_reconciliation_issue_events",
|
||||
columns: new[] { "tenant_id", "issue_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_assigned_to",
|
||||
table: "commerce_reconciliation_issues",
|
||||
column: "assigned_to");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_created_by",
|
||||
table: "commerce_reconciliation_issues",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_resolved_by",
|
||||
table: "commerce_reconciliation_issues",
|
||||
column: "resolved_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_assigned_to_status~",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "assigned_to", "status", "due_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_batch_id_status_cr~",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "batch_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_issue_no",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "issue_no" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_item_id",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "item_id" },
|
||||
unique: true,
|
||||
filter: "item_id is not null and status in ('open', 'investigating', 'escalated')");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_order_id",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "order_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_order_no_created_at",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "order_no", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_payment_id_created~",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "payment_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_refund_request_id",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "refund_request_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_issues_tenant_id_status_severity_cr~",
|
||||
table: "commerce_reconciliation_issues",
|
||||
columns: new[] { "tenant_id", "status", "severity", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_batch_id_row_no",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "batch_id", "row_no" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_batch_id_match_stat~",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "batch_id", "match_status", "row_no" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_order_id",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "order_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_order_no_created_at",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "order_no", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_payment_id",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "payment_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_provider_provider_t~",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "provider", "provider_trade_no", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_refund_no_provider_~",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "refund_no", "provider_refund_no", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_reconciliation_items_tenant_id_refund_request_id",
|
||||
table: "commerce_reconciliation_items",
|
||||
columns: new[] { "tenant_id", "refund_request_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_events_actor_user_id",
|
||||
table: "commerce_refund_events",
|
||||
column: "actor_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_events_tenant_id_refund_request_id_created_~",
|
||||
table: "commerce_refund_events",
|
||||
columns: new[] { "tenant_id", "refund_request_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_processed_by",
|
||||
table: "commerce_refund_requests",
|
||||
column: "processed_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_requested_by",
|
||||
table: "commerce_refund_requests",
|
||||
column: "requested_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_reviewed_by",
|
||||
table: "commerce_refund_requests",
|
||||
column: "reviewed_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_tenant_id_order_id_created_at",
|
||||
table: "commerce_refund_requests",
|
||||
columns: new[] { "tenant_id", "order_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_tenant_id_payment_id",
|
||||
table: "commerce_refund_requests",
|
||||
columns: new[] { "tenant_id", "payment_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_tenant_id_refund_no",
|
||||
table: "commerce_refund_requests",
|
||||
columns: new[] { "tenant_id", "refund_no" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_refund_requests_tenant_id_status_created_at",
|
||||
table: "commerce_refund_requests",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_entitlements_users_revoked_by",
|
||||
table: "entitlements",
|
||||
column: "revoked_by",
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_entitlements_users_revoked_by",
|
||||
table: "entitlements");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_reconciliation_issue_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_refund_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_reconciliation_issues");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_reconciliation_items");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_reconciliation_batches");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_refund_requests");
|
||||
|
||||
migrationBuilder.DropCheckConstraint(
|
||||
name: "ck_payments_refunded_amount",
|
||||
table: "payments");
|
||||
|
||||
migrationBuilder.DropCheckConstraint(
|
||||
name: "ck_orders_refunded_amount",
|
||||
table: "orders");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_entitlements_revoked_by",
|
||||
table: "entitlements");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "refunded_amount_cents",
|
||||
table: "payments");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "refunded_amount_cents",
|
||||
table: "orders");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "revoked_at",
|
||||
table: "entitlements");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "revoked_by",
|
||||
table: "entitlements");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "revoked_reason",
|
||||
table: "entitlements");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,452 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddContentPlatformOperationsPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "security_scan_provider",
|
||||
table: "content_assets",
|
||||
type: "character varying(100)",
|
||||
maxLength: 100,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "security_scan_status",
|
||||
table: "content_assets",
|
||||
type: "character varying(32)",
|
||||
maxLength: 32,
|
||||
nullable: false,
|
||||
defaultValue: "not_required");
|
||||
|
||||
migrationBuilder.AddColumn<JsonElement>(
|
||||
name: "security_scan_summary",
|
||||
table: "content_assets",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "security_scanned_at",
|
||||
table: "content_assets",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ai_recommendation_reports",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
region_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
model = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
prompt_version = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
input_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
context_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
result_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
error_message = table.Column<string>(type: "text", nullable: true),
|
||||
generated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_ai_recommendation_reports", x => x.id);
|
||||
table.UniqueConstraint("ak_ai_recommendation_reports_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_ai_recommendation_reports_regions_tenant_id_region_id",
|
||||
columns: x => new { x.tenant_id, x.region_id },
|
||||
principalTable: "regions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_ai_recommendation_reports_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_ai_recommendation_reports_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_asset_access_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
asset_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
actor_role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
access_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
visibility = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
asset_type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
storage_provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
disposition = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
expires_in_seconds = table.Column<int>(type: "integer", nullable: true),
|
||||
signature_mode = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
result = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
deny_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_asset_access_events", x => x.id);
|
||||
table.UniqueConstraint("ak_content_asset_access_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_content_asset_access_events_expiry", "expires_in_seconds is null or expires_in_seconds > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_content_asset_access_events_content_assets_tenant_id_asset_~",
|
||||
columns: x => new { x.tenant_id, x.asset_id },
|
||||
principalTable: "content_assets",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_asset_access_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_asset_access_events_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_asset_security_scan_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
asset_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
provider = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
scan_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
risk_level = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
issue_codes = table.Column<string[]>(type: "text[]", nullable: false, defaultValueSql: "'{}'::text[]"),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_content_asset_security_scan_events", x => x.id);
|
||||
table.UniqueConstraint("ak_content_asset_security_scan_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_content_asset_security_scan_events_content_assets_tenant_id~",
|
||||
columns: x => new { x.tenant_id, x.asset_id },
|
||||
principalTable: "content_assets",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_content_asset_security_scan_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "question_bank_grants",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
source_question_bank_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
grant_scope = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
allowed_plan_codes = table.Column<string[]>(type: "text[]", nullable: false, defaultValueSql: "'{}'::text[]"),
|
||||
allowed_tenant_ids = table.Column<Guid[]>(type: "uuid[]", nullable: false, defaultValueSql: "'{}'::uuid[]"),
|
||||
allowed_region_ids = table.Column<Guid[]>(type: "uuid[]", nullable: false, defaultValueSql: "'{}'::uuid[]"),
|
||||
allowed_subject_ids = table.Column<Guid[]>(type: "uuid[]", nullable: false, defaultValueSql: "'{}'::uuid[]"),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
starts_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_question_bank_grants", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_bank_grants_question_banks_source_question_bank_id",
|
||||
column: x => x.source_question_bank_id,
|
||||
principalTable: "question_banks",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_bank_grants_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_question_bank_grants_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_question_bank_adoptions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
source_question_bank_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
grant_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_question_bank_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_entry_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
target_collection_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
adoption_mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sync_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
source_snapshot = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
copied_question_count = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
last_synced_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_question_bank_adoptions", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_question_bank_adoptions_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_tenant_question_bank_adoptions_copied_count", "copied_question_count >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_content_entries_tenant_id_ta~",
|
||||
columns: x => new { x.tenant_id, x.target_entry_id },
|
||||
principalTable: "content_entries",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_question_bank_grants_grant_id",
|
||||
column: x => x.grant_id,
|
||||
principalTable: "question_bank_grants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_question_banks_source_questi~",
|
||||
column: x => x.source_question_bank_id,
|
||||
principalTable: "question_banks",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_question_banks_tenant_id_tar~",
|
||||
columns: x => new { x.tenant_id, x.target_question_bank_id },
|
||||
principalTable: "question_banks",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_question_collections_tenant_~",
|
||||
columns: x => new { x.tenant_id, x.target_collection_id },
|
||||
principalTable: "question_collections",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_question_bank_adoptions_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_assets_tenant_id_security_scan_status_upload_status~",
|
||||
table: "content_assets",
|
||||
columns: new[] { "tenant_id", "security_scan_status", "upload_status", "status", "updated_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_ai_recommendation_reports_tenant_id_region_id_created_at",
|
||||
table: "ai_recommendation_reports",
|
||||
columns: new[] { "tenant_id", "region_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_ai_recommendation_reports_tenant_id_user_id_created_at",
|
||||
table: "ai_recommendation_reports",
|
||||
columns: new[] { "tenant_id", "user_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_ai_recommendation_reports_user_id",
|
||||
table: "ai_recommendation_reports",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_asset_access_events_tenant_id_access_type_result_cr~",
|
||||
table: "content_asset_access_events",
|
||||
columns: new[] { "tenant_id", "access_type", "result", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_asset_access_events_tenant_id_asset_id_created_at",
|
||||
table: "content_asset_access_events",
|
||||
columns: new[] { "tenant_id", "asset_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_asset_access_events_tenant_id_user_id_created_at",
|
||||
table: "content_asset_access_events",
|
||||
columns: new[] { "tenant_id", "user_id", "created_at" },
|
||||
filter: "user_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_asset_access_events_user_id",
|
||||
table: "content_asset_access_events",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_asset_security_scan_events_tenant_id_asset_id_creat~",
|
||||
table: "content_asset_security_scan_events",
|
||||
columns: new[] { "tenant_id", "asset_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_content_asset_security_scan_events_tenant_id_scan_status_ri~",
|
||||
table: "content_asset_security_scan_events",
|
||||
columns: new[] { "tenant_id", "scan_status", "risk_level", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_bank_grants_allowed_plan_codes",
|
||||
table: "question_bank_grants",
|
||||
column: "allowed_plan_codes")
|
||||
.Annotation("Npgsql:IndexMethod", "gin");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_bank_grants_allowed_tenant_ids",
|
||||
table: "question_bank_grants",
|
||||
column: "allowed_tenant_ids")
|
||||
.Annotation("Npgsql:IndexMethod", "gin");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_bank_grants_created_by",
|
||||
table: "question_bank_grants",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_bank_grants_source_question_bank_id_status_starts_~",
|
||||
table: "question_bank_grants",
|
||||
columns: new[] { "source_question_bank_id", "status", "starts_at", "expires_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_question_bank_grants_updated_by",
|
||||
table: "question_bank_grants",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_created_by",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_grant_id",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
column: "grant_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_source_question_bank_id",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
column: "source_question_bank_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_tenant_id_source_question_ba~",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
columns: new[] { "tenant_id", "source_question_bank_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_tenant_id_status_updated_at",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
columns: new[] { "tenant_id", "status", "updated_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_tenant_id_target_collection_~",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
columns: new[] { "tenant_id", "target_collection_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_tenant_id_target_entry_id",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
columns: new[] { "tenant_id", "target_entry_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_tenant_id_target_question_ba~",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
columns: new[] { "tenant_id", "target_question_bank_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_question_bank_adoptions_updated_by",
|
||||
table: "tenant_question_bank_adoptions",
|
||||
column: "updated_by");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ai_recommendation_reports");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_asset_access_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "content_asset_security_scan_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_question_bank_adoptions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "question_bank_grants");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_content_assets_tenant_id_security_scan_status_upload_status~",
|
||||
table: "content_assets");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "security_scan_provider",
|
||||
table: "content_assets");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "security_scan_status",
|
||||
table: "content_assets");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "security_scan_summary",
|
||||
table: "content_assets");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "security_scanned_at",
|
||||
table: "content_assets");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,633 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPlatformBillingDunningAndAuditPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_audit_alert_rules",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
action_patterns = table.Column<string[]>(type: "text[]", nullable: false, defaultValueSql: "'{}'::text[]"),
|
||||
target_types = table.Column<string[]>(type: "text[]", nullable: false, defaultValueSql: "'{}'::text[]"),
|
||||
conditions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_platform_audit_alert_rules", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_audit_alert_rules_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_dunning_notification_channels",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
channel_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
webhook_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||
secret_ref = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
reminder_types = table.Column<string[]>(type: "text[]", nullable: false, defaultValueSql: "array['overdue', 'final_notice']::text[]"),
|
||||
reminder_channels = table.Column<string[]>(type: "text[]", nullable: false, defaultValueSql: "array['internal']::text[]"),
|
||||
min_reminder_level = table.Column<int>(type: "integer", nullable: false),
|
||||
tenant_ids = table.Column<Guid[]>(type: "uuid[]", nullable: false, defaultValueSql: "'{}'::uuid[]"),
|
||||
timeout_seconds = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_platform_dunning_notification_channels", x => x.id);
|
||||
table.CheckConstraint("ck_platform_dunning_channels_level", "min_reminder_level between 1 and 20");
|
||||
table.CheckConstraint("ck_platform_dunning_channels_timeout", "timeout_seconds between 1 and 60");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_saas_plans",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "text", nullable: true),
|
||||
billing_cycle = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
base_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
currency = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||
included_quotas = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
overage_prices = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
feature_flags = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_platform_saas_plans", x => x.id);
|
||||
table.CheckConstraint("ck_platform_saas_plans_amount", "base_amount_cents >= 0");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_billing_profiles",
|
||||
columns: table => new
|
||||
{
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
billing_name = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
tax_id = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
contact_name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
contact_phone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
contact_email = table.Column<string>(type: "citext", maxLength: 300, nullable: true),
|
||||
billing_address = table.Column<string>(type: "text", nullable: true),
|
||||
invoice_title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
|
||||
invoice_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
bank_name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
bank_account_masked = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_billing_profiles", x => x.tenant_id);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_billing_profiles_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_invoices",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
invoice_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
invoice_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
currency = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||
subtotal_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
discount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
tax_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
total_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
paid_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
balance_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
billing_period_start = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
billing_period_end = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
due_date = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
issued_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
note = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_invoices", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_invoices_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_tenant_invoices_amounts", "subtotal_cents >= 0 and discount_cents >= 0 and tax_cents >= 0 and total_cents >= 0 and paid_cents >= 0 and balance_cents >= 0");
|
||||
table.CheckConstraint("ck_tenant_invoices_period", "billing_period_end is null or billing_period_start is null or billing_period_end >= billing_period_start");
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoices_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoices_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_audit_alerts",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
rule_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
audit_log_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
acknowledged_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
resolved_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
action = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
target_type = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
target_id = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
title = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: false),
|
||||
summary = table.Column<string>(type: "text", nullable: true),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
first_seen_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
last_seen_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
acknowledged_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
resolved_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
resolution_note = table.Column<string>(type: "text", nullable: true),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_platform_audit_alerts", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_audit_alerts_audit_logs_audit_log_id",
|
||||
column: x => x.audit_log_id,
|
||||
principalTable: "audit_logs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_audit_alerts_platform_audit_alert_rules_rule_id",
|
||||
column: x => x.rule_id,
|
||||
principalTable: "platform_audit_alert_rules",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_audit_alerts_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_audit_alerts_users_acknowledged_by",
|
||||
column: x => x.acknowledged_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_audit_alerts_users_resolved_by",
|
||||
column: x => x.resolved_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_invoice_items",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
invoice_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
item_type = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
item_ref_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
description = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: false),
|
||||
quantity = table.Column<decimal>(type: "numeric(12,2)", precision: 12, scale: 2, nullable: false),
|
||||
unit_amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_invoice_items", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_invoice_items_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_tenant_invoice_items_amounts", "unit_amount_cents >= 0 and amount_cents >= 0");
|
||||
table.CheckConstraint("ck_tenant_invoice_items_quantity", "quantity > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_items_tenant_invoices_tenant_id_invoice_id",
|
||||
columns: x => new { x.tenant_id, x.invoice_id },
|
||||
principalTable: "tenant_invoices",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_items_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_invoice_payments",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
invoice_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
received_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
payment_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
method = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
paid_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
provider_trade_no = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
raw_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_invoice_payments", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_invoice_payments_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_tenant_invoice_payments_amount", "amount_cents >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_payments_tenant_invoices_tenant_id_invoice_id",
|
||||
columns: x => new { x.tenant_id, x.invoice_id },
|
||||
principalTable: "tenant_invoices",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_payments_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_payments_users_received_by",
|
||||
column: x => x.received_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_invoice_reminders",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
invoice_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
reminder_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
channel = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
reminder_date = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
reminder_level = table.Column<int>(type: "integer", nullable: false),
|
||||
due_date = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
balance_cents_snapshot = table.Column<int>(type: "integer", nullable: false),
|
||||
message = table.Column<string>(type: "text", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
sent_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
acknowledged_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_invoice_reminders", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_invoice_reminders_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_tenant_invoice_reminders_balance", "balance_cents_snapshot >= 0");
|
||||
table.CheckConstraint("ck_tenant_invoice_reminders_level", "reminder_level between 1 and 20");
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_reminders_tenant_invoices_tenant_id_invoice_~",
|
||||
columns: x => new { x.tenant_id, x.invoice_id },
|
||||
principalTable: "tenant_invoices",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_reminders_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_invoice_reminders_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_dunning_notification_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
channel_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
reminder_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
invoice_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
attempts = table.Column<int>(type: "integer", nullable: false),
|
||||
scheduled_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
next_attempt_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
last_attempt_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
sent_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
last_error = table.Column<string>(type: "text", nullable: true),
|
||||
last_http_code = table.Column<int>(type: "integer", nullable: true),
|
||||
last_response_summary = table.Column<string>(type: "text", nullable: true),
|
||||
request_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_platform_dunning_notification_events", x => x.id);
|
||||
table.UniqueConstraint("ak_platform_dunning_notification_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_platform_dunning_events_attempts", "attempts >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_dunning_notification_events_platform_dunning_notif~",
|
||||
column: x => x.channel_id,
|
||||
principalTable: "platform_dunning_notification_channels",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_dunning_notification_events_tenant_invoice_reminde~",
|
||||
columns: x => new { x.tenant_id, x.reminder_id },
|
||||
principalTable: "tenant_invoice_reminders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_dunning_notification_events_tenant_invoices_tenant~",
|
||||
columns: x => new { x.tenant_id, x.invoice_id },
|
||||
principalTable: "tenant_invoices",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_platform_dunning_notification_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alert_rules_code",
|
||||
table: "platform_audit_alert_rules",
|
||||
column: "code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alert_rules_enabled_severity_code",
|
||||
table: "platform_audit_alert_rules",
|
||||
columns: new[] { "enabled", "severity", "code" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alert_rules_tenant_id",
|
||||
table: "platform_audit_alert_rules",
|
||||
column: "tenant_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alerts_acknowledged_by",
|
||||
table: "platform_audit_alerts",
|
||||
column: "acknowledged_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alerts_audit_log_id",
|
||||
table: "platform_audit_alerts",
|
||||
column: "audit_log_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alerts_resolved_by",
|
||||
table: "platform_audit_alerts",
|
||||
column: "resolved_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alerts_rule_id_audit_log_id",
|
||||
table: "platform_audit_alerts",
|
||||
columns: new[] { "rule_id", "audit_log_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alerts_status_severity_created_at",
|
||||
table: "platform_audit_alerts",
|
||||
columns: new[] { "status", "severity", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_audit_alerts_tenant_id_status_created_at",
|
||||
table: "platform_audit_alerts",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_channels_channel_code",
|
||||
table: "platform_dunning_notification_channels",
|
||||
column: "channel_code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_channels_enabled_min_reminder~",
|
||||
table: "platform_dunning_notification_channels",
|
||||
columns: new[] { "enabled", "min_reminder_level", "channel_code" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_channel_id_reminder_id",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "channel_id", "reminder_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_invoice_id_status_crea~",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "invoice_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_reminder_id_status_cre~",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "reminder_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_status_next_attempt_at~",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "status", "next_attempt_at", "scheduled_at", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_tenant_id_invoice_id",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "tenant_id", "invoice_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_tenant_id_reminder_id",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "tenant_id", "reminder_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_dunning_notification_events_tenant_id_status_creat~",
|
||||
table: "platform_dunning_notification_events",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_saas_plans_code",
|
||||
table: "platform_saas_plans",
|
||||
column: "code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_platform_saas_plans_status_sort_order",
|
||||
table: "platform_saas_plans",
|
||||
columns: new[] { "status", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_items_invoice_id",
|
||||
table: "tenant_invoice_items",
|
||||
column: "invoice_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_items_tenant_id_invoice_id",
|
||||
table: "tenant_invoice_items",
|
||||
columns: new[] { "tenant_id", "invoice_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_payments_invoice_id_status",
|
||||
table: "tenant_invoice_payments",
|
||||
columns: new[] { "invoice_id", "status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_payments_payment_no",
|
||||
table: "tenant_invoice_payments",
|
||||
column: "payment_no",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_payments_received_by",
|
||||
table: "tenant_invoice_payments",
|
||||
column: "received_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_payments_tenant_id_invoice_id",
|
||||
table: "tenant_invoice_payments",
|
||||
columns: new[] { "tenant_id", "invoice_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_reminders_created_by",
|
||||
table: "tenant_invoice_reminders",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_reminders_invoice_id_reminder_date",
|
||||
table: "tenant_invoice_reminders",
|
||||
columns: new[] { "invoice_id", "reminder_date" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_reminders_tenant_id_invoice_id_reminder_type~",
|
||||
table: "tenant_invoice_reminders",
|
||||
columns: new[] { "tenant_id", "invoice_id", "reminder_type", "channel", "reminder_date" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoice_reminders_tenant_id_status_reminder_date",
|
||||
table: "tenant_invoice_reminders",
|
||||
columns: new[] { "tenant_id", "status", "reminder_date" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoices_created_by",
|
||||
table: "tenant_invoices",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoices_invoice_no",
|
||||
table: "tenant_invoices",
|
||||
column: "invoice_no",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoices_tenant_id_billing_period_start_billing_peri~",
|
||||
table: "tenant_invoices",
|
||||
columns: new[] { "tenant_id", "billing_period_start", "billing_period_end" },
|
||||
unique: true,
|
||||
filter: "invoice_type = 'usage_overage' and status <> 'void' and metadata->>'source' = 'usage_overage_auto'");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_invoices_tenant_id_status_due_date",
|
||||
table: "tenant_invoices",
|
||||
columns: new[] { "tenant_id", "status", "due_date" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "platform_audit_alerts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "platform_dunning_notification_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "platform_saas_plans");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_billing_profiles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_invoice_items");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_invoice_payments");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "platform_audit_alert_rules");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "platform_dunning_notification_channels");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_invoice_reminders");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_invoices");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPocketBaseImportAuditPersistence : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "pb_import_runs",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
source_name = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: false),
|
||||
source_kind = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
stats = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
started_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
finished_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_pb_import_runs", x => x.id);
|
||||
table.UniqueConstraint("ak_pb_import_runs_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_pb_import_runs_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "pb_import_issues",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
run_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
collection_name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
legacy_id = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
severity = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
issue_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
message = table.Column<string>(type: "text", nullable: false),
|
||||
field_path = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
raw_value_sample = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_pb_import_issues", x => x.id);
|
||||
table.UniqueConstraint("ak_pb_import_issues_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_pb_import_issues_pb_import_runs_tenant_id_run_id",
|
||||
columns: x => new { x.tenant_id, x.run_id },
|
||||
principalTable: "pb_import_runs",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_pb_import_issues_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "pb_raw_records",
|
||||
columns: table => new
|
||||
{
|
||||
run_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
collection_name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
legacy_id = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
record = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
normalized = table.Column<bool>(type: "boolean", nullable: false),
|
||||
errors = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'[]'::jsonb"),
|
||||
imported_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_pb_raw_records", x => new { x.run_id, x.collection_name, x.legacy_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_pb_raw_records_pb_import_runs_tenant_id_run_id",
|
||||
columns: x => new { x.tenant_id, x.run_id },
|
||||
principalTable: "pb_import_runs",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_pb_raw_records_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pb_import_issues_run_id_severity_collection_name",
|
||||
table: "pb_import_issues",
|
||||
columns: new[] { "run_id", "severity", "collection_name" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pb_import_issues_tenant_id_collection_name_legacy_id",
|
||||
table: "pb_import_issues",
|
||||
columns: new[] { "tenant_id", "collection_name", "legacy_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pb_import_issues_tenant_id_run_id",
|
||||
table: "pb_import_issues",
|
||||
columns: new[] { "tenant_id", "run_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pb_import_runs_tenant_id_status_started_at",
|
||||
table: "pb_import_runs",
|
||||
columns: new[] { "tenant_id", "status", "started_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pb_raw_records_tenant_id_collection_name_legacy_id",
|
||||
table: "pb_raw_records",
|
||||
columns: new[] { "tenant_id", "collection_name", "legacy_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pb_raw_records_tenant_id_run_id",
|
||||
table: "pb_raw_records",
|
||||
columns: new[] { "tenant_id", "run_id" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "pb_import_issues");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "pb_raw_records");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "pb_import_runs");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ using Tiku.Infrastructure.Persistence;
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(TikuDbContext))]
|
||||
[Migration("20260725220429_AddPocketBaseImportAuditPersistence")]
|
||||
partial class AddPocketBaseImportAuditPersistence
|
||||
[Migration("20260725220742_InitialSchema")]
|
||||
partial class InitialSchema
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user