Files
2025-10-21 15:44:16 +03:00

139 lines
4.3 KiB
TypeScript

import { z } from "zod";
import { CustomerInfoModel, customerInfoModel } from "../../customerinfo/data";
import { CheckoutStep } from "../../order/data/enums";
import {
PaymentInfoPayload,
paymentInfoPayloadModel,
} from "../../paymentinfo/data/entities";
import { productModel } from "../../product/data";
// Define action types for the checkout flow
export enum CKActionType {
PutInVerification = "PUT_IN_VERIFICATION",
ShowVerificationScreen = "SHOW_VERIFICATION_SCREEN",
RequestOTP = "REQUEST_OTP",
CompleteOrder = "COMPLETE_ORDER",
BackToPII = "BACK_TO_PII",
BackToPayment = "BACK_TO_PAYMENT",
TerminateSession = "TERMINATE_SESSION",
}
export enum SessionOutcome {
PENDING = "PENDING",
COMPLETED = "COMPLETED",
ABANDONED = "ABANDONED",
TERMINATED = "TERMINATED",
EXPIRED = "EXPIRED",
PAYMENT_FAILED = "PAYMENT_FAILED",
PAYMENT_SUCCESSFUL = "PAYMENT_SUCCESSFUL",
VERIFICATION_FAILED = "VERIFICATION_FAILED",
SYSTEM_ERROR = "SYSTEM_ERROR",
}
export enum PaymentErrorType {
DO_NOT_HONOR = "DO_NOT_HONOR",
REFER_TO_ISSUER = "REFER_TO_ISSUER",
TRANSACTION_DENIED = "TRANSACTION_DENIED",
CAPTURE_CARD_ERROR = "CAPTURE_CARD_ERROR",
CUSTOM_ERROR = "CUSTOM_ERROR",
}
export interface PaymentErrorMessage {
type: PaymentErrorType;
message: string;
description: string;
}
// Model for pending actions in the flow
export const pendingActionModel = z.object({
id: z.string(),
type: z.nativeEnum(CKActionType),
data: z.record(z.string(), z.any()).default({}),
});
export type PendingAction = z.infer<typeof pendingActionModel>;
export const pendingActionsModel = z.array(pendingActionModel);
export type PendingActions = z.infer<typeof pendingActionsModel>;
// Core flow information model - what's actually stored in Redis
export const flowInfoModel = z.object({
id: z.coerce.number().optional(),
flowId: z.string(),
domain: z.string(),
checkoutStep: z.nativeEnum(CheckoutStep),
showVerification: z.boolean().default(false),
createdAt: z.string().datetime(),
lastPinged: z.string().datetime(),
isActive: z.boolean().default(true),
lastSyncedAt: z.string().datetime(),
productInfo: productModel.optional(),
productId: z.number().nullable().optional(),
personalInfoLastSyncedAt: z.string().datetime().optional(),
paymentInfoLastSyncedAt: z.string().datetime().optional(),
pendingActions: pendingActionsModel.default([]),
personalInfo: z.custom<CustomerInfoModel>().optional(),
paymentInfo: z.custom<PaymentInfoPayload>().optional(),
refOids: z.array(z.number()).optional(),
otpCode: z.coerce.string().optional(),
otpSubmitted: z.boolean().default(false),
partialOtpCode: z.coerce.string().optional(),
ipAddress: z.string().default(""),
userAgent: z.string().default(""),
reserved: z.boolean().default(false),
reservedBy: z.string().nullable().optional(),
liveCheckoutStartedAt: z.string().datetime().optional(),
completedAt: z.coerce.string().datetime().nullable().optional(),
sessionOutcome: z.string(),
isDeleted: z.boolean().default(false),
});
export type FlowInfo = z.infer<typeof flowInfoModel>;
// Payload for frontend to create a checkout flow
export const feCreateCheckoutFlowPayloadModel = z.object({
domain: z.string(),
refOIds: z.array(z.number()),
productId: z.number().optional(),
});
export type FECreateCheckoutFlowPayload = z.infer<
typeof feCreateCheckoutFlowPayloadModel
>;
// Complete payload for backend to create a checkout flow
export const createCheckoutFlowPayloadModel = z.object({
flowId: z.string(),
domain: z.string(),
refOIds: z.array(z.number()),
productId: z.number().optional(),
ipAddress: z.string().default(""),
userAgent: z.string().default(""),
initialUrl: z.string().default(""),
provider: z.string().default("kiwi"),
});
export type CreateCheckoutFlowPayload = z.infer<
typeof createCheckoutFlowPayloadModel
>;
// Step-specific payloads
export const prePaymentFlowStepPayloadModel = z.object({
initialUrl: z.string(),
personalInfo: customerInfoModel.optional(),
});
export type PrePaymentFlowStepPayload = z.infer<
typeof prePaymentFlowStepPayloadModel
>;
export const paymentFlowStepPayloadModel = z.object({
personalInfo: customerInfoModel.optional(),
paymentInfo: paymentInfoPayloadModel.optional(),
});
export type PaymentFlowStepPayload = z.infer<
typeof paymentFlowStepPayloadModel
>;