132 lines
3.6 KiB
TypeScript
Raw Normal View History

/**
* SIM Domain - Validation
*
* Business validation functions for SIM subscriptions.
* These functions contain no infrastructure dependencies.
*/
import type { Subscription } from "../subscriptions/schema";
/**
* 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, unknown>
): 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, "");
}