Move 39 documentation files from top-level docs/ into each module's docs/ folder, accessible via symlinks from docs/modules/. Create data-model.md files for 10 modules with full schema documentation. Replace originals with redirect stubs. Remove empty guide stubs. Modules migrated: tenancy, billing, loyalty, marketplace, orders, messaging, cms, catalog, inventory, hosting, prospecting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
13 KiB
Messaging Data Model
Entity relationships and database schema for the messaging module.
Entity Relationship Overview
Store 1──1 StoreEmailSettings
Store 1──* StoreEmailTemplate
Store 1──* Conversation 1──* Message 1──* MessageAttachment
└──* ConversationParticipant
EmailTemplate 1──* EmailLog
Models
EmailTemplate
Multi-language email templates stored in database with Jinja2 variable interpolation.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
code |
String(100) | not null, indexed | Template identifier (e.g., "signup_welcome") |
language |
String(5) | not null, default "en" | Language code |
name |
String(255) | not null | Human-readable name |
description |
Text | nullable | Template purpose description |
category |
String(50) | not null, default "system", indexed | auth, orders, billing, system, marketing |
subject |
String(500) | not null | Subject line (supports variables) |
body_html |
Text | not null | HTML body content |
body_text |
Text | nullable | Plain text fallback |
variables |
Text | nullable | JSON list of expected variables |
required_variables |
Text | nullable | JSON list of mandatory variables |
is_active |
Boolean | not null, default True | Activation status |
is_platform_only |
Boolean | not null, default False | If True, stores cannot override |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Unique Index: (code, language)
StoreEmailTemplate
Store-specific email template overrides. Stores can customize platform templates without modifying defaults.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
store_id |
Integer | FK, not null, indexed | Store owning the override |
template_code |
String(100) | not null, indexed | References EmailTemplate.code |
language |
String(5) | not null, default "en" | Language code |
name |
String(255) | nullable | Custom name (null = use platform) |
subject |
String(500) | not null | Custom subject line |
body_html |
Text | not null | Custom HTML body |
body_text |
Text | nullable | Custom plain text body |
is_active |
Boolean | not null, default True | Activation status |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Unique Constraint: (store_id, template_code, language)
EmailLog
Email sending history and tracking for debugging, analytics, and compliance.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
template_code |
String(100) | nullable, indexed | Reference to template code |
template_id |
Integer | FK, nullable | Reference to template |
recipient_email |
String(255) | not null, indexed | Recipient address |
recipient_name |
String(255) | nullable | Recipient name |
subject |
String(500) | not null | Email subject line |
body_html |
Text | nullable | HTML body snapshot |
body_text |
Text | nullable | Plain text body snapshot |
from_email |
String(255) | not null | Sender email address |
from_name |
String(255) | nullable | Sender name |
reply_to |
String(255) | nullable | Reply-to address |
status |
String(20) | not null, default "pending", indexed | pending, sent, failed, bounced, delivered, opened, clicked |
sent_at |
DateTime | nullable | When sent |
delivered_at |
DateTime | nullable | When delivered |
opened_at |
DateTime | nullable | When opened |
clicked_at |
DateTime | nullable | When clicked |
error_message |
Text | nullable | Error details if failed |
retry_count |
Integer | not null, default 0 | Retry attempts |
provider |
String(50) | nullable | smtp, sendgrid, mailgun, ses |
provider_message_id |
String(255) | nullable, indexed | Provider's message ID |
store_id |
Integer | FK, nullable, indexed | Associated store |
user_id |
Integer | FK, nullable, indexed | Associated user |
related_type |
String(50) | nullable | Related entity type |
related_id |
Integer | nullable | Related entity ID |
extra_data |
Text | nullable | JSON additional context |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
StoreEmailSettings
Per-store email sending configuration. One-to-one with Store.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
store_id |
Integer | FK, unique, not null | One-to-one with store |
from_email |
String(255) | not null | Sender email address |
from_name |
String(100) | not null | Sender display name |
reply_to_email |
String(255) | nullable | Reply-to address |
signature_text |
Text | nullable | Plain text signature |
signature_html |
Text | nullable | HTML signature/footer |
provider |
String(20) | not null, default "smtp" | smtp, sendgrid, mailgun, ses |
smtp_host |
String(255) | nullable | SMTP server hostname |
smtp_port |
Integer | nullable, default 587 | SMTP port |
smtp_username |
String(255) | nullable | SMTP username |
smtp_password |
String(500) | nullable | SMTP password (encrypted) |
smtp_use_tls |
Boolean | not null, default True | Use TLS |
smtp_use_ssl |
Boolean | not null, default False | Use SSL (port 465) |
sendgrid_api_key |
String(500) | nullable | SendGrid API key (encrypted) |
mailgun_api_key |
String(500) | nullable | Mailgun API key (encrypted) |
mailgun_domain |
String(255) | nullable | Mailgun domain |
ses_access_key_id |
String(100) | nullable | SES access key ID |
ses_secret_access_key |
String(500) | nullable | SES secret key (encrypted) |
ses_region |
String(50) | nullable, default "eu-west-1" | AWS region |
is_configured |
Boolean | not null, default False | Has complete config |
is_verified |
Boolean | not null, default False | Test email succeeded |
last_verified_at |
DateTime | nullable, tz-aware | Last verification |
verification_error |
Text | nullable | Last error message |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Index: (store_id, is_configured)
AdminNotification
Admin-specific notifications for system alerts and warnings.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
type |
String(50) | not null, indexed | system_alert, store_issue, import_failure |
priority |
String(20) | not null, default "normal", indexed | low, normal, high, critical |
title |
String(200) | not null | Notification title |
message |
Text | not null | Notification message |
is_read |
Boolean | not null, default False, indexed | Read status |
read_at |
DateTime | nullable | When read |
read_by_user_id |
Integer | FK, nullable | User who read it |
action_required |
Boolean | not null, default False, indexed | Action needed |
action_url |
String(500) | nullable | Link to relevant admin page |
notification_metadata |
JSON | nullable | Additional context |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Conversation
Threaded conversation between participants with multi-tenant isolation.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
conversation_type |
Enum | not null, indexed | admin_store, store_customer, admin_customer |
subject |
String(500) | not null | Thread subject line |
store_id |
Integer | FK, nullable, indexed | Multi-tenant isolation |
is_closed |
Boolean | not null, default False | Closed status |
closed_at |
DateTime | nullable | When closed |
closed_by_type |
Enum | nullable | Type of closer |
closed_by_id |
Integer | nullable | ID of closer |
last_message_at |
DateTime | nullable, indexed | Last activity |
message_count |
Integer | not null, default 0 | Total messages |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Composite Index: (conversation_type, store_id)
ConversationParticipant
Links participants (users or customers) to conversations with polymorphic relationships.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
conversation_id |
Integer | FK, not null, indexed | Parent conversation |
participant_type |
Enum | not null | admin, store, customer |
participant_id |
Integer | not null, indexed | Polymorphic participant ID |
store_id |
Integer | FK, nullable | Store context |
unread_count |
Integer | not null, default 0 | Unread messages |
last_read_at |
DateTime | nullable | Last read time |
email_notifications |
Boolean | not null, default True | Email notification pref |
muted |
Boolean | not null, default False | Muted status |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Unique Constraint: (conversation_id, participant_type, participant_id)
Composite Index: (participant_type, participant_id)
Message
Individual message within a conversation thread.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
conversation_id |
Integer | FK, not null, indexed | Parent conversation |
sender_type |
Enum | not null | admin, store, customer |
sender_id |
Integer | not null, indexed | Polymorphic sender ID |
content |
Text | not null | Message body |
is_system_message |
Boolean | not null, default False | System-generated flag |
is_deleted |
Boolean | not null, default False | Soft delete flag |
deleted_at |
DateTime | nullable | When deleted |
deleted_by_type |
Enum | nullable | Type of deleter |
deleted_by_id |
Integer | nullable | ID of deleter |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Composite Index: (conversation_id, created_at)
MessageAttachment
File attachments for messages.
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
Integer | PK | Primary key |
message_id |
Integer | FK, not null, indexed | Parent message |
filename |
String(255) | not null | System filename |
original_filename |
String(255) | not null | Original upload name |
file_path |
String(1000) | not null | Storage path |
file_size |
Integer | not null | File size in bytes |
mime_type |
String(100) | not null | MIME type |
is_image |
Boolean | not null, default False | Image flag |
image_width |
Integer | nullable | Width in pixels |
image_height |
Integer | nullable | Height in pixels |
thumbnail_path |
String(1000) | nullable | Thumbnail path |
created_at |
DateTime | tz-aware | Record creation time |
updated_at |
DateTime | tz-aware | Record update time |
Enums
EmailCategory
| Value | Description |
|---|---|
auth |
Signup, password reset, verification |
orders |
Order confirmations, shipping |
billing |
Invoices, payment failures |
system |
Team invites, notifications |
marketing |
Newsletters, promotions |
EmailStatus
| Value | Description |
|---|---|
pending |
Queued for sending |
sent |
Sent to provider |
failed |
Send failed |
bounced |
Bounced back |
delivered |
Confirmed delivered |
opened |
Recipient opened |
clicked |
Link clicked |
EmailProvider
| Value | Description |
|---|---|
smtp |
Standard SMTP (all tiers) |
sendgrid |
SendGrid API (Business+ tier) |
mailgun |
Mailgun API (Business+ tier) |
ses |
Amazon SES (Business+ tier) |
ConversationType
| Value | Description |
|---|---|
admin_store |
Admin-store conversations |
store_customer |
Store-customer conversations |
admin_customer |
Admin-customer conversations |
ParticipantType
| Value | Description |
|---|---|
admin |
Platform admin user |
store |
Store team user |
customer |
Customer |
Design Patterns
- Template override system: Platform templates + per-store overrides with language fallback
- Polymorphic participants: Conversations support admin, store, and customer participants
- Email tracking: Full lifecycle tracking (sent → delivered → opened → clicked)
- Provider abstraction: Multiple email providers with per-store configuration
- Premium tier gating: SendGrid, Mailgun, SES require Business+ tier
- Soft deletes: Messages support soft delete with audit trail