Agent 2 - Database Integration (P0 Critical): - Add Prisma ORM with PostgreSQL for persistent data storage - Create comprehensive database schema with 20+ models: - User & authentication models - Plant & lineage tracking - Transport events & supply chain - Vertical farming (farms, zones, batches, recipes) - Demand & market matching - Audit logging & blockchain storage - Implement complete database service layer (lib/db/): - users.ts: User CRUD with search and stats - plants.ts: Plant operations with lineage tracking - transport.ts: Transport events and carbon tracking - farms.ts: Vertical farm and crop batch management - demand.ts: Consumer preferences and market matching - audit.ts: Audit logging and blockchain integrity - Add PlantChainDB for database-backed blockchain - Create development seed script with sample data - Add database documentation (docs/DATABASE.md) - Update package.json with Prisma dependencies and scripts This provides the foundation for all other agents to build upon with persistent, scalable data storage.
1084 lines
22 KiB
Text
1084 lines
22 KiB
Text
// 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])
|
|
}
|