Add comprehensive email template management for both admin and vendors:
Admin Features:
- Email templates management page at /admin/email-templates
- Edit platform templates with language support (en, fr, de, lb)
- Preview templates with sample variables
- Send test emails
- View email logs per template
Vendor Features:
- Email templates customization page at /vendor/{code}/email-templates
- Override platform templates with vendor-specific versions
- Preview and test customized templates
- Revert to platform defaults
Technical Changes:
- Migration for vendor_email_templates table
- VendorEmailTemplate model with override management
- Enhanced EmailService with language resolution chain
(customer preferred -> vendor preferred -> platform default)
- Branding resolution (Wizamart default, removed for whitelabel)
- Platform-only template protection (billing templates)
- Admin and vendor API endpoints with full CRUD
- Updated seed script with billing and team templates
Files: 22 changed, ~3,900 lines added
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.0 KiB
8.0 KiB
Email System Enhancements - Implementation Plan
Overview
Enhance the email system to support:
- Platform-level templates with vendor overrides
- Wizamart branding by default (removed for Enterprise whitelabel tier)
- Platform-only templates that cannot be overridden
- Admin UI for editing platform templates
- 4-language support (en, fr, de, lb)
- Smart language resolution (customer → vendor → platform default)
Phase 1: Database & Model Foundation
1.1 Update EmailTemplate Model
File: models/database/email.py
Add columns:
is_platform_only: bool = False- Cannot be overridden by vendorsrequired_variables: JSON- List of variables that must be provided
is_platform_only = Column(Boolean, default=False, nullable=False)
required_variables = Column(JSON, default=list)
1.2 Create VendorEmailTemplate Model
File: models/database/vendor_email_template.py
class VendorEmailTemplate(Base):
__tablename__ = "vendor_email_templates"
id: int
vendor_id: int (FK → vendors.id)
template_code: str # References EmailTemplate.code
language: str # en, fr, de, lb
subject: str
body_html: str
body_text: str
is_active: bool = True
created_at: datetime
updated_at: datetime
# Unique constraint: (vendor_id, template_code, language)
1.3 Migration
File: alembic/versions/xxx_add_vendor_email_templates.py
- Add columns to email_templates table
- Create vendor_email_templates table
- Add indexes for lookup performance
Phase 2: Email Service Enhancement
2.1 Language Resolution
Priority order for customer-facing emails:
customer.preferred_language(if customer exists)vendor.storefront_language- Platform default (
en)
Priority order for vendor-facing emails:
vendor.preferred_language- Platform default (
en)
2.2 Template Resolution
File: app/services/email_service.py
def resolve_template(
self,
template_code: str,
language: str,
vendor_id: int | None = None
) -> tuple[str, str, str]: # subject, body_html, body_text
"""
Resolve template with vendor override support.
1. If vendor_id provided and template not platform-only:
- Look for VendorEmailTemplate override
- Fall back to platform EmailTemplate
2. If no vendor or platform-only:
- Use platform EmailTemplate
3. Language fallback: requested → en
"""
2.3 Branding Resolution
def get_branding(self, vendor_id: int | None) -> dict:
"""
Get branding variables for email.
Returns:
- platform_name: "Wizamart" or vendor.name (if whitelabel)
- platform_logo: Wizamart logo or vendor logo (if whitelabel)
- support_email: platform or vendor support email
- vendor_name: Always vendor.name
- vendor_logo: Always vendor logo
"""
if vendor_id:
vendor = self._get_vendor(vendor_id)
if has_feature(vendor, "white_label"):
return {
"platform_name": vendor.name,
"platform_logo": vendor.logo_url,
...
}
return {
"platform_name": "Wizamart",
"platform_logo": PLATFORM_LOGO_URL,
...
}
Phase 3: Admin API & UI
3.1 Admin API Endpoints
File: app/api/v1/admin/email_templates.py
| Method | Endpoint | Description |
|---|---|---|
| GET | /email-templates |
List all platform templates |
| GET | /email-templates/{code} |
Get template (all languages) |
| PUT | /email-templates/{code}/{language} |
Update template |
| POST | /email-templates/{code}/preview |
Preview with sample data |
| POST | /email-templates/{code}/test |
Send test email |
3.2 Admin UI
File: app/templates/admin/email-templates.html
Features:
- List view with template codes, categories, language badges
- Edit view with:
- Language tabs (en, fr, de, lb)
- Subject field
- Rich text editor for body_html
- Plain text preview for body_text
- Variable reference panel
- Preview pane
- Test send button
- Platform-only badge/indicator
- Required variables display
Phase 4: Vendor API & UI
4.1 Vendor API Endpoints
File: app/api/v1/vendor/email_templates.py
| Method | Endpoint | Description |
|---|---|---|
| GET | /email-templates |
List overridable templates |
| GET | /email-templates/{code} |
Get vendor override or default |
| PUT | /email-templates/{code}/{language} |
Create/update override |
| DELETE | /email-templates/{code}/{language} |
Reset to platform default |
| POST | /email-templates/{code}/preview |
Preview with vendor branding |
| POST | /email-templates/{code}/test |
Send test email |
4.2 Vendor UI
File: app/templates/vendor/email-templates.html
Features:
- List view with templates, showing "Customized" vs "Using Default"
- Edit view similar to admin but:
- Can only edit non-platform-only templates
- "Reset to Default" button
- Shows platform default as reference
- Tier gating: Only accessible for Business+ tiers
Phase 5: Missing Templates
Platform-Only Templates (Billing/Subscription)
| Code | Category | Description |
|---|---|---|
tier_upgrade |
BILLING | Vendor upgraded subscription |
tier_downgrade |
BILLING | Vendor downgraded subscription |
payment_failed |
BILLING | Subscription payment failed |
subscription_cancelled |
BILLING | Subscription cancelled |
trial_ending |
BILLING | Trial period ending soon |
usage_limit_warning |
BILLING | Approaching usage limits |
Overridable Templates
| Code | Category | Description |
|---|---|---|
team_invite |
AUTH | Team member invitation |
order_shipped |
ORDERS | Order has shipped |
shipping_update |
ORDERS | Shipping status update |
low_stock_alert |
SYSTEM | Low inventory warning |
Language Support Matrix
| Language | Code | Platform Default |
|---|---|---|
| English | en |
Yes (fallback) |
| French | fr |
No |
| German | de |
No |
| Luxembourgish | lb |
No |
Fallback Logic:
requested_language → en (if template not found)
Files to Create/Modify
Phase 1 (Database)
| File | Action |
|---|---|
alembic/versions/xxx_add_vendor_email_templates.py |
Create |
models/database/email.py |
Modify |
models/database/vendor_email_template.py |
Create |
models/database/__init__.py |
Modify |
models/schema/email.py |
Create |
Phase 2 (Service)
| File | Action |
|---|---|
app/services/email_service.py |
Modify |
Phase 3 (Admin)
| File | Action |
|---|---|
app/api/v1/admin/email_templates.py |
Create |
app/api/v1/admin/__init__.py |
Modify |
app/templates/admin/email-templates.html |
Create |
app/routes/admin_pages.py |
Modify |
static/admin/js/email-templates.js |
Create |
Phase 4 (Vendor)
| File | Action |
|---|---|
app/api/v1/vendor/email_templates.py |
Create |
app/api/v1/vendor/__init__.py |
Modify |
app/templates/vendor/email-templates.html |
Create |
app/routes/vendor_pages.py |
Modify |
static/vendor/js/email-templates.js |
Create |
Phase 5 (Templates)
| File | Action |
|---|---|
scripts/seed_email_templates.py |
Modify |
Execution Order
- Phase 1: Database migration and models (~30 min)
- Phase 2: Email service enhancement (~45 min)
- Phase 3: Admin API and UI (~1-2 hours)
- Phase 4: Vendor API and UI (~1-2 hours)
- Phase 5: Add missing templates (~30 min)
- Testing: Integration tests for all phases
Security Considerations
- XSS Prevention: Sanitize HTML in templates before storage
- Access Control: Vendors can only edit their own templates
- Platform-only Protection: API enforces is_platform_only flag
- Template Validation: Ensure required variables are present in template
- Rate Limiting: Test email sending limited to prevent abuse