Fix email system and implement OTP confirmation flow

Email System Fixes:
- Fix email sending after payment: handle-order-paid now calls send-notification
  instead of send-email-v2 directly, properly processing template variables
- Fix order_created email timing: sent immediately after order creation,
  before payment QR code generation
- Update email templates to use short order ID (8 chars) instead of full UUID
- Add working "Akses Sekarang" buttons to payment_success and access_granted emails
- Add platform_url column to platform_settings for email links

OTP Verification Flow:
- Create dedicated /confirm-otp page for users who close registration modal
- Add link in checkout modal and email to dedicated OTP page
- Update OTP email template with better copywriting and dedicated page link
- Fix send-auth-otp to fetch platform settings for dynamic brand_name and platform_url
- Auto-login users after OTP verification in checkout flow

Admin Features:
- Add delete user functionality with cascade deletion of all related data
- Update IntegrasiTab to read/write email settings from platform_settings only
- Add test email template for email configuration testing

Cleanup:
- Remove obsolete send-consultation-reminder and send-test-email functions
- Update send-email-v2 to read email config from platform_settings
- Remove footer links (Ubah Preferensi/Unsubscribe) from email templates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-01-03 18:02:25 +07:00
parent 4f9a6f4ae3
commit 053465afa3
21 changed files with 1381 additions and 948 deletions

View File

@@ -0,0 +1,54 @@
-- ============================================================================
-- Update Auth OTP Email Template - Better Copywriting with Dedicated Page Link
-- ============================================================================
-- Update auth_email_verification template with improved copywriting
UPDATE notification_templates
SET
email_subject = 'Konfirmasi Email Anda - {platform_name}',
email_body_html = '---
<h1>🔐 Konfirmasi Alamat Email</h1>
<p>Selamat datang di <strong>{platform_name}</strong>!</p>
<p>Terima kasih telah mendaftar. Untuk mengaktifkan akun Anda, masukkan kode verifikasi 6 digit berikut:</p>
<div class="otp-box">{otp_code}</div>
<p><strong>⏰ Berlaku selama {expiry_minutes} menit</strong></p>
<h2>🎯 Cara Verifikasi:</h2>
<ol>
<li><strong>Kembali ke halaman pendaftaran</strong> - Form OTP sudah otomatis muncul</li>
<li><strong>Masukkan kode 6 digit</strong> di atas pada kolom verifikasi</li>
<li><strong>Klik "Verifikasi Email"</strong> dan akun Anda siap digunakan!</li>
</ol>
<h2>🔄 Halaman Khusus Verifikasi</h2>
<p>Jika Anda kehilangan halaman pendaftaran atau tertutup tidak sengaja, jangan khawatir! Anda tetap bisa memverifikasi akun melalui:</p>
<p class="text-center" style="margin: 20px 0;">
<a href="{platform_url}/confirm-otp?user_id={user_id}&email={email}" class="button" style="display: inline-block; padding: 12px 24px; background-color: #000; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">
📧 Buka Halaman Verifikasi Khusus
</a>
</p>
<p style="font-size: 14px; color: #666;">
<em>Link ini akan membawa Anda ke halaman khusus untuk memasukkan kode verifikasi.</em>
</p>
<div class="alert-warning" style="margin: 20px 0; padding: 15px; background-color: #fff3cd; border-left: 4px solid #ffc107;">
<p style="margin: 0;"><strong>💡 Tips:</strong> Cek folder <em>Spam</em> atau <em>Promotions</em> jika email tidak muncul di inbox dalam 1-2 menit.</p>
</div>
<blockquote class="alert-info">
<strong> Info:</strong> Jika Anda tidak merasa mendaftar di {platform_name}, abaikan email ini dengan aman.
</blockquote>
---'
WHERE key = 'auth_email_verification';
-- Return success message
DO $$
BEGIN
RAISE NOTICE 'Auth email template updated with improved copywriting and dedicated page link';
END $$;

View File

