// LocalGreenChain Database Schema // Prisma ORM configuration for PostgreSQL generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================ // USER & AUTHENTICATION // ============================================ model User { id String @id @default(cuid()) email String @unique name String walletAddress String? @unique passwordHash String? // Profile avatarUrl String? bio String? // Location latitude Float? longitude Float? address String? city String? country String? // User type userType UserType @default(CONSUMER) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt lastLoginAt DateTime? // Relations ownedPlants Plant[] verticalFarms VerticalFarm[] consumerPreferences ConsumerPreference[] supplyCommitments SupplyCommitment[] sentTransportEvents TransportEvent[] @relation("Sender") receivedTransportEvents TransportEvent[] @relation("Receiver") seasonalPlans SeasonalPlan[] auditLogs AuditLog[] @@index([email]) @@index([userType]) } enum UserType { CONSUMER GROWER DISTRIBUTOR PROCESSOR ADMIN } // ============================================ // PLANT & LINEAGE TRACKING // ============================================ model Plant { id String @id @default(cuid()) // Plant identification commonName String scientificName String? species String? genus String? family String? // Lineage tracking parentPlantId String? parentPlant Plant? @relation("PlantLineage", fields: [parentPlantId], references: [id]) childPlants Plant[] @relation("PlantLineage") propagationType PropagationType @default(ORIGINAL) generation Int @default(0) // Lifecycle plantedDate DateTime harvestedDate DateTime? status PlantStatus @default(SPROUTED) // Location latitude Float longitude Float address String? city String? country String? // Owner ownerId String owner User @relation(fields: [ownerId], references: [id]) // Environmental data (JSON for flexibility) environment Json? growthMetrics Json? // Metadata notes String? images String[] plantsNetId String? // Blockchain integration blockIndex Int? blockHash String? // Timestamps registeredAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations transportEvents TransportEvent[] cropBatches CropBatch[] @@index([ownerId]) @@index([commonName]) @@index([status]) @@index([parentPlantId]) @@index([latitude, longitude]) } enum PropagationType { SEED CLONE CUTTING DIVISION GRAFTING ORIGINAL } enum PlantStatus { SPROUTED GROWING MATURE FLOWERING FRUITING DORMANT DECEASED } // ============================================ // TRANSPORT & SUPPLY CHAIN // ============================================ model TransportEvent { id String @id @default(cuid()) // Event type eventType TransportEventType // Locations fromLatitude Float fromLongitude Float fromAddress String? fromCity String? fromCountry String? fromLocationType LocationType fromFacilityId String? fromFacilityName String? toLatitude Float toLongitude Float toAddress String? toCity String? toCountry String? toLocationType LocationType toFacilityId String? toFacilityName String? // Distance and duration distanceKm Float durationMinutes Int // Environmental impact transportMethod TransportMethod carbonFootprintKg Float // Parties senderId String sender User @relation("Sender", fields: [senderId], references: [id]) receiverId String receiver User @relation("Receiver", fields: [receiverId], references: [id]) // Verification signatures senderSignature String? receiverSignature String? verifierSignature String? // Status status TransportStatus @default(PENDING) // Metadata notes String? photos String[] documents String[] // Extended event data (JSON for type-specific fields) eventData Json? // Blockchain integration blockIndex Int? blockHash String? cumulativeCarbonKg Float? cumulativeFoodMiles Float? // Timestamps timestamp DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations plants Plant[] seedBatch SeedBatch? @relation(fields: [seedBatchId], references: [id]) seedBatchId String? harvestBatch HarvestBatch? @relation(fields: [harvestBatchId], references: [id]) harvestBatchId String? @@index([eventType]) @@index([senderId]) @@index([receiverId]) @@index([status]) @@index([timestamp]) } enum TransportEventType { SEED_ACQUISITION PLANTING GROWING_TRANSPORT HARVEST PROCESSING DISTRIBUTION CONSUMER_DELIVERY SEED_SAVING SEED_SHARING } enum LocationType { FARM GREENHOUSE VERTICAL_FARM WAREHOUSE HUB MARKET CONSUMER SEED_BANK OTHER } enum TransportMethod { WALKING BICYCLE ELECTRIC_VEHICLE HYBRID_VEHICLE GASOLINE_VEHICLE DIESEL_TRUCK ELECTRIC_TRUCK REFRIGERATED_TRUCK RAIL SHIP AIR DRONE LOCAL_DELIVERY CUSTOMER_PICKUP } enum TransportStatus { PENDING IN_TRANSIT DELIVERED VERIFIED DISPUTED } // Seed Batch for tracking seeds through the system model SeedBatch { id String @id @default(cuid()) // Seed info species String variety String? quantity Float quantityUnit String @default("seeds") // Lineage geneticLineageId String? parentPlantIds String[] generation Int @default(0) // Quality germinationRate Float? purityPercentage Float? harvestDate DateTime? expirationDate DateTime? // Certifications certifications String[] certificationDocs String[] // Storage storageTemperature Float? storageHumidity Float? containerType String? // Status status SeedBatchStatus @default(AVAILABLE) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations transportEvents TransportEvent[] cropBatches CropBatch[] @@index([species]) @@index([status]) } enum SeedBatchStatus { AVAILABLE PARTIALLY_USED DEPLETED EXPIRED } // Harvest Batch for tracking harvested produce model HarvestBatch { id String @id @default(cuid()) // Harvest info produceType String harvestType String @default("full") // Quantities grossWeight Float netWeight Float weightUnit String @default("kg") itemCount Int? // Quality qualityGrade String? qualityNotes String? // Storage packagingType String? shelfLifeHours Int? temperatureMin Float? temperatureMax Float? // Timestamps harvestedAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations transportEvents TransportEvent[] cropBatch CropBatch? @relation(fields: [cropBatchId], references: [id]) cropBatchId String? @@index([produceType]) @@index([harvestedAt]) } // ============================================ // VERTICAL FARMING // ============================================ model VerticalFarm { id String @id @default(cuid()) name String // Owner ownerId String owner User @relation(fields: [ownerId], references: [id]) // Location latitude Float longitude Float address String city String country String timezone String @default("UTC") // Facility specs (JSON for complex nested structure) specs Json // Systems configuration (JSON for flexibility) environmentalControl Json? irrigationSystem Json? lightingSystem Json? nutrientSystem Json? // Automation automationLevel AutomationLevel @default(MANUAL) automationSystems Json? // Status status FarmStatus @default(OFFLINE) operationalSince DateTime? lastMaintenanceDate DateTime? // Performance metrics capacityUtilization Float? yieldEfficiency Float? energyEfficiencyScore Float? // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations zones GrowingZone[] cropBatches CropBatch[] resourceUsage ResourceUsage[] farmAnalytics FarmAnalytics[] @@index([ownerId]) @@index([status]) @@index([city, country]) } enum AutomationLevel { MANUAL SEMI_AUTOMATED FULLY_AUTOMATED } enum FarmStatus { OFFLINE STARTING OPERATIONAL MAINTENANCE EMERGENCY } model GrowingZone { id String @id @default(cuid()) name String level Int // Dimensions areaSqm Float lengthM Float? widthM Float? // Growing system growingMethod GrowingMethod plantPositions Int // Current status currentCrop String? plantingDate DateTime? expectedHarvestDate DateTime? // Environment targets (JSON) environmentTargets Json? // Current readings (JSON) currentEnvironment Json? // Status status ZoneStatus @default(EMPTY) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm VerticalFarm @relation(fields: [farmId], references: [id], onDelete: Cascade) farmId String cropBatches CropBatch[] @@index([farmId]) @@index([status]) } enum GrowingMethod { NFT DWC EBB_FLOW AEROPONICS VERTICAL_TOWERS RACK_SYSTEM } enum ZoneStatus { EMPTY PREPARING PLANTED GROWING HARVESTING CLEANING } model CropBatch { id String @id @default(cuid()) // Crop info cropType String variety String? // Growing plantCount Int plantingDate DateTime transplantDate DateTime? // Progress currentStage String @default("germinating") currentDay Int @default(0) healthScore Float? // Expected expectedHarvestDate DateTime expectedYieldKg Float // Actual (after harvest) actualHarvestDate DateTime? actualYieldKg Float? qualityGrade String? // Status status CropBatchStatus @default(GERMINATING) // Issues (JSON array) issues Json? // Environmental log (JSON array) environmentLog Json? // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm VerticalFarm @relation(fields: [farmId], references: [id]) farmId String zone GrowingZone @relation(fields: [zoneId], references: [id]) zoneId String recipe GrowingRecipe? @relation(fields: [recipeId], references: [id]) recipeId String? seedBatch SeedBatch? @relation(fields: [seedBatchId], references: [id]) seedBatchId String? plants Plant[] harvestBatches HarvestBatch[] @@index([farmId]) @@index([zoneId]) @@index([status]) @@index([cropType]) } enum CropBatchStatus { GERMINATING GROWING READY HARVESTING COMPLETED FAILED } model GrowingRecipe { id String @id @default(cuid()) name String cropType String variety String? version String @default("1.0") // Stages (JSON array of GrowthStage) stages Json // Expected outcomes expectedDays Int expectedYieldGrams Float expectedYieldPerSqm Float? // Requirements (JSON) requirements Json? // Source source RecipeSource @default(INTERNAL) author String? rating Float? timesUsed Int @default(0) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations cropBatches CropBatch[] @@index([cropType]) @@index([source]) } enum RecipeSource { INTERNAL COMMUNITY COMMERCIAL } model ResourceUsage { id String @id @default(cuid()) // Period periodStart DateTime periodEnd DateTime // Energy electricityKwh Float electricityCostUsd Float? renewablePercent Float? peakDemandKw Float? // Water waterUsageL Float waterCostUsd Float? waterRecycledPercent Float? // CO2 co2UsedKg Float? co2CostUsd Float? // Nutrients nutrientsUsedL Float? nutrientCostUsd Float? // Efficiency metrics kwhPerKgProduce Float? litersPerKgProduce Float? costPerKgProduce Float? // Timestamps createdAt DateTime @default(now()) // Relations farm VerticalFarm @relation(fields: [farmId], references: [id]) farmId String @@index([farmId]) @@index([periodStart, periodEnd]) } model FarmAnalytics { id String @id @default(cuid()) // Period period String generatedAt DateTime @default(now()) // Production totalYieldKg Float yieldPerSqmPerYear Float? cropCyclesCompleted Int averageCyclesDays Float? // Quality averageQualityScore Float? gradeAPercent Float? wastagePercent Float? // Efficiency cropSuccessRate Float? spaceUtilization Float? laborHoursPerKg Float? // Financial revenueUsd Float? costUsd Float? profitMarginPercent Float? revenuePerSqm Float? // Environmental carbonFootprintKgPerKg Float? waterUseLPerKg Float? energyUseKwhPerKg Float? // Top crops (JSON arrays) topCropsByYield Json? topCropsByRevenue Json? topCropsByEfficiency Json? // Timestamps createdAt DateTime @default(now()) // Relations farm VerticalFarm @relation(fields: [farmId], references: [id]) farmId String @@index([farmId]) @@index([period]) } // ============================================ // DEMAND & MARKET MATCHING // ============================================ model ConsumerPreference { id String @id @default(cuid()) // Consumer consumerId String consumer User @relation(fields: [consumerId], references: [id]) // Location latitude Float longitude Float maxDeliveryRadiusKm Float @default(50) city String? region String? // Dietary preferences dietaryType String[] allergies String[] dislikes String[] // Produce preferences (JSON) preferredCategories String[] preferredItems Json? // Quality preferences certificationPreferences String[] freshnessImportance Int @default(3) priceImportance Int @default(3) sustainabilityImportance Int @default(3) // Delivery preferences (JSON) deliveryPreferences Json? // Household householdSize Int @default(1) weeklyBudget Float? currency String? @default("USD") // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([consumerId]) @@index([latitude, longitude]) } model DemandSignal { id String @id @default(cuid()) // Region scope centerLat Float centerLon Float radiusKm Float regionName String // Time scope periodStart DateTime periodEnd DateTime seasonalPeriod String // spring, summer, fall, winter // Aggregated demand (JSON array of DemandItem) demandItems Json // Statistics totalConsumers Int totalWeeklyDemandKg Float confidenceLevel Float // Supply status currentSupplyKg Float? supplyGapKg Float? supplyStatus SupplyStatus @default(BALANCED) // Timestamps timestamp DateTime @default(now()) createdAt DateTime @default(now()) // Relations marketMatches MarketMatch[] @@index([regionName]) @@index([periodStart, periodEnd]) @@index([supplyStatus]) } enum SupplyStatus { SURPLUS BALANCED SHORTAGE CRITICAL } model SupplyCommitment { id String @id @default(cuid()) // Grower growerId String grower User @relation(fields: [growerId], references: [id]) // Produce produceType String variety String? // Commitment committedQuantityKg Float availableFrom DateTime availableUntil DateTime // Pricing pricePerKg Float currency String @default("USD") minimumOrderKg Float @default(0) bulkDiscountThreshold Float? bulkDiscountPercent Float? // Quality certifications String[] freshnessGuaranteeHours Int? // Delivery deliveryRadiusKm Float deliveryMethods String[] // Status status CommitmentStatus @default(AVAILABLE) remainingKg Float // Timestamps timestamp DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations marketMatches MarketMatch[] @@index([growerId]) @@index([produceType]) @@index([status]) @@index([availableFrom, availableUntil]) } enum CommitmentStatus { AVAILABLE PARTIALLY_COMMITTED FULLY_COMMITTED EXPIRED } model MarketMatch { id String @id @default(cuid()) // Parties consumerId String growerId String // Links demandSignalId String demandSignal DemandSignal @relation(fields: [demandSignalId], references: [id]) supplyCommitmentId String supplyCommitment SupplyCommitment @relation(fields: [supplyCommitmentId], references: [id]) // Match details produceType String matchedQuantityKg Float // Transaction agreedPricePerKg Float totalPrice Float currency String @default("USD") // Delivery deliveryDate DateTime deliveryMethod String deliveryLatitude Float? deliveryLongitude Float? deliveryAddress String? // Status status MatchStatus @default(PENDING) // Ratings consumerRating Float? growerRating Float? feedback String? // Timestamps timestamp DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([consumerId]) @@index([growerId]) @@index([status]) @@index([deliveryDate]) } enum MatchStatus { PENDING CONFIRMED IN_TRANSIT DELIVERED COMPLETED CANCELLED } model SeasonalPlan { id String @id @default(cuid()) // Grower growerId String grower User @relation(fields: [growerId], references: [id]) // Season year Int season String // spring, summer, fall, winter // Location context (JSON) location Json // Growing capacity (JSON) growingCapacity Json // Planned crops (JSON array) plannedCrops Json // Expected outcomes expectedTotalYieldKg Float? expectedRevenue Float? expectedCarbonFootprintKg Float? // Status status PlanStatus @default(DRAFT) completionPercentage Float? // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([growerId]) @@index([year, season]) @@index([status]) } enum PlanStatus { DRAFT CONFIRMED IN_PROGRESS COMPLETED } model DemandForecast { id String @id @default(cuid()) // Scope region String forecastPeriodStart DateTime forecastPeriodEnd DateTime // Forecasts (JSON array of ProduceForecast) forecasts Json // Model info modelVersion String dataPointsUsed Int lastTrainingDate DateTime? // Timestamps generatedAt DateTime @default(now()) createdAt DateTime @default(now()) @@index([region]) @@index([forecastPeriodStart, forecastPeriodEnd]) } model PlantingRecommendation { id String @id @default(cuid()) // Grower growerId String // Recommendation produceType String variety String? category String // Quantities recommendedQuantity Float quantityUnit String expectedYieldKg Float yieldConfidence Float // Timing plantByDate DateTime expectedHarvestStart DateTime expectedHarvestEnd DateTime growingDays Int // Market opportunity projectedDemandKg Float? projectedPricePerKg Float? projectedRevenue Float? marketConfidence Float? // Risk assessment (JSON) riskFactors Json? overallRisk String @default("medium") // Reasoning demandSignalIds String[] explanation String? // Timestamps timestamp DateTime @default(now()) createdAt DateTime @default(now()) @@index([growerId]) @@index([produceType]) @@index([plantByDate]) } // ============================================ // AUDIT & TRANSPARENCY // ============================================ model AuditLog { id String @id @default(cuid()) // Actor userId String? user User? @relation(fields: [userId], references: [id]) // Action action String entityType String entityId String? // Details previousValue Json? newValue Json? metadata Json? // Source ipAddress String? userAgent String? // Timestamps timestamp DateTime @default(now()) @@index([userId]) @@index([entityType, entityId]) @@index([action]) @@index([timestamp]) } model BlockchainBlock { id String @id @default(cuid()) // Block data index Int @unique timestamp DateTime previousHash String hash String @unique nonce Int // Block content type blockType String // "plant" or "transport" // Content reference plantId String? transportEventId String? // Content snapshot (JSON) content Json // Timestamps createdAt DateTime @default(now()) @@index([blockType]) @@index([hash]) }