175 lines
5.5 KiB
TypeScript
Raw Normal View History

/**
* SIM Domain - Schemas
*/
import { z } from "zod";
import type {
SimTopUpRequest,
SimPlanChangeRequest,
SimCancelRequest,
SimTopUpHistoryRequest,
SimFeaturesUpdateRequest,
} from "./contract";
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.ZodType<SimTopUpRequest> = 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.ZodType<SimPlanChangeRequest> = 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.ZodType<SimCancelRequest> = z.object({
scheduledAt: z
.string()
.regex(/^\d{8}$/, "Scheduled date must be in YYYYMMDD format")
.optional(),
});
export const simTopUpHistoryRequestSchema: z.ZodType<SimTopUpHistoryRequest> = 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.ZodType<SimFeaturesUpdateRequest> = 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<typeof simOrderActivationRequestSchema>;
export type SimOrderActivationMnp = z.infer<typeof simOrderActivationMnpSchema>;
export type SimOrderActivationAddons = z.infer<typeof simOrderActivationAddonsSchema>;