@@ -1,5 +1,5 @@
-- Update order_created email template to include QR code
-- This migration adds the QR code section to the order confirmation email
-- Update order_created email template to remove QR code
-- QR code is now displayed on the order detail page instead
UPDATE notification_templates
SET
@@ -12,28 +12,6 @@ SET
<p>Terima kasih telah melakukan pemesanan! Berikut adalah detail pesanan Anda:</p>
<!-- QR Code Section -->
<div style="text-align: center; margin: 30px 0; padding: 20px; background-color: #f5f5f5; border-radius: 8px;">
<h3 style="margin: 0 0 15px 0; font-size: 18px; color: #333;">Scan QR untuk Pembayaran</h3>
<!-- QR Code Image -->
<img src="{qr_code_image}" alt="QRIS Payment QR Code" style="width: 200px; height: 200px; border: 2px solid #000; padding: 10px; background-color: #fff; display: inline-block;" />
<p style="margin: 15px 0 5px 0; font-size: 14px; color: #666;">
Scan dengan aplikasi e-wallet atau mobile banking Anda
</p>
<p style="margin: 5px 0 0 0; font-size: 12px; color: #999;">
Berlaku hingga: {qr_expiry_time}
</p>
<div style="margin-top: 15px;">
<a href="{payment_link}" style="display: inline-block; padding: 12px 24px; background-color: #000; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">
Bayar Sekarang
</a>
</div>
</div>
<!-- Order Summary Section -->
<div style="margin: 30px 0; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
<h3 style="margin: 0 0 15px 0; font-size: 16px; color: #333;">Detail Pesanan</h3>
@@ -59,6 +37,16 @@ SET
</p>
</div>
<div style="margin: 30px 0; padding: 20px; background-color: #f5f5f5; border-radius: 8px; text-align: center;">
<p style="margin: 0 0 15px 0; font-size: 14px; color: #666;">
Silakan selesaikan pembayaran Anda dengan mengklik tombol di bawah:
</p>
<a href="{payment_link}" style="display: inline-block; padding: 12px 24px; background-color: #000; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">
Bayar Sekarang
</a>
</div>
<p style="font-size: 14px; color: #666;">
Silakan selesaikan pembayaran Anda sebelum waktu habis. Setelah pembayaran berhasil, akses ke produk akan segera aktif.
</p>

View File

@@ -0,0 +1,15 @@
-- ============================================================================
-- Add platform_url column to platform_settings
-- ============================================================================
-- Add platform_url column if it doesn't exist
ALTER TABLE platform_settings
ADD COLUMN IF NOT EXISTS platform_url TEXT;
-- Set default value if null
UPDATE platform_settings
SET platform_url = 'https://access-hub.com'
WHERE platform_url IS NULL;
-- Add comment
COMMENT ON COLUMN platform_settings.platform_url IS 'Base URL of the platform (used for email links)';

View File

@@ -0,0 +1,48 @@
-- Add test_email template for "Uji Coba Email" button in Integrasi tab
INSERT INTO notification_templates (key, name, email_subject, email_body_html, is_active, created_at, updated_at)
VALUES (
'test_email',
'Test Email',
'Email Test - {platform_name}',
'
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #333;">Email Test - {platform_name}</h2>
<p>Halo,</p>
<p>Ini adalah email tes dari sistem <strong>{platform_name}</strong>.</p>
<div style="margin: 20px 0; padding: 15px; background-color: #f0f0f0; border-left: 4px solid #000;">
<p style="margin: 0; font-size: 14px;">
<strong>✓ Konfigurasi email berhasil!</strong><br>
Email Anda telah terkirim dengan benar menggunakan provider: <strong>Mailketing</strong>
</p>
</div>
<p style="font-size: 14px; color: #666;">
Jika Anda menerima email ini, berarti konfigurasi email sudah benar.
</p>
<p style="font-size: 14px;">
Terima kasih,<br>
Tim {platform_name}
</p>
</div>
',
true,
NOW(),
NOW()
)
ON CONFLICT (key) DO UPDATE SET
email_subject = EXCLUDED.email_subject,
email_body_html = EXCLUDED.email_body_html,
updated_at = NOW();
-- Verify the template
SELECT
key,
name,
email_subject,
is_active
FROM notification_templates
WHERE key = 'test_email';

View File

