/** * SIM Domain - Schemas */ import { z } from "zod"; export const simStatusSchema = z.enum(["active", "suspended", "cancelled", "pending"]); export const simTypeSchema = z.enum(["standard", "nano", "micro", "esim"]); export const simDetailsSchema = z.object({ account: z.string(), status: simStatusSchema, planCode: z.string(), planName: z.string(), simType: simTypeSchema, iccid: z.string(), eid: z.string(), msisdn: z.string(), imsi: z.string(), remainingQuotaMb: z.number(), remainingQuotaKb: z.number(), voiceMailEnabled: z.boolean(), callWaitingEnabled: z.boolean(), internationalRoamingEnabled: z.boolean(), networkType: z.string(), activatedAt: z.string().optional(), expiresAt: z.string().optional(), }); export const recentDayUsageSchema = z.object({ date: z.string(), usageKb: z.number(), usageMb: z.number(), }); export const simUsageSchema = z.object({ account: z.string(), todayUsageMb: z.number(), todayUsageKb: z.number(), monthlyUsageMb: z.number().optional(), monthlyUsageKb: z.number().optional(), recentDaysUsage: z.array(recentDayUsageSchema), isBlacklisted: z.boolean(), lastUpdated: z.string().optional(), }); export const simTopUpHistoryEntrySchema = z.object({ quotaKb: z.number(), quotaMb: z.number(), addedDate: z.string(), expiryDate: z.string(), campaignCode: z.string(), }); export const simTopUpHistorySchema = z.object({ account: z.string(), totalAdditions: z.number(), additionCount: z.number(), history: z.array(simTopUpHistoryEntrySchema), }); // ============================================================================ // SIM Management Request Schemas // ============================================================================ export const simTopUpRequestSchema = z.object({ quotaMb: z .number() .int() .min(100, "Quota must be at least 100MB") .max(51200, "Quota must be 50GB or less"), }); export const simPlanChangeRequestSchema = z.object({ newPlanCode: z.string().min(1, "New plan code is required"), assignGlobalIp: z.boolean().optional(), scheduledAt: z .string() .regex(/^\d{8}$/, "Scheduled date must be in YYYYMMDD format") .optional(), }); export const simCancelRequestSchema = z.object({ scheduledAt: z .string() .regex(/^\d{8}$/, "Scheduled date must be in YYYYMMDD format") .optional(), }); export const simTopUpHistoryRequestSchema = z.object({ fromDate: z .string() .regex(/^\d{8}$/, "From date must be in YYYYMMDD format"), toDate: z .string() .regex(/^\d{8}$/, "To date must be in YYYYMMDD format"), }); export const simFeaturesUpdateRequestSchema = z.object({ voiceMailEnabled: z.boolean().optional(), callWaitingEnabled: z.boolean().optional(), internationalRoamingEnabled: z.boolean().optional(), networkType: z.enum(["4G", "5G"]).optional(), }); // ============================================================================ // SIM Order Activation Schemas // ============================================================================ export const simOrderActivationMnpSchema = z.object({ reserveNumber: z.string().min(1, "Reserve number is required"), reserveExpireDate: z.string().regex(/^\d{8}$/, "Reserve expire date must be in YYYYMMDD format"), account: z.string().optional(), firstnameKanji: z.string().optional(), lastnameKanji: z.string().optional(), firstnameZenKana: z.string().optional(), lastnameZenKana: z.string().optional(), gender: z.string().optional(), birthday: z.string().regex(/^\d{8}$/, "Birthday must be in YYYYMMDD format").optional(), }); export const simOrderActivationAddonsSchema = z.object({ voiceMail: z.boolean().optional(), callWaiting: z.boolean().optional(), }); export const simOrderActivationRequestSchema = z.object({ planSku: z.string().min(1, "Plan SKU is required"), simType: z.enum(["eSIM", "Physical SIM"]), eid: z.string().min(15, "EID must be at least 15 characters").optional(), activationType: z.enum(["Immediate", "Scheduled"]), scheduledAt: z.string().regex(/^\d{8}$/, "Scheduled date must be in YYYYMMDD format").optional(), addons: simOrderActivationAddonsSchema.optional(), mnp: simOrderActivationMnpSchema.optional(), msisdn: z.string().min(1, "Phone number (msisdn) is required"), oneTimeAmountJpy: z.number().nonnegative("One-time amount must be non-negative"), monthlyAmountJpy: z.number().nonnegative("Monthly amount must be non-negative"), }).refine( (data) => { // If simType is eSIM, eid is required if (data.simType === "eSIM" && (!data.eid || data.eid.length < 15)) { return false; } return true; }, { message: "EID is required for eSIM and must be at least 15 characters", path: ["eid"], } ).refine( (data) => { // If activationType is Scheduled, scheduledAt is required if (data.activationType === "Scheduled" && !data.scheduledAt) { return false; } return true; }, { message: "Scheduled date is required for Scheduled activation", path: ["scheduledAt"], } ); export type SimOrderActivationRequest = z.infer; export type SimOrderActivationMnp = z.infer; export type SimOrderActivationAddons = z.infer; // Legacy aliases for backward compatibility export const simTopupRequestSchema = simTopUpRequestSchema; export type SimTopupRequest = SimTopUpRequest; export const simChangePlanRequestSchema = simPlanChangeRequestSchema; export type SimChangePlanRequest = SimPlanChangeRequest; export const simFeaturesRequestSchema = simFeaturesUpdateRequestSchema; export type SimFeaturesRequest = SimFeaturesUpdateRequest; // ============================================================================ // Inferred Types from Schemas (Schema-First Approach) // ============================================================================ export type SimStatus = z.infer; export type SimType = z.infer; export type SimDetails = z.infer; export type RecentDayUsage = z.infer; export type SimUsage = z.infer; export type SimTopUpHistoryEntry = z.infer; export type SimTopUpHistory = z.infer; // Request types (derived from request schemas) export type SimTopUpRequest = z.infer; export type SimPlanChangeRequest = z.infer; export type SimCancelRequest = z.infer; export type SimTopUpHistoryRequest = z.infer; export type SimFeaturesUpdateRequest = z.infer;