import { prisma } from "./db.server"; import type { Vehicle } from "@prisma/client"; import type { CreateVehicleData, UpdateVehicleData, VehicleWithOwner, VehicleWithRelations } from "~/types/database"; // Get all vehicles with search and pagination export async function getVehicles( searchQuery?: string, page: number = 1, limit: number = 10, ownerId?: number, plateNumber?: string ): Promise<{ vehicles: VehicleWithOwner[]; total: number; totalPages: number; }> { const offset = (page - 1) * limit; // Build where clause for search const whereClause: any = {}; if (ownerId) { whereClause.ownerId = ownerId; } if (plateNumber) { whereClause.plateNumber = { contains: plateNumber.toLowerCase() }; } if (searchQuery) { const searchLower = searchQuery.toLowerCase(); whereClause.OR = [ { plateNumber: { contains: searchLower } }, { manufacturer: { contains: searchLower } }, { model: { contains: searchLower } }, { bodyType: { contains: searchLower } }, { owner: { name: { contains: searchLower } } }, ]; } const [vehicles, total] = await Promise.all([ prisma.vehicle.findMany({ where: whereClause, include: { owner: { select: { id: true, name: true, phone: true, email: true, }, }, }, orderBy: { createdDate: 'desc' }, skip: offset, take: limit, }), prisma.vehicle.count({ where: whereClause }), ]); return { vehicles, total, totalPages: Math.ceil(total / limit), }; } // Get vehicle by ID with full relationships export async function getVehicleById(id: number): Promise { return await prisma.vehicle.findUnique({ where: { id }, include: { owner: true, maintenanceVisits: { orderBy: { visitDate: 'desc' }, take: 10, }, }, }); } // Create new vehicle export async function createVehicle( vehicleData: CreateVehicleData ): Promise<{ success: boolean; vehicle?: Vehicle; error?: string }> { try { // Check if vehicle with same plate number already exists const existingVehicle = await prisma.vehicle.findUnique({ where: { plateNumber: vehicleData.plateNumber }, }); if (existingVehicle) { return { success: false, error: "رقم اللوحة موجود بالفعل" }; } // Check if owner exists const owner = await prisma.customer.findUnique({ where: { id: vehicleData.ownerId }, }); if (!owner) { return { success: false, error: "المالك غير موجود" }; } // Create vehicle const vehicle = await prisma.vehicle.create({ data: { plateNumber: vehicleData.plateNumber.trim(), bodyType: vehicleData.bodyType.trim(), manufacturer: vehicleData.manufacturer.trim(), model: vehicleData.model.trim(), trim: vehicleData.trim?.trim() || null, year: vehicleData.year, transmission: vehicleData.transmission, fuel: vehicleData.fuel, cylinders: vehicleData.cylinders || null, engineDisplacement: vehicleData.engineDisplacement || null, useType: vehicleData.useType, ownerId: vehicleData.ownerId, }, }); return { success: true, vehicle }; } catch (error) { console.error("Error creating vehicle:", error); return { success: false, error: "حدث خطأ أثناء إنشاء المركبة" }; } } // Update vehicle export async function updateVehicle( id: number, vehicleData: UpdateVehicleData ): Promise<{ success: boolean; vehicle?: Vehicle; error?: string }> { try { // Check if vehicle exists const existingVehicle = await prisma.vehicle.findUnique({ where: { id }, }); if (!existingVehicle) { return { success: false, error: "المركبة غير موجودة" }; } // Check for plate number conflicts with other vehicles if (vehicleData.plateNumber) { const conflictVehicle = await prisma.vehicle.findFirst({ where: { AND: [ { id: { not: id } }, { plateNumber: vehicleData.plateNumber }, ], }, }); if (conflictVehicle) { return { success: false, error: "رقم اللوحة موجود بالفعل" }; } } // Check if new owner exists (if changing owner) if (vehicleData.ownerId && vehicleData.ownerId !== existingVehicle.ownerId) { const owner = await prisma.customer.findUnique({ where: { id: vehicleData.ownerId }, }); if (!owner) { return { success: false, error: "المالك الجديد غير موجود" }; } } // Prepare update data const updateData: any = {}; if (vehicleData.plateNumber !== undefined) updateData.plateNumber = vehicleData.plateNumber.trim(); if (vehicleData.bodyType !== undefined) updateData.bodyType = vehicleData.bodyType.trim(); if (vehicleData.manufacturer !== undefined) updateData.manufacturer = vehicleData.manufacturer.trim(); if (vehicleData.model !== undefined) updateData.model = vehicleData.model.trim(); if (vehicleData.trim !== undefined) updateData.trim = vehicleData.trim?.trim() || null; if (vehicleData.year !== undefined) updateData.year = vehicleData.year; if (vehicleData.transmission !== undefined) updateData.transmission = vehicleData.transmission; if (vehicleData.fuel !== undefined) updateData.fuel = vehicleData.fuel; if (vehicleData.cylinders !== undefined) updateData.cylinders = vehicleData.cylinders || null; if (vehicleData.engineDisplacement !== undefined) updateData.engineDisplacement = vehicleData.engineDisplacement || null; if (vehicleData.useType !== undefined) updateData.useType = vehicleData.useType; if (vehicleData.ownerId !== undefined) updateData.ownerId = vehicleData.ownerId; if (vehicleData.lastVisitDate !== undefined) updateData.lastVisitDate = vehicleData.lastVisitDate; if (vehicleData.suggestedNextVisitDate !== undefined) updateData.suggestedNextVisitDate = vehicleData.suggestedNextVisitDate; // Update vehicle const vehicle = await prisma.vehicle.update({ where: { id }, data: updateData, }); return { success: true, vehicle }; } catch (error) { console.error("Error updating vehicle:", error); return { success: false, error: "حدث خطأ أثناء تحديث المركبة" }; } } // Delete vehicle with relationship handling export async function deleteVehicle( id: number ): Promise<{ success: boolean; error?: string }> { try { // Check if vehicle exists const existingVehicle = await prisma.vehicle.findUnique({ where: { id }, include: { maintenanceVisits: true, }, }); if (!existingVehicle) { return { success: false, error: "المركبة غير موجودة" }; } // Check if vehicle has maintenance visits if (existingVehicle.maintenanceVisits.length > 0) { return { success: false, error: `لا يمكن حذف المركبة لأنها تحتوي على ${existingVehicle.maintenanceVisits.length} زيارة صيانة. يرجى حذف الزيارات أولاً` }; } // Delete vehicle await prisma.vehicle.delete({ where: { id }, }); return { success: true }; } catch (error) { console.error("Error deleting vehicle:", error); return { success: false, error: "حدث خطأ أثناء حذف المركبة" }; } } // Get vehicles for dropdown/select options export async function getVehiclesForSelect(ownerId?: number): Promise<{ id: number; plateNumber: string; manufacturer: string; model: string; year: number; }[]> { const whereClause = ownerId ? { ownerId } : {}; return await prisma.vehicle.findMany({ where: whereClause, select: { id: true, plateNumber: true, manufacturer: true, model: true, year: true, }, orderBy: { plateNumber: 'asc' }, }); } // Get vehicle statistics export async function getVehicleStats(vehicleId: number): Promise<{ totalVisits: number; totalSpent: number; lastVisitDate?: Date; nextSuggestedVisitDate?: Date; averageVisitCost: number; } | null> { const vehicle = await prisma.vehicle.findUnique({ where: { id: vehicleId }, include: { maintenanceVisits: { select: { cost: true, visitDate: true, }, orderBy: { visitDate: 'desc' }, }, }, }); if (!vehicle) return null; const totalSpent = vehicle.maintenanceVisits.reduce((sum, visit) => sum + visit.cost, 0); const averageVisitCost = vehicle.maintenanceVisits.length > 0 ? totalSpent / vehicle.maintenanceVisits.length : 0; const lastVisitDate = vehicle.maintenanceVisits.length > 0 ? vehicle.maintenanceVisits[0].visitDate : undefined; return { totalVisits: vehicle.maintenanceVisits.length, totalSpent, lastVisitDate, nextSuggestedVisitDate: vehicle.suggestedNextVisitDate || undefined, averageVisitCost, }; } // Search vehicles by plate number or manufacturer (for autocomplete) export async function searchVehicles(query: string, limit: number = 10): Promise<{ id: number; plateNumber: string; manufacturer: string; model: string; year: number; owner: { id: number; name: string; }; }[]> { if (!query || query.trim().length < 2) { return []; } const searchLower = query.toLowerCase(); return await prisma.vehicle.findMany({ where: { OR: [ { plateNumber: { contains: searchLower } }, { manufacturer: { contains: searchLower } }, { model: { contains: searchLower } }, ], }, select: { id: true, plateNumber: true, manufacturer: true, model: true, year: true, owner: { select: { id: true, name: true, }, }, }, orderBy: { plateNumber: 'asc' }, take: limit, }); } // Get vehicles by owner ID export async function getVehiclesByOwner(ownerId: number): Promise { return await prisma.vehicle.findMany({ where: { ownerId }, include: { owner: { select: { id: true, name: true, phone: true, email: true, }, }, }, orderBy: { createdDate: 'desc' }, }); } export async function getMaintenanceVisitsByVehicle(vehicleId: number) { const visits = await prisma.maintenanceVisit.findMany({ where: { vehicleId: vehicleId }, orderBy: { createdDate: 'desc' }, }); return visits }