import { NextRequest, NextResponse } from 'next/server'; import { ObjectId } from 'mongodb'; import { getDb } from '@/lib/mongodb'; export async function GET(request: NextRequest) { const { searchParams } = request.nextUrl; const page = Math.max(1, parseInt(searchParams.get('page') || '1')); const limit = Math.min(100, Math.max(1, parseInt(searchParams.get('limit') || '10'))); const search = searchParams.get('search') || ''; const categoryId = searchParams.get('categoryId'); const subcategoryId = searchParams.get('subcategoryId'); const db = await getDb(); const matchStage: Record = {}; if (categoryId) { matchStage.categoryId = new ObjectId(categoryId); } if (subcategoryId) { matchStage.subcategoryId = new ObjectId(subcategoryId); } if (search) { matchStage.$or = [ { name: { $regex: search, $options: 'i' } }, { code: { $regex: search, $options: 'i' } }, ]; } const pipeline = [ { $match: matchStage }, { $lookup: { from: 'categories', localField: 'categoryId', foreignField: '_id', as: 'categoryDoc', }, }, { $lookup: { from: 'subcategories', localField: 'subcategoryId', foreignField: '_id', as: 'subcategoryDoc', }, }, { $lookup: { from: 'suppliers', localField: 'supplierId', foreignField: '_id', as: 'supplierDoc', }, }, { $project: { code: 1, name: 1, category: { $arrayElemAt: ['$categoryDoc.name', 0] }, subcategory: { $arrayElemAt: ['$subcategoryDoc.name', 0] }, quantity: 1, unit: 1, unitPrice: 1, vat: 1, supplier: { $arrayElemAt: ['$supplierDoc.name', 0] }, createdAt: 1, updatedAt: 1, }, }, { $sort: { createdAt: -1 as const } }, ]; const [data, countResult] = await Promise.all([ db.collection('ingredients') .aggregate(pipeline) .skip((page - 1) * limit) .limit(limit) .toArray(), db.collection('ingredients') .countDocuments(matchStage), ]); return NextResponse.json({ data, total: countResult, page, limit, }); } export async function POST(request: Request) { const body = await request.json(); const { name, categoryId, subcategoryId, quantity, unit, unitPrice, vat, supplierId } = body; if (!name || !categoryId || !subcategoryId || !quantity || !unit || unitPrice == null || vat == null || !supplierId) { return NextResponse.json({ error: 'All fields are required' }, { status: 400 }); } const db = await getDb(); // Auto-generate code const last = await db.collection('ingredients') .find({}, { projection: { code: 1 } }) .sort({ code: -1 }) .limit(1) .next(); const lastNum = last?.code ? parseInt(last.code.replace('ING-', '')) : 0; const code = `ING-${String(lastNum + 1).padStart(3, '0')}`; const now = new Date(); const doc: Record = { code, name, categoryId: new ObjectId(categoryId), subcategoryId: new ObjectId(subcategoryId), quantity, unit, unitPrice, vat, supplierId: new ObjectId(supplierId), createdAt: now, updatedAt: now, }; // Optional discount fields if (body.discountType) { doc.discountType = body.discountType; doc.discountValue = body.discountValue ?? 0; doc.applyDiscountToNet = body.applyDiscountToNet ?? false; } // Optional advanced fields if (body.minStockLevel != null) doc.minStockLevel = body.minStockLevel; if (body.storageInstructions) doc.storageInstructions = body.storageInstructions; if (body.shelfLifeDays != null) doc.shelfLifeDays = body.shelfLifeDays; if (body.notes) doc.notes = body.notes; const result = await db.collection('ingredients').insertOne(doc); return NextResponse.json({ _id: result.insertedId, ...doc }, { status: 201 }); }