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 | export const dynamic = "force-dynamic"; import { NextRequest, NextResponse } from 'next/server'; import { } from "next-auth"; import { prisma } from "@/lib/prisma"; import { logger } from "@/lib/logging"; import { z } from "zod"; import { pricingEngine, PricingContext } from "@/lib/ecommerce"; import { withAdmin, withErrorHandling, successResponse, ApiError, ApiSuccessResponse, ApiErrorResponse } from "@/lib/api"; import { } from "@/lib/api/middleware"; const LOG_CATEGORY = "ADMIN_PRICING_PREVIEW_API"; const previewSchema = z.object({ productId: z.number().int().positive(), quantity: z.number().int().positive().default(1), userId: z.number().int().positive().optional(), cartTotal: z.number().min(0).optional(), isFirstPurchase: z.boolean().optional(), customerSegmentIds: z.array(z.number()).optional() }); /** * POST /api/admin/pricing/preview * Preview dynamic pricing for a product */ async function handlePost(request: NextRequest): Promise<NextResponse<ApiSuccessResponse<unknown> | ApiErrorResponse>> { const body = await request.json(); // Validate input const validationResult = previewSchema.safeParse(body); if (!validationResult.success) { throw ApiError.validation("Validation failed", validationResult.error.issues); } const validatedData = validationResult.data; // Get product info const product = await prisma.product.findUnique({ where: { id: validatedData.productId }, select: { id: true, title: true, price: true, discountedPrice: true, categoryId: true, stock: true } }); if (!product) { throw ApiError.notFound("Product"); } // Build pricing context const context: PricingContext = { productId: product.id, quantity: validatedData.quantity, categoryId: product.categoryId, stockLevel: product.stock, currentTime: new Date(), dayOfWeek: new Date().getDay(), hourOfDay: new Date().getHours(), userId: validatedData.userId, cartTotal: validatedData.cartTotal, isFirstPurchase: validatedData.isFirstPurchase, customerSegmentIds: validatedData.customerSegmentIds }; // Calculate dynamic price const result = await pricingEngine.previewPrice( product.id, product.price, context ); // Get volume tiers for this product const volumeTiers = await pricingEngine.getVolumeTiers(product.id); logger.info("Pricing preview calculated", { category: LOG_CATEGORY, productId: product.id, originalPrice: result.originalPrice, finalPrice: result.finalPrice }); return successResponse({ product: { id: product.id, title: product.title, basePrice: product.price, currentDiscountedPrice: product.discountedPrice }, pricing: { originalPrice: result.originalPrice, finalPrice: result.finalPrice, discountAmount: result.discountAmount, discountPercent: result.discountPercent, appliedRules: result.appliedRules }, volumeTiers, context: { quantity: context.quantity, stockLevel: context.stockLevel, dayOfWeek: context.dayOfWeek, hourOfDay: context.hourOfDay } }); } export const POST = withErrorHandling(withAdmin(handlePost)); |