All files / src/app/api/promotions/validate-code route.ts

100% Statements 74/74
90.9% Branches 20/22
100% Functions 1/1
100% Lines 74/74

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 25x 25x 25x 25x 25x 25x 25x 2x 2x 2x 2x 2x 25x 25x 25x 25x 25x 4x 4x 21x 25x 5x 5x 16x 16x 16x 27x 27x 27x 27x 16x 16x 16x 16x 14x 25x 6x 6x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 25x 25x 25x 25x 1x 1x  
export const dynamic = "force-dynamic";
 
import { NextRequest, NextResponse } from 'next/server';
import { auth } from "@/lib/auth/auth";
import { prisma } from "@/lib/prisma";
import { promotionEngine } from "@/lib/promotions";
import {
  withErrorHandling,
  successResponse,
  ApiError,
  ApiSuccessResponse,
  ApiErrorResponse } from "@/lib/api";
import type { CartItem } from "@/lib/promotions/types";
 
/**
 * POST /api/promotions/validate-code
 * Validate a promo code against cart without applying it
 */
async function handlePost(
  request: NextRequest
): Promise<NextResponse<ApiSuccessResponse<unknown> | ApiErrorResponse>> {
  const session = await auth();
  let userId: number | undefined;
 
  if (session?.user?.email) {
    const user = await prisma.user.findUnique({
      where: { email: session.user.email },
      select: { id: true }});
    userId = user?.id;
  }
 
  const body = await request.json();
  const { code, cart } = body;
 
  if (!code || typeof code !== "string") {
    throw ApiError.badRequest("Promo code is required");
  }
 
  if (!cart || !Array.isArray(cart) || cart.length === 0) {
    throw ApiError.badRequest("Cart items are required");
  }
 
  // Validate cart items structure
  const cartItems: CartItem[] = cart.map((item) => ({
    productId: item.productId,
    quantity: item.quantity,
    price: item.price,
    categoryId: item.categoryId,
    title: item.title}));
 
  // Apply promo code using the engine
  const result = await promotionEngine.applyPromoCode(code.trim(), cartItems, userId);
 
  if (!result.success) {
    throw ApiError.badRequest(result.error || "Invalid promo code");
  }
 
  // Return validation result without actually applying
  return successResponse({
    promotion: {
      id: result.promotion!.id,
      name: result.promotion!.name,
      displayName: result.promotion!.displayName,
      type: result.promotion!.type,
      discountType: result.promotion!.discountType,
      discountValue: result.promotion!.discountValue},
    discount: {
      totalDiscount: result.discount!.totalDiscount,
      freeShipping: result.discount!.freeShipping || false,
      freeItems: result.discount!.freeItems || [],
      savingsMessage: result.discount!.savingsMessage}});
}
 
export const POST = withErrorHandling(handlePost);