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 { fieldpineServerApi } from '@/lib/server/fieldpineApi';
3import { getRequestContext, validateApiAccess } from '@/lib/server/sessionUtils';
4
5/**
6 * Sales/Invoices Endpoint (ELINK API)
7 * GET /api/v1/openapi/sales - List sales/invoices
8 * POST /api/v1/openapi/sales - Create new sale
9 *
10 * Uses ELINK API (retailmax.elink.sale.list)
11 * Security: Retail stores can access this (ELINK only)
12 */
13export async function GET(request: NextRequest) {
14 try {
15 // 1. Get session and store context
16 const context = await getRequestContext(request);
17
18 if (!context || !context.isAuthenticated) {
19 return NextResponse.json(
20 { error: 'Authentication required' },
21 { status: 401 }
22 );
23 }
24
25 // 2. SECURITY: Validate ELINK access
26 const apiAccessValidation = validateApiAccess(context, 'elink');
27 if (!apiAccessValidation.valid) {
28 console.warn(`[API Security] ELINK access denied: ${apiAccessValidation.error}`);
29 return NextResponse.json(
30 {
31 error: apiAccessValidation.error,
32 code: apiAccessValidation.errorCode
33 },
34 { status: 403 }
35 );
36 }
37
38 // 3. Parse query parameters
39 const { searchParams } = new URL(request.url);
40 const limit = searchParams.get('$top') || searchParams.get('limit') || '100';
41 const skip = searchParams.get('$skip') || searchParams.get('skip') || '0';
42 const customerId = searchParams.get('customerId');
43 const phase = searchParams.get('phase');
44
45 console.log('[Sales API] Fetching sales with:', { limit, skip, customerId, phase });
46
47 // 4. Build ELINK BUCK parameters
48 // Field reference: f102=sale ID, f131/f132=completed date, f210=total, f300=phase, f301=customer ID
49 const buckParams: Record<string, string> = {
50 '3': 'retailmax.elink.sale.list',
51 '10': '102,131,132,140,141,210,211,212,213,214,300,301,302,303,304,305',
52 '13': 'completeddt', // Sort by completion date (descending)
53 '20': limit,
54 '21': skip,
55 '99': Math.random().toString()
56 };
57
58 // Add filters if provided
59 if (customerId) {
60 buckParams['301'] = customerId;
61 }
62
63 if (phase) {
64 buckParams['300'] = phase;
65 }
66
67 // 5. Make ELINK API call using singleton
68 // Use store-specific URL for API calls
69 const result = await fieldpineServerApi.buckApiCall(buckParams, context.session.apiKey, context.store.url);
70
71 // 6. Transform BUCK response
72 let sales: any[] = [];
73 if (result && result.DATS && Array.isArray(result.DATS)) {
74 sales = result.DATS.map((sale: any) => ({
75 Sid: sale.f102_E || 0,
76 ExternalId: sale.f140_s || sale.f141_s || null,
77 CompletedDt: sale.f131_DT || sale.f132_DT || null,
78 Total: parseFloat(sale.f210_$) || 0,
79 Phase: parseInt(sale.f300_E) || 0,
80 CustomerId: sale.f301_s || null,
81 CustomerName: sale.f302_s || null,
82 LocationId: parseInt(sale.f303_E) || null,
83 LocationName: sale.f304_s || null,
84 CreatedDt: sale.f305_DT || null
85 }));
86 }
87
88 return NextResponse.json({
89 success: true,
90 data: {
91 value: sales,
92 '@odata.count': sales.length
93 },
94 source: 'elink'
95 });
96
97 } catch (error: any) {
98 console.error('[Sales API] Error:', error);
99 return NextResponse.json(
100 { error: error.message || 'Failed to fetch sales' },
101 { status: 500 }
102 );
103 }
104}
105
106/**
107 * Create new sale/invoice
108 */
109export async function POST(request: NextRequest) {
110 try {
111 // 1. Get session and store context
112 const context = await getRequestContext(request);
113
114 if (!context || !context.isAuthenticated) {
115 return NextResponse.json(
116 { error: 'Authentication required' },
117 { status: 401 }
118 );
119 }
120
121 // 2. SECURITY: Validate ELINK access
122 const apiAccessValidation = validateApiAccess(context, 'elink');
123 if (!apiAccessValidation.valid) {
124 return NextResponse.json(
125 {
126 error: apiAccessValidation.error,
127 code: apiAccessValidation.errorCode
128 },
129 { status: 403 }
130 );
131 }
132
133 const saleData = await request.json();
134 console.log('[Sales API] Creating sale:', saleData);
135
136 const result = await fieldpineServerApi.createSale(saleData, context.session.apiKey);
137
138 return NextResponse.json({
139 success: true,
140 data: result,
141 source: 'elink'
142 });
143
144 } catch (error: any) {
145 console.error('[Sales API] Create error:', error);
146 return NextResponse.json(
147 { error: error.message || 'Failed to create sale' },
148 { status: 500 }
149 );
150 }
151}