@@ -0,0 +1,197 @@
-- ============================================================================
-- Fix Email Templates: Use Short Order ID and Add Missing Links
-- ============================================================================
-- 1. Fix order_created template - use short order_id and fix subject
UPDATE notification_templates
SET
email_subject = 'Konfirmasi Pesanan - #{order_id_short}',
email_body_html = '---
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #333;">Konfirmasi Pesanan</h2>
<p>Halo {nama},</p>
<p>Terima kasih telah melakukan pemesanan! Berikut adalah detail pesanan Anda:</p>
<!-- Order Summary Section -->
<div style="margin: 30px 0; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
<h3 style="margin: 0 0 15px 0; font-size: 16px; color: #333;">Detail Pesanan</h3>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Order ID:</strong> #{order_id_short}
</p>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Tanggal:</strong> {tanggal_pesanan}
</p>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Produk:</strong> {produk}
</p>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Metode Pembayaran:</strong> {metode_pembayaran}
</p>
<p style="margin: 15px 0 5px 0; font-size: 16px; font-weight: bold; color: #000;">
Total: {total}
</p>
</div>
<div style="margin: 30px 0; padding: 20px; background-color: #f5f5f5; border-radius: 8px; text-align: center;">
<p style="margin: 0 0 15px 0; font-size: 14px; color: #666;">
Silakan selesaikan pembayaran Anda dengan mengklik tombol di bawah:
</p>
<a href="{payment_link}" style="display: inline-block; padding: 12px 24px; background-color: #000; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">
Bayar Sekarang
</a>
</div>
<p style="font-size: 14px; color: #666;">
Silakan selesaikan pembayaran Anda sebelum waktu habis. Setelah pembayaran berhasil, akses ke produk akan segera aktif.
</p>
<p style="font-size: 14px;">
Jika Anda memiliki pertanyaan, jangan ragu untuk menghubungi kami.
</p>
<p style="font-size: 14px;">
Terima kasih,<br>
Tim {platform_name}
</p>
</div>
---',
updated_at = NOW()
WHERE key = 'order_created';
-- 2. Create or update payment_success template
INSERT INTO notification_templates (key, name, email_subject, email_body_html, is_active, created_at, updated_at)
VALUES (
'payment_success',
'Payment Success Email',
'Pembayaran Berhasil - Order #{order_id_short}',
'---
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #28a745;">Pembayaran Berhasil! ✓</h2>
<p>Halo {nama},</p>
<p>Terima kasih! Pembayaran Anda telah berhasil dikonfirmasi.</p>
<div style="margin: 30px 0; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
<h3 style="margin: 0 0 15px 0; font-size: 16px; color: #333;">Detail Pesanan</h3>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Order ID:</strong> #{order_id_short}
</p>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Tanggal:</strong> {tanggal_pesanan}
</p>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Produk:</strong> {produk}
</p>
<p style="margin: 5px 0; font-size: 14px;">
<strong>Metode Pembayaran:</strong> {metode_pembayaran}
</p>
<p style="margin: 15px 0 5px 0; font-size: 16px; font-weight: bold; color: #28a745;">
Total: {total}
</p>
</div>
<div style="margin: 30px 0; padding: 20px; background-color: #f0f8ff; border-radius: 8px; text-align: center;">
<p style="margin: 0 0 15px 0; font-size: 14px; color: #666;">
Akses ke produk Anda sudah aktif! Klik tombol di bawah untuk mulai belajar:
</p>
<a href="{link_akses}" style="display: inline-block; padding: 12px 24px; background-color: #28a745; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">
Akses Sekarang
</a>
</div>
<p style="font-size: 14px; color: #666;">
Jika Anda mengalami masalah saat mengakses produk, jangan ragu untuk menghubungi kami.
</p>
<p style="font-size: 14px;">
Selamat belajar!<br>
Tim {platform_name}
</p>
</div>
---',
true,
NOW(),
NOW()
)
ON CONFLICT (key) DO UPDATE SET
email_subject = EXCLUDED.email_subject,
email_body_html = EXCLUDED.email_body_html,
is_active = EXCLUDED.is_active,
updated_at = NOW();
-- 3. Create or update access_granted template
INSERT INTO notification_templates (key, name, email_subject, email_body_html, is_active, created_at, updated_at)
VALUES (
'access_granted',
'Access Granted Email',
'Akses Produk Diberikan - {produk}',
'---
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #28a745;">Akses Produk Aktif! 🎉</h2>
<p>Halo {nama},</p>
<p>Selamat! Akses ke produk Anda telah diaktifkan.</p>
<div style="margin: 30px 0; padding: 20px; background-color: #f0f8ff; border: 1px solid #b3d9ff; border-radius: 8px;">
<h3 style="margin: 0 0 15px 0; font-size: 16px; color: #333;">Produk Anda:</h3>
<p style="margin: 5px 0; font-size: 14px;">
<strong>{produk}</strong>
</p>
</div>
<div style="margin: 30px 0; padding: 20px; background-color: #f0f8ff; border-radius: 8px; text-align: center;">
<p style="margin: 0 0 15px 0; font-size: 14px; color: #666;">
Mulai belajar sekarang dengan mengklik tombol di bawah:
</p>
<a href="{link_akses}" style="display: inline-block; padding: 12px 24px; background-color: #28a745; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">
Akses Sekarang
</a>
</div>
<p style="font-size: 14px; color: #666;">
Nikmati pembelajaran Anda! Jika ada pertanyaan, jangan ragu untuk menghubungi kami.
</p>
<p style="font-size: 14px;">
Happy learning!<br>
Tim {platform_name}
</p>
</div>
---',
true,
NOW(),
NOW()
)
ON CONFLICT (key) DO UPDATE SET
email_subject = EXCLUDED.email_subject,
email_body_html = EXCLUDED.email_body_html,
is_active = EXCLUDED.is_active,
updated_at = NOW();
-- Verify updates
SELECT
key,
email_subject,
is_active,
updated_at
FROM notification_templates
WHERE key IN ('order_created', 'payment_success', 'access_granted')
ORDER BY key;