TorbatYar/docs/reference/database-schema.md
Mortezakoohjani e41ecfad4c Sync platform docs, infra, and module services with Accounting integration.
Include Loyalty/Communication/Sports Center backends and registry updates alongside production nginx and compose wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 22:35:23 +03:30

292 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# طرح دیتابیس (Database Schema)
> Reference only. Architecture rules → [database-architecture.md](../architecture/database-architecture.md).
> Dual memberships → [ADR-007](../architecture/adr/ADR-007.md) · [Glossary](../glossary.md).
## بخش ۱ — دیتابیس 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:**
- `public``user` (ثبت‌نام عمومی)
- `admin``pending_tenant_admin` (پنل ادمین tenant)
- `PLATFORM_ADMIN_MOBILES``platform_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` می‌سازد.
## بخش ۴ — دیتابیس Accounting (`accounting_db`) — فاز ۵.۱ تا ۵
Migration: `0001_initial` در `backend/services/accounting/alembic/versions/`.
### Foundation (5.1)
`chart_of_accounts`, `accounts`, `currencies`, `exchange_rates`, `fiscal_years`,
`fiscal_periods`, `cost_centers`, `projects`, `dimensions`, `accounting_settings`,
`document_number_sequences`, `tenant_accounting_configurations`
### Posting (5.2)
`vouchers`, `voucher_lines`, `journals`, `journal_entries`, `posting_logs`,
`posting_errors`, `posting_references`, `accounting_audit_logs`
### Ledger (5.3)
`general_ledgers`, `ledger_balances`, `trial_balance_snapshots`, `balance_snapshots`,
`closing_entries`, `opening_entries`, `accounting_calendars`
### Treasury (5.4)
`cash_boxes`, `cash_transactions`, `banks`, `bank_accounts`, `bank_transactions`,
`cheque_books`, `cheques`, `transfers`, `receipt_vouchers`, `payment_vouchers`,
`reconciliations`, `treasury_settings`
### AR/AP (5.5)
`customer_accounts`, `supplier_accounts`, `receivable_invoices`, `payable_invoices`,
`settlements`, `settlement_allocations`, `credit_notes`, `debit_notes`,
`advance_payments`, `advance_receipts`, `customer_statements`, `supplier_statements`,
`aging_snapshots`
### Sales Accounting (5.6)
`sales_posting_profiles`, `accounting_profiles`, `posting_rules`,
`sales_accounting_configurations`, `revenue_recognitions`, `revenue_schedules`,
`accounting_previews`, `posting_simulations`
### Purchase/Inventory (5.7)
`purchase_posting_profiles`, `inventory_posting_profiles`, `inventory_valuation_methods`,
`inventory_valuation_history`, `inventory_cost_adjustments`, `purchase_accounting_configurations`,
`inventory_accounting_configurations`, `inventory_snapshots`
### Fixed Assets (5.8)
`asset_categories`, `asset_groups`, `assets`, `asset_depreciations`, `depreciation_schedules`,
`asset_transfers`, `asset_disposals`, `asset_revaluations`, `asset_impairments`,
`asset_accounting_profiles`, `asset_history`, `asset_locations`
### Payroll (5.9)
`departments`, `positions`, `employees`, `employment_contracts`, `salary_components`,
`payroll_periods`, `payrolls`, `payroll_items`, `benefits`, `allowances`, `deductions`,
`employee_loans`, `employee_advances`, `payroll_accounting_profiles`, `payroll_history`,
`payroll_settlements`
### Reporting (5.10)
`financial_reports`, `report_templates`, `dashboards`, `dashboard_widgets`, `kpis`,
`report_snapshots`, `scheduled_reports`, `report_exports`, `report_history`, `report_configurations`
### Compliance (5.11)
`audit_records`, `audit_history`, `compliance_policies`, `governance_rules`,
`approval_workflows`, `approval_steps`, `approval_requests`, `delegations`,
`risk_records`, `policy_violations`, `evidence`, `retention_policies`, `control_definitions`
همه جداول دارای `tenant_id` (UUID، بدون FK بین DB).
---
## بخش ۲ — طراحی اولیه دیتابیس سرویس‌های آینده (بدون migration)
> accounting_db اکنون پیاده‌سازی شده — جزئیات در بخش ۴ بالا.
> crm_db پیاده‌سازی شده — Phases 6.06.3.
> loyalty_db پیاده‌سازی شده — Phase 7.0 foundation:
> `loyalty_programs`, `membership_tiers`, `members`, `point_accounts`,
> `rewards`, `campaigns`, `loyalty_audit_logs`.
> communication_db پیاده‌سازی شده — Phase 8.08.10:
> `provider_configs`, `sender_numbers`, `message_templates`, `manual_contacts`,
> `contact_sources`, `messages`, `queue_items`, `delivery_events`, `provider_logs`,
> `otp_challenges`, `webhook_receipts`, `communication_audit_logs`.
- **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 via `loyalty_db` / Loyalty service).
هر سرویس دسترسی قابلیت‌ها را از 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`.