// Prisma Schema for LocalGreenChain // Note: This requires Agent 2 (Database) to set up the database connection // For now, marketplace uses in-memory storage in lib/marketplace/store.ts generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // =========================================== // User & Authentication Models (Agent 1) // =========================================== enum Role { USER GROWER SELLER ADMIN } model User { id String @id @default(cuid()) email String @unique emailVerified DateTime? passwordHash String? name String? image String? role Role @default(USER) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations plants Plant[] farms VerticalFarm[] listings Listing[] offers Offer[] wishlistItems WishlistItem[] sellerProfile SellerProfile? auditLogs AuditLog[] } // =========================================== // Plant & Blockchain Models // =========================================== model Plant { id String @id @default(cuid()) name String species String variety String? parentId String? generation Int @default(1) registeredAt DateTime @default(now()) ownerId String locationLat Float? locationLng Float? blockHash String? owner User @relation(fields: [ownerId], references: [id]) parent Plant? @relation("PlantLineage", fields: [parentId], references: [id]) children Plant[] @relation("PlantLineage") transportEvents TransportEvent[] environmentRecords EnvironmentRecord[] listings Listing[] } model TransportEvent { id String @id @default(cuid()) plantId String eventType String fromLat Float? fromLng Float? toLat Float? toLng Float? distance Float? carbonKg Float? timestamp DateTime @default(now()) metadata Json? plant Plant @relation(fields: [plantId], references: [id]) } model EnvironmentRecord { id String @id @default(cuid()) plantId String temperature Float? humidity Float? light Float? soilMoisture Float? recordedAt DateTime @default(now()) plant Plant @relation(fields: [plantId], references: [id]) } // =========================================== // Vertical Farm Models // =========================================== model VerticalFarm { id String @id @default(cuid()) name String ownerId String totalArea Float zones Int createdAt DateTime @default(now()) owner User @relation(fields: [ownerId], references: [id]) farmZones FarmZone[] batches CropBatch[] } model FarmZone { id String @id @default(cuid()) farmId String name String area Float lightType String status String farm VerticalFarm @relation(fields: [farmId], references: [id]) batches CropBatch[] } model CropBatch { id String @id @default(cuid()) farmId String zoneId String cropType String plantedAt DateTime @default(now()) harvestedAt DateTime? status String farm VerticalFarm @relation(fields: [farmId], references: [id]) zone FarmZone @relation(fields: [zoneId], references: [id]) } // =========================================== // Marketplace Models (Agent 9) // =========================================== enum ListingCategory { seeds seedlings mature_plants cuttings produce supplies } enum ListingStatus { draft active sold expired cancelled } enum OfferStatus { pending accepted rejected withdrawn expired } model Listing { id String @id @default(cuid()) sellerId String plantId String? title String description String @db.Text price Decimal @db.Decimal(10, 2) currency String @default("USD") quantity Int category ListingCategory status ListingStatus @default(draft) locationLat Float? locationLng Float? locationCity String? locationRegion String? tags String[] viewCount Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt expiresAt DateTime? seller User @relation(fields: [sellerId], references: [id]) plant Plant? @relation(fields: [plantId], references: [id]) offers Offer[] images ListingImage[] wishlistItems WishlistItem[] @@index([sellerId]) @@index([category]) @@index([status]) @@index([createdAt]) } model ListingImage { id String @id @default(cuid()) listingId String url String alt String? isPrimary Boolean @default(false) createdAt DateTime @default(now()) listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade) @@index([listingId]) } model Offer { id String @id @default(cuid()) listingId String buyerId String amount Decimal @db.Decimal(10, 2) message String? @db.Text status OfferStatus @default(pending) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt expiresAt DateTime? listing Listing @relation(fields: [listingId], references: [id]) buyer User @relation(fields: [buyerId], references: [id]) @@index([listingId]) @@index([buyerId]) @@index([status]) } model SellerProfile { id String @id @default(cuid()) userId String @unique displayName String bio String? @db.Text locationCity String? locationRegion String? rating Float @default(0) reviewCount Int @default(0) totalSales Int @default(0) verified Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id]) } model WishlistItem { id String @id @default(cuid()) userId String listingId String addedAt DateTime @default(now()) user User @relation(fields: [userId], references: [id]) listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade) @@unique([userId, listingId]) @@index([userId]) } // =========================================== // Transparency & Audit Models // =========================================== model AuditLog { id String @id @default(cuid()) userId String? action String entityType String entityId String details Json? ipAddress String? userAgent String? createdAt DateTime @default(now()) user User? @relation(fields: [userId], references: [id]) @@index([entityType, entityId]) @@index([createdAt]) }