generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum UserStatus { invited active inactive suspended } model User { id String @id @default(uuid()) name String email String @unique passwordHash String? @map("password_hash") refreshTokenHash String? @map("refresh_token_hash") refreshTokenExpiresAt DateTime? @map("refresh_token_expires_at") sessionVersion Int @default(0) @map("session_version") status UserStatus @default(invited) roleId String? @map("role_id") inviteTokenHash String? @map("invite_token_hash") inviteTokenExpiresAt DateTime? @map("invite_token_expires_at") passwordResetTokenHash String? @map("password_reset_token_hash") passwordResetTokenExpiresAt DateTime? @map("password_reset_token_expires_at") twoFactorEnabled Boolean @default(false) @map("two_factor_enabled") twoFactorSecretEncrypted String? @map("two_factor_secret_encrypted") twoFactorPendingSecretEncrypted String? @map("two_factor_pending_secret_encrypted") twoFactorRecoveryCodesHashJson Json? @map("two_factor_recovery_codes_hash_json") twoFactorConfirmedAt DateTime? @map("two_factor_confirmed_at") emailVerifiedAt DateTime? @map("email_verified_at") lastLoginAt DateTime? @map("last_login_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") role Role? @relation(fields: [roleId], references: [id]) @@index([passwordResetTokenHash]) @@map("users") } model Role { id String @id @default(uuid()) key String @unique name String summary String badge String tone String icon String permissionsJson Json @map("permissions_json") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") users User[] @@map("roles") } model Contact { id String @id @default(uuid()) name String phoneNumber String @unique @map("phone_number") email String? company String? notes String? isBlacklisted Boolean @default(false) @map("is_blacklisted") assignedUserId String? @map("assigned_user_id") assignedUserName String? @map("assigned_user_name") assignedAt DateTime? @map("assigned_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") conversationMessages ConversationMessage[] @@map("contacts") } model ConversationMessage { id String @id @default(uuid()) contactId String @map("contact_id") direction String messageType String @default("text") @map("message_type") source String @default("agent") body String status String @default("sent") senderUserId String? @map("sender_user_id") senderName String? @map("sender_name") externalMessageId String? @map("external_message_id") webhookEventId String? @unique @map("webhook_event_id") occurredAt DateTime @default(now()) @map("occurred_at") readAt DateTime? @map("read_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade) @@index([contactId, occurredAt]) @@map("conversation_messages") } model WebhookEvent { id String @id @default(uuid()) provider String eventId String @unique @map("event_id") eventType String @map("event_type") senderPhone String? @map("sender_phone") recipientPhone String? @map("recipient_phone") externalMessageId String? @map("external_message_id") eventTimestamp DateTime @map("event_timestamp") payloadJson Json @map("payload_json") verified Boolean @default(false) processingStatus String @default("received") @map("processing_status") processingNotes String? @map("processing_notes") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("webhook_events") } model IntegrationConfig { id String @id @default(uuid()) configKey String @unique @map("config_key") provider String isEnabled Boolean @default(true) @map("is_enabled") configJson Json @map("config_json") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("integration_configs") } model Job { id String @id @default(uuid()) queueName String @map("queue_name") jobType String @map("job_type") status String @default("queued") payloadJson Json @map("payload_json") attempts Int @default(0) maxAttempts Int @default(3) @map("max_attempts") availableAt DateTime @default(now()) @map("available_at") processedAt DateTime? @map("processed_at") failedAt DateTime? @map("failed_at") errorMessage String? @map("error_message") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([queueName, status, availableAt]) @@map("jobs") } model AuditLog { id String @id @default(uuid()) actorUserId String? @map("actor_user_id") actorName String @map("actor_name") actorEmail String? @map("actor_email") actionType String @map("action_type") module String ipAddress String? @map("ip_address") severity String @default("default") details String metadataJson Json? @map("metadata_json") createdAt DateTime @default(now()) @map("created_at") @@index([createdAt]) @@index([actorName]) @@index([actionType]) @@index([module]) @@map("audit_logs") } model MessageTemplate { id String @id @default(uuid()) name String @unique category String status String language String headerText String? @map("header_text") bodyText String @map("body_text") footerText String? @map("footer_text") buttonsJson Json? @map("buttons_json") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([status, category, language]) @@map("message_templates") } model Campaign { id String @id @default(uuid()) code String @unique name String audienceLabel String @map("audience_label") audienceGroup String @map("audience_group") status String totalRecipients Int @default(0) @map("total_recipients") deliveredCount Int @default(0) @map("delivered_count") readCount Int @default(0) @map("read_count") failedCount Int @default(0) @map("failed_count") deliveryRate Float? @map("delivery_rate") readRate Float? @map("read_rate") sentAt DateTime? @map("sent_at") scheduledAt DateTime? @map("scheduled_at") templateName String? @map("template_name") language String? messageTitle String? @map("message_title") messageBody String? @map("message_body") primaryButton String? @map("primary_button") secondaryButton String? @map("secondary_button") bannerImageUrl String? @map("banner_image_url") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") recipients CampaignRecipient[] @@map("campaigns") } model CampaignRecipient { id String @id @default(uuid()) campaignId String @map("campaign_id") phoneNumber String @map("phone_number") status String sentAt DateTime? @map("sent_at") errorReason String? @map("error_reason") deviceOs String? @map("device_os") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade) @@index([campaignId, status]) @@index([campaignId, sentAt]) @@map("campaign_recipients") } model Wallet { id String @id @default(uuid()) ownerKey String @unique @map("owner_key") currency String @default("IDR") balanceMinor Int @default(0) @map("balance_minor") heldMinor Int @default(0) @map("held_minor") status String @default("active") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") transactions WalletTransaction[] paymentOrders PaymentOrder[] @@map("wallets") } model WalletTransaction { id String @id @default(uuid()) walletId String @map("wallet_id") type String direction String amountMinor Int @map("amount_minor") balanceBeforeMinor Int @map("balance_before_minor") balanceAfterMinor Int @map("balance_after_minor") status String @default("posted") referenceType String? @map("reference_type") referenceId String? @map("reference_id") description String? metadataJson Json? @map("metadata_json") createdAt DateTime @default(now()) @map("created_at") wallet Wallet @relation(fields: [walletId], references: [id], onDelete: Cascade) @@index([walletId, createdAt]) @@index([referenceType, referenceId]) @@map("wallet_transactions") } model PaymentOrder { id String @id @default(uuid()) walletId String @map("wallet_id") provider String @default("midtrans") providerOrderId String @unique @map("provider_order_id") amountMinor Int @map("amount_minor") currency String @default("IDR") status String @default("pending") snapToken String? @map("snap_token") redirectUrl String? @map("redirect_url") paidAt DateTime? @map("paid_at") expiredAt DateTime? @map("expired_at") metadataJson Json? @map("metadata_json") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") wallet Wallet @relation(fields: [walletId], references: [id], onDelete: Cascade) @@index([walletId, status]) @@map("payment_orders") }