diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 82a1bf7..1482dcd 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,24 +1,8 @@ -// Datasource configuration datasource db { provider = "sqlserver" url = env("DATABASE_URL") } -// Enums for Request -enum RequestType { - NEW_USER - CHANGE_LEVEL - DELETE -} - -enum RequestOutcome { - FULFILLED - REJECTED - IN_PROGRESS - CANCELLED - OTHER -} - // User model model User { id Int @id @default(autoincrement()) @@ -26,20 +10,19 @@ model User { name String email String @unique passwordHash String - role String @default("GUEST") @db.VarChar(10) // ADMIN, SCIENTIST, GUEST + role String @default("GUEST") @db.VarChar(10) // Allowed: ADMIN, SCIENTIST, GUEST scientist Scientist? @relation purchasedArtefacts Artefact[] @relation("UserPurchasedArtefacts") requests Request[] @relation("UserRequests") } -// Request model model Request { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - requestType RequestType - requestingUser User @relation("UserRequests", fields: [requestingUserId], references: [id]) + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) + requestType String @db.VarChar(20) // Allowed: NEW_USER, CHANGE_LEVEL, DELETE + requestingUser User @relation("UserRequests", fields: [requestingUserId], references: [id]) requestingUserId Int - outcome RequestOutcome @default(IN_PROGRESS) + outcome String @default("IN_PROGRESS") @db.VarChar(20) // Allowed: FULFILLED, REJECTED, IN_PROGRESS, CANCELLED, OTHER } // Scientist model @@ -58,7 +41,6 @@ model Scientist { artefacts Artefact[] @relation("ScientistArtefactCreator") } -// Earthquake model model Earthquake { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) @@ -75,7 +57,6 @@ model Earthquake { observatories Observatory[] @relation("EarthquakeObservatory") } -// Observatory model model Observatory { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) @@ -92,13 +73,12 @@ model Observatory { earthquakes Earthquake[] @relation("EarthquakeObservatory") } -// Artefact model model Artefact { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt type String @db.VarChar(50) // Lava, Tephra, Ash, Soil - warehouseArea String // Examples: "ZoneA-Shelf1", "ZoneB-Rack2", "ZoneC-Bin3" + warehouseArea String description String earthquakeId Int earthquake Earthquake @relation(fields: [earthquakeId], references: [id]) @@ -106,7 +86,7 @@ model Artefact { creator Scientist? @relation("ScientistArtefactCreator", fields: [creatorId], references: [id], onDelete: NoAction, onUpdate: NoAction) required Boolean @default(true) dateAddedToShop DateTime? - shopPrice Float? // In Euros + shopPrice Float? purchased Boolean @default(false) purchasedById Int? purchasedBy User? @relation("UserPurchasedArtefacts", fields: [purchasedById], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -117,6 +97,6 @@ model Pallet { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - warehouseArea String // Examples: "ZoneA-Shelf1", "ZoneB-Rack2", "ZoneC-Bin3" + warehouseArea String palletNote String } diff --git a/src/app/api/import-requests/route.ts b/src/app/api/import-requests/route.ts index e792b66..1ca4a67 100644 --- a/src/app/api/import-requests/route.ts +++ b/src/app/api/import-requests/route.ts @@ -1,60 +1,61 @@ import { NextResponse } from "next/server"; -import { PrismaClient, RequestType, RequestOutcome } from "@prisma/client"; +import { PrismaClient } from "@prisma/client"; import fs from "fs/promises"; import path from "path"; import { parse } from "csv-parse/sync"; -// Path to CSV file const csvFilePath = path.resolve(process.cwd(), "public/requests.csv"); const prisma = new PrismaClient(); +type RequestType = "NEW_USER" | "CHANGE_LEVEL" | "DELETE"; +type RequestOutcome = "FULFILLED" | "REJECTED" | "IN_PROGRESS" | "CANCELLED" | "OTHER"; + type CsvRow = { RequestType: string; - RequestingUserId: string; // User id as string in CSV - Outcome?: string; // optional; default is IN_PROGRESS if not supplied + RequestingUserId: string; + Outcome?: string; }; -// Valid enums for checking -const validRequestTypes = Object.values(RequestType); -const validOutcomes = Object.values(RequestOutcome); +const validRequestTypes: RequestType[] = ["NEW_USER", "CHANGE_LEVEL", "DELETE"]; +const validOutcomes: RequestOutcome[] = [ + "FULFILLED", + "REJECTED", + "IN_PROGRESS", + "CANCELLED", + "OTHER", +]; function normalizeRequestType(type: string | undefined): RequestType { - if (!type) return RequestType.NEW_USER; + if (!type) return "NEW_USER"; const norm = type.trim().toUpperCase().replace(" ", "_"); - return (validRequestTypes.includes(norm as any) ? norm : RequestType.NEW_USER) as RequestType; + return (validRequestTypes.includes(norm as RequestType) ? norm : "NEW_USER") as RequestType; } function normalizeOutcome(outcome: string | undefined): RequestOutcome { - if (!outcome) return RequestOutcome.IN_PROGRESS; + if (!outcome) return "IN_PROGRESS"; const norm = outcome.trim().toUpperCase().replace(" ", "_"); - return (validOutcomes.includes(norm as any) ? norm : RequestOutcome.IN_PROGRESS) as RequestOutcome; + return (validOutcomes.includes(norm as RequestOutcome) ? norm : "IN_PROGRESS") as RequestOutcome; } export async function POST() { try { - // 1. Read the CSV file const fileContent = await fs.readFile(csvFilePath, "utf8"); - - // 2. Parse the CSV const records: CsvRow[] = parse(fileContent, { columns: true, skip_empty_lines: true, }); - // 3. Transform each record for Prisma const requests = records.map(row => ({ requestType: normalizeRequestType(row.RequestType), requestingUserId: parseInt(row.RequestingUserId, 10), outcome: normalizeOutcome(row.Outcome), })); - // (optional) Filter out rows missing requestingUserId const filteredRequests = requests.filter(r => !isNaN(r.requestingUserId)); - // 4. Bulk create requests in database await prisma.request.createMany({ data: filteredRequests, - skipDuplicates: true, // in case request id/user-id already exists + skipDuplicates: true, }); return NextResponse.json({ success: true, count: filteredRequests.length });