1import { NextRequest, NextResponse } from "next/server";
2import { getRequestContext, validateApiAccess } from "@/lib/server/sessionUtils";
3import { fieldpineServerApi } from "@/lib/server/fieldpineApi";
6 * GET /api/v1/elink/sales-report
7 * POS Sales Report - uses ELINK retailmax.elink.saleflat.list
9 * Security: Retail stores can access this (ELINK only)
11export async function GET(request: NextRequest) {
13 // 1. Get session and store context
14 const context = await getRequestContext(request);
17 return NextResponse.json(
18 { success: false, error: "Unauthorized - Please log in" },
23 // 2. SECURITY: Validate ELINK access (allowed for retail stores)
24 const apiAccessValidation = validateApiAccess(context, 'elink');
25 if (!apiAccessValidation.valid) {
26 console.warn(`[API Security] ELINK access denied: ${apiAccessValidation.error}`);
27 return NextResponse.json(
30 error: apiAccessValidation.error,
31 code: apiAccessValidation.errorCode
37 // 3. Get query parameters
38 const { searchParams } = new URL(request.url);
39 const fromDate = searchParams.get('fromDate') || new Date().toISOString().split('T')[0];
40 const toDate = searchParams.get('toDate') || new Date().toISOString().split('T')[0];
41 const limit = searchParams.get('limit') || '200';
43 // 4. Format dates for Fieldpine API (DD-MM-YYYY)
44 const formatDateForAPI = (dateStr: string) => {
45 const [year, month, day] = dateStr.split("-");
46 return `${day}-${month}-${year}`;
49 const fromDateAPI = formatDateForAPI(fromDate);
50 const toDateAPI = formatDateForAPI(toDate);
52 console.log(`[POS Sales Report] Loading sales for ${context.store.name} from ${fromDate} to ${toDate}`);
54 // 5. Build ELINK BUCK parameters
55 // retailmax.elink.saleflat.list - Returns flat list of sale items
56 // Field predicates: f102,4,DATE = f102 >= DATE (greater than or equal)
57 // f102,1,DATE = f102 != DATE (not equal - acts as less than for end date)
58 const buckParams: Record<string, string | string[]> = {
59 "3": "retailmax.elink.saleflat.list",
60 "103": "1", // Include full product packet
61 "104": "1", // Include customer packet
62 "8": limit, // Max rows
63 "99": Math.random().toString() // Cache buster
66 // Add date filters as array (multiple "9" parameters)
68 `f102,4,${fromDateAPI}`, // f102 >= fromDate
69 `f102,1,${toDateAPI}` // f102 != toDate (effectively < toDate)
72 // 6. Make ELINK API call using singleton
73 // Use store-specific URL for API calls
74 const response = await fieldpineServerApi.buckApiCall(buckParams, context.session.apiKey, context.store.url);
77 return NextResponse.json({
81 store: context.store.name,
82 storeType: context.store.type,
83 dateRange: { from: fromDate, to: toDate },
84 endpoint: 'retailmax.elink.saleflat.list'
88 } catch (error: any) {
89 console.error("[POS Sales Report API] Error:", error);
90 return NextResponse.json(
91 { success: false, error: error.message || "Failed to fetch sales report" },