package models import ( "time" "github.com/google/uuid" ) // ── Enum consts ─────────────────────────────────────────────────────────────── const ( // NotificationKind KindRenderCompleted = "RenderCompleted" KindRenderFailed = "RenderFailed" KindRenderProgress = "RenderProgress" KindPlanExpiring = "PlanExpiring" KindPlanExpired = "PlanExpired" KindPaymentSuccess = "PaymentSuccess" KindPaymentFailed = "PaymentFailed" KindStorageWarning = "StorageWarning" KindStorageFull = "StorageFull" KindExportExpiring = "ExportExpiring" KindExportDeleted = "ExportDeleted" KindGiftEarned = "GiftEarned" KindQuestCompleted = "QuestCompleted" KindLevelUp = "LevelUp" KindAccountSecurity = "AccountSecurity" KindSystemAnnouncement = "SystemAnnouncement" KindTenantInvite = "TenantInvite" KindMarketing = "Marketing" KindOther = "Other" // Priority PriorityLow = "Low" PriorityNormal = "Normal" PriorityHigh = "High" PriorityUrgent = "Urgent" // DeliveryChannel ChannelInApp = "InApp" ChannelPush = "Push" ChannelEmail = "Email" ChannelSMS = "SMS" ChannelTelegram = "Telegram" ChannelWebhook = "Webhook" // DeliveryStatus StatusPending = "Pending" StatusSent = "Sent" StatusDelivered = "Delivered" StatusFailed = "Failed" StatusBounced = "Bounced" StatusSuppressed = "Suppressed" ) // ── Domain entities ────────────────────────────────────────────────────────── type Notification struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` UserID uuid.UUID `json:"user_id"` NotificationType string `json:"notification_type"` Priority string `json:"priority"` Title string `json:"title"` Message string `json:"message"` Label *string `json:"label,omitempty"` Signature *string `json:"signature,omitempty"` Icon *string `json:"icon,omitempty"` Image *string `json:"image,omitempty"` AnimationDemo *string `json:"animation_demo,omitempty"` Design *string `json:"design,omitempty"` ActionURL *string `json:"action_url,omitempty"` ActionText *string `json:"action_text,omitempty"` RenderJobID *uuid.UUID `json:"render_job_id,omitempty"` ExportID *uuid.UUID `json:"export_id,omitempty"` PaymentID *uuid.UUID `json:"payment_id,omitempty"` GiftID *uuid.UUID `json:"gift_id,omitempty"` EarnedGiftID *uuid.UUID `json:"earned_gift_id,omitempty"` IsEmergency bool `json:"is_emergency"` Seen bool `json:"seen"` SeenAt *time.Time `json:"seen_at,omitempty"` Clicked bool `json:"clicked"` ClickedAt *time.Time `json:"clicked_at,omitempty"` GiftUsed bool `json:"gift_used"` ExpireDate *time.Time `json:"expire_date,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type NotificationPreference struct { ID uuid.UUID `json:"id"` UserID uuid.UUID `json:"user_id"` NotificationType string `json:"notification_type"` Channel string `json:"channel"` Enabled bool `json:"enabled"` UpdatedAt time.Time `json:"updated_at"` } type NotificationTemplate struct { ID uuid.UUID `json:"id"` TenantID *uuid.UUID `json:"tenant_id,omitempty"` Code string `json:"code"` Channel string `json:"channel"` Locale string `json:"locale"` Subject *string `json:"subject,omitempty"` BodyText *string `json:"body_text,omitempty"` BodyHTML *string `json:"body_html,omitempty"` PushTitle *string `json:"push_title,omitempty"` PushBody *string `json:"push_body,omitempty"` PushIcon *string `json:"push_icon,omitempty"` VariablesSchema *string `json:"variables_schema,omitempty"` IsActive bool `json:"is_active"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type NotificationDelivery struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` UserID uuid.UUID `json:"user_id"` NotificationID *uuid.UUID `json:"notification_id,omitempty"` Channel string `json:"channel"` Recipient string `json:"recipient"` Subject *string `json:"subject,omitempty"` Provider *string `json:"provider,omitempty"` ProviderMessageID *string `json:"provider_message_id,omitempty"` Status string `json:"status"` ErrorMessage *string `json:"error_message,omitempty"` Attempt int `json:"attempt"` MaxAttempts int `json:"max_attempts"` SentAt *time.Time `json:"sent_at,omitempty"` DeliveredAt *time.Time `json:"delivered_at,omitempty"` FailedAt *time.Time `json:"failed_at,omitempty"` CreatedAt time.Time `json:"created_at"` } // ── Request / Response types ───────────────────────────────────────────────── type PagedResponse[T any] struct { Data []T `json:"data"` Meta PaginationMeta `json:"meta"` } type PaginationMeta struct { Page int `json:"page"` PageSize int `json:"page_size"` Total int64 `json:"total"` HasMore bool `json:"has_more"` } type CreateNotificationRequest struct { UserID uuid.UUID `json:"user_id" binding:"required"` TenantID uuid.UUID `json:"tenant_id" binding:"required"` NotificationType string `json:"notification_type" binding:"required"` Priority *string `json:"priority"` Title string `json:"title" binding:"required"` Message string `json:"message" binding:"required"` Label *string `json:"label"` Icon *string `json:"icon"` Image *string `json:"image"` ActionURL *string `json:"action_url"` ActionText *string `json:"action_text"` RenderJobID *uuid.UUID `json:"render_job_id"` ExportID *uuid.UUID `json:"export_id"` PaymentID *uuid.UUID `json:"payment_id"` GiftID *uuid.UUID `json:"gift_id"` EarnedGiftID *uuid.UUID `json:"earned_gift_id"` IsEmergency bool `json:"is_emergency"` ExpireDate *time.Time `json:"expire_date"` Channels []string `json:"channels"` // which delivery channels to trigger } type UpdatePreferenceRequest struct { NotificationType string `json:"notification_type" binding:"required"` Channel string `json:"channel" binding:"required"` Enabled bool `json:"enabled"` } type TemplateUpsertRequest struct { Code string `json:"code" binding:"required"` Channel string `json:"channel" binding:"required"` Locale string `json:"locale" binding:"required"` Subject *string `json:"subject"` BodyText *string `json:"body_text"` BodyHTML *string `json:"body_html"` PushTitle *string `json:"push_title"` PushBody *string `json:"push_body"` PushIcon *string `json:"push_icon"` IsActive *bool `json:"is_active"` } type APIError struct { Code string `json:"code"` Message string `json:"message"` } // ── Channel provider config (SMS / Email) ──────────────────────────────────── type ChannelConfig struct { TenantID uuid.UUID `json:"tenant_id"` Channel string `json:"channel"` // 'sms' | 'email' Settings map[string]any `json:"settings"` Enabled bool `json:"enabled"` UpdatedAt time.Time `json:"updated_at"` } type UpsertChannelConfigRequest struct { Settings map[string]any `json:"settings"` Enabled *bool `json:"enabled"` } type SendSMSRequest struct { To string `json:"to" binding:"required"` Message string `json:"message" binding:"required"` } type SendEmailRequest struct { To string `json:"to" binding:"required"` Subject string `json:"subject"` BodyHTML string `json:"body_html"` BodyText string `json:"body_text"` TemplateCode string `json:"template_code"` Locale string `json:"locale"` Variables map[string]string `json:"variables"` } // ── Marketing campaigns ────────────────────────────────────────────────────── type Campaign struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` Name string `json:"name"` Channel string `json:"channel"` // sms | email Audience string `json:"audience"` // all | verified | with_plan Subject *string `json:"subject,omitempty"` BodyHTML *string `json:"body_html,omitempty"` TemplateCode *string `json:"template_code,omitempty"` Status string `json:"status"` TotalCount int `json:"total_count"` SentCount int `json:"sent_count"` FailedCount int `json:"failed_count"` CreatedAt time.Time `json:"created_at"` SentAt *time.Time `json:"sent_at,omitempty"` } type CreateCampaignRequest struct { Name string `json:"name" binding:"required"` Channel string `json:"channel" binding:"required"` // sms | email Audience string `json:"audience"` Subject *string `json:"subject"` BodyHTML *string `json:"body_html"` TemplateCode *string `json:"template_code"` }