All files / src/app/api/loyalty/balance route.ts

0% Statements 0/115
100% Branches 0/0
0% Functions 0/1
0% Lines 0/115

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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                                                                                                                                                                                                                                       
export const dynamic = "force-dynamic";

import { NextRequest, NextResponse } from 'next/server';
import { Session } from "next-auth";
import { prisma } from "@/lib/prisma";
import {
  withAuth,
  withErrorHandling,
  successResponse,
  ApiSuccessResponse,
  ApiErrorResponse,
  RouteContext } from "@/lib/api";

interface LoyaltyBalanceData {
  totalPoints: number;
  lifetimePoints: number;
  pointsValue: number;
  currentTier: {
    id: number;
    name: string;
    pointsMultiplier: number;
    perks: unknown;
  } | null;
  nextTier: {
    id: number;
    name: string;
    minPoints: number;
    pointsToReach: number | null;
  } | null;
  program: {
    name: string;
    pointsPerDollar: number;
    redemptionRate: number;
  } | null;
}

/**
 * GET /api/loyalty/balance
 * Get current user's loyalty points balance
 */
async function handleGet(
  request: NextRequest,
  context: RouteContext | undefined,
  session: Session
): Promise<NextResponse<ApiSuccessResponse<LoyaltyBalanceData> | ApiErrorResponse>> {
  const userId = session.user.id;

  // Get customer loyalty record
  let loyalty = await prisma.customerLoyalty.findUnique({
    where: { userId }});

  // Create loyalty record if it doesn't exist
  if (!loyalty) {
    loyalty = await prisma.customerLoyalty.create({
      data: {
        userId,
        totalPoints: 0,
        lifetimePoints: 0}});
  }

  // Get active loyalty program
  const program = await prisma.loyaltyProgram.findFirst({
    where: { isActive: true },
    include: {
      tiers: { orderBy: { minPoints: "asc" } }}});

  // Calculate current tier and next tier
  let currentTier = null;
  let nextTier = null;
  let pointsToNextTier = null;

  if (program && program.tiers.length > 0) {
    // Find current tier (highest tier the user qualifies for)
    for (const tier of program.tiers) {
      if (loyalty.lifetimePoints >= tier.minPoints) {
        currentTier = tier;
      } else if (!nextTier) {
        nextTier = tier;
        pointsToNextTier = tier.minPoints - loyalty.lifetimePoints;
      }
    }
  }

  // Calculate dollar value of points
  const pointsValue = program
    ? loyalty.totalPoints * program.redemptionRate
    : loyalty.totalPoints * 0.01;

  return successResponse({
    totalPoints: loyalty.totalPoints,
    lifetimePoints: loyalty.lifetimePoints,
    pointsValue: Math.round(pointsValue * 100) / 100,
    currentTier: currentTier
      ? {
          id: currentTier.id,
          name: currentTier.name,
          pointsMultiplier: currentTier.pointsMultiplier,
          perks: currentTier.perks}
      : null,
    nextTier: nextTier
      ? {
          id: nextTier.id,
          name: nextTier.name,
          minPoints: nextTier.minPoints,
          pointsToReach: pointsToNextTier}
      : null,
    program: program
      ? {
          name: program.name,
          pointsPerDollar: program.pointsPerDollar,
          redemptionRate: program.redemptionRate}
      : null});
}

export const GET = withErrorHandling(withAuth(handleGet));