feat: send ticket receipts via WhatsApp and normalize phone numbers

Add WhatsApp API integration for automated receipt delivery
Enforce country codes for all phone number inputs (defaults to +60)
This commit is contained in:
2026-04-27 13:12:25 +08:00
parent faa998c7e1
commit c214d643dd
18 changed files with 208 additions and 28 deletions

View File

@@ -3,6 +3,7 @@ import { randomUUID } from 'node:crypto'
import type { AuthenticatorTransportFuture, CredentialDeviceType } from '@simplewebauthn/server'
import type { AuthUser, ManagedUser, PasskeySummary, PublicContact, UserRole } from '~~/shared/auth'
import { normalizePhoneNumber } from '~~/shared/auth'
import { encodeBase64Url, toIsoString } from './base64url'
import { ensureDatabaseReady } from './db-init'
@@ -80,7 +81,7 @@ function mapAuthUser(row: DbUserRow): AuthUser {
id: row.id,
username: row.username,
fullName: row.full_name,
phoneNumber: row.phone_number,
phoneNumber: row.phone_number ? normalizePhoneNumber(row.phone_number) : null,
role: row.role,
isActive: row.is_active,
mustChangePassword: row.must_change_password,
@@ -251,7 +252,7 @@ export async function listPublicContacts(): Promise<PublicContact[]> {
return rows.map((row) => ({
id: row.id,
fullName: row.full_name,
phoneNumber: row.phone_number || '',
phoneNumber: normalizePhoneNumber(row.phone_number || ''),
role: row.role
}))
}
@@ -281,7 +282,7 @@ export async function getPublicContactById(contactId: string): Promise<PublicCon
return {
id: row.id,
fullName: row.full_name,
phoneNumber: row.phone_number || '',
phoneNumber: normalizePhoneNumber(row.phone_number || ''),
role: row.role
}
}