// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique phone String? name String role UserRole isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer? buyer Buyer? administrator Administrator? @@map("users") } model Farmer { id String @id @default(cuid()) userId String @unique farmerCode String @unique name String phone String? email String? dateOfBirth DateTime? gender Gender? maritalStatus MaritalStatus? spouseName String? numberOfChildren Int? @default(0) religion Religion? nationality String? @default("Indonesian") address String? village String? district String? province String? postalCode String? country String? @default("Indonesia") // Location data latitude Float? longitude Float? addressGeoJson Json? // GeoJSON point for precise location // Identity information identityType IdentityType? identityNumber String? identityExpiry DateTime? // Banking information bankAccount String? bankName String? accountHolderName String? // Photos and attachments profilePhotoUrl String? idCardFrontUrl String? idCardBackUrl String? // Verification status isVerified Boolean @default(false) verificationDate DateTime? verifiedBy String? // admin ID who verified verificationNotes String? // Farming experience farmingExperience Int? // years of experience educationLevel EducationLevel? occupation String? // primary occupation if not full-time farmer monthlyIncome Float? // estimated monthly income landOwnership LandOwnership? primaryCrop String? farmingMethods String[] // organic, conventional, etc. hasVehicle Boolean? // for transportation vehicleType String? // motorcycle, car, truck, etc. hasSmartphone Boolean? @default(true) internetAccess Boolean? @default(true) // Emergency contact emergencyContactName String? emergencyContactPhone String? emergencyContactRelation String? // Status and metadata status FarmerStatus @default(ACTIVE) notes String? joinedAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) farms Farm[] trainings FarmerTraining[] certifications FarmerCertification[] procurements Procurement[] harvests Harvest[] attachments FarmerAttachment[] workers FarmWorker[] laborRecords LaborRecord[] laborSchedules LaborSchedule[] equipment Equipment[] assets Asset[] financialRecords FinancialRecord[] reviews BuyerReview[] @@map("farmers") } model Buyer { id String @id @default(cuid()) userId String @unique buyerCode String @unique name String company String? phone String? email String? address String? // Enhanced buyer details buyerType BuyerType? businessLicense String? taxNumber String? contactPerson String? contactPersonPhone String? paymentTerms Int? // days creditLimit Float? preferredProducts String[] qualityRequirements String? // Location and logistics warehouseAddress String? deliveryPreference String? operatingRadius Float? // km // Business details businessSize BusinessSize? yearEstablished Int? annualVolume Float? // estimated annual purchase volume employeeCount Int? website String? // Financial information bankAccount String? bankName String? accountHolderName String? // Verification and status isVerified Boolean @default(false) verificationDate DateTime? verifiedBy String? // admin ID who verified verificationNotes String? status BuyerStatus @default(ACTIVE) // Photos and documents profilePhotoUrl String? businessLicenseUrl String? taxCertificateUrl String? // Preferences preferredPickupDays String[] // Mon, Tue, Wed, etc. preferredPickupTime String? minimumOrderQuantity Float? maximumOrderQuantity Float? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) procurements Procurement[] reviews BuyerReview[] @@map("buyers") } model Administrator { id String @id @default(cuid()) userId String @unique adminCode String @unique name String phone String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("administrators") } 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 Float? // 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 Float? annualProduction Float? // 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[] @@map("farms") } model Plot { id String @id @default(cuid()) farmId String name String area Float? // 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[] @@map("plots") } model Harvest { id String @id @default(cuid()) farmerId String farmId String plotId String? variantId String quantity Float // in kg harvestDate DateTime qualityGrade QualityGrade waterContent Float? // percentage density Float? // kg/m3 notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) farm Farm @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) variant ProductVariant @relation(fields: [variantId], references: [id]) procurement Procurement? modifiers HarvestModifier[] @@map("harvests") } model Procurement { id String @id @default(cuid()) procurementCode String @unique farmerId String buyerId String? harvestId String @unique variantId String // Quantity and quality details quantity Float // in kg qualityGrade QualityGrade waterContent Float? // percentage density Float? // kg/m3 // Pricing details basePrice Float // price per kg premiumRate Float @default(0) // percentage totalPrice Float transportCost Float? @default(0) processingCost Float? @default(0) finalAmount Float // total amount to be paid // Location and logistics pickupLocation String? deliveryLocation String? pickupDate DateTime? deliveryDate DateTime? transportMethod String? // truck, motorcycle, etc. // Quality assessment assessedBy String? // quality assessor ID assessmentDate DateTime? assessmentNotes String? rejectedQuantity Float? @default(0) rejectionReason String? // Payment details paymentMethod PaymentMethod? paymentReference String? bankAccount String? // Status and tracking status ProcurementStatus @default(PENDING) procurementDate DateTime @default(now()) approvedDate DateTime? approvedBy String? // admin ID who approved paymentDate DateTime? completedDate DateTime? // Documentation contractNumber String? invoiceNumber String? receiptNumber String? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) buyer Buyer? @relation(fields: [buyerId], references: [id]) harvest Harvest @relation(fields: [harvestId], references: [id]) variant ProductVariant @relation(fields: [variantId], references: [id]) attachments ProcurementAttachment[] @@map("procurements") } model HarvestModifier { id String @id @default(cuid()) harvestId String modifierId String value String // actual value applied adjustment Float? // calculated price adjustment createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations harvest Harvest @relation(fields: [harvestId], references: [id], onDelete: Cascade) modifier ProductModifier @relation(fields: [modifierId], references: [id]) @@unique([harvestId, modifierId]) @@map("harvest_modifiers") } model FarmerAttachment { id String @id @default(cuid()) farmerId String type AttachmentType title String description String? fileUrl String fileName String fileSize Int? // in bytes mimeType String? uploadedBy String? // user ID who uploaded isVerified Boolean @default(false) verifiedBy String? // admin ID who verified verifiedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id], onDelete: Cascade) @@map("farmer_attachments") } 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) @@map("farm_attachments") } model ProcurementAttachment { id String @id @default(cuid()) procurementId String type ProcurementAttachmentType 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 procurement Procurement @relation(fields: [procurementId], references: [id], onDelete: Cascade) @@map("procurement_attachments") } model Training { id String @id @default(cuid()) title String description String? content String? category String duration Int? // in minutes level String? // beginner, intermediate, advanced isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmerTrainings FarmerTraining[] @@map("trainings") } model FarmerTraining { id String @id @default(cuid()) farmerId String trainingId String status TrainingStatus @default(ENROLLED) progress Int @default(0) // percentage score Float? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id], onDelete: Cascade) training Training @relation(fields: [trainingId], references: [id], onDelete: Cascade) @@unique([farmerId, trainingId]) @@map("farmer_trainings") } model Certification { id String @id @default(cuid()) name String description String? validityPeriod Int? // in months requirements String? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmerCertifications FarmerCertification[] @@map("certifications") } model FarmerCertification { id String @id @default(cuid()) farmerId String certificationId String status CertificationStatus @default(PENDING) issuedDate DateTime? expiryDate DateTime? certificateNumber String? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id], onDelete: Cascade) certification Certification @relation(fields: [certificationId], references: [id], onDelete: Cascade) @@unique([farmerId, certificationId]) @@map("farmer_certifications") } model Article { id String @id @default(cuid()) title String content String excerpt String? category String tags String[] author String? status ArticleStatus @default(DRAFT) views Int @default(0) publishedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("articles") } model Product { id String @id @default(cuid()) name String // e.g., "Pepper" code String @unique description String? category String unit String @default("kg") // kg, ton, etc isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations plots Plot[] variants ProductVariant[] modifiers ProductModifier[] priceHistory PriceHistory[] marketPrices MarketPrice[] marketDemand MarketDemand[] @@map("products") } model ProductVariant { id String @id @default(cuid()) productId String name String // e.g., "Black Pepper", "White Pepper" code String @unique description String? basePrice Float? // default base price isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations product Product @relation(fields: [productId], references: [id], onDelete: Cascade) plots Plot[] harvests Harvest[] procurements Procurement[] priceHistory PriceHistory[] marketPrices MarketPrice[] marketDemand MarketDemand[] @@map("product_variants") } model ProductModifier { id String @id @default(cuid()) productId String name String // e.g., "Water Content", "Density" code String description String? selectionType ModifierSelectionType @default(INPUT) nominalType NominalType @default(NOMINAL) options String[] // For dropdown selections minimum Float? maximum Float? unit String? // %, kg/m3, etc isRequired Boolean @default(false) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations product Product @relation(fields: [productId], references: [id], onDelete: Cascade) rules ProductModifierRule[] harvestModifiers HarvestModifier[] @@unique([productId, code]) @@map("product_modifiers") } model ProductModifierRule { id String @id @default(cuid()) modifierId String condition RuleCondition priceAdjustment Float // amount to adjust price value String? // For equals condition minValue Float? // For lessThan or between conditions maxValue Float? // For greaterThan or between conditions description String? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations modifier ProductModifier @relation(fields: [modifierId], references: [id], onDelete: Cascade) @@map("product_modifier_rules") } model PriceHistory { id String @id @default(cuid()) productId String? variantId String? qualityGrade QualityGrade basePrice Float marketPrice Float? premiumRate Float @default(0) effectiveDate DateTime region String? notes String? createdAt DateTime @default(now()) // Relations product Product? @relation(fields: [productId], references: [id]) variant ProductVariant? @relation(fields: [variantId], references: [id]) @@map("price_history") } model WeatherData { id String @id @default(cuid()) farmId String? plotId String? latitude Float longitude Float date DateTime temperature Float? // celsius humidity Float? // percentage rainfall Float? // mm windSpeed Float? // km/h windDirection String? // N, NE, E, SE, S, SW, W, NW pressure Float? // hPa uvIndex Float? visibility Float? // km weatherCondition String? // sunny, cloudy, rainy, etc. dataSource String? // manual, weather_station, api createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm? @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("weather_data") } model WeatherForecast { id String @id @default(cuid()) farmId String? plotId String? latitude Float longitude Float forecastDate DateTime minTemperature Float? maxTemperature Float? humidity Float? rainfall Float? windSpeed Float? weatherCondition String? confidence Float? // percentage source String createdAt DateTime @default(now()) // Relations farm Farm? @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("weather_forecasts") } model FarmInput { id String @id @default(cuid()) farmId String plotId String? inputType InputType productName String brand String? quantity Float unit String cost Float supplier String? supplierContact String? batchNumber String? expiryDate DateTime? applicationDate DateTime? applicationMethod String? applicationRate String? // per hectare or per plant activeIngredient String? // for pesticides/fertilizers concentration Float? // percentage notes String? invoiceNumber String? receiptUrl String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("farm_inputs") } model InputSchedule { id String @id @default(cuid()) farmId String plotId String? inputType InputType productName String scheduledDate DateTime quantity Float unit String method String? status ScheduleStatus @default(PENDING) appliedDate DateTime? appliedBy String? actualQuantity Float? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("input_schedules") } model Supplier { id String @id @default(cuid()) name String contactPerson String? phone String? email String? address String? supplierType SupplierType paymentTerms String? deliveryTerms String? qualityCertifications String[] isActive Boolean @default(true) notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("suppliers") } model FarmWorker { id String @id @default(cuid()) farmerId String workerCode String @unique name String phone String? email String? address String? identityNumber String? role WorkerRole skillLevel SkillLevel? dailyWage Float? monthlyWage Float? paymentMethod PaymentMethod? bankAccount String? emergencyContact String? emergencyPhone String? hireDate DateTime? contractType ContractType? contractEnd DateTime? isActive Boolean @default(true) notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) laborRecords LaborRecord[] laborSchedules LaborSchedule[] @@map("farm_workers") } model LaborRecord { id String @id @default(cuid()) farmerId String farmId String workerId String? plotId String? workType WorkType hoursWorked Float wages Float workDate DateTime startTime DateTime? endTime DateTime? description String? supervisor String? // supervisor name or ID qualityRating Float? // 1-5 rating weather String? notes String? approved Boolean @default(false) approvedBy String? approvedDate DateTime? paymentStatus PaymentStatus @default(PENDING) paidDate DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) farm Farm @relation(fields: [farmId], references: [id]) worker FarmWorker? @relation(fields: [workerId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("labor_records") } model LaborSchedule { id String @id @default(cuid()) farmerId String farmId String workerId String? plotId String? workType WorkType scheduledDate DateTime estimatedHours Float estimatedWage Float? status ScheduleStatus @default(PENDING) assignedBy String? notes String? actualRecord String? // reference to LaborRecord ID createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) farm Farm @relation(fields: [farmId], references: [id]) worker FarmWorker? @relation(fields: [workerId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("labor_schedules") } model Equipment { id String @id @default(cuid()) farmerId String equipmentCode String @unique name String type EquipmentType brand String? model String? serialNumber String? purchaseDate DateTime? purchasePrice Float? currentValue Float? condition EquipmentCondition status EquipmentStatus @default(ACTIVE) location String? // where equipment is stored fuelType String? // diesel, petrol, electric, manual capacity String? // engine capacity, load capacity powerRating String? // horsepower, wattage yearManufactured Int? warranty String? insurancePolicy String? insuranceExpiry DateTime? lastMaintenance DateTime? nextMaintenance DateTime? maintenanceCost Float? operatingHours Float? // total operating hours isActive Boolean @default(true) notes String? photoUrl String? manualUrl String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) maintenanceRecords MaintenanceRecord[] usageRecords EquipmentUsage[] @@map("equipment") } model MaintenanceRecord { id String @id @default(cuid()) equipmentId String maintenanceType MaintenanceType description String cost Float serviceProvider String? serviceDate DateTime nextServiceDue DateTime? partsReplaced String[] laborHours Float? invoiceNumber String? receiptUrl String? performedBy String? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations equipment Equipment @relation(fields: [equipmentId], references: [id]) @@map("maintenance_records") } model EquipmentUsage { id String @id @default(cuid()) equipmentId String farmId String? plotId String? operatorName String? usageDate DateTime startTime DateTime? endTime DateTime? hoursUsed Float fuelConsumed Float? workType WorkType? description String? meterReading Float? // odometer, hour meter reading notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations equipment Equipment @relation(fields: [equipmentId], references: [id]) farm Farm? @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("equipment_usage") } model Asset { id String @id @default(cuid()) farmerId String assetCode String @unique name String type AssetType category String? // building, land improvement, infrastructure description String? purchaseDate DateTime? purchasePrice Float? currentValue Float? depreciation Float? // annual depreciation rate condition AssetCondition location String? size String? // dimensions, area material String? // construction material lifespan Int? // expected lifespan in years warrantyExpiry DateTime? insurancePolicy String? insuranceExpiry DateTime? photoUrls String[] documentUrls String[] isActive Boolean @default(true) notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) @@map("assets") } model BuyerReview { id String @id @default(cuid()) buyerId String farmerId String rating Float // 1-5 rating comment String? reviewType ReviewType procurementId String? // reference to procurement if applicable isAnonymous Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations buyer Buyer @relation(fields: [buyerId], references: [id]) farmer Farmer @relation(fields: [farmerId], references: [id]) @@map("buyer_reviews") } model PestDiseaseRecord { id String @id @default(cuid()) farmId String plotId String? type PestDiseaseType name String scientificName String? severity SeverityLevel affectedArea Float? // percentage or hectares identifiedDate DateTime identifiedBy String? // farmer, expert, etc. symptoms String? treatmentApplied String? treatmentDate DateTime? treatmentCost Float? treatmentMethod String? preventionTaken String? resolved Boolean @default(false) resolvedDate DateTime? recurrence Boolean @default(false) photos String[] // photo URLs notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farm Farm @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("pest_disease_records") } model FinancialRecord { id String @id @default(cuid()) farmerId String farmId String? plotId String? type TransactionType category String subcategory String? amount Float currency String @default("IDR") description String transactionDate DateTime paymentMethod PaymentMethod? receiptNumber String? invoiceNumber String? referenceNumber String? taxAmount Float? @default(0) bankAccount String? payee String? // who received payment approvedBy String? // admin who approved status TransactionStatus @default(PENDING) notes String? attachmentUrls String[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations farmer Farmer @relation(fields: [farmerId], references: [id]) farm Farm? @relation(fields: [farmId], references: [id]) plot Plot? @relation(fields: [plotId], references: [id]) @@map("financial_records") } model SoilTest { id String @id @default(cuid()) farmId String plotId String? testCode String @unique testDate DateTime sampleDepth Float? // cm sampleLocation String? gpsCoordinates Json? // GeoJSON point // Basic soil properties pH Float? organicMatter Float? // percentage soilTexture String? // clay, sand, loam, etc. bulkDensity Float? // g/cm³ porosity Float? // percentage // Nutrients (ppm) nitrogen Float? phosphorus Float? potassium Float? calcium Float? magnesium Float? sulfur Float? // Micronutrients (ppm) zinc Float? iron Float? manganese Float? copper Float? boron Float? // Other properties conductivity Float? // dS/m cationExchangeCapacity Float? // cmol/kg baseStaturation Float? // percentage carbonNitrogenRatio Float? // Analysis details recommendations String? testLaboratory String? technicianName String? testCost Float? 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]) @@map("soil_tests") } model Message { id String @id @default(cuid()) senderId String receiverId String? groupId String? subject String? content String messageType MessageType priority Priority @default(NORMAL) isRead Boolean @default(false) readAt DateTime? attachments String[] // file URLs deliveryStatus MessageStatus @default(SENT) sentAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("messages") } model MarketPrice { id String @id @default(cuid()) productId String variantId String? market String region String price Float unit String @default("kg") qualityGrade QualityGrade priceDate DateTime source String? // where price data came from volume Float? // trading volume trend PriceTrend? verified Boolean @default(false) verifiedBy String? notes String? createdAt DateTime @default(now()) // Relations product Product @relation(fields: [productId], references: [id]) variant ProductVariant? @relation(fields: [variantId], references: [id]) @@map("market_prices") } model MarketDemand { id String @id @default(cuid()) productId String variantId String? region String demandLevel DemandLevel estimatedVolume Float? priceRange String? season String? factors String[] // factors affecting demand forecastDate DateTime forecastBy String? accuracy Float? // percentage notes String? createdAt DateTime @default(now()) // Relations product Product @relation(fields: [productId], references: [id]) variant ProductVariant? @relation(fields: [variantId], references: [id]) @@map("market_demand") } // Enums enum UserRole { FARMER BUYER ADMINISTRATOR } enum QualityGrade { A B C } enum ProcurementStatus { PENDING QUALITY_ASSESSMENT APPROVED REJECTED IN_TRANSIT DELIVERED INVOICED PAID COMPLETED CANCELLED PARTIALLY_REJECTED } enum TrainingStatus { ENROLLED IN_PROGRESS COMPLETED DROPPED } enum CertificationStatus { PENDING APPROVED REJECTED EXPIRED } enum ArticleStatus { DRAFT PUBLISHED ARCHIVED } enum ModifierSelectionType { DROPDOWN INPUT } enum NominalType { NOMINAL PERCENTAGE } enum RuleCondition { EQUALS LESS_THAN GREATER_THAN BETWEEN } enum Gender { MALE FEMALE OTHER } enum IdentityType { KTP // Indonesian ID Card PASSPORT DRIVING_LICENSE OTHER } enum EducationLevel { NO_FORMAL_EDUCATION ELEMENTARY MIDDLE_SCHOOL HIGH_SCHOOL DIPLOMA BACHELOR MASTER DOCTORATE } enum FarmerStatus { ACTIVE INACTIVE SUSPENDED PENDING_VERIFICATION BLACKLISTED } enum AttachmentType { PROFILE_PHOTO ID_CARD_FRONT ID_CARD_BACK FARMING_LICENSE LAND_CERTIFICATE BANK_STATEMENT CONTRACT CERTIFICATE OTHER_DOCUMENT } enum MaritalStatus { SINGLE MARRIED DIVORCED WIDOWED SEPARATED } enum Religion { ISLAM CHRISTIAN CATHOLIC HINDU BUDDHIST CONFUCIAN OTHER } enum LandOwnership { OWNER TENANT SHARECROPPER COOPERATIVE_MEMBER GOVERNMENT_LEASE FAMILY_LAND OTHER } enum WaterSource { RAIN_FED IRRIGATION_CANAL WELL RIVER POND GROUNDWATER SPRING MIXED } enum IrrigationType { FLOOD SPRINKLER DRIP FURROW MANUAL NONE } enum SlopeType { FLAT GENTLE MODERATE STEEP VERY_STEEP } enum ClimateType { TROPICAL_WET TROPICAL_DRY SUBTROPICAL TEMPERATE HIGHLAND } enum RoadType { PAVED GRAVEL DIRT FOOTPATH NO_ACCESS } 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 } enum PaymentMethod { CASH BANK_TRANSFER MOBILE_MONEY CHECK DIGITAL_WALLET CREDIT BARTER INSTALLMENT } enum ProcurementAttachmentType { PRODUCT_PHOTO QUALITY_ASSESSMENT_PHOTO WEIGHING_PHOTO PACKAGING_PHOTO LOADING_PHOTO DELIVERY_PHOTO CONTRACT_DOCUMENT INVOICE RECEIPT PAYMENT_PROOF QUALITY_CERTIFICATE TRANSPORT_DOCUMENT REJECTION_PHOTO SIGNATURE_DOCUMENT OTHER_DOCUMENT } // Input Management Enums enum InputType { SEED FERTILIZER PESTICIDE HERBICIDE FUNGICIDE INSECTICIDE EQUIPMENT_RENTAL FUEL IRRIGATION_WATER MULCH COMPOST LIME OTHER } enum ScheduleStatus { PENDING SCHEDULED IN_PROGRESS COMPLETED CANCELLED OVERDUE } enum SupplierType { SEED_SUPPLIER FERTILIZER_SUPPLIER PESTICIDE_SUPPLIER EQUIPMENT_SUPPLIER GENERAL_SUPPLIER COOPERATIVE GOVERNMENT_AGENCY } // Labor Management Enums enum WorkerRole { PERMANENT SEASONAL DAILY CONTRACTOR SUPERVISOR FOREMAN SPECIALIST } enum SkillLevel { BEGINNER INTERMEDIATE ADVANCED EXPERT } enum ContractType { PERMANENT TEMPORARY SEASONAL PROJECT_BASED DAILY } enum WorkType { PLANTING WEEDING FERTILIZING HARVESTING IRRIGATION PEST_CONTROL SOIL_PREPARATION PRUNING GENERAL_MAINTENANCE EQUIPMENT_OPERATION PROCESSING PACKAGING TRANSPORT } enum PaymentStatus { PENDING APPROVED PAID OVERDUE CANCELLED } // Equipment & Asset Enums enum EquipmentType { TRACTOR HARVESTER PLANTER CULTIVATOR IRRIGATION_SYSTEM SPRAYER THRESHER MOWER TOOLS VEHICLE PROCESSING_EQUIPMENT STORAGE_EQUIPMENT } enum EquipmentCondition { EXCELLENT GOOD FAIR POOR NEEDS_REPAIR OUT_OF_ORDER } enum EquipmentStatus { ACTIVE INACTIVE MAINTENANCE REPAIR RETIRED } enum MaintenanceType { PREVENTIVE CORRECTIVE EMERGENCY OVERHAUL INSPECTION CALIBRATION } enum AssetType { BUILDING LAND_IMPROVEMENT INFRASTRUCTURE VEHICLE MACHINERY FURNITURE TECHNOLOGY OTHER } enum AssetCondition { NEW EXCELLENT GOOD FAIR POOR DAMAGED } // Buyer Enums enum BuyerType { INDIVIDUAL WHOLESALER RETAILER PROCESSOR EXPORTER COOPERATIVE GOVERNMENT RESTAURANT HOTEL } enum BusinessSize { MICRO SMALL MEDIUM LARGE ENTERPRISE } enum BuyerStatus { ACTIVE INACTIVE SUSPENDED PENDING_VERIFICATION BLACKLISTED } enum ReviewType { PAYMENT_TIMELINESS QUALITY_REQUIREMENTS COMMUNICATION OVERALL_EXPERIENCE PRICE_FAIRNESS } // Pest & Disease Enums enum PestDiseaseType { PEST DISEASE WEED NUTRIENT_DEFICIENCY VIRUS FUNGUS BACTERIA } enum SeverityLevel { LOW MEDIUM HIGH CRITICAL CATASTROPHIC } // Financial Enums enum TransactionType { INCOME EXPENSE INVESTMENT LOAN LOAN_PAYMENT INSURANCE_PAYMENT TAX_PAYMENT GRANT SUBSIDY REFUND } enum TransactionStatus { PENDING APPROVED COMPLETED REJECTED CANCELLED FAILED } // Communication Enums enum MessageType { PERSONAL BROADCAST NOTIFICATION ALERT SYSTEM ANNOUNCEMENT } enum Priority { LOW NORMAL HIGH URGENT CRITICAL } enum MessageStatus { SENT DELIVERED READ FAILED PENDING } // Market Intelligence Enums enum PriceTrend { RISING FALLING STABLE VOLATILE } enum DemandLevel { VERY_LOW LOW MODERATE HIGH VERY_HIGH EXCESSIVE }