161 lines
4.4 KiB
TypeScript
Raw Normal View History

/**
* Orders Domain - Validation
*
* Extended business validation rules for orders.
* These rules represent domain logic and should be reusable across frontend/backend.
*/
import { z } from "zod";
import { orderBusinessValidationSchema } from "./schema";
// ============================================================================
// SKU Business Rules Helpers
// ============================================================================
/**
* Check if SKUs array contains a SIM service plan
* (excludes activation fees and addons)
*/
export function hasSimServicePlan(skus: string[]): boolean {
return skus.some(
(sku) =>
sku.toUpperCase().includes("SIM") &&
!sku.toUpperCase().includes("ACTIVATION") &&
!sku.toUpperCase().includes("ADDON")
);
}
/**
* Check if SKUs array contains a SIM activation fee
*/
export function hasSimActivationFee(skus: string[]): boolean {
return skus.some(
(sku) =>
sku.toUpperCase().includes("ACTIVATION") ||
sku.toUpperCase().includes("SIM-ACTIVATION")
);
}
/**
* Check if SKUs array contains a VPN activation fee
*/
export function hasVpnActivationFee(skus: string[]): boolean {
return skus.some(
(sku) =>
sku.toUpperCase().includes("VPN") &&
sku.toUpperCase().includes("ACTIVATION")
);
}
/**
* Check if SKUs array contains an Internet service plan
* (excludes installation and addons)
*/
export function hasInternetServicePlan(skus: string[]): boolean {
return skus.some(
(sku) =>
sku.toUpperCase().includes("INTERNET") &&
!sku.toUpperCase().includes("INSTALL") &&
!sku.toUpperCase().includes("ADDON")
);
}
/**
* Check if SKUs array contains main service SKUs for Internet orders
* (filters out installation, addons, activation fees)
*/
export function getMainServiceSkus(skus: string[]): string[] {
return skus.filter((sku) => {
const upperSku = sku.toUpperCase();
return (
!upperSku.includes("INSTALL") &&
!upperSku.includes("ADDON") &&
!upperSku.includes("ACTIVATION") &&
!upperSku.includes("FEE")
);
});
}
// ============================================================================
// Extended Order Validation with SKU Business Rules
// ============================================================================
/**
* Complete order validation including all SKU business rules
*
* This schema delegates to the helper functions above for DRY validation.
* Helper functions are reusable in both schema refinements and imperative validation.
*
* Validates:
* - Basic order structure (from orderBusinessValidationSchema)
* - SIM orders have service plan + activation fee
* - VPN orders have activation fee
* - Internet orders have service plan
*/
export const orderWithSkuValidationSchema = orderBusinessValidationSchema
.refine(
(data) => data.orderType !== "SIM" || hasSimServicePlan(data.skus),
{
message: "SIM orders must include a SIM service plan",
path: ["skus"],
}
)
.refine(
(data) => data.orderType !== "SIM" || hasSimActivationFee(data.skus),
{
message: "SIM orders require an activation fee",
path: ["skus"],
}
)
.refine(
(data) => data.orderType !== "VPN" || hasVpnActivationFee(data.skus),
{
message: "VPN orders require an activation fee",
path: ["skus"],
}
)
.refine(
(data) => data.orderType !== "Internet" || hasInternetServicePlan(data.skus),
{
message: "Internet orders require a service plan",
path: ["skus"],
}
);
export type OrderWithSkuValidation = z.infer<typeof orderWithSkuValidationSchema>;
// ============================================================================
// Validation Error Messages
// ============================================================================
/**
* Get specific validation error message for order type
*/
export function getOrderTypeValidationError(orderType: string, skus: string[]): string | null {
switch (orderType) {
case "SIM":
if (!hasSimServicePlan(skus)) {
return "A SIM plan must be selected";
}
if (!hasSimActivationFee(skus)) {
return "SIM orders require an activation fee";
}
break;
case "VPN":
if (!hasVpnActivationFee(skus)) {
return "VPN orders require an activation fee";
}
break;
case "Internet":
if (!hasInternetServicePlan(skus)) {
return "Internet orders require a service plan";
}
break;
}
return null;
}