/** * SIM Domain - Validation * * Business validation functions for SIM subscriptions. * These functions contain no infrastructure dependencies. */ import type { Subscription } from "../subscriptions/schema.js"; /** * Check if a subscription is a SIM service * * Business rule: A subscription is considered a SIM service if its product name * or group name contains "SIM" (case-insensitive). * * @param subscription - The subscription to check * @returns true if this is a SIM subscription */ export function isSimSubscription(subscription: Subscription): boolean { const productName = subscription.productName?.toLowerCase() || ""; const groupName = subscription.groupName?.toLowerCase() || ""; return productName.includes("sim") || groupName.includes("sim"); } /** * Extract SIM account identifier from subscription data * * The SIM account identifier (typically a phone number/MSISDN) can be stored * in various places depending on the subscription source and configuration. * This function tries multiple locations in priority order. * * @param subscription - The subscription to extract the account from * @returns The SIM account identifier (phone number), or null if not found */ export function extractSimAccountFromSubscription( subscription: Subscription ): string | null { // 1. Try domain field first (most common location) if (subscription.domain && subscription.domain.trim()) { return subscription.domain.trim(); } // 2. Check custom fields for phone number/MSISDN if (subscription.customFields) { const account = extractFromCustomFields(subscription.customFields); if (account) return account; } // 3. Check if order number looks like a phone number (10-11 digits) if (subscription.orderNumber) { const orderNum = subscription.orderNumber.toString(); if (/^\d{10,11}$/.test(orderNum)) { return orderNum; } } return null; } /** * Extract account from custom fields using known field names * * WHMCS and other billing systems may store the SIM phone number in various * custom field names. This function checks all known variations. * * @param customFields - The custom fields record to search * @returns The SIM account if found, null otherwise */ function extractFromCustomFields( customFields: Record ): string | null { // Known field names for SIM phone numbers across different WHMCS configurations const phoneFields = [ // Standard field names "phone", "msisdn", "phonenumber", "phone_number", "mobile", "sim_phone", // Title case variations "Phone Number", "MSISDN", "Phone", "Mobile", "SIM Phone", "PhoneNumber", // Additional variations "mobile_number", "sim_number", "account_number", "Account Number", "SIM Account", "Phone Number (SIM)", "Mobile Number", "SIM Number", // Underscore variations "SIM_Number", "SIM_Phone_Number", "Phone_Number_SIM", "Mobile_SIM_Number", "SIM_Account_Number", ]; for (const fieldName of phoneFields) { const value = customFields[fieldName]; if (value !== undefined && value !== null && value !== "") { return String(value); } } return null; } /** * Clean SIM account format * * Removes common formatting characters (hyphens, spaces, parentheses) * from phone numbers to get a clean numeric string. * * @param account - The account string to clean * @returns Cleaned account string with only digits */ export function cleanSimAccount(account: string): string { return account.replace(/[-\s()]/g, ""); }