TorbatYar/docs/database_schema.md
Mortezakoohjani 800b0ba2c5 Deploy TorbatYar for torbatyar.ir with nginx multi-tenant routing.
Wire production domain, CORS for tenant subdomains, celery volume mounts, and nginx reverse proxy configs for apex, API, identity, auth, and wildcard tenants.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 21:43:33 +03:30

12 KiB
Raw Blame History

طرح دیتابیس (Database Schema)

بخش ۱ — دیتابیس Core Platform (core_platform_db) — فاز ۱

همه مدل‌ها با SQLAlchemy 2.x و Alembic پیاده شده‌اند. شناسه‌ها از نوع UUID و زمان‌ها timezone-aware هستند.

جدول tenants

ستون نوع توضیح
id UUID (PK)
name varchar(255) نام مستأجر (business_name در onboarding)
slug varchar(100) unique شناسه یکتا برای resolve
status enum draft / pending_activation / active / suspended / archived (+ مقادیر قدیمی inactive/deleted برای سازگاری)
owner_user_id UUID null مالک (از Identity Service)
business_type varchar(100) null نوع کسب‌وکار (فاز ۴ — onboarding)
default_locale varchar(20) پیش‌فرض fa-IR
timezone varchar(50) پیش‌فرض Asia/Tehran
primary_color varchar(20) null برندینگ
secondary_color varchar(20) null برندینگ
logo_url varchar(500) null برندینگ
favicon_url varchar(500) null برندینگ
onboarding_completed bool پیش‌فرض false؛ با POST .../complete به true تغییر می‌کند
created_at, updated_at timestamptz

ایندکس‌ها: slug (unique)، status.

فیلدهای business_type تا onboarding_completed در migration 0005_tenant_onboarding اضافه شده‌اند (فاز ۴ — Tenant Onboarding).

جدول domains

ستون نوع توضیح
id UUID (PK)
tenant_id UUID (FK→tenants)
domain varchar(255) unique
domain_type enum subdomain / custom_domain
is_verified bool
verified_at timestamptz null
is_primary bool دامنهٔ اصلی/پیش‌فرض tenant (زیردامنهٔ خودکار onboarding) — فاز ۴
verification_status enum pending / verified / failed — فاز ۴
created_at timestamptz

ایندکس‌ها: domain (unique)، tenant_id.

جدول plans

id, code(unique), name, description, is_active, created_at. ایندکس: code.

جدول features

id, feature_key(unique), name, description, service_key, is_active. ایندکس‌ها: feature_key (unique)، service_key. مثال feature_key: accounting.invoice.create، crm.lead.create، ecommerce.product.create، live_chat.widget.enable، ai_assistant.chat.reply.

جدول plan_features

id, plan_id(FK), feature_id(FK), limit_value(null=نامحدود), limit_period(enum: day/month/year/total), is_enabled. محدودیت یکتا: (plan_id, feature_id). ایندکس‌ها روی هر دو کلید خارجی.

جدول tenant_subscriptions

id, tenant_id(FK), plan_id(FK), status(enum: trialing/active/past_due/ canceled/expired), starts_at, ends_at, trial_ends_at, created_at. ایندکس‌ها: tenant_id، status.

جدول tenant_feature_access

override سفارشی دسترسی: id, tenant_id(FK), feature_id(FK), is_enabled, custom_limit_value(null=نامحدود), used_value, reset_at. محدودیت یکتا: (tenant_id, feature_id). ایندکس‌ها روی هر دو کلید خارجی.

جدول service_registry

id, service_key(unique), name, base_url, status(enum), health_check_url, created_at. ایندکس: service_key.

جدول module_registry

id, module_key(unique), name, description, is_system_module, is_active. ایندکس: module_key.

جدول tenant_module_access

id, tenant_id(FK), module_id(FK), is_enabled, enabled_at, disabled_at. محدودیت یکتا: (tenant_id, module_id). ایندکس: tenant_id.

جدول internal_service_tokens

id, service_key, token_hash(unique), scopes, expires_at, is_active, created_at. فقط hash توکن ذخیره می‌شود. ایندکس‌ها: service_key، token_hash.

جدول outbox_events

id, event_type, aggregate_type, aggregate_id, tenant_id, payload(JSON), status(enum: pending/processed/failed), retry_count, created_at, processed_at. ایندکس‌ها: status، tenant_id.

جدول inbox_events

id, event_id(unique), source_service, event_type, tenant_id, payload(JSON), processed_at. ایندکس‌ها: event_id، tenant_id.

جدول audit_logs

id, tenant_id, actor_user_id, action, resource_type, resource_id, metadata(JSON), ip_address, user_agent, created_at. ایندکس‌ها: tenant_id، created_at.

جدول users (OTP + لینک SSO — فاز ۳)

ستون نوع توضیح
id UUID (PK)
mobile varchar(15) unique شماره موبایل (09xxxxxxxxx) — الزامی
keycloak_sub varchar(100) null unique لینک به کاربر Keycloak (SSO)
email varchar(255) null ایمیل (اختیاری، برای لینک SSO)
mobile_verified bool تأیید OTP — true پس از verify موفق
role enum user / pending_tenant_admin / tenant_admin / platform_admin
status enum active / inactive / suspended
current_tenant_id UUID null (FK→tenants, ON DELETE SET NULL) tenant انتخاب‌شده جاری کاربر — فاز ۴
created_at, updated_at timestamptz

ایندکس‌ها: mobile (unique)، keycloak_sub (unique)، status.

نقش‌ها بر اساس context OTP:

  • publicuser (ثبت‌نام عمومی)
  • adminpending_tenant_admin (پنل ادمین tenant)
  • PLATFORM_ADMIN_MOBILESplatform_admin

جدول tenant_memberships (فاز ۴ — Tenant Onboarding)

توجه: این جدول در core_platform_db است و با جدول هم‌نام در identity_access_db (بخش ۳ همین سند) کاملاً متفاوت و بدون ارتباط مستقیم است. جدول Core عضویت واقعی کاربر↔workspace را برای جریان onboarding/authorization مدیریت می‌کند.

ستون نوع توضیح
id UUID (PK)
tenant_id UUID (FK→tenants, cascade)
user_id UUID (FK→users, cascade)
role enum platform_admin / tenant_owner / tenant_admin / tenant_editor / tenant_viewer
status enum active / invited / disabled
is_owner bool فقط یک یا چند owner فعال در هر tenant (حداقل یکی الزامی)
created_at, updated_at timestamptz

محدودیت یکتا: (tenant_id, user_id). ایندکس‌ها: tenant_id، user_id، role، status.

قواعد:

  • هنگام POST /onboarding/tenant، کاربر سازنده به‌صورت خودکار عضویت tenant_owner / is_owner=true / status=active می‌گیرد.
  • POST /onboarding/tenant/{id}/complete بررسی می‌کند که حداقل یک owner فعال وجود داشته باشد؛ در غیر این صورت خطای owner_required.
  • کاربر می‌تواند در آینده چند عضویت (چند tenant) داشته باشد؛ users.current_tenant_id مشخص می‌کند کدام‌یک «جاری» است.

جدول plans و tenant_subscriptions (seed پیش‌فرض — فاز ۴)

ساختار جدول‌ها از فاز ۱ بدون تغییر باقی مانده (نگاه کنید به پایین همین بخش)؛ در فاز ۴ موارد زیر اضافه شد:

  • Migration 0005_tenant_onboarding دو پلن FREE و STARTER را با ON CONFLICT (code) DO NOTHING seed می‌کند (idempotent).
  • PlanService.ensure_default_plan() همان پلن FREE را در زمان اجرا نیز به‌صورت idempotent تضمین می‌کند (برای محیط‌های SQLite تست که migration اجرا نمی‌شود).
  • POST /onboarding/tenant به‌صورت خودکار یک tenant_subscriptions با plan=FREE، status=active می‌سازد.

بخش ۲ — طراحی اولیه دیتابیس سرویس‌های آینده (بدون migration)

این‌ها فقط طراحی مفهومی‌اند؛ در فازهای بعدی هر سرویس دیتابیس مستقل خود را با ستون tenant_id در جداول بیزینسی خواهد داشت.

  • accounting_db: accounts (۴ سطحی)، journal_entries، journal_lines، cost_centers، projects، invoices، payments، taxes، reports.
  • crm_db: customers، leads، opportunities، pipelines، stages، tasks، activities، automations.
  • ecommerce_db: products، categories، inventory، orders، order_items، payments، shipments، discounts، carts.
  • website_builder_db: sites، pages، blocks، forms، menus، media، content.
  • live_chat_db: widgets، conversations، messages، agents، routing_rules.
  • ai_assistant_db: assistants، knowledge_bases، documents، chat_sessions، messages، handoffs.
  • smart_messenger_db: channels، accounts، threads، messages، automations.
  • sms_panel_db: providers، templates، campaigns، messages، send_queue.
  • link_shortener_db: links، domains، clicks، campaigns.
  • notification_db: notifications، channels، templates، delivery_logs.
  • file_storage_db: files، buckets، access_policies.
  • restaurant_db: menus، menu_items، tables، orders، kitchen_tickets، payments، loyalty.

هر سرویس دسترسی قابلیت‌ها را از Core (check_feature_access) استعلام می‌کند و هرگز مستقیماً به core_platform_db متصل نمی‌شود.

بخش ۳ — دیتابیس Identity & Access (identity_access_db) — فاز ۲

جدول user_profiles

ستون نوع توضیح
id UUID (PK)
keycloak_sub varchar unique شناسه کاربر در Keycloak
email varchar
username varchar null
display_name varchar null
mobile varchar(15) null unique شماره موبایل — الزامی برای کاربران جدید
mobile_verified bool تأیید OTP
mobile_verified_at timestamptz null زمان تأیید
core_user_id UUID null لینک به core_platform_db.users
status enum active / inactive / suspended
created_at, updated_at timestamptz

ایندکس‌ها: keycloak_sub (unique)، email، mobile (unique).

قانون: کاربر تازه‌ثبت‌نام‌شده تا پیش از mobile_verified=true کامل محسوب نمی‌شود. کاربران SSO قدیمی بدون موبایل باید از /auth/verify-mobile تکمیل کنند.

جدول tenant_memberships

توجه: این جدول مربوط به identity_access_db (لایهٔ هویت SSO) است و جدول متفاوتی نسبت به tenant_memberships در core_platform_db است که در بخش ۱ (فاز ۴ — Tenant Onboarding) مستند شده. این دو جدول در دو سرویس/ دیتابیس جدا زندگی می‌کنند و sync خودکار بین آن‌ها وجود ندارد؛ منبع حقیقت (source of truth) برای نقش عملیاتی کاربر در یک workspace، جدول Core است.

ستون نوع توضیح
id UUID (PK)
tenant_id UUID مرجع به tenant در Core (بدون FK بین DB)
user_id UUID (FK→user_profiles)
role enum tenant_admin / tenant_member
is_active bool
joined_at timestamptz

محدودیت یکتا: (tenant_id, user_id). ایندکس‌ها: tenant_id, user_id.