-- CreateEnum CREATE TYPE "tenant_subscription_status" AS ENUM ('TRIALING', 'ACTIVE', 'PAST_DUE', 'CANCELED'); -- CreateEnum CREATE TYPE "price_item_type" AS ENUM ('BASE_SUBSCRIPTION', 'EXTENSION_MONTH', 'AGENT_MONTH', 'TRUNK_MONTH', 'CALL', 'CALL_MINUTE', 'FIXED_MINUTE', 'MOBILE_MINUTE', 'INTERNATIONAL_MINUTE', 'AI_TRANSCRIPTION_MINUTE', 'AI_ANALYSIS_CALL', 'AI_INPUT_TOKEN', 'AI_OUTPUT_TOKEN', 'RECORDING_GB_MONTH'); -- CreateEnum CREATE TYPE "destination_type" AS ENUM ('FIXED', 'MOBILE', 'INTERNATIONAL'); -- CreateEnum CREATE TYPE "usage_meter" AS ENUM ('CALL_COUNT', 'CALL_SECONDS', 'EXTENSION_ACTIVE_DAY', 'AGENT_ACTIVE_DAY', 'TRUNK_ACTIVE_DAY', 'RECORDING_BYTES', 'AI_TRANSCRIPTION_SECONDS', 'AI_ANALYSIS_REQUEST', 'AI_INPUT_TOKENS', 'AI_OUTPUT_TOKENS'); -- CreateEnum CREATE TYPE "billing_period_status" AS ENUM ('OPEN', 'CALCULATING', 'READY', 'CLOSED', 'REOPENED'); -- CreateEnum CREATE TYPE "billing_statement_category" AS ENUM ('PLAN_BASE', 'EXTENSIONS', 'AGENTS', 'TRUNKS', 'CALLS', 'MINUTES', 'AI_TRANSCRIPTION', 'AI_ANALYSIS', 'AI_TOKENS', 'STORAGE', 'ADJUSTMENT'); -- AlterTable ALTER TABLE "calls" ADD COLUMN "billing_increment_seconds" INTEGER, ADD COLUMN "destination_rate" DOUBLE PRECISION, ADD COLUMN "rated_amount" DOUBLE PRECISION, ADD COLUMN "rated_minutes" DOUBLE PRECISION; -- AlterTable ALTER TABLE "tenants" ADD COLUMN "price_book_id" UUID, ADD COLUMN "rate_deck_id" UUID; -- CreateTable CREATE TABLE "plan_versions" ( "id" UUID NOT NULL, "plan_id" UUID NOT NULL, "version" INTEGER NOT NULL, "base_price" DOUBLE PRECISION NOT NULL, "currency" TEXT NOT NULL DEFAULT 'BRL', "effective_from" TIMESTAMP(3) NOT NULL, "effective_until" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "plan_versions_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "tenant_subscriptions" ( "id" UUID NOT NULL, "tenant_id" UUID NOT NULL, "plan_version_id" UUID NOT NULL, "status" "tenant_subscription_status" NOT NULL DEFAULT 'ACTIVE', "started_at" TIMESTAMP(3) NOT NULL, "ends_at" TIMESTAMP(3), "billing_cycle_anchor" INTEGER NOT NULL, "currency" TEXT NOT NULL DEFAULT 'BRL', "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "tenant_subscriptions_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "price_books" ( "id" UUID NOT NULL, "name" TEXT NOT NULL, "currency" TEXT NOT NULL DEFAULT 'BRL', "is_default" BOOLEAN NOT NULL DEFAULT false, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "price_books_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "price_book_items" ( "id" UUID NOT NULL, "price_book_id" UUID NOT NULL, "type" "price_item_type" NOT NULL, "unit_price" DOUBLE PRECISION NOT NULL, "effective_from" TIMESTAMP(3) NOT NULL, "effective_until" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "price_book_items_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "rate_decks" ( "id" UUID NOT NULL, "name" TEXT NOT NULL, "is_default" BOOLEAN NOT NULL DEFAULT false, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "rate_decks_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "rate_deck_entries" ( "id" UUID NOT NULL, "rate_deck_id" UUID NOT NULL, "prefix" TEXT NOT NULL, "destination_name" TEXT NOT NULL, "destination_type" "destination_type" NOT NULL, "price_per_minute" DOUBLE PRECISION NOT NULL, "billing_increment_seconds" INTEGER NOT NULL DEFAULT 60, "minimum_seconds" INTEGER NOT NULL DEFAULT 0, "connection_fee" DOUBLE PRECISION NOT NULL DEFAULT 0, "valid_from" TIMESTAMP(3) NOT NULL, "valid_until" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "rate_deck_entries_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "usage_events" ( "id" UUID NOT NULL, "tenant_id" UUID NOT NULL, "call_id" UUID, "meter" "usage_meter" NOT NULL, "quantity" DOUBLE PRECISION NOT NULL, "unit" TEXT NOT NULL, "source_type" TEXT NOT NULL, "source_id" TEXT, "occurred_at" TIMESTAMP(3) NOT NULL, "metadata" JSONB, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "usage_events_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "rated_usage_items" ( "id" UUID NOT NULL, "tenant_id" UUID NOT NULL, "usage_event_id" UUID, "ai_usage_record_id" UUID, "call_id" UUID, "price_book_item_id" UUID, "rate_deck_entry_id" UUID, "quantity" DOUBLE PRECISION NOT NULL, "unit_price" DOUBLE PRECISION NOT NULL, "amount" DOUBLE PRECISION NOT NULL, "currency" TEXT NOT NULL DEFAULT 'BRL', "billing_period_id" UUID, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "rated_usage_items_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "billing_periods" ( "id" UUID NOT NULL, "tenant_id" UUID NOT NULL, "period_start" TIMESTAMP(3) NOT NULL, "period_end" TIMESTAMP(3) NOT NULL, "status" "billing_period_status" NOT NULL DEFAULT 'OPEN', "closed_at" TIMESTAMP(3), "reopened_at" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "billing_periods_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "billing_statements" ( "id" UUID NOT NULL, "tenant_id" UUID NOT NULL, "billing_period_id" UUID NOT NULL, "currency" TEXT NOT NULL DEFAULT 'BRL', "subtotal" DOUBLE PRECISION NOT NULL, "adjustments" DOUBLE PRECISION NOT NULL DEFAULT 0, "total" DOUBLE PRECISION NOT NULL, "generated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "billing_statements_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "billing_statement_items" ( "id" UUID NOT NULL, "tenant_id" UUID NOT NULL, "billing_statement_id" UUID NOT NULL, "category" "billing_statement_category" NOT NULL, "description" TEXT NOT NULL, "quantity" DOUBLE PRECISION, "unit_price" DOUBLE PRECISION, "amount" DOUBLE PRECISION NOT NULL, CONSTRAINT "billing_statement_items_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE UNIQUE INDEX "plan_versions_plan_id_version_key" ON "plan_versions"("plan_id", "version"); -- CreateIndex CREATE INDEX "tenant_subscriptions_tenant_id_status_idx" ON "tenant_subscriptions"("tenant_id", "status"); -- CreateIndex CREATE INDEX "price_book_items_price_book_id_type_effective_from_idx" ON "price_book_items"("price_book_id", "type", "effective_from"); -- CreateIndex CREATE INDEX "rate_deck_entries_rate_deck_id_valid_from_idx" ON "rate_deck_entries"("rate_deck_id", "valid_from"); -- CreateIndex CREATE INDEX "usage_events_tenant_id_occurred_at_idx" ON "usage_events"("tenant_id", "occurred_at"); -- CreateIndex CREATE INDEX "usage_events_tenant_id_meter_idx" ON "usage_events"("tenant_id", "meter"); -- CreateIndex CREATE INDEX "rated_usage_items_tenant_id_billing_period_id_idx" ON "rated_usage_items"("tenant_id", "billing_period_id"); -- CreateIndex CREATE INDEX "billing_periods_tenant_id_status_idx" ON "billing_periods"("tenant_id", "status"); -- CreateIndex CREATE UNIQUE INDEX "billing_periods_tenant_id_period_start_period_end_key" ON "billing_periods"("tenant_id", "period_start", "period_end"); -- CreateIndex CREATE INDEX "billing_statements_tenant_id_billing_period_id_idx" ON "billing_statements"("tenant_id", "billing_period_id"); -- CreateIndex CREATE INDEX "billing_statement_items_billing_statement_id_idx" ON "billing_statement_items"("billing_statement_id"); -- AddForeignKey ALTER TABLE "tenants" ADD CONSTRAINT "tenants_price_book_id_fkey" FOREIGN KEY ("price_book_id") REFERENCES "price_books"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "tenants" ADD CONSTRAINT "tenants_rate_deck_id_fkey" FOREIGN KEY ("rate_deck_id") REFERENCES "rate_decks"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "plan_versions" ADD CONSTRAINT "plan_versions_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "plans"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "tenant_subscriptions" ADD CONSTRAINT "tenant_subscriptions_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "tenant_subscriptions" ADD CONSTRAINT "tenant_subscriptions_plan_version_id_fkey" FOREIGN KEY ("plan_version_id") REFERENCES "plan_versions"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "price_book_items" ADD CONSTRAINT "price_book_items_price_book_id_fkey" FOREIGN KEY ("price_book_id") REFERENCES "price_books"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rate_deck_entries" ADD CONSTRAINT "rate_deck_entries_rate_deck_id_fkey" FOREIGN KEY ("rate_deck_id") REFERENCES "rate_decks"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "usage_events" ADD CONSTRAINT "usage_events_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "usage_events" ADD CONSTRAINT "usage_events_call_id_fkey" FOREIGN KEY ("call_id") REFERENCES "calls"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_usage_event_id_fkey" FOREIGN KEY ("usage_event_id") REFERENCES "usage_events"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_ai_usage_record_id_fkey" FOREIGN KEY ("ai_usage_record_id") REFERENCES "ai_usage_records"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_call_id_fkey" FOREIGN KEY ("call_id") REFERENCES "calls"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_price_book_item_id_fkey" FOREIGN KEY ("price_book_item_id") REFERENCES "price_book_items"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_rate_deck_entry_id_fkey" FOREIGN KEY ("rate_deck_entry_id") REFERENCES "rate_deck_entries"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "rated_usage_items" ADD CONSTRAINT "rated_usage_items_billing_period_id_fkey" FOREIGN KEY ("billing_period_id") REFERENCES "billing_periods"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "billing_periods" ADD CONSTRAINT "billing_periods_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "billing_statements" ADD CONSTRAINT "billing_statements_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "billing_statements" ADD CONSTRAINT "billing_statements_billing_period_id_fkey" FOREIGN KEY ("billing_period_id") REFERENCES "billing_periods"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "billing_statement_items" ADD CONSTRAINT "billing_statement_items_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "billing_statement_items" ADD CONSTRAINT "billing_statement_items_billing_statement_id_fkey" FOREIGN KEY ("billing_statement_id") REFERENCES "billing_statements"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- RLS (agente.md secao 233, docs/TENANT_ISOLATION.md) — mesmo padrao do -- resto do sistema: FORCE ROW LEVEL SECURITY + policy unica baseada em -- app.current_tenant_id. price_books/price_book_items/rate_decks/ -- rate_deck_entries/plan_versions NAO tem RLS (catalogos globais da -- plataforma, sem tenant_id, mesmo padrao ja usado por "plans"). ALTER TABLE "tenant_subscriptions" ENABLE ROW LEVEL SECURITY; ALTER TABLE "tenant_subscriptions" FORCE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation" ON "tenant_subscriptions" USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid); ALTER TABLE "usage_events" ENABLE ROW LEVEL SECURITY; ALTER TABLE "usage_events" FORCE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation" ON "usage_events" USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid); ALTER TABLE "rated_usage_items" ENABLE ROW LEVEL SECURITY; ALTER TABLE "rated_usage_items" FORCE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation" ON "rated_usage_items" USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid); ALTER TABLE "billing_periods" ENABLE ROW LEVEL SECURITY; ALTER TABLE "billing_periods" FORCE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation" ON "billing_periods" USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid); ALTER TABLE "billing_statements" ENABLE ROW LEVEL SECURITY; ALTER TABLE "billing_statements" FORCE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation" ON "billing_statements" USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid); ALTER TABLE "billing_statement_items" ENABLE ROW LEVEL SECURITY; ALTER TABLE "billing_statement_items" FORCE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation" ON "billing_statement_items" USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid);