EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
route.ts
Go to the documentation of this file.
1import { NextRequest, NextResponse } from "next/server";
2import { getRequestContext, validateStoreAccess, getStoreApiUrl } from "@/lib/server/sessionUtils";
3import { FieldpineServerApi } from "@/lib/server/fieldpineApi";
4
5/**
6 * GET /api/v1/products/stock-alerts
7 * Get products with low stock levels across locations
8 * Uses OpenAPI Products endpoint (store-specific)
9 */
10export async function GET(request: NextRequest) {
11 try {
12 // Get session and store context
13 const context = await getRequestContext(request);
14
15 if (!context) {
16 return NextResponse.json(
17 { success: false, error: "Unauthorized" },
18 { status: 401 }
19 );
20 }
21
22 // Validate this is a retail store (not management portal)
23 const validation = validateStoreAccess(context, 'store');
24 if (!validation.valid) {
25 return NextResponse.json(
26 { success: false, error: validation.error },
27 { status: 403 }
28 );
29 }
30
31 const searchParams = request.nextUrl.searchParams;
32 const limit = parseInt(searchParams.get("limit") || "20");
33 const threshold = parseInt(searchParams.get("threshold") || "5");
34
35 // Get store-specific API URL for OpenAPI
36 const apiUrl = getStoreApiUrl(context, 'openapi');
37 const api = new FieldpineServerApi(apiUrl);
38
39 // Fetch products from store's OpenAPI endpoint
40 const productsResponse = await api.apiCall('/Products', {
41 method: 'GET',
42 params: { limit: '1000' },
43 cookie: context.session.apiKey
44 });
45
46 const products = productsResponse?.data?.Product || [];
47
48 console.log(`[Stock Alerts API] Found ${products.length} products at ${context.store.name}`);
49
50 // Filter products with low stock using OpenAPI StockLevel field
51 const lowStockProducts = products
52 .filter((p: any) => {
53 const stockLevel = p.StockLevel || 0;
54 return stockLevel <= threshold && stockLevel >= 0;
55 })
56 .sort((a: any, b: any) => (a.StockLevel || 0) - (b.StockLevel || 0))
57 .slice(0, limit)
58 .map((p: any) => ({
59 pid: p.pid,
60 description: p.Name || p.ProductName || 'Unknown Product',
61 totalQty: p.StockLevel || 0,
62 locations: [] // OpenAPI doesn't provide per-location breakdown
63 }));
64
65 console.log(`[Stock Alerts API] Low stock products found: ${lowStockProducts.length}`);
66
67 if (lowStockProducts.length === 0) {
68 return NextResponse.json({
69 success: true,
70 data: [],
71 meta: {
72 total: 0,
73 threshold,
74 store: context.store.name,
75 storeType: context.store.type
76 },
77 });
78 }
79
80 return NextResponse.json({
81 success: true,
82 data: lowStockProducts,
83 meta: {
84 total: lowStockProducts.length,
85 threshold,
86 scannedProducts: products.length,
87 store: context.store.name,
88 storeType: context.store.type
89 },
90 });
91 } catch (error: any) {
92 console.error("[Stock Alerts API] Error:", error);
93 return NextResponse.json(
94 { success: false, error: error.message || "Failed to fetch stock alerts" },
95 { status: 500 }
96 );
97 }
98}