Files
ocean-cleanup/server/prisma/schema.prisma
Paul Bailey c0ec28c5c9 Set up backend API server with Express and Prisma
- Initialize Node.js/Express backend project structure
- Configure TypeScript for backend development
- Set up Prisma ORM with MySQL database schema
- Implement authentication middleware with Clerk
- Create photo upload endpoint with EXIF extraction
- Build report CRUD endpoints (create, read, delete)
- Add file upload handling with Multer
- Configure CORS and security middleware (helmet)
- Set up error handling and validation
- Create development environment configuration

Task 21 complete: Backend foundation ready for report submissions
2025-11-16 17:29:26 +00:00

193 lines
8.3 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
email String @unique(map: "email") @db.VarChar(255)
password_hash String @db.VarChar(255)
username String @unique(map: "username") @db.VarChar(100)
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime? @default(now()) @updatedAt @map("updated_at") @db.Timestamp(0)
firstName String? @map("first_name") @db.VarChar(100)
lastName String? @map("last_name") @db.VarChar(100)
avatarUrl String? @map("avatar_url") @db.VarChar(500)
impactScore Int? @default(0) @map("impact_score")
notificationEmail Boolean? @default(true) @map("notification_email")
notificationInApp Boolean? @default(true) @map("notification_in_app")
areasOfInterest Json? @map("areas_of_interest")
eventRegistrations EventRegistration[]
organizedEvents Event[] @relation("EventOrganizer")
reports Report[]
verifications Verification[]
@@index([email], map: "idx_email")
@@index([username], map: "idx_username")
@@map("users")
}
model Report {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
userId String @map("user_id") @db.VarChar(36)
location Unsupported("point")
latitude Decimal @db.Decimal(10, 8)
longitude Decimal @db.Decimal(11, 8)
locationSource reports_location_source @map("location_source")
photoUrls Json @map("photo_urls")
photoTimestamp DateTime? @map("photo_timestamp") @db.Timestamp(0)
litterType reports_litter_type @map("litter_type")
quantity reports_quantity
description String? @db.Text
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime? @default(now()) @updatedAt @map("updated_at") @db.Timestamp(0)
submittedAt DateTime? @default(now()) @map("submitted_at") @db.Timestamp(0)
verificationStatus reports_verification_status? @default(pending) @map("verification_status")
environmentalConcerns EnvironmentalConcern[]
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "reports_ibfk_1")
verifications Verification[]
@@index([createdAt], map: "idx_created_at")
@@index([latitude, longitude], map: "idx_lat_lng")
@@index([litterType], map: "idx_litter_type")
@@index([location(length: 32)], map: "idx_location")
@@index([userId], map: "user_id")
@@map("reports")
}
model Event {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
organizerId String @map("organizer_id") @db.VarChar(36)
title String @db.VarChar(255)
description String @db.Text
location Unsupported("point")
latitude Decimal @db.Decimal(10, 8)
longitude Decimal @db.Decimal(11, 8)
locationName String @map("location_name") @db.VarChar(255)
scheduledDate DateTime @map("scheduled_date") @db.Timestamp(0)
duration Int
status events_status? @default(upcoming)
participantCount Int? @default(0) @map("participant_count")
litterCollected Decimal? @map("litter_collected") @db.Decimal(10, 2)
photos Json?
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime? @default(now()) @updatedAt @map("updated_at") @db.Timestamp(0)
registrations EventRegistration[]
organizer User @relation("EventOrganizer", fields: [organizerId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "events_ibfk_1")
@@index([location(length: 32)], map: "idx_location")
@@index([scheduledDate], map: "idx_scheduled_date")
@@index([status], map: "idx_status")
@@index([organizerId], map: "organizer_id")
@@map("events")
}
model EventRegistration {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
userId String @map("user_id") @db.VarChar(36)
eventId String @map("event_id") @db.VarChar(36)
registeredAt DateTime? @default(now()) @map("registered_at") @db.Timestamp(0)
attended Boolean? @default(false)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "event_registrations_ibfk_1")
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "event_registrations_ibfk_2")
@@unique([userId, eventId], map: "unique_user_event")
@@index([eventId], map: "event_id")
@@map("event_registrations")
}
model Verification {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
reportId String @map("report_id") @db.VarChar(36)
userId String @map("user_id") @db.VarChar(36)
verificationType verifications_verification_type @map("verification_type")
comment String? @db.Text
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
report Report @relation(fields: [reportId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "verifications_ibfk_1")
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "verifications_ibfk_2")
@@unique([reportId, userId], map: "unique_report_user")
@@index([userId], map: "user_id")
@@map("verifications")
}
model EnvironmentalConcern {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
reportId String @map("report_id") @db.VarChar(36)
concernType String @map("concern_type") @db.VarChar(100)
severity environmental_concerns_severity
description String @db.Text
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
report Report @relation(fields: [reportId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "environmental_concerns_ibfk_1")
@@index([concernType], map: "idx_concern_type")
@@index([reportId], map: "report_id")
@@map("environmental_concerns")
}
model Hotspot {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
location Unsupported("point")
latitude Decimal @db.Decimal(10, 8)
longitude Decimal @db.Decimal(11, 8)
radius Decimal @db.Decimal(10, 2)
reportCount Int @map("report_count")
severityScore Decimal @map("severity_score") @db.Decimal(5, 2)
lastReportDate DateTime @map("last_report_date") @db.Timestamp(0)
calculatedAt DateTime? @default(now()) @map("calculated_at") @db.Timestamp(0)
@@index([location(length: 32)], map: "idx_location")
@@index([severityScore], map: "idx_severity_score")
@@map("hotspots")
}
enum verifications_verification_type {
verify
dispute
}
enum environmental_concerns_severity {
low
medium
high
critical
}
enum reports_location_source {
exif
gps
manual
}
enum reports_litter_type {
plastic
metal
glass
organic
hazardous
other
}
enum reports_quantity {
minimal
moderate
significant
severe
}
enum events_status {
upcoming
completed
cancelled
}
enum reports_verification_status {
pending
verified
disputed
}