1import { NextRequest, NextResponse } from 'next/server';
2import { fieldpineServerApi } from '@/lib/server/fieldpineApi';
3import { getStoredAuth } from '@/lib/server/auth';
6 * Product Stock Adjustment API
7 * POST /api/v1/products/stock-adjustment
8 * Adjust product stock levels with reason tracking
10export async function POST(request: NextRequest) {
12 const authData = await getStoredAuth();
13 if (!authData || !authData.authenticated) {
14 return NextResponse.json(
15 { success: false, error: 'Authentication required' },
20 const body = await request.json();
21 const { productId, adjustment, reason, locationId = 1 } = body;
24 return NextResponse.json(
25 { success: false, error: 'Product ID is required' },
30 if (adjustment === undefined || adjustment === null) {
31 return NextResponse.json(
32 { success: false, error: 'Adjustment amount is required' },
37 const adjustmentNum = parseFloat(adjustment);
38 if (isNaN(adjustmentNum)) {
39 return NextResponse.json(
40 { success: false, error: 'Invalid adjustment amount' },
45 console.log('[Stock Adjustment] Request:', { productId, adjustment: adjustmentNum, reason, locationId });
48 const escapeXml = (v: string | number) =>
49 String(v).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
51 // Determine transaction type based on reason
52 let transactionType = 204; // Default: Manual Adjustment
53 let comments = reason || 'Manual adjustment';
57 transactionType = 100; // Received
58 comments = 'Stock Received';
61 transactionType = 210; // Sales
62 comments = 'Sale Adjustment';
66 transactionType = 201; // Write Off
67 comments = 'Damage/Loss';
70 transactionType = 200; // Supplier Return
71 comments = 'Stock Return';
75 transactionType = 204; // Stocktake Adjustment
76 comments = 'Manual Adjustment';
79 // Build DATI XML for goods in history (stock movement)
82 '<f8_s>retailmax.elink.goodsin.edit</f8_s>',
84 `<f100_E>${escapeXml(productId)}</f100_E>`,
85 `<f110_E>${transactionType}</f110_E>`,
86 `<f111>${Math.abs(adjustmentNum)}</f111>`,
87 `<f120_E>${escapeXml(locationId)}</f120_E>`,
88 `<f140_s>${escapeXml(comments)}</f140_s>`,
92 console.log('[Stock Adjustment] DATI XML:', xml);
95 const url = `${process.env.FIELDPINE_BASE_URL || 'https://iig.cwanz.online'}/GNAP/j/buck`;
96 const headers: Record<string, string> = {
97 'Accept': 'application/json',
98 'Content-Type': 'text/xml',
99 'Cookie': `FieldpineApiKey=${authData.apiKey}`
102 const response = await fetch(url, {
109 const errorText = await response.text();
110 console.error('[Stock Adjustment] Error response:', errorText);
111 throw new Error(`Stock adjustment failed: ${response.status} ${response.statusText}`);
114 const result = await response.json();
115 console.log('[Stock Adjustment] Success:', result);
117 return NextResponse.json({
120 message: `Stock adjusted by ${adjustmentNum > 0 ? '+' : ''}${adjustmentNum}`,
124 } catch (error: any) {
125 console.error('[Stock Adjustment] Error:', error);
126 return NextResponse.json(
127 { success: false, error: error.message || 'Failed to adjust stock' },