barsa f447ba1800 Refactor codebase: eliminate duplication, standardize patterns, resolve circular deps
Phase 1: Portal Duplication Cleanup
- Delete apps/portal/src/lib/ directory (12 duplicate files)
- Update imports to use canonical locations (core/, shared/)

Phase 2: Domain Package Standardization
- Add contract.ts to notifications and checkout modules
- Update billing schema to derive enums from contract

Phase 3: BFF Error Handling
- Remove hardcoded test SIM number from SimValidationService
- Use ConfigService for TEST_SIM_ACCOUNT env variable

Phase 4: Circular Dependency Resolution
- Create VoiceOptionsModule to break FreebitModule <-> SimManagementModule cycle
- Remove forwardRef usage between these modules
- Move SimVoiceOptionsService to new voice-options module

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:25:14 +09:00

174 lines
5.9 KiB
TypeScript

/**
* Notifications Contract
*
* Business constants, enums, and templates for in-app notifications.
*/
// =============================================================================
// Enums
// =============================================================================
export const NOTIFICATION_TYPE = {
ELIGIBILITY_ELIGIBLE: "ELIGIBILITY_ELIGIBLE",
ELIGIBILITY_INELIGIBLE: "ELIGIBILITY_INELIGIBLE",
VERIFICATION_VERIFIED: "VERIFICATION_VERIFIED",
VERIFICATION_REJECTED: "VERIFICATION_REJECTED",
ORDER_APPROVED: "ORDER_APPROVED",
ORDER_ACTIVATED: "ORDER_ACTIVATED",
ORDER_FAILED: "ORDER_FAILED",
CANCELLATION_SCHEDULED: "CANCELLATION_SCHEDULED",
CANCELLATION_COMPLETE: "CANCELLATION_COMPLETE",
PAYMENT_METHOD_EXPIRING: "PAYMENT_METHOD_EXPIRING",
INVOICE_DUE: "INVOICE_DUE",
SYSTEM_ANNOUNCEMENT: "SYSTEM_ANNOUNCEMENT",
} as const;
export type NotificationTypeValue = (typeof NOTIFICATION_TYPE)[keyof typeof NOTIFICATION_TYPE];
export const NOTIFICATION_SOURCE = {
SALESFORCE: "SALESFORCE",
WHMCS: "WHMCS",
PORTAL: "PORTAL",
SYSTEM: "SYSTEM",
} as const;
export type NotificationSourceValue =
(typeof NOTIFICATION_SOURCE)[keyof typeof NOTIFICATION_SOURCE];
// =============================================================================
// Notification Templates
// =============================================================================
export interface NotificationTemplate {
type: NotificationTypeValue;
title: string;
message: string;
actionUrl?: string;
actionLabel?: string;
priority: "low" | "medium" | "high";
}
export const NOTIFICATION_TEMPLATES: Record<NotificationTypeValue, NotificationTemplate> = {
[NOTIFICATION_TYPE.ELIGIBILITY_ELIGIBLE]: {
type: NOTIFICATION_TYPE.ELIGIBILITY_ELIGIBLE,
title: "Good news! Internet service is available",
message:
"We've confirmed internet service is available at your address. You can now select a plan and complete your order.",
actionUrl: "/account/services/internet",
actionLabel: "View Plans",
priority: "high",
},
[NOTIFICATION_TYPE.ELIGIBILITY_INELIGIBLE]: {
type: NOTIFICATION_TYPE.ELIGIBILITY_INELIGIBLE,
title: "Internet service not available",
message:
"Unfortunately, internet service is not currently available at your address. We'll notify you if this changes.",
actionUrl: "/account/support",
actionLabel: "Contact Support",
priority: "high",
},
[NOTIFICATION_TYPE.VERIFICATION_VERIFIED]: {
type: NOTIFICATION_TYPE.VERIFICATION_VERIFIED,
title: "ID verification complete",
message: "Your identity has been verified. You can now complete your order.",
actionUrl: "/account/order",
actionLabel: "Continue Checkout",
priority: "high",
},
[NOTIFICATION_TYPE.VERIFICATION_REJECTED]: {
type: NOTIFICATION_TYPE.VERIFICATION_REJECTED,
title: "ID verification requires attention",
message: "We couldn't verify your ID. Please review the feedback and resubmit.",
actionUrl: "/account/settings/verification",
actionLabel: "Resubmit",
priority: "high",
},
[NOTIFICATION_TYPE.ORDER_APPROVED]: {
type: NOTIFICATION_TYPE.ORDER_APPROVED,
title: "Order approved",
message: "Your order has been approved and is being processed.",
actionUrl: "/account/orders",
actionLabel: "View Order",
priority: "medium",
},
[NOTIFICATION_TYPE.ORDER_ACTIVATED]: {
type: NOTIFICATION_TYPE.ORDER_ACTIVATED,
title: "Service activated",
message: "Your service is now active and ready to use.",
actionUrl: "/account/services",
actionLabel: "View Service",
priority: "high",
},
[NOTIFICATION_TYPE.ORDER_FAILED]: {
type: NOTIFICATION_TYPE.ORDER_FAILED,
title: "Order requires attention",
message: "There was an issue processing your order. Please contact support.",
actionUrl: "/account/support",
actionLabel: "Contact Support",
priority: "high",
},
[NOTIFICATION_TYPE.CANCELLATION_SCHEDULED]: {
type: NOTIFICATION_TYPE.CANCELLATION_SCHEDULED,
title: "Cancellation scheduled",
message: "Your cancellation request has been received and scheduled.",
actionUrl: "/account/services",
actionLabel: "View Details",
priority: "medium",
},
[NOTIFICATION_TYPE.CANCELLATION_COMPLETE]: {
type: NOTIFICATION_TYPE.CANCELLATION_COMPLETE,
title: "Service cancelled",
message: "Your service has been successfully cancelled.",
actionUrl: "/account/services",
actionLabel: "View Details",
priority: "medium",
},
[NOTIFICATION_TYPE.PAYMENT_METHOD_EXPIRING]: {
type: NOTIFICATION_TYPE.PAYMENT_METHOD_EXPIRING,
title: "Payment method expiring soon",
message:
"Your payment method is expiring soon. Please update it to avoid service interruption.",
actionUrl: "/account/billing/payments",
actionLabel: "Update Payment",
priority: "high",
},
[NOTIFICATION_TYPE.INVOICE_DUE]: {
type: NOTIFICATION_TYPE.INVOICE_DUE,
title: "Invoice due",
message: "You have an invoice due. Please make a payment to keep your service active.",
actionUrl: "/account/billing/invoices",
actionLabel: "Pay Now",
priority: "high",
},
[NOTIFICATION_TYPE.SYSTEM_ANNOUNCEMENT]: {
type: NOTIFICATION_TYPE.SYSTEM_ANNOUNCEMENT,
title: "System announcement",
message: "Important information about your service.",
priority: "low",
},
};
/**
* Get notification template by type with optional overrides
*/
export function getNotificationTemplate(
type: NotificationTypeValue,
overrides?: Partial<NotificationTemplate>
): NotificationTemplate {
const template = NOTIFICATION_TEMPLATES[type];
if (!template) {
throw new Error(`Unknown notification type: ${type}`);
}
return { ...template, ...overrides };
}
// Re-export types from schema
export type {
Notification,
CreateNotificationRequest,
NotificationListResponse,
NotificationUnreadCountResponse,
NotificationQuery,
NotificationIdParam,
} from "./schema.js";