// Farm Management Domain // Contains Farm, Plot, and related farming infrastructure models // Farm-specific Enums enum FarmOwnership { PRIVATE_OWNED LEASED SHARECROPPED COOPERATIVE GOVERNMENT COMMUNAL FAMILY_INHERITED } enum FarmingSystem { MONOCULTURE POLYCULTURE MIXED_FARMING ORGANIC CONVENTIONAL INTEGRATED PERMACULTURE AGROFORESTRY } enum FarmAttachmentType { MAIN_PHOTO AERIAL_PHOTO SOIL_PHOTO CROP_PHOTO INFRASTRUCTURE_PHOTO LAND_CERTIFICATE SURVEY_MAP WATER_SOURCE_PHOTO ENTRANCE_PHOTO BOUNDARY_PHOTO EQUIPMENT_PHOTO STORAGE_PHOTO OTHER_DOCUMENT } // Farm Models model Farm { id String @id @default(cuid()) farmerId String farmCode String @unique name String address String? village String? district String? province String? postalCode String? area Decimal? // in hectares // Location data latitude Float? longitude Float? boundaries Json? // GeoJSON polygon for farm boundaries elevation Float? // meters above sea level // Farm characteristics soilType String? soilPH Float? waterSource WaterSource? irrigationType IrrigationType? slope SlopeType? climate ClimateType? // Infrastructure hasElectricity Boolean? @default(false) hasWaterAccess Boolean? @default(false) hasStorageFacility Boolean? @default(false) hasProcessingUnit Boolean? @default(false) accessRoadType RoadType? // Photos and documentation mainPhotoUrl String? aerialPhotoUrl String? soilPhotoUrl String? // Ownership and legal ownershipType FarmOwnership? landCertificateNumber String? landCertificateUrl String? // Agricultural details establishedYear Int? totalInvestment Decimal? annualProduction Decimal? // estimated kg per year mainCrops String[] // primary crops grown farmingSystem FarmingSystem? organicCertified Boolean? @default(false) description String? notes String? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id], onDelete: Cascade) plots Plot[] harvests Harvest[] attachments FarmAttachment[] weatherData WeatherData[] weatherForecasts WeatherForecast[] inputs FarmInput[] inputSchedules InputSchedule[] laborRecords LaborRecord[] laborSchedules LaborSchedule[] equipmentUsage EquipmentUsage[] pestDiseaseRecords PestDiseaseRecord[] financialRecords FinancialRecord[] soilTests SoilTest[] @@index([farmCode]) @@index([farmerId]) @@index([latitude, longitude]) @@index([isActive]) @@index([establishedYear]) @@map("farms") } model Plot { id String @id @default(cuid()) farmId String name String area Decimal? // in hectares productId String? variantId String? plantedDate DateTime? boundaries Json? // GeoJSON polygon for plot boundaries description String? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm @relation(fields: [farmId], references: [id], onDelete: Cascade) product Product? @relation(fields: [productId], references: [id]) variant ProductVariant? @relation(fields: [variantId], references: [id]) harvests Harvest[] weatherData WeatherData[] weatherForecasts WeatherForecast[] inputs FarmInput[] inputSchedules InputSchedule[] laborRecords LaborRecord[] laborSchedules LaborSchedule[] equipmentUsage EquipmentUsage[] pestDiseaseRecords PestDiseaseRecord[] financialRecords FinancialRecord[] soilTests SoilTest[] seasons PlotSeason[] @@index([farmId]) @@index([productId, variantId]) @@index([plantedDate]) @@index([isActive]) @@map("plots") } model FarmAttachment { id String @id @default(cuid()) farmId String type FarmAttachmentType title String description String? fileUrl String fileName String fileSize Int? // in bytes mimeType String? uploadedBy String? // user ID who uploaded takenDate DateTime? // when photo was taken gpsLocation Json? // GeoJSON point where photo was taken isVerified Boolean @default(false) verifiedBy String? // admin ID who verified verifiedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm @relation(fields: [farmId], references: [id], onDelete: Cascade) @@index([farmId]) @@index([type]) @@index([isVerified]) @@index([createdAt]) @@map("farm_attachments") } model SoilTest { id String @id @default(cuid()) farmId String plotId String? testCode String @unique testDate DateTime sampleDepth Decimal? // cm sampleLocation String? gpsCoordinates Json? // GeoJSON point // Basic soil properties pH Decimal? organicMatter Decimal? // percentage soilTexture String? // clay, sand, loam, etc. bulkDensity Decimal? // g/cm³ porosity Decimal? // percentage // Nutrients (ppm) nitrogen Decimal? phosphorus Decimal? potassium Decimal? calcium Decimal? magnesium Decimal? sulfur Decimal? // Micronutrients (ppm) zinc Decimal? iron Decimal? manganese Decimal? copper Decimal? boron Decimal? // Other properties conductivity Decimal? // dS/m cationExchangeCapacity Decimal? // cmol/kg baseStaturation Decimal? // percentage carbonNitrogenRatio Decimal? // Analysis details recommendations String? testLaboratory String? technicianName String? testCost Decimal? reportUrl String? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@index([testCode]) @@index([farmId, plotId]) @@index([testDate]) @@index([testLaboratory]) @@map("soil_tests") }