122 lines
4.2 KiB
TypeScript
122 lines
4.2 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { VendorType, VendorStatus } from '@prisma/client'
|
|
import { generateUniqueSlug, slugify } from '@/lib/utils/slugify'
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json()
|
|
|
|
console.log('Received data:', body) // Debug logging
|
|
|
|
// Validate required fields
|
|
if (!body.name || !body.type) {
|
|
return NextResponse.json(
|
|
{ error: 'Name and vendor type are required' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
const baseSlug = slugify(body.name)
|
|
const uniqueSlug = await generateUniqueSlug(
|
|
baseSlug,
|
|
async (slug) => {
|
|
const existing = await prisma.vendor.findUnique({
|
|
where: { slug }
|
|
})
|
|
return !!existing
|
|
}
|
|
)
|
|
|
|
// Check if we have address data
|
|
const hasAddress = body.street && body.city && body.state && body.postalCode
|
|
|
|
// Parse numeric values
|
|
const parseFloatOrNull = (value: any): number | null => {
|
|
if (value === null || value === undefined || value === '') return null
|
|
const num = parseFloat(value)
|
|
return isNaN(num) ? null : num
|
|
}
|
|
|
|
const parseDateOrNull = (value: any): Date | null => {
|
|
if (!value) return null
|
|
const date = new Date(value)
|
|
return isNaN(date.getTime()) ? null : date
|
|
}
|
|
|
|
// Prepare vendor data WITHOUT addressId
|
|
const vendorData: any = {
|
|
slug: uniqueSlug,
|
|
name: body.name,
|
|
type: body.type as VendorType,
|
|
description: body.description || null,
|
|
website: body.website || null,
|
|
contactPerson: body.contactPerson || null,
|
|
email: body.email || null,
|
|
phone: body.phone || null,
|
|
status: (body.status as VendorStatus) || 'CONTACTING',
|
|
isBooked: Boolean(body.isBooked),
|
|
bookedDate: parseDateOrNull(body.bookedDate),
|
|
quotedPrice: parseFloatOrNull(body.quotedPrice),
|
|
finalCost: parseFloatOrNull(body.finalCost),
|
|
depositPaid: parseFloatOrNull(body.depositPaid),
|
|
depositDueDate: parseDateOrNull(body.depositDueDate),
|
|
finalPaymentDue: parseDateOrNull(body.finalPaymentDue),
|
|
paymentNotes: body.paymentNotes || null,
|
|
contractUrl: body.contractUrl || null,
|
|
proposalUrl: body.proposalUrl || null,
|
|
notes: body.notes || null,
|
|
}
|
|
|
|
// Add address relation if we have address data
|
|
if (hasAddress) {
|
|
vendorData.address = {
|
|
create: {
|
|
street: body.street,
|
|
city: body.city,
|
|
state: body.state,
|
|
zip: parseInt(body.postalCode),
|
|
}
|
|
}
|
|
}
|
|
// If no address, don't include address field at all
|
|
|
|
console.log('Creating vendor with data:', vendorData) // Debug logging
|
|
|
|
const vendor = await prisma.vendor.create({
|
|
data: vendorData,
|
|
include: {
|
|
address: hasAddress // Only include address if we created one
|
|
}
|
|
})
|
|
|
|
return NextResponse.json(vendor, { status: 201 })
|
|
|
|
} catch (error: any) {
|
|
console.error('Error creating vendor:', error)
|
|
|
|
// Provide helpful error messages
|
|
if (error.code === 'P2002') {
|
|
return NextResponse.json(
|
|
{ error: 'A vendor with this name already exists' },
|
|
{ status: 409 }
|
|
)
|
|
}
|
|
|
|
if (error.code === 'P2023') {
|
|
return NextResponse.json(
|
|
{ error: 'Invalid data format provided' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Failed to create vendor',
|
|
details: error.message,
|
|
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
|
|
},
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
} |