1import { NextRequest, NextResponse } from 'next/server';
2import { fieldpineServerApi } from '@/lib/server/fieldpineApi';
3import { getRequestContext, validateApiAccess } from '@/lib/server/sessionUtils';
6 * Customers Endpoint (ELINK API)
7 * GET /api/v1/openapi/customers
9 * Uses Fieldpine's ELINK API (retailmax.elink.customers)
10 * Security: Retail stores can access this (ELINK only)
12export async function GET(request: NextRequest) {
14 // 1. Get session and store context
15 const context = await getRequestContext(request);
17 if (!context || !context.isAuthenticated) {
18 return NextResponse.json(
19 { error: 'Authentication required' },
24 // 2. SECURITY: Validate ELINK access
25 const apiAccessValidation = validateApiAccess(context, 'elink');
26 if (!apiAccessValidation.valid) {
27 console.warn(`[API Security] ELINK access denied: ${apiAccessValidation.error}`);
28 return NextResponse.json(
30 error: apiAccessValidation.error,
31 code: apiAccessValidation.errorCode
38 const clientId = request.headers.get('x-forwarded-for') ||
39 request.headers.get('x-real-ip') ||
40 context.session.userId ||
42 if (!fieldpineServerApi.checkClientRateLimit(clientId)) {
43 return NextResponse.json(
44 { error: 'Rate limit exceeded' },
49 // 4. Parse query parameters
50 const { searchParams } = new URL(request.url);
51 const search = searchParams.get('search');
52 const customerId = searchParams.get('customerId');
53 const phone = searchParams.get('phone');
54 const email = searchParams.get('email');
55 const limit = searchParams.get('limit') || '100';
57 console.log(`[Customers API] Search params:`, { search, customerId, phone, email, limit });
59 // 5. Build ELINK BUCK parameters for customers
60 // Field reference: f100=customer ID, f1130=customer name, f152=phone, f153=email
61 const buckParams: Record<string, string> = {
62 "3": "retailmax.elink.customers",
63 "16": "4", // Detail level
65 "99": Math.random().toString()
70 buckParams["9"] = `f1130,8,${encodeURIComponent(search)}`;
71 } else if (customerId) {
72 buckParams["9"] = `f100,0,${customerId}`;
74 buckParams["9"] = `f152,8,${encodeURIComponent(phone)}`;
76 buckParams["9"] = `f153,8,${encodeURIComponent(email)}`;
79 // 6. Make ELINK API call using singleton
80 console.log(`[Customers API] Session data:`, {
81 hasApiKey: !!context.session.apiKey,
82 apiKeyLength: context.session.apiKey?.length,
83 userId: context.session.userId
86 if (!context.session.apiKey) {
87 console.error('[Customers API] No API key in session!');
88 return NextResponse.json(
89 { error: 'Session expired or invalid. Please log in again.' },
94 // Use store-specific URL for API calls
95 const buckResponse = await fieldpineServerApi.buckApiCall(
97 context.session.apiKey,
101 // 7. Transform BUCK response to OData format with proper field mapping
102 let customers: any[] = [];
103 if (buckResponse && buckResponse.RootType === "ARAY" && buckResponse.DATS && Array.isArray(buckResponse.DATS)) {
104 customers = buckResponse.DATS.map((item: any) => ({
106 Name: item.f1130 || '',
107 Email: item.f153 || '',
108 Phone: item.f152 || '',
109 Mobile: item.f159 || '', // f159 = mobile number
110 AccountBalance: item.f160 || 0, // f160 = account balance
111 Address1: item.f150 || '',
112 Address2: item.f151 || '',
113 City: item.f154 || '',
114 State: item.f155 || '',
115 Postcode: item.f156 || '',
116 Country: item.f157 || '',
117 DeliveryAddress1: item.f170 || '',
118 DeliveryAddress2: item.f171 || '',
119 DeliveryCity: item.f174 || '',
120 DeliveryState: item.f175 || '',
121 DeliveryPostcode: item.f176 || '',
122 DeliveryCountry: item.f177 || ''
126 console.log(`[Customers API] Returning ${customers.length} customers via ELINK`);
128 return NextResponse.json({
130 data: customers, // Return array directly for frontend compatibility
131 count: customers.length,
135 } catch (error: any) {
136 console.error('[Customers API] Error:', error);
138 // Check if it's a 403/authentication error
139 if (error.message && error.message.includes('403')) {
140 return NextResponse.json(
142 error: 'Your session has expired. Please refresh the page and log in again.',
143 code: 'SESSION_EXPIRED'
149 return NextResponse.json(
150 { error: error.message || 'Failed to fetch customers' },