Files
tgex-backend/migrations/models/0_20260102162851_init.py
Artem Tsyrulnikov 0577d2a00e change domen
2026-01-02 19:37:35 +03:00

336 lines
23 KiB
Python

from tortoise import BaseDBAsyncClient
RUN_IN_TRANSACTION = True
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
CREATE TABLE IF NOT EXISTS "channel"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"telegram_id" BIGINT NOT NULL UNIQUE,
"title" VARCHAR(255) NOT NULL,
"username" VARCHAR(255) NOT NULL UNIQUE,
"access_hash" BIGINT,
"pts" INT
);
CREATE INDEX IF NOT EXISTS "idx_channel_telegra_414c3b" ON "channel" ("telegram_id");
CREATE INDEX IF NOT EXISTS "idx_channel_usernam_7fd87a" ON "channel" ("username");
CREATE TABLE IF NOT EXISTS "post"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"message_id" INT NOT NULL,
"text" TEXT NOT NULL,
"deleted_from_channel_at" TIMESTAMPTZ,
"channel_id" UUID NOT NULL REFERENCES "channel" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_post_channel_0a2cba" UNIQUE ("channel_id", "message_id")
);
CREATE INDEX IF NOT EXISTS "idx_post_channel_197bed" ON "post" ("channel_id");
CREATE TABLE IF NOT EXISTS "post_views_history"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"views_count" INT NOT NULL,
"fetched_at" TIMESTAMPTZ NOT NULL,
"post_id" UUID NOT NULL REFERENCES "post" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_post_views__post_id_c6cc9f" UNIQUE ("post_id", "fetched_at")
);
CREATE INDEX IF NOT EXISTS "idx_post_views__fetched_103eb5" ON "post_views_history" ("fetched_at");
CREATE INDEX IF NOT EXISTS "idx_post_views__post_id_dfb1ca" ON "post_views_history" ("post_id");
CREATE TABLE IF NOT EXISTS "user"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"telegram_id" BIGINT NOT NULL UNIQUE,
"username" VARCHAR(255),
"first_name" VARCHAR(255),
"last_name" VARCHAR(255)
);
CREATE INDEX IF NOT EXISTS "idx_user_telegra_66ffbd" ON "user" ("telegram_id");
CREATE TABLE IF NOT EXISTS "login_token"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"token" VARCHAR(255) NOT NULL UNIQUE,
"expires_at" TIMESTAMPTZ NOT NULL,
"used_at" TIMESTAMPTZ,
"user_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "idx_login_token_token_2582d2" ON "login_token" ("token");
CREATE INDEX IF NOT EXISTS "idx_login_token_user_id_c85d7c" ON "login_token" ("user_id");
CREATE TABLE IF NOT EXISTS "workspace"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"name" VARCHAR(255) NOT NULL
);
CREATE TABLE IF NOT EXISTS "project"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"status" VARCHAR(8) NOT NULL DEFAULT 'active',
"purchase_invite_type_default" VARCHAR(10) NOT NULL DEFAULT 'approval',
"channel_id" UUID NOT NULL REFERENCES "channel" ("id") ON DELETE CASCADE,
"workspace_id" UUID NOT NULL REFERENCES "workspace" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_project_workspa_2f80f2" UNIQUE ("workspace_id", "channel_id")
);
CREATE INDEX IF NOT EXISTS "idx_project_channel_ce2466" ON "project" ("channel_id");
CREATE INDEX IF NOT EXISTS "idx_project_workspa_2354fd" ON "project" ("workspace_id");
COMMENT ON COLUMN "project"."status" IS 'ACTIVE: active\nINACTIVE: inactive\nARCHIVED: archived';
COMMENT ON COLUMN "project"."purchase_invite_type_default" IS 'PUBLIC: public\nAPPROVAL: approval';
CREATE TABLE IF NOT EXISTS "creative"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"name" VARCHAR(255) NOT NULL,
"text" TEXT NOT NULL,
"status" VARCHAR(8) NOT NULL DEFAULT 'active',
"project_id" UUID NOT NULL REFERENCES "project" ("id") ON DELETE CASCADE,
"workspace_id" UUID NOT NULL REFERENCES "workspace" ("id") ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "idx_creative_project_0766a6" ON "creative" ("project_id");
CREATE INDEX IF NOT EXISTS "idx_creative_workspa_2de546" ON "creative" ("workspace_id");
COMMENT ON COLUMN "creative"."status" IS 'ACTIVE: active\nARCHIVED: archived';
CREATE TABLE IF NOT EXISTS "purchase"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"status" VARCHAR(8) NOT NULL DEFAULT 'active',
"creative_id" UUID NOT NULL REFERENCES "creative" ("id") ON DELETE CASCADE,
"project_id" UUID NOT NULL REFERENCES "project" ("id") ON DELETE CASCADE,
"workspace_id" UUID NOT NULL REFERENCES "workspace" ("id") ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "idx_purchase_creativ_6829cd" ON "purchase" ("creative_id");
CREATE INDEX IF NOT EXISTS "idx_purchase_project_95b1c2" ON "purchase" ("project_id");
CREATE INDEX IF NOT EXISTS "idx_purchase_workspa_8784a5" ON "purchase" ("workspace_id");
CREATE INDEX IF NOT EXISTS "idx_purchase_project_dee224" ON "purchase" ("project_id", "status");
COMMENT ON COLUMN "purchase"."status" IS 'ACTIVE: active\nARCHIVED: archived';
CREATE TABLE IF NOT EXISTS "purchase_channel"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"status" VARCHAR(11) NOT NULL DEFAULT 'planned',
"planned_cost" DOUBLE PRECISION,
"comment" TEXT,
"invite_link" VARCHAR(512) NOT NULL,
"invite_link_type" VARCHAR(8) NOT NULL,
"channel_id" UUID NOT NULL REFERENCES "channel" ("id") ON DELETE CASCADE,
"purchase_id" UUID NOT NULL REFERENCES "purchase" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_purchase_ch_purchas_f7c86e" UNIQUE ("purchase_id", "channel_id")
);
CREATE INDEX IF NOT EXISTS "idx_purchase_ch_channel_2b1264" ON "purchase_channel" ("channel_id");
CREATE INDEX IF NOT EXISTS "idx_purchase_ch_purchas_1fe84a" ON "purchase_channel" ("purchase_id");
COMMENT ON COLUMN "purchase_channel"."status" IS 'PLANNED: planned\nAPPROVED: approved\nREJECTED: rejected\nIN_PROGRESS: in_progress\nCOMPLETED: completed';
COMMENT ON COLUMN "purchase_channel"."invite_link_type" IS 'PUBLIC: public\nAPPROVAL: approval';
CREATE TABLE IF NOT EXISTS "placement"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"wanted_placement_date" TIMESTAMPTZ NOT NULL,
"cost" DOUBLE PRECISION,
"comment" TEXT,
"invite_link" VARCHAR(512) NOT NULL,
"status" VARCHAR(8) NOT NULL DEFAULT 'active',
"creative_id" UUID NOT NULL REFERENCES "creative" ("id") ON DELETE CASCADE,
"placement_channel_id" UUID NOT NULL REFERENCES "channel" ("id") ON DELETE CASCADE,
"post_id" UUID REFERENCES "post" ("id") ON DELETE SET NULL,
"project_id" UUID NOT NULL REFERENCES "project" ("id") ON DELETE CASCADE,
"purchase_id" UUID REFERENCES "purchase" ("id") ON DELETE CASCADE,
"purchase_channel_id" UUID REFERENCES "purchase_channel" ("id") ON DELETE CASCADE,
"workspace_id" UUID NOT NULL REFERENCES "workspace" ("id") ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "idx_placement_creativ_32111d" ON "placement" ("creative_id");
CREATE INDEX IF NOT EXISTS "idx_placement_placeme_20cf53" ON "placement" ("placement_channel_id");
CREATE INDEX IF NOT EXISTS "idx_placement_post_id_e4a16e" ON "placement" ("post_id");
CREATE INDEX IF NOT EXISTS "idx_placement_project_2c6aa4" ON "placement" ("project_id");
CREATE INDEX IF NOT EXISTS "idx_placement_purchas_3e3775" ON "placement" ("purchase_id");
CREATE INDEX IF NOT EXISTS "idx_placement_purchas_61f9e6" ON "placement" ("purchase_channel_id");
CREATE INDEX IF NOT EXISTS "idx_placement_workspa_632b20" ON "placement" ("workspace_id");
COMMENT ON COLUMN "placement"."status" IS 'ACTIVE: active\nARCHIVED: archived';
CREATE TABLE IF NOT EXISTS "subscription"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"invite_link" VARCHAR(512) NOT NULL,
"status" VARCHAR(12) NOT NULL DEFAULT 'active',
"unsubscribed_at" TIMESTAMPTZ,
"placement_id" UUID NOT NULL REFERENCES "placement" ("id") ON DELETE CASCADE,
"subscriber_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_subscriptio_placeme_8fcb8f" UNIQUE ("placement_id", "subscriber_id")
);
CREATE INDEX IF NOT EXISTS "idx_subscriptio_invite__f2058d" ON "subscription" ("invite_link");
CREATE INDEX IF NOT EXISTS "idx_subscriptio_placeme_5decb2" ON "subscription" ("placement_id");
CREATE INDEX IF NOT EXISTS "idx_subscriptio_subscri_e75729" ON "subscription" ("subscriber_id");
COMMENT ON COLUMN "subscription"."status" IS 'ACTIVE: active\nUNSUBSCRIBED: unsubscribed';
CREATE TABLE IF NOT EXISTS "workspace_invite"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"status" VARCHAR(8) NOT NULL DEFAULT 'pending',
"invited_by_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE,
"user_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE,
"workspace_id" UUID NOT NULL REFERENCES "workspace" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_workspace_i_workspa_abd9c4" UNIQUE ("workspace_id", "user_id")
);
CREATE INDEX IF NOT EXISTS "idx_workspace_i_invited_3ed9f8" ON "workspace_invite" ("invited_by_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_i_user_id_a96e1e" ON "workspace_invite" ("user_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_i_workspa_71e9d2" ON "workspace_invite" ("workspace_id");
COMMENT ON COLUMN "workspace_invite"."status" IS 'PENDING: pending\nACCEPTED: accepted\nREVOKED: revoked';
CREATE TABLE IF NOT EXISTS "workspace_user"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"status" VARCHAR(7) NOT NULL DEFAULT 'active',
"user_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE,
"workspace_id" UUID NOT NULL REFERENCES "workspace" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_workspace_u_workspa_13c46c" UNIQUE ("workspace_id", "user_id")
);
CREATE INDEX IF NOT EXISTS "idx_workspace_u_user_id_246318" ON "workspace_user" ("user_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_u_workspa_a403b0" ON "workspace_user" ("workspace_id");
COMMENT ON COLUMN "workspace_user"."status" IS 'ACTIVE: active\nINVITED: invited\nBLOCKED: blocked';
CREATE TABLE IF NOT EXISTS "workspace_user_permission"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"permission" VARCHAR(24) NOT NULL,
"workspace_user_id" UUID NOT NULL REFERENCES "workspace_user" ("id") ON DELETE CASCADE,
CONSTRAINT "uid_workspace_u_workspa_86f574" UNIQUE ("workspace_user_id", "permission")
);
CREATE INDEX IF NOT EXISTS "idx_workspace_u_workspa_b9b7b0" ON "workspace_user_permission" ("workspace_user_id");
COMMENT ON COLUMN "workspace_user_permission"."permission" IS 'ADMIN_FULL: admin_full\nPROJECTS_READ: projects_read\nPROJECTS_WRITE: projects_write\nCREATIVES_READ: creatives_read\nCREATIVES_WRITE: creatives_write\nPLACEMENTS_READ: placements_read\nPLACEMENTS_WRITE: placements_write\nANALYTICS_READ: analytics_read\nANALYTICS_WITHOUT_CLICKS: analytics_without_clicks\nCHANNELS_READ: channels_read\nCHANNELS_WRITE: channels_write';
CREATE TABLE IF NOT EXISTS "workspace_user_permission_scope"
(
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMPTZ,
"permission" VARCHAR(24) NOT NULL,
"channel_id" UUID REFERENCES "channel" ("id") ON DELETE CASCADE,
"creative_id" UUID REFERENCES "creative" ("id") ON DELETE CASCADE,
"placement_id" UUID REFERENCES "placement" ("id") ON DELETE CASCADE,
"project_id" UUID REFERENCES "project" ("id") ON DELETE CASCADE,
"workspace_user_id" UUID NOT NULL REFERENCES "workspace_user" ("id") ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "idx_workspace_u_channel_d94b48" ON "workspace_user_permission_scope" ("channel_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_u_creativ_8da562" ON "workspace_user_permission_scope" ("creative_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_u_placeme_ea1846" ON "workspace_user_permission_scope" ("placement_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_u_project_bd7fea" ON "workspace_user_permission_scope" ("project_id");
CREATE INDEX IF NOT EXISTS "idx_workspace_u_workspa_82a35a" ON "workspace_user_permission_scope" ("workspace_user_id");
COMMENT ON COLUMN "workspace_user_permission_scope"."permission" IS 'ADMIN_FULL: admin_full\nPROJECTS_READ: projects_read\nPROJECTS_WRITE: projects_write\nCREATIVES_READ: creatives_read\nCREATIVES_WRITE: creatives_write\nPLACEMENTS_READ: placements_read\nPLACEMENTS_WRITE: placements_write\nANALYTICS_READ: analytics_read\nANALYTICS_WITHOUT_CLICKS: analytics_without_clicks\nCHANNELS_READ: channels_read\nCHANNELS_WRITE: channels_write';
CREATE TABLE IF NOT EXISTS "aerich"
(
"id" SERIAL NOT NULL PRIMARY KEY,
"version" VARCHAR(255) NOT NULL,
"app" VARCHAR(100) NOT NULL,
"content" JSONB NOT NULL
);"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
"""
MODELS_STATE = (
'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'
)