feat: Introduce comprehensive training and user management schemas
- Added Training, FarmerTraining, and Certification models to manage training programs and certifications for farmers. - Implemented User, Farmer, Buyer, and Administrator models to enhance user management and roles within the platform. - Established relationships between training and user models to track participation and progress. - Included enums for training and certification statuses to standardize state management. - Enhanced documentation for the new schema structure to improve maintainability and collaboration.
This commit is contained in:
parent
dacae9e70e
commit
2c7294a75b
|
|
@ -969,32 +969,89 @@ This comprehensive database schema is designed for a modern agricultural technol
|
||||||
## Training & Certification
|
## Training & Certification
|
||||||
|
|
||||||
### Training
|
### Training
|
||||||
**Purpose**: Farmer education and skill development
|
**Purpose**: Admin-managed training program system for farmer skill development
|
||||||
**Key Features**:
|
**Key Features**:
|
||||||
- Course content management
|
- Administrative training program management
|
||||||
- Difficulty level classification
|
- Course content and curriculum design
|
||||||
- Duration tracking
|
- Participant capacity and prerequisites management
|
||||||
- Category organization
|
- Admin assignment and selection workflows
|
||||||
|
|
||||||
**Course Management**:
|
**Administrative Management**:
|
||||||
- Structured learning content
|
- Training program creation and maintenance by admins
|
||||||
- Beginner to advanced levels
|
- Content management with multimedia support
|
||||||
- Time-based progression
|
- Participant capacity limits and prerequisite requirements
|
||||||
- Category-based organization
|
- Admin-controlled activation and deactivation
|
||||||
|
|
||||||
|
**Course Structure**:
|
||||||
|
- Structured learning content with modules and assessments
|
||||||
|
- Difficulty level classification (beginner to advanced)
|
||||||
|
- Duration tracking and scheduling
|
||||||
|
- Category-based organization and filtering
|
||||||
|
|
||||||
|
**Assignment System**:
|
||||||
|
- Admin-driven farmer selection and assignment
|
||||||
|
- Capacity management and participant limits
|
||||||
|
- Assignment reason tracking and documentation
|
||||||
|
- Notification workflow for selected farmers
|
||||||
|
|
||||||
|
**Fields**:
|
||||||
|
- `id`: Unique training program identifier
|
||||||
|
- `title`: Training program name
|
||||||
|
- `description`: Detailed program description
|
||||||
|
- `content`: Training materials and curriculum
|
||||||
|
- `category`: Subject area classification
|
||||||
|
- `duration`: Training duration in minutes
|
||||||
|
- `level`: Difficulty level (beginner/intermediate/advanced)
|
||||||
|
- `prerequisites`: Required knowledge or certifications
|
||||||
|
- `maxParticipants`: Maximum number of participants
|
||||||
|
- `createdBy`: Admin who created the training program
|
||||||
|
- `isActive`: Program availability status
|
||||||
|
- `createdAt`, `updatedAt`: Timestamps
|
||||||
|
|
||||||
|
**Relations**: Connected to farmer training assignments and admin management
|
||||||
|
|
||||||
### FarmerTraining
|
### FarmerTraining
|
||||||
**Purpose**: Individual training progress and achievement tracking
|
**Purpose**: Admin-assigned training participation and progress tracking
|
||||||
**Key Features**:
|
**Key Features**:
|
||||||
- Enrollment and progress tracking
|
- Admin-controlled farmer assignment system
|
||||||
- Score and completion management
|
- Training progress and completion tracking
|
||||||
- Certificate generation
|
- Assignment reason and deadline management
|
||||||
- Learning analytics
|
- Notification workflow for assignments
|
||||||
|
|
||||||
|
**Assignment Management**:
|
||||||
|
- Admin assignment with reason documentation
|
||||||
|
- Assignment date and deadline tracking
|
||||||
|
- Notification system for assigned farmers
|
||||||
|
- Assignment audit trail and history
|
||||||
|
|
||||||
**Progress Tracking**:
|
**Progress Tracking**:
|
||||||
- Enrollment status and progress percentage
|
- Enrollment status and progress percentage
|
||||||
- Score tracking and assessments
|
- Score tracking and assessment results
|
||||||
- Completion certificates
|
- Completion certificates and achievements
|
||||||
- Learning path optimization
|
- Learning analytics and performance metrics
|
||||||
|
|
||||||
|
**Assignment Workflow**:
|
||||||
|
- Admin selects training program
|
||||||
|
- Admin filters and selects suitable farmers
|
||||||
|
- System creates assignments with notifications
|
||||||
|
- Farmers receive assignment notifications
|
||||||
|
- Progress tracking through completion
|
||||||
|
|
||||||
|
**Fields**:
|
||||||
|
- `id`: Unique assignment identifier
|
||||||
|
- `farmerId`: Assigned farmer reference
|
||||||
|
- `trainingId`: Training program reference
|
||||||
|
- `status`: Training status (ENROLLED, IN_PROGRESS, COMPLETED, DROPPED)
|
||||||
|
- `progress`: Completion percentage (0-100)
|
||||||
|
- `score`: Assessment score
|
||||||
|
- `completedAt`: Completion timestamp
|
||||||
|
- `assignedBy`: Admin who made the assignment
|
||||||
|
- `assignedAt`: Assignment creation date
|
||||||
|
- `assignmentReason`: Reason for farmer selection
|
||||||
|
- `deadline`: Expected completion date
|
||||||
|
- `createdAt`, `updatedAt`: Timestamps
|
||||||
|
|
||||||
|
**Relations**: Connected to farmers, training programs, and admin management
|
||||||
|
|
||||||
### Certification
|
### Certification
|
||||||
**Purpose**: Professional certification and credential management
|
**Purpose**: Professional certification and credential management
|
||||||
|
|
@ -1002,7 +1059,24 @@ This comprehensive database schema is designed for a modern agricultural technol
|
||||||
- Certification program management
|
- Certification program management
|
||||||
- Validity period tracking
|
- Validity period tracking
|
||||||
- Requirements documentation
|
- Requirements documentation
|
||||||
- Industry recognition
|
- Industry recognition and standards
|
||||||
|
|
||||||
|
**Certification Management**:
|
||||||
|
- Certification program definition and maintenance
|
||||||
|
- Validity period and renewal requirements
|
||||||
|
- Industry standard compliance
|
||||||
|
- Quality assurance and recognition
|
||||||
|
|
||||||
|
**Fields**:
|
||||||
|
- `id`: Unique certification identifier
|
||||||
|
- `name`: Certification name
|
||||||
|
- `description`: Certification details and requirements
|
||||||
|
- `validityPeriod`: Certification validity in months
|
||||||
|
- `requirements`: Qualification requirements
|
||||||
|
- `isActive`: Certification program status
|
||||||
|
- `createdAt`, `updatedAt`: Timestamps
|
||||||
|
|
||||||
|
**Relations**: Connected to farmer certifications and training programs
|
||||||
|
|
||||||
### FarmerCertification
|
### FarmerCertification
|
||||||
**Purpose**: Individual certification status and management
|
**Purpose**: Individual certification status and management
|
||||||
|
|
@ -1010,7 +1084,26 @@ This comprehensive database schema is designed for a modern agricultural technol
|
||||||
- Certification status tracking
|
- Certification status tracking
|
||||||
- Issue and expiry date management
|
- Issue and expiry date management
|
||||||
- Certificate number assignment
|
- Certificate number assignment
|
||||||
- Renewal notifications
|
- Renewal notifications and workflow
|
||||||
|
|
||||||
|
**Certification Tracking**:
|
||||||
|
- Application and approval workflow
|
||||||
|
- Certificate generation and numbering
|
||||||
|
- Expiry date monitoring and renewal alerts
|
||||||
|
- Certification verification and validation
|
||||||
|
|
||||||
|
**Fields**:
|
||||||
|
- `id`: Unique certification record identifier
|
||||||
|
- `farmerId`: Certified farmer reference
|
||||||
|
- `certificationId`: Certification program reference
|
||||||
|
- `status`: Certification status (PENDING, APPROVED, REJECTED, EXPIRED)
|
||||||
|
- `issuedDate`: Certificate issue date
|
||||||
|
- `expiryDate`: Certificate expiry date
|
||||||
|
- `certificateNumber`: Unique certificate number
|
||||||
|
- `notes`: Additional certification notes
|
||||||
|
- `createdAt`, `updatedAt`: Timestamps
|
||||||
|
|
||||||
|
**Relations**: Connected to farmers and certification programs
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -1158,6 +1251,10 @@ High-volume counters use `BigInt`:
|
||||||
- `PestDiseaseType`: PEST, DISEASE, WEED, NUTRIENT_DEFICIENCY, etc.
|
- `PestDiseaseType`: PEST, DISEASE, WEED, NUTRIENT_DEFICIENCY, etc.
|
||||||
- `SeverityLevel`: LOW, MEDIUM, HIGH, CRITICAL, CATASTROPHIC
|
- `SeverityLevel`: LOW, MEDIUM, HIGH, CRITICAL, CATASTROPHIC
|
||||||
|
|
||||||
|
**Training & Certification**:
|
||||||
|
- `TrainingStatus`: ENROLLED, IN_PROGRESS, COMPLETED, DROPPED
|
||||||
|
- `CertificationStatus`: PENDING, APPROVED, REJECTED, EXPIRED
|
||||||
|
|
||||||
**Business Operations**:
|
**Business Operations**:
|
||||||
- `ProcurementStatus`: PENDING to COMPLETED (11 stages)
|
- `ProcurementStatus`: PENDING to COMPLETED (11 stages)
|
||||||
- `PaymentMethod`: CASH, BANK_TRANSFER, MOBILE_MONEY, etc.
|
- `PaymentMethod`: CASH, BANK_TRANSFER, MOBILE_MONEY, etc.
|
||||||
|
|
|
||||||
2228
schema.prisma
2228
schema.prisma
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,214 @@
|
||||||
|
# Split Schema Structure
|
||||||
|
|
||||||
|
This directory contains the split version of the agricultural platform's Prisma schema, organized by domain for better maintainability and team collaboration.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
schemas/
|
||||||
|
├── README.md # This file
|
||||||
|
├── base.prisma # Generator, datasource, and shared enums
|
||||||
|
├── user.prisma # User management (User, Farmer, Buyer, Administrator)
|
||||||
|
├── reference.prisma # Reference data (Country, Currency, Religion, EducationLevel)
|
||||||
|
├── farm.prisma # Farm management (Farm, Plot, SoilTest, FarmAttachment)
|
||||||
|
├── product.prisma # Product system (Product, ProductVariant, modifiers)
|
||||||
|
├── procurement.prisma # Trading (Procurement, Contract, Harvest)
|
||||||
|
├── season.prisma # Seasonal planning (Season, PlotSeason, analytics)
|
||||||
|
├── operations.prisma # Operations (Input, Labor, Equipment, Assets)
|
||||||
|
├── financial.prisma # Financial records and transactions
|
||||||
|
├── communication.prisma # Notifications and messaging
|
||||||
|
├── weather.prisma # Weather data and forecasts
|
||||||
|
├── training.prisma # Training and certification
|
||||||
|
├── market.prisma # Market intelligence and pricing
|
||||||
|
├── knowledge.prisma # Articles and knowledge base
|
||||||
|
├── attachments.prisma # File and attachment management
|
||||||
|
└── pest-disease.prisma # Pest, disease, and review management
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benefits of Split Schema
|
||||||
|
|
||||||
|
### 1. **Better Organization**
|
||||||
|
- Logical grouping by business domain
|
||||||
|
- Easier to find specific models
|
||||||
|
- Reduced cognitive load when working on specific features
|
||||||
|
- Clear separation of concerns
|
||||||
|
|
||||||
|
### 2. **Team Collaboration**
|
||||||
|
- Multiple developers can work on different schema files simultaneously
|
||||||
|
- Reduced merge conflicts
|
||||||
|
- Clear ownership boundaries
|
||||||
|
- Focused code reviews
|
||||||
|
|
||||||
|
### 3. **Maintainability**
|
||||||
|
- Easier to understand and modify specific domains
|
||||||
|
- Better debugging and troubleshooting
|
||||||
|
- Cleaner dependency management
|
||||||
|
- Improved documentation per domain
|
||||||
|
|
||||||
|
### 4. **Performance Benefits**
|
||||||
|
- Faster schema compilation for individual domains
|
||||||
|
- Easier to identify bottlenecks
|
||||||
|
- Better indexing strategy per domain
|
||||||
|
- Optimized queries per business area
|
||||||
|
|
||||||
|
## How to Use Split Schema
|
||||||
|
|
||||||
|
### Option 1: Replace Original Schema
|
||||||
|
1. **Backup original schema.prisma**:
|
||||||
|
```bash
|
||||||
|
mv schema.prisma schema.prisma.backup
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use split schema directory**:
|
||||||
|
```bash
|
||||||
|
# Prisma will automatically read all .prisma files in the directory
|
||||||
|
npx prisma generate
|
||||||
|
npx prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: Parallel Development
|
||||||
|
Keep both structures and choose based on your needs:
|
||||||
|
- Use original `schema.prisma` for production
|
||||||
|
- Use `schemas/` directory for development and feature work
|
||||||
|
- Gradually migrate teams to split structure
|
||||||
|
|
||||||
|
## Domain Responsibilities
|
||||||
|
|
||||||
|
### **Core Domains**
|
||||||
|
- **user.prisma**: Authentication, user profiles, role management
|
||||||
|
- **reference.prisma**: Master data (countries, currencies, education levels)
|
||||||
|
- **farm.prisma**: Farm infrastructure, plots, soil management
|
||||||
|
|
||||||
|
### **Business Domains**
|
||||||
|
- **product.prisma**: Product catalog, variants, quality modifiers
|
||||||
|
- **procurement.prisma**: Trading, contracts, harvest management
|
||||||
|
- **season.prisma**: Agricultural cycles, seasonal planning
|
||||||
|
- **operations.prisma**: Daily operations, labor, equipment
|
||||||
|
|
||||||
|
### **Support Domains**
|
||||||
|
- **financial.prisma**: Financial tracking, transactions
|
||||||
|
- **communication.prisma**: Notifications, messaging
|
||||||
|
- **weather.prisma**: Climate data, forecasts
|
||||||
|
- **training.prisma**: Education, certifications
|
||||||
|
|
||||||
|
### **Analytics Domains**
|
||||||
|
- **market.prisma**: Market intelligence, pricing
|
||||||
|
- **knowledge.prisma**: Content management
|
||||||
|
- **attachments.prisma**: File management
|
||||||
|
- **pest-disease.prisma**: Agricultural health tracking
|
||||||
|
|
||||||
|
## File Size Comparison
|
||||||
|
|
||||||
|
| Structure | File Count | Lines per File | Total Lines |
|
||||||
|
|-----------|------------|----------------|-------------|
|
||||||
|
| Original | 1 file | ~1,800 lines | 1,800 |
|
||||||
|
| Split | 15 files | ~120-300 lines| 1,800 |
|
||||||
|
|
||||||
|
## Cross-Domain Relationships
|
||||||
|
|
||||||
|
The split maintains all relationships between domains:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
// farmer.prisma references farm.prisma
|
||||||
|
model Farmer {
|
||||||
|
farms Farm[] // → farm.prisma
|
||||||
|
}
|
||||||
|
|
||||||
|
// farm.prisma references farmer.prisma
|
||||||
|
model Farm {
|
||||||
|
farmer Farmer @relation(...) // → user.prisma
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration Strategy
|
||||||
|
|
||||||
|
### Phase 1: Parallel Structure
|
||||||
|
- Keep original schema.prisma
|
||||||
|
- Create split structure alongside
|
||||||
|
- Use for new feature development
|
||||||
|
|
||||||
|
### Phase 2: Team Adoption
|
||||||
|
- Train teams on domain boundaries
|
||||||
|
- Establish ownership per domain
|
||||||
|
- Use split structure for reviews
|
||||||
|
|
||||||
|
### Phase 3: Full Migration
|
||||||
|
- Move production to split structure
|
||||||
|
- Archive original schema.prisma
|
||||||
|
- Update CI/CD pipelines
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. **Domain Boundaries**
|
||||||
|
- Keep related models together
|
||||||
|
- Minimize cross-domain dependencies
|
||||||
|
- Use clear naming conventions
|
||||||
|
|
||||||
|
### 2. **Shared Elements**
|
||||||
|
- Keep shared enums in base.prisma
|
||||||
|
- Document cross-domain relationships
|
||||||
|
- Maintain consistent data types
|
||||||
|
|
||||||
|
### 3. **Team Workflow**
|
||||||
|
- Assign domain ownership
|
||||||
|
- Review changes by domain
|
||||||
|
- Coordinate cross-domain changes
|
||||||
|
|
||||||
|
### 4. **Development**
|
||||||
|
- Test schema compilation regularly
|
||||||
|
- Validate relationships across files
|
||||||
|
- Monitor performance impact
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Duplicate Models/Enums**:
|
||||||
|
- Ensure original schema.prisma is not in the same directory
|
||||||
|
- Check for naming conflicts across files
|
||||||
|
|
||||||
|
2. **Missing Relations**:
|
||||||
|
- Verify cross-file relationships are properly defined
|
||||||
|
- Check import paths and model references
|
||||||
|
|
||||||
|
3. **Compilation Errors**:
|
||||||
|
- Run `npx prisma validate` to check schema integrity
|
||||||
|
- Verify all referenced models exist across files
|
||||||
|
|
||||||
|
### Validation Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Validate entire schema
|
||||||
|
npx prisma validate
|
||||||
|
|
||||||
|
# Generate client to test compilation
|
||||||
|
npx prisma generate
|
||||||
|
|
||||||
|
# Check database sync
|
||||||
|
npx prisma migrate dev --create-only
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
### Potential Improvements
|
||||||
|
1. **Microservice Extraction**: Easier to identify service boundaries
|
||||||
|
2. **Database Sharding**: Clear data partitioning strategies
|
||||||
|
3. **Team Scaling**: Better support for large development teams
|
||||||
|
4. **Domain-Driven Design**: Enhanced DDD implementation
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
- Track file modification patterns
|
||||||
|
- Monitor domain interaction frequency
|
||||||
|
- Identify optimization opportunities
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For questions about the split schema structure:
|
||||||
|
1. Check this README for common issues
|
||||||
|
2. Review domain documentation in each file
|
||||||
|
3. Validate schema compilation with Prisma CLI
|
||||||
|
4. Contact the database team for complex migrations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note**: This split structure maintains full compatibility with the original schema.prisma. All relationships, constraints, and data types remain identical.
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Attachment Management Domain
|
||||||
|
// Contains all attachment and file management models
|
||||||
|
|
||||||
|
// Attachment-specific Enums
|
||||||
|
enum AttachmentType {
|
||||||
|
PROFILE_PHOTO
|
||||||
|
ID_CARD_FRONT
|
||||||
|
ID_CARD_BACK
|
||||||
|
FARMING_LICENSE
|
||||||
|
LAND_CERTIFICATE
|
||||||
|
BANK_STATEMENT
|
||||||
|
CONTRACT
|
||||||
|
CERTIFICATE
|
||||||
|
OTHER_DOCUMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attachment Models
|
||||||
|
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)
|
||||||
|
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([type])
|
||||||
|
@@index([isVerified])
|
||||||
|
@@index([uploadedBy])
|
||||||
|
@@index([createdAt])
|
||||||
|
@@index([mimeType])
|
||||||
|
@@map("farmer_attachments")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
// This is the base Prisma schema file
|
||||||
|
// Contains generator, datasource, and shared enums
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared Enums - Used across multiple domains
|
||||||
|
|
||||||
|
// Core User Management Enums
|
||||||
|
enum UserRole {
|
||||||
|
FARMER
|
||||||
|
BUYER
|
||||||
|
ADMINISTRATOR
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Gender {
|
||||||
|
MALE
|
||||||
|
FEMALE
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MaritalStatus {
|
||||||
|
SINGLE
|
||||||
|
MARRIED
|
||||||
|
DIVORCED
|
||||||
|
WIDOWED
|
||||||
|
SEPARATED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum IdentityType {
|
||||||
|
KTP // Indonesian ID Card
|
||||||
|
PASSPORT
|
||||||
|
DRIVING_LICENSE
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quality and Status Enums
|
||||||
|
enum QualityGrade {
|
||||||
|
A
|
||||||
|
B
|
||||||
|
C
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PaymentMethod {
|
||||||
|
CASH
|
||||||
|
BANK_TRANSFER
|
||||||
|
MOBILE_MONEY
|
||||||
|
CHECK
|
||||||
|
DIGITAL_WALLET
|
||||||
|
CREDIT
|
||||||
|
BARTER
|
||||||
|
INSTALLMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PaymentStatus {
|
||||||
|
PENDING
|
||||||
|
APPROVED
|
||||||
|
PAID
|
||||||
|
OVERDUE
|
||||||
|
CANCELLED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ScheduleStatus {
|
||||||
|
PENDING
|
||||||
|
SCHEDULED
|
||||||
|
IN_PROGRESS
|
||||||
|
COMPLETED
|
||||||
|
CANCELLED
|
||||||
|
OVERDUE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Geographic and Environmental Enums
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Agricultural Enums
|
||||||
|
enum WorkType {
|
||||||
|
PLANTING
|
||||||
|
WEEDING
|
||||||
|
FERTILIZING
|
||||||
|
HARVESTING
|
||||||
|
IRRIGATION
|
||||||
|
PEST_CONTROL
|
||||||
|
SOIL_PREPARATION
|
||||||
|
PRUNING
|
||||||
|
GENERAL_MAINTENANCE
|
||||||
|
EQUIPMENT_OPERATION
|
||||||
|
PROCESSING
|
||||||
|
PACKAGING
|
||||||
|
TRANSPORT
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InputType {
|
||||||
|
SEED
|
||||||
|
FERTILIZER
|
||||||
|
PESTICIDE
|
||||||
|
HERBICIDE
|
||||||
|
FUNGICIDE
|
||||||
|
INSECTICIDE
|
||||||
|
EQUIPMENT_RENTAL
|
||||||
|
FUEL
|
||||||
|
IRRIGATION_WATER
|
||||||
|
MULCH
|
||||||
|
COMPOST
|
||||||
|
LIME
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SeverityLevel {
|
||||||
|
LOW
|
||||||
|
MEDIUM
|
||||||
|
HIGH
|
||||||
|
CRITICAL
|
||||||
|
CATASTROPHIC
|
||||||
|
}
|
||||||
|
|
||||||
|
// Communication and Priority Enums
|
||||||
|
enum Priority {
|
||||||
|
LOW
|
||||||
|
NORMAL
|
||||||
|
HIGH
|
||||||
|
URGENT
|
||||||
|
CRITICAL
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MessageType {
|
||||||
|
PERSONAL
|
||||||
|
BROADCAST
|
||||||
|
NOTIFICATION
|
||||||
|
ALERT
|
||||||
|
SYSTEM
|
||||||
|
ANNOUNCEMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
// Communication & Notifications Domain
|
||||||
|
// Contains Notification, Message, and communication models
|
||||||
|
|
||||||
|
// Communication-specific Enums
|
||||||
|
enum NotificationType {
|
||||||
|
SYSTEM
|
||||||
|
ANNOUNCEMENT
|
||||||
|
ALERT
|
||||||
|
REMINDER
|
||||||
|
PROMOTION
|
||||||
|
UPDATE
|
||||||
|
WARNING
|
||||||
|
INFO
|
||||||
|
SUCCESS
|
||||||
|
ERROR
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotificationCategory {
|
||||||
|
GENERAL
|
||||||
|
PROCUREMENT
|
||||||
|
PAYMENT
|
||||||
|
QUALITY
|
||||||
|
WEATHER
|
||||||
|
PRICE_ALERT
|
||||||
|
TRAINING
|
||||||
|
CERTIFICATION
|
||||||
|
MAINTENANCE
|
||||||
|
HARVEST
|
||||||
|
PLANTING
|
||||||
|
MARKET
|
||||||
|
CONTRACT
|
||||||
|
COMPLIANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotificationStatus {
|
||||||
|
PENDING
|
||||||
|
SCHEDULED
|
||||||
|
SENT
|
||||||
|
DELIVERED
|
||||||
|
FAILED
|
||||||
|
CANCELLED
|
||||||
|
EXPIRED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Communication Models
|
||||||
|
model Notification {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
message String
|
||||||
|
type NotificationType
|
||||||
|
category NotificationCategory @default(GENERAL)
|
||||||
|
priority Priority @default(NORMAL)
|
||||||
|
|
||||||
|
// Recipients
|
||||||
|
recipientId String? // specific user ID
|
||||||
|
recipientType UserRole? // or broadcast to user type
|
||||||
|
recipientIds String[] // multiple specific users
|
||||||
|
|
||||||
|
// Targeting
|
||||||
|
farmerIds String[] // specific farmers
|
||||||
|
buyerIds String[] // specific buyers
|
||||||
|
region String? // geographic targeting
|
||||||
|
productIds String[] // product-specific notifications
|
||||||
|
|
||||||
|
// Content and media
|
||||||
|
content String? // detailed content/body
|
||||||
|
imageUrl String?
|
||||||
|
actionUrl String? // deep link or action URL
|
||||||
|
actionLabel String? // button text
|
||||||
|
|
||||||
|
// Scheduling
|
||||||
|
scheduledAt DateTime? // for scheduled notifications
|
||||||
|
expiresAt DateTime? // expiration date
|
||||||
|
|
||||||
|
// Status tracking
|
||||||
|
status NotificationStatus @default(PENDING)
|
||||||
|
sentAt DateTime?
|
||||||
|
deliveredCount Int @default(0)
|
||||||
|
readCount Int @default(0)
|
||||||
|
clickCount Int @default(0)
|
||||||
|
|
||||||
|
// Metadata
|
||||||
|
source String? // system, admin, automated, etc.
|
||||||
|
sourceId String? // reference to source entity
|
||||||
|
tags String[] // for categorization
|
||||||
|
metadata Json? // additional data
|
||||||
|
|
||||||
|
// Tracking
|
||||||
|
isRead Boolean @default(false)
|
||||||
|
readAt DateTime?
|
||||||
|
isClicked Boolean @default(false)
|
||||||
|
clickedAt DateTime?
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
recipients NotificationRecipient[]
|
||||||
|
|
||||||
|
@@index([type])
|
||||||
|
@@index([category])
|
||||||
|
@@index([priority])
|
||||||
|
@@index([status])
|
||||||
|
@@index([scheduledAt])
|
||||||
|
@@index([recipientType])
|
||||||
|
@@index([region])
|
||||||
|
@@index([createdAt])
|
||||||
|
@@map("notifications")
|
||||||
|
}
|
||||||
|
|
||||||
|
model NotificationRecipient {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
notificationId String
|
||||||
|
userId String
|
||||||
|
isRead Boolean @default(false)
|
||||||
|
readAt DateTime?
|
||||||
|
isClicked Boolean @default(false)
|
||||||
|
clickedAt DateTime?
|
||||||
|
isDelivered Boolean @default(false)
|
||||||
|
deliveredAt DateTime?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@unique([notificationId, userId])
|
||||||
|
@@index([notificationId])
|
||||||
|
@@index([userId])
|
||||||
|
@@index([isRead])
|
||||||
|
@@index([isDelivered])
|
||||||
|
@@index([createdAt])
|
||||||
|
@@map("notification_recipients")
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
@@index([senderId])
|
||||||
|
@@index([receiverId])
|
||||||
|
@@index([messageType])
|
||||||
|
@@index([isRead])
|
||||||
|
@@index([sentAt])
|
||||||
|
@@index([deliveryStatus])
|
||||||
|
@@map("messages")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
// 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")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Financial Management Domain
|
||||||
|
// Contains financial records, transactions, and currency models
|
||||||
|
|
||||||
|
// Financial-specific Enums
|
||||||
|
enum TransactionType {
|
||||||
|
INCOME
|
||||||
|
EXPENSE
|
||||||
|
INVESTMENT
|
||||||
|
LOAN
|
||||||
|
LOAN_PAYMENT
|
||||||
|
INSURANCE_PAYMENT
|
||||||
|
TAX_PAYMENT
|
||||||
|
GRANT
|
||||||
|
SUBSIDY
|
||||||
|
REFUND
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TransactionStatus {
|
||||||
|
PENDING
|
||||||
|
APPROVED
|
||||||
|
COMPLETED
|
||||||
|
REJECTED
|
||||||
|
CANCELLED
|
||||||
|
FAILED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Financial Models
|
||||||
|
model FinancialRecord {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmerId String
|
||||||
|
farmId String?
|
||||||
|
plotId String?
|
||||||
|
type TransactionType
|
||||||
|
category String
|
||||||
|
subcategory String?
|
||||||
|
amount Decimal
|
||||||
|
currencyId String @default("idr")
|
||||||
|
currency Currency @relation(fields: [currencyId], references: [id])
|
||||||
|
description String
|
||||||
|
transactionDate DateTime
|
||||||
|
paymentMethod PaymentMethod?
|
||||||
|
receiptNumber String?
|
||||||
|
invoiceNumber String?
|
||||||
|
referenceNumber String?
|
||||||
|
taxAmount Decimal? @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])
|
||||||
|
|
||||||
|
@@index([farmerId, farmId])
|
||||||
|
@@index([type])
|
||||||
|
@@index([transactionDate])
|
||||||
|
@@index([status])
|
||||||
|
@@index([category])
|
||||||
|
@@index([paymentMethod])
|
||||||
|
@@index([amount])
|
||||||
|
@@map("financial_records")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Knowledge Management Domain
|
||||||
|
// Contains articles, content management, and knowledge base
|
||||||
|
|
||||||
|
// Knowledge-specific Enums
|
||||||
|
enum ArticleStatus {
|
||||||
|
DRAFT
|
||||||
|
PUBLISHED
|
||||||
|
ARCHIVED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Knowledge Models
|
||||||
|
model Article {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
content String
|
||||||
|
excerpt String?
|
||||||
|
category String
|
||||||
|
tags String[]
|
||||||
|
author String?
|
||||||
|
status ArticleStatus @default(DRAFT)
|
||||||
|
views BigInt @default(0)
|
||||||
|
publishedAt DateTime?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([category])
|
||||||
|
@@index([status])
|
||||||
|
@@index([publishedAt])
|
||||||
|
@@index([author])
|
||||||
|
@@index([views])
|
||||||
|
@@index([title])
|
||||||
|
@@map("articles")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Market Intelligence Domain
|
||||||
|
// Contains market prices, demand analysis, and business intelligence
|
||||||
|
|
||||||
|
model MarketPrice {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
productId String
|
||||||
|
variantId String?
|
||||||
|
market String
|
||||||
|
region String
|
||||||
|
price Decimal
|
||||||
|
unit String @default("kg")
|
||||||
|
qualityGrade QualityGrade
|
||||||
|
priceDate DateTime
|
||||||
|
source String? // where price data came from
|
||||||
|
volume Decimal? // 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])
|
||||||
|
|
||||||
|
@@index([productId, variantId])
|
||||||
|
@@index([market, region])
|
||||||
|
@@index([priceDate])
|
||||||
|
@@index([qualityGrade])
|
||||||
|
@@index([trend])
|
||||||
|
@@index([verified])
|
||||||
|
@@index([price])
|
||||||
|
@@map("market_prices")
|
||||||
|
}
|
||||||
|
|
||||||
|
model MarketDemand {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
productId String
|
||||||
|
variantId String?
|
||||||
|
region String
|
||||||
|
demandLevel DemandLevel
|
||||||
|
estimatedVolume Decimal?
|
||||||
|
priceRange String?
|
||||||
|
season String?
|
||||||
|
factors String[] // factors affecting demand
|
||||||
|
forecastDate DateTime
|
||||||
|
forecastBy String?
|
||||||
|
accuracy Decimal? // percentage
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
product Product @relation(fields: [productId], references: [id])
|
||||||
|
variant ProductVariant? @relation(fields: [variantId], references: [id])
|
||||||
|
|
||||||
|
@@index([productId, variantId])
|
||||||
|
@@index([region])
|
||||||
|
@@index([demandLevel])
|
||||||
|
@@index([forecastDate])
|
||||||
|
@@index([season])
|
||||||
|
@@index([accuracy])
|
||||||
|
@@map("market_demand")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,439 @@
|
||||||
|
// Operations Management Domain
|
||||||
|
// Contains Input management, Labor, Equipment, and daily operations
|
||||||
|
|
||||||
|
// Operations-specific Enums
|
||||||
|
enum SupplierType {
|
||||||
|
SEED_SUPPLIER
|
||||||
|
FERTILIZER_SUPPLIER
|
||||||
|
PESTICIDE_SUPPLIER
|
||||||
|
EQUIPMENT_SUPPLIER
|
||||||
|
GENERAL_SUPPLIER
|
||||||
|
COOPERATIVE
|
||||||
|
GOVERNMENT_AGENCY
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WorkerRole {
|
||||||
|
PERMANENT
|
||||||
|
SEASONAL
|
||||||
|
DAILY
|
||||||
|
CONTRACTOR
|
||||||
|
SUPERVISOR
|
||||||
|
FOREMAN
|
||||||
|
SPECIALIST
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SkillLevel {
|
||||||
|
BEGINNER
|
||||||
|
INTERMEDIATE
|
||||||
|
ADVANCED
|
||||||
|
EXPERT
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ContractType {
|
||||||
|
PERMANENT
|
||||||
|
TEMPORARY
|
||||||
|
SEASONAL
|
||||||
|
PROJECT_BASED
|
||||||
|
DAILY
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operations Models
|
||||||
|
model FarmInput {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmId String
|
||||||
|
plotId String?
|
||||||
|
inputType InputType
|
||||||
|
productName String
|
||||||
|
brand String?
|
||||||
|
quantity Decimal
|
||||||
|
unit String
|
||||||
|
cost Decimal
|
||||||
|
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 Decimal? // 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])
|
||||||
|
|
||||||
|
@@index([farmId, plotId])
|
||||||
|
@@index([inputType])
|
||||||
|
@@index([applicationDate])
|
||||||
|
@@index([supplier])
|
||||||
|
@@index([expiryDate])
|
||||||
|
@@map("farm_inputs")
|
||||||
|
}
|
||||||
|
|
||||||
|
model InputSchedule {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmId String
|
||||||
|
plotId String?
|
||||||
|
inputType InputType
|
||||||
|
productName String
|
||||||
|
scheduledDate DateTime
|
||||||
|
quantity Decimal
|
||||||
|
unit String
|
||||||
|
method String?
|
||||||
|
status ScheduleStatus @default(PENDING)
|
||||||
|
appliedDate DateTime?
|
||||||
|
appliedBy String?
|
||||||
|
actualQuantity Decimal?
|
||||||
|
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([farmId, plotId])
|
||||||
|
@@index([scheduledDate])
|
||||||
|
@@index([status])
|
||||||
|
@@index([inputType])
|
||||||
|
@@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
|
||||||
|
|
||||||
|
@@index([supplierType])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([name])
|
||||||
|
@@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 Decimal?
|
||||||
|
monthlyWage Decimal?
|
||||||
|
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[]
|
||||||
|
|
||||||
|
@@index([workerCode])
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([role])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([contractType])
|
||||||
|
@@map("farm_workers")
|
||||||
|
}
|
||||||
|
|
||||||
|
model LaborRecord {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmerId String
|
||||||
|
farmId String
|
||||||
|
workerId String?
|
||||||
|
plotId String?
|
||||||
|
workType WorkType
|
||||||
|
hoursWorked Decimal
|
||||||
|
wages Decimal
|
||||||
|
workDate DateTime
|
||||||
|
startTime DateTime?
|
||||||
|
endTime DateTime?
|
||||||
|
description String?
|
||||||
|
supervisor String? // supervisor name or ID
|
||||||
|
qualityRating Decimal? // 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])
|
||||||
|
|
||||||
|
@@index([farmerId, farmId])
|
||||||
|
@@index([workDate])
|
||||||
|
@@index([workType])
|
||||||
|
@@index([paymentStatus])
|
||||||
|
@@index([workerId])
|
||||||
|
@@map("labor_records")
|
||||||
|
}
|
||||||
|
|
||||||
|
model LaborSchedule {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmerId String
|
||||||
|
farmId String
|
||||||
|
workerId String?
|
||||||
|
plotId String?
|
||||||
|
workType WorkType
|
||||||
|
scheduledDate DateTime
|
||||||
|
estimatedHours Decimal
|
||||||
|
estimatedWage Decimal?
|
||||||
|
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])
|
||||||
|
|
||||||
|
@@index([farmerId, farmId])
|
||||||
|
@@index([scheduledDate])
|
||||||
|
@@index([status])
|
||||||
|
@@index([workType])
|
||||||
|
@@index([workerId])
|
||||||
|
@@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 Decimal?
|
||||||
|
currentValue Decimal?
|
||||||
|
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 Decimal?
|
||||||
|
operatingHours Decimal? // 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[]
|
||||||
|
|
||||||
|
@@index([equipmentCode])
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([type])
|
||||||
|
@@index([status])
|
||||||
|
@@index([nextMaintenance])
|
||||||
|
@@index([isActive])
|
||||||
|
@@map("equipment")
|
||||||
|
}
|
||||||
|
|
||||||
|
model MaintenanceRecord {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
equipmentId String
|
||||||
|
maintenanceType MaintenanceType
|
||||||
|
description String
|
||||||
|
cost Decimal
|
||||||
|
serviceProvider String?
|
||||||
|
serviceDate DateTime
|
||||||
|
nextServiceDue DateTime?
|
||||||
|
partsReplaced String[]
|
||||||
|
laborHours Decimal?
|
||||||
|
invoiceNumber String?
|
||||||
|
receiptUrl String?
|
||||||
|
performedBy String?
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
equipment Equipment @relation(fields: [equipmentId], references: [id])
|
||||||
|
|
||||||
|
@@index([equipmentId])
|
||||||
|
@@index([serviceDate])
|
||||||
|
@@index([maintenanceType])
|
||||||
|
@@index([nextServiceDue])
|
||||||
|
@@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 Decimal
|
||||||
|
fuelConsumed Decimal?
|
||||||
|
workType WorkType?
|
||||||
|
description String?
|
||||||
|
meterReading Decimal? // 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])
|
||||||
|
|
||||||
|
@@index([equipmentId])
|
||||||
|
@@index([usageDate])
|
||||||
|
@@index([farmId, plotId])
|
||||||
|
@@index([workType])
|
||||||
|
@@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 Decimal?
|
||||||
|
currentValue Decimal?
|
||||||
|
depreciation Decimal? // 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])
|
||||||
|
|
||||||
|
@@index([assetCode])
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([type])
|
||||||
|
@@index([condition])
|
||||||
|
@@index([isActive])
|
||||||
|
@@map("assets")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Pest & Disease Management Domain
|
||||||
|
// Contains pest, disease, and agricultural health tracking
|
||||||
|
|
||||||
|
// Pest & Disease Enums
|
||||||
|
enum PestDiseaseType {
|
||||||
|
PEST
|
||||||
|
DISEASE
|
||||||
|
WEED
|
||||||
|
NUTRIENT_DEFICIENCY
|
||||||
|
VIRUS
|
||||||
|
FUNGUS
|
||||||
|
BACTERIA
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ReviewType {
|
||||||
|
PAYMENT_TIMELINESS
|
||||||
|
QUALITY_REQUIREMENTS
|
||||||
|
COMMUNICATION
|
||||||
|
OVERALL_EXPERIENCE
|
||||||
|
PRICE_FAIRNESS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pest & Disease Models
|
||||||
|
model PestDiseaseRecord {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmId String
|
||||||
|
plotId String?
|
||||||
|
type PestDiseaseType
|
||||||
|
name String
|
||||||
|
scientificName String?
|
||||||
|
severity SeverityLevel
|
||||||
|
affectedArea Decimal? // percentage or hectares
|
||||||
|
identifiedDate DateTime
|
||||||
|
identifiedBy String? // farmer, expert, etc.
|
||||||
|
symptoms String?
|
||||||
|
treatmentApplied String?
|
||||||
|
treatmentDate DateTime?
|
||||||
|
treatmentCost Decimal?
|
||||||
|
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])
|
||||||
|
|
||||||
|
@@index([farmId, plotId])
|
||||||
|
@@index([type])
|
||||||
|
@@index([severity])
|
||||||
|
@@index([identifiedDate])
|
||||||
|
@@index([resolved])
|
||||||
|
@@index([name])
|
||||||
|
@@index([recurrence])
|
||||||
|
@@map("pest_disease_records")
|
||||||
|
}
|
||||||
|
|
||||||
|
model BuyerReview {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
buyerId String
|
||||||
|
farmerId String
|
||||||
|
rating Decimal // 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])
|
||||||
|
|
||||||
|
@@index([buyerId])
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([reviewType])
|
||||||
|
@@index([rating])
|
||||||
|
@@index([procurementId])
|
||||||
|
@@index([createdAt])
|
||||||
|
@@map("buyer_reviews")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,284 @@
|
||||||
|
// Procurement & Trading Domain
|
||||||
|
// Contains Procurement, Contract, Harvest, and related trading models
|
||||||
|
|
||||||
|
// Procurement-specific Enums
|
||||||
|
enum ProcurementStatus {
|
||||||
|
PENDING
|
||||||
|
QUALITY_ASSESSMENT
|
||||||
|
APPROVED
|
||||||
|
REJECTED
|
||||||
|
IN_TRANSIT
|
||||||
|
DELIVERED
|
||||||
|
INVOICED
|
||||||
|
PAID
|
||||||
|
COMPLETED
|
||||||
|
CANCELLED
|
||||||
|
PARTIALLY_REJECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AgreementType {
|
||||||
|
PURCHASE_AGREEMENT
|
||||||
|
SUPPLY_CONTRACT
|
||||||
|
EXCLUSIVE_SUPPLY
|
||||||
|
SEASONAL_CONTRACT
|
||||||
|
FORWARD_CONTRACT
|
||||||
|
SPOT_CONTRACT
|
||||||
|
CONSIGNMENT
|
||||||
|
PARTNERSHIP
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ContractStatus {
|
||||||
|
DRAFT
|
||||||
|
PENDING_REVIEW
|
||||||
|
PENDING_SIGNATURE
|
||||||
|
ACTIVE
|
||||||
|
FULFILLED
|
||||||
|
EXPIRED
|
||||||
|
TERMINATED
|
||||||
|
CANCELLED
|
||||||
|
BREACH
|
||||||
|
RENEWED
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Procurement Models
|
||||||
|
model Harvest {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
farmerId String
|
||||||
|
farmId String
|
||||||
|
plotId String?
|
||||||
|
variantId String
|
||||||
|
quantity Decimal // in kg
|
||||||
|
harvestDate DateTime
|
||||||
|
qualityGrade QualityGrade
|
||||||
|
waterContent Decimal? // percentage
|
||||||
|
density Decimal? // 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[]
|
||||||
|
|
||||||
|
@@index([farmerId, farmId])
|
||||||
|
@@index([harvestDate])
|
||||||
|
@@index([variantId])
|
||||||
|
@@index([qualityGrade])
|
||||||
|
@@index([plotId])
|
||||||
|
@@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 Decimal // in kg
|
||||||
|
qualityGrade QualityGrade
|
||||||
|
waterContent Decimal? // percentage
|
||||||
|
density Decimal? // kg/m3
|
||||||
|
|
||||||
|
// Pricing details
|
||||||
|
basePrice Decimal // price per kg
|
||||||
|
premiumRate Decimal @default(0) // percentage
|
||||||
|
totalPrice Decimal
|
||||||
|
transportCost Decimal? @default(0)
|
||||||
|
processingCost Decimal? @default(0)
|
||||||
|
finalAmount Decimal // 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 Decimal? @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
|
||||||
|
contractId String? // link to formal contract
|
||||||
|
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])
|
||||||
|
contract Contract? @relation(fields: [contractId], references: [id])
|
||||||
|
attachments ProcurementAttachment[]
|
||||||
|
|
||||||
|
@@index([procurementCode])
|
||||||
|
@@index([farmerId, buyerId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([procurementDate])
|
||||||
|
@@index([variantId])
|
||||||
|
@@index([qualityGrade])
|
||||||
|
@@index([paymentMethod])
|
||||||
|
@@map("procurements")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Contract {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
contractNumber String @unique
|
||||||
|
farmerId String
|
||||||
|
buyerId String
|
||||||
|
productId String?
|
||||||
|
variantId String?
|
||||||
|
|
||||||
|
// Contract terms
|
||||||
|
title String
|
||||||
|
description String?
|
||||||
|
contractType AgreementType @default(PURCHASE_AGREEMENT)
|
||||||
|
|
||||||
|
// Pricing and quantity
|
||||||
|
agreedPrice Decimal // price per unit
|
||||||
|
minimumQuantity Decimal?
|
||||||
|
maximumQuantity Decimal?
|
||||||
|
totalValue Decimal?
|
||||||
|
unit String @default("kg")
|
||||||
|
|
||||||
|
// Quality specifications
|
||||||
|
qualityGrade QualityGrade?
|
||||||
|
qualityRequirements String?
|
||||||
|
|
||||||
|
// Timeline
|
||||||
|
startDate DateTime
|
||||||
|
endDate DateTime
|
||||||
|
deliverySchedule String? // delivery frequency/schedule
|
||||||
|
|
||||||
|
// Payment terms
|
||||||
|
paymentTerms String? // payment conditions
|
||||||
|
paymentMethod PaymentMethod?
|
||||||
|
advancePayment Decimal? @default(0)
|
||||||
|
advancePercentage Decimal? @default(0)
|
||||||
|
|
||||||
|
// Legal and compliance
|
||||||
|
terms String? // full terms and conditions
|
||||||
|
penalties String? // penalty clauses
|
||||||
|
forcemajeure String? // force majeure clause
|
||||||
|
governingLaw String? // applicable law
|
||||||
|
|
||||||
|
// Status and tracking
|
||||||
|
status ContractStatus @default(DRAFT)
|
||||||
|
signedDate DateTime?
|
||||||
|
signedByFarmer Boolean @default(false)
|
||||||
|
signedByBuyer Boolean @default(false)
|
||||||
|
farmerSignature String? // signature data or URL
|
||||||
|
buyerSignature String? // signature data or URL
|
||||||
|
witnessName String?
|
||||||
|
witnessSignature String?
|
||||||
|
|
||||||
|
// Performance tracking
|
||||||
|
totalDelivered Decimal? @default(0)
|
||||||
|
totalPaid Decimal? @default(0)
|
||||||
|
deliveryCount Int @default(0)
|
||||||
|
|
||||||
|
// Renewal and amendments
|
||||||
|
renewalDate DateTime?
|
||||||
|
amendmentCount Int @default(0)
|
||||||
|
parentContractId String? // for contract renewals
|
||||||
|
|
||||||
|
// Documentation
|
||||||
|
documentUrl String? // contract document
|
||||||
|
attachmentUrls String[] // supporting documents
|
||||||
|
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
farmer Farmer @relation(fields: [farmerId], references: [id])
|
||||||
|
buyer Buyer @relation(fields: [buyerId], references: [id])
|
||||||
|
product Product? @relation(fields: [productId], references: [id])
|
||||||
|
variant ProductVariant? @relation(fields: [variantId], references: [id])
|
||||||
|
parentContract Contract? @relation("ContractRenewal", fields: [parentContractId], references: [id])
|
||||||
|
renewalContracts Contract[] @relation("ContractRenewal")
|
||||||
|
procurements Procurement[] // deliveries under this contract
|
||||||
|
|
||||||
|
@@index([contractNumber])
|
||||||
|
@@index([farmerId, buyerId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([startDate, endDate])
|
||||||
|
@@index([productId, variantId])
|
||||||
|
@@index([signedDate])
|
||||||
|
@@map("contracts")
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
@@index([procurementId])
|
||||||
|
@@index([type])
|
||||||
|
@@index([isVerified])
|
||||||
|
@@index([createdAt])
|
||||||
|
@@map("procurement_attachments")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
// Product Management Domain
|
||||||
|
// Contains Product, ProductVariant, modifiers, and pricing models
|
||||||
|
|
||||||
|
// Product-specific Enums
|
||||||
|
enum ModifierSelectionType {
|
||||||
|
DROPDOWN
|
||||||
|
INPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NominalType {
|
||||||
|
NOMINAL
|
||||||
|
PERCENTAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RuleCondition {
|
||||||
|
EQUALS
|
||||||
|
LESS_THAN
|
||||||
|
GREATER_THAN
|
||||||
|
BETWEEN
|
||||||
|
}
|
||||||
|
|
||||||
|
// Product Models
|
||||||
|
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[]
|
||||||
|
contracts Contract[]
|
||||||
|
priceHistory PriceHistory[]
|
||||||
|
marketPrices MarketPrice[]
|
||||||
|
marketDemand MarketDemand[]
|
||||||
|
plotSeasons PlotSeason[]
|
||||||
|
seasonHarvests SeasonHarvest[]
|
||||||
|
|
||||||
|
@@index([code])
|
||||||
|
@@index([category])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([name])
|
||||||
|
@@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 Decimal? // 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[]
|
||||||
|
contracts Contract[]
|
||||||
|
priceHistory PriceHistory[]
|
||||||
|
marketPrices MarketPrice[]
|
||||||
|
marketDemand MarketDemand[]
|
||||||
|
plotSeasons PlotSeason[]
|
||||||
|
seasonHarvests SeasonHarvest[]
|
||||||
|
|
||||||
|
@@index([code])
|
||||||
|
@@index([productId])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([basePrice])
|
||||||
|
@@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 Decimal?
|
||||||
|
maximum Decimal?
|
||||||
|
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])
|
||||||
|
@@index([productId])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([selectionType])
|
||||||
|
@@map("product_modifiers")
|
||||||
|
}
|
||||||
|
|
||||||
|
model ProductModifierRule {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
modifierId String
|
||||||
|
condition RuleCondition
|
||||||
|
priceAdjustment Decimal // amount to adjust price
|
||||||
|
value String? // For equals condition
|
||||||
|
minValue Decimal? // For lessThan or between conditions
|
||||||
|
maxValue Decimal? // 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 HarvestModifier {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
harvestId String
|
||||||
|
modifierId String
|
||||||
|
value String // actual value applied
|
||||||
|
adjustment Decimal? // 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 PriceHistory {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
productId String?
|
||||||
|
variantId String?
|
||||||
|
qualityGrade QualityGrade
|
||||||
|
basePrice Decimal
|
||||||
|
marketPrice Decimal?
|
||||||
|
premiumRate Decimal @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])
|
||||||
|
|
||||||
|
@@index([productId, variantId])
|
||||||
|
@@index([effectiveDate])
|
||||||
|
@@index([qualityGrade])
|
||||||
|
@@index([region])
|
||||||
|
@@map("price_history")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
// Reference Data Domain
|
||||||
|
// Contains normalized reference tables for countries, currencies, education, religion
|
||||||
|
|
||||||
|
model EducationLevel {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String @unique
|
||||||
|
level Int // 0=No formal, 1=Elementary, etc.
|
||||||
|
description String?
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
farmers Farmer[]
|
||||||
|
|
||||||
|
@@index([name])
|
||||||
|
@@index([level])
|
||||||
|
@@index([isActive])
|
||||||
|
@@map("education_levels")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Currency {
|
||||||
|
id String @id // ISO currency code like "idr", "usd"
|
||||||
|
name String @unique
|
||||||
|
code String @unique // ISO 4217 currency code
|
||||||
|
symbol String // ₹, $, Rp, etc.
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
financialRecords FinancialRecord[]
|
||||||
|
|
||||||
|
@@index([code])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([name])
|
||||||
|
@@map("currencies")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Country {
|
||||||
|
id String @id // ISO country code like "indonesia", "malaysia"
|
||||||
|
name String @unique
|
||||||
|
code String @unique // ISO 3166-1 alpha-2 code
|
||||||
|
region String?
|
||||||
|
continent String?
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
farmerNationalities Farmer[] @relation("FarmerNationality")
|
||||||
|
farmerCountries Farmer[] @relation("FarmerCountry")
|
||||||
|
|
||||||
|
@@index([code])
|
||||||
|
@@index([region])
|
||||||
|
@@index([continent])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([name])
|
||||||
|
@@map("countries")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Religion {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String @unique
|
||||||
|
description String?
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
farmers Farmer[]
|
||||||
|
|
||||||
|
@@index([name])
|
||||||
|
@@index([isActive])
|
||||||
|
@@map("religions")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
// Season & Cycle Management Domain
|
||||||
|
// Contains Season planning, PlotSeason tracking, and seasonal analytics
|
||||||
|
|
||||||
|
// Season-specific Enums
|
||||||
|
enum SeasonType {
|
||||||
|
WET_SEASON
|
||||||
|
DRY_SEASON
|
||||||
|
TRANSITION
|
||||||
|
YEAR_ROUND
|
||||||
|
SPRING
|
||||||
|
SUMMER
|
||||||
|
FALL
|
||||||
|
WINTER
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlantingStatus {
|
||||||
|
PLANNED
|
||||||
|
PLANTED
|
||||||
|
GROWING
|
||||||
|
FLOWERING
|
||||||
|
FRUITING
|
||||||
|
HARVESTING
|
||||||
|
HARVESTED
|
||||||
|
FAILED
|
||||||
|
ABANDONED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Season Models
|
||||||
|
model Season {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String // e.g., "Wet Season 2024", "Dry Season 2024"
|
||||||
|
seasonType SeasonType
|
||||||
|
year Int
|
||||||
|
|
||||||
|
// Timeline
|
||||||
|
startDate DateTime
|
||||||
|
endDate DateTime
|
||||||
|
|
||||||
|
// Weather characteristics
|
||||||
|
avgRainfall Decimal? // mm
|
||||||
|
avgTemperature Float? // celsius
|
||||||
|
avgHumidity Decimal? // percentage
|
||||||
|
|
||||||
|
// Agricultural phases
|
||||||
|
plantingStart DateTime?
|
||||||
|
plantingEnd DateTime?
|
||||||
|
growingStart DateTime?
|
||||||
|
growingEnd DateTime?
|
||||||
|
harvestStart DateTime?
|
||||||
|
harvestEnd DateTime?
|
||||||
|
|
||||||
|
// Region and scope
|
||||||
|
region String?
|
||||||
|
province String?
|
||||||
|
country String @default("Indonesia")
|
||||||
|
|
||||||
|
// Crop recommendations
|
||||||
|
recommendedCrops String[] // suitable crops for this season
|
||||||
|
notRecommendedCrops String[] // crops to avoid
|
||||||
|
|
||||||
|
// Market expectations
|
||||||
|
expectedDemand DemandLevel?
|
||||||
|
priceOutlook PriceTrend?
|
||||||
|
marketNotes String?
|
||||||
|
|
||||||
|
// Agricultural activities
|
||||||
|
activities Json? // structured data for farming activities
|
||||||
|
|
||||||
|
// Status
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
isCurrent Boolean @default(false)
|
||||||
|
|
||||||
|
description String?
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
plots PlotSeason[]
|
||||||
|
harvests SeasonHarvest[]
|
||||||
|
weatherData SeasonWeather[]
|
||||||
|
|
||||||
|
@@unique([seasonType, year, region])
|
||||||
|
@@index([seasonType, year])
|
||||||
|
@@index([region])
|
||||||
|
@@index([startDate, endDate])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([isCurrent])
|
||||||
|
@@map("seasons")
|
||||||
|
}
|
||||||
|
|
||||||
|
model PlotSeason {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
plotId String
|
||||||
|
seasonId String
|
||||||
|
productId String?
|
||||||
|
variantId String?
|
||||||
|
|
||||||
|
// Planting details
|
||||||
|
plantedDate DateTime?
|
||||||
|
plantedArea Decimal? // hectares actually planted
|
||||||
|
seedVariety String?
|
||||||
|
|
||||||
|
// Expected outcomes
|
||||||
|
expectedYield Decimal? // kg per hectare
|
||||||
|
expectedHarvest Decimal? // total kg expected
|
||||||
|
expectedHarvestDate DateTime?
|
||||||
|
|
||||||
|
// Actual outcomes
|
||||||
|
actualYield Decimal? // kg per hectare
|
||||||
|
actualHarvest Decimal? // total kg harvested
|
||||||
|
actualHarvestDate DateTime?
|
||||||
|
|
||||||
|
status PlantingStatus @default(PLANNED)
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
plot Plot @relation(fields: [plotId], references: [id])
|
||||||
|
season Season @relation(fields: [seasonId], references: [id])
|
||||||
|
product Product? @relation(fields: [productId], references: [id])
|
||||||
|
variant ProductVariant? @relation(fields: [variantId], references: [id])
|
||||||
|
|
||||||
|
@@unique([plotId, seasonId])
|
||||||
|
@@index([plotId, seasonId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([plantedDate])
|
||||||
|
@@index([productId, variantId])
|
||||||
|
@@map("plot_seasons")
|
||||||
|
}
|
||||||
|
|
||||||
|
model SeasonHarvest {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
seasonId String
|
||||||
|
farmerId String
|
||||||
|
productId String
|
||||||
|
variantId String?
|
||||||
|
|
||||||
|
totalQuantity Decimal
|
||||||
|
averageQuality QualityGrade
|
||||||
|
totalValue Decimal
|
||||||
|
|
||||||
|
harvestCount Int @default(1)
|
||||||
|
firstHarvest DateTime
|
||||||
|
lastHarvest DateTime?
|
||||||
|
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
season Season @relation(fields: [seasonId], references: [id])
|
||||||
|
farmer Farmer @relation(fields: [farmerId], references: [id])
|
||||||
|
product Product @relation(fields: [productId], references: [id])
|
||||||
|
variant ProductVariant? @relation(fields: [variantId], references: [id])
|
||||||
|
|
||||||
|
@@index([seasonId, farmerId])
|
||||||
|
@@index([productId, variantId])
|
||||||
|
@@index([firstHarvest])
|
||||||
|
@@index([averageQuality])
|
||||||
|
@@map("season_harvests")
|
||||||
|
}
|
||||||
|
|
||||||
|
model SeasonWeather {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
seasonId String
|
||||||
|
region String
|
||||||
|
|
||||||
|
// Aggregated weather data
|
||||||
|
totalRainfall Decimal? // mm
|
||||||
|
avgTemperature Float? // celsius
|
||||||
|
minTemperature Float? // celsius
|
||||||
|
maxTemperature Float? // celsius
|
||||||
|
avgHumidity Decimal? // percentage
|
||||||
|
|
||||||
|
// Extreme events
|
||||||
|
droughtDays Int? @default(0)
|
||||||
|
floodDays Int? @default(0)
|
||||||
|
stormCount Int? @default(0)
|
||||||
|
|
||||||
|
// Impact assessment
|
||||||
|
cropDamage Decimal? // percentage
|
||||||
|
yieldImpact Decimal? // percentage change
|
||||||
|
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
season Season @relation(fields: [seasonId], references: [id])
|
||||||
|
|
||||||
|
@@unique([seasonId, region])
|
||||||
|
@@index([seasonId, region])
|
||||||
|
@@index([totalRainfall])
|
||||||
|
@@index([avgTemperature])
|
||||||
|
@@map("season_weather")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
// Training & Certification Domain
|
||||||
|
// Contains training programs, certifications, and farmer development
|
||||||
|
|
||||||
|
// Training-specific Enums
|
||||||
|
enum TrainingStatus {
|
||||||
|
ENROLLED
|
||||||
|
IN_PROGRESS
|
||||||
|
COMPLETED
|
||||||
|
DROPPED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CertificationStatus {
|
||||||
|
PENDING
|
||||||
|
APPROVED
|
||||||
|
REJECTED
|
||||||
|
EXPIRED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Training Models
|
||||||
|
model Training {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
description String?
|
||||||
|
content String?
|
||||||
|
category String
|
||||||
|
duration Int? // in minutes
|
||||||
|
level String? // beginner, intermediate, advanced
|
||||||
|
prerequisites String?
|
||||||
|
maxParticipants Int? // Maximum number of participants
|
||||||
|
createdBy String? // Admin who created the training
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
farmerTrainings FarmerTraining[]
|
||||||
|
|
||||||
|
@@index([category])
|
||||||
|
@@index([level])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([duration])
|
||||||
|
@@index([createdBy])
|
||||||
|
@@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?
|
||||||
|
assignedBy String? // Admin who assigned the farmer to training
|
||||||
|
assignedAt DateTime? // When the assignment was made
|
||||||
|
assignmentReason String? // Reason for assignment
|
||||||
|
deadline DateTime? // Expected completion deadline
|
||||||
|
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])
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([trainingId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([completedAt])
|
||||||
|
@@index([progress])
|
||||||
|
@@index([assignedBy])
|
||||||
|
@@index([assignedAt])
|
||||||
|
@@index([deadline])
|
||||||
|
@@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[]
|
||||||
|
|
||||||
|
@@index([name])
|
||||||
|
@@index([isActive])
|
||||||
|
@@index([validityPeriod])
|
||||||
|
@@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])
|
||||||
|
@@index([farmerId])
|
||||||
|
@@index([certificationId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([expiryDate])
|
||||||
|
@@index([issuedDate])
|
||||||
|
@@map("farmer_certifications")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,261 @@
|
||||||
|
// User Management Domain
|
||||||
|
// Contains User, Farmer, Buyer, Administrator models and related enums
|
||||||
|
|
||||||
|
// User Status Enums
|
||||||
|
enum FarmerStatus {
|
||||||
|
ACTIVE
|
||||||
|
INACTIVE
|
||||||
|
SUSPENDED
|
||||||
|
PENDING_VERIFICATION
|
||||||
|
BLACKLISTED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BuyerStatus {
|
||||||
|
ACTIVE
|
||||||
|
INACTIVE
|
||||||
|
SUSPENDED
|
||||||
|
PENDING_VERIFICATION
|
||||||
|
BLACKLISTED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BuyerType {
|
||||||
|
INDIVIDUAL
|
||||||
|
WHOLESALER
|
||||||
|
RETAILER
|
||||||
|
PROCESSOR
|
||||||
|
EXPORTER
|
||||||
|
COOPERATIVE
|
||||||
|
GOVERNMENT
|
||||||
|
RESTAURANT
|
||||||
|
HOTEL
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BusinessSize {
|
||||||
|
MICRO
|
||||||
|
SMALL
|
||||||
|
MEDIUM
|
||||||
|
LARGE
|
||||||
|
ENTERPRISE
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LandOwnership {
|
||||||
|
OWNER
|
||||||
|
TENANT
|
||||||
|
SHARECROPPER
|
||||||
|
COOPERATIVE_MEMBER
|
||||||
|
GOVERNMENT_LEASE
|
||||||
|
FAMILY_LAND
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
|
// User Models
|
||||||
|
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?
|
||||||
|
notifications NotificationRecipient[]
|
||||||
|
|
||||||
|
@@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)
|
||||||
|
religionId String?
|
||||||
|
religion Religion? @relation(fields: [religionId], references: [id])
|
||||||
|
nationalityId String? @default("indonesia")
|
||||||
|
nationality Country? @relation("FarmerNationality", fields: [nationalityId], references: [id])
|
||||||
|
address String?
|
||||||
|
village String?
|
||||||
|
district String?
|
||||||
|
province String?
|
||||||
|
postalCode String?
|
||||||
|
countryId String? @default("indonesia")
|
||||||
|
country Country? @relation("FarmerCountry", fields: [countryId], references: [id])
|
||||||
|
|
||||||
|
// 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
|
||||||
|
educationLevelId String?
|
||||||
|
educationLevel EducationLevel? @relation(fields: [educationLevelId], references: [id])
|
||||||
|
occupation String? // primary occupation if not full-time farmer
|
||||||
|
monthlyIncome Decimal? // 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[]
|
||||||
|
contracts Contract[]
|
||||||
|
seasonHarvests SeasonHarvest[]
|
||||||
|
|
||||||
|
@@index([farmerCode])
|
||||||
|
@@index([userId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([joinedAt])
|
||||||
|
@@index([latitude, longitude])
|
||||||
|
@@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 Decimal?
|
||||||
|
preferredProducts String[]
|
||||||
|
qualityRequirements String?
|
||||||
|
|
||||||
|
// Location and logistics
|
||||||
|
warehouseAddress String?
|
||||||
|
deliveryPreference String?
|
||||||
|
operatingRadius Decimal? // km
|
||||||
|
|
||||||
|
// Business details
|
||||||
|
businessSize BusinessSize?
|
||||||
|
yearEstablished Int?
|
||||||
|
annualVolume Decimal? // 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 Decimal?
|
||||||
|
maximumOrderQuantity Decimal?
|
||||||
|
|
||||||
|
notes String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
procurements Procurement[]
|
||||||
|
reviews BuyerReview[]
|
||||||
|
contracts Contract[]
|
||||||
|
|
||||||
|
@@index([buyerCode])
|
||||||
|
@@index([userId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([buyerType])
|
||||||
|
@@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)
|
||||||
|
|
||||||
|
@@index([adminCode])
|
||||||
|
@@index([userId])
|
||||||
|
@@map("administrators")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Weather & Climate Domain
|
||||||
|
// Contains weather data, forecasts, and climate tracking
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
@@index([farmId, plotId])
|
||||||
|
@@index([latitude, longitude])
|
||||||
|
@@index([date])
|
||||||
|
@@index([weatherCondition])
|
||||||
|
@@index([dataSource])
|
||||||
|
@@index([temperature])
|
||||||
|
@@index([rainfall])
|
||||||
|
@@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])
|
||||||
|
|
||||||
|
@@index([farmId, plotId])
|
||||||
|
@@index([latitude, longitude])
|
||||||
|
@@index([forecastDate])
|
||||||
|
@@index([weatherCondition])
|
||||||
|
@@index([source])
|
||||||
|
@@index([confidence])
|
||||||
|
@@map("weather_forecasts")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,518 @@
|
||||||
|
# Training System User Stories
|
||||||
|
|
||||||
|
## 📚 **Epic: Farmer Training & Development Platform**
|
||||||
|
|
||||||
|
### **Theme: Skill Development & Certification**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **👨🌾 As a Farmer:**
|
||||||
|
|
||||||
|
### **Training Participation**
|
||||||
|
|
||||||
|
#### **User Story 1: View Assigned Training Programs**
|
||||||
|
```gherkin
|
||||||
|
Feature: View and participate in assigned training programs
|
||||||
|
|
||||||
|
Scenario: View assigned training programs
|
||||||
|
Given I am logged into the farmer dashboard
|
||||||
|
When I navigate to the training section
|
||||||
|
Then I should see training programs assigned to me by admin:
|
||||||
|
- Training title and description
|
||||||
|
- Duration and schedule
|
||||||
|
- Level and prerequisites
|
||||||
|
- Assignment date and deadline
|
||||||
|
And I should see training status (ENROLLED, IN_PROGRESS, COMPLETED)
|
||||||
|
And I can view detailed training information
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 2: Receive Training Assignment Notification**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Receive notification when assigned to training
|
||||||
|
Given an admin has assigned me to a training program
|
||||||
|
When the assignment is created
|
||||||
|
Then I should receive a notification stating:
|
||||||
|
- Training program name
|
||||||
|
- Assignment reason
|
||||||
|
- Training schedule and duration
|
||||||
|
- Expected completion date
|
||||||
|
And the training should appear in my "My Trainings" dashboard
|
||||||
|
And my status should be set to "ENROLLED"
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Training Progress & Learning**
|
||||||
|
|
||||||
|
#### **User Story 3: Access Training Content**
|
||||||
|
```gherkin
|
||||||
|
Feature: Complete training and track progress
|
||||||
|
|
||||||
|
Scenario: Access training content
|
||||||
|
Given I am enrolled in "Integrated Pest Management" training
|
||||||
|
When I click "Start Learning"
|
||||||
|
Then I should see the training content modules:
|
||||||
|
- Video lessons
|
||||||
|
- Reading materials
|
||||||
|
- Interactive quizzes
|
||||||
|
- Practical exercises
|
||||||
|
And my progress should be tracked as I complete sections
|
||||||
|
And I can bookmark important content for later reference
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 4: Complete Training Modules**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Complete training modules progressively
|
||||||
|
Given I am in progress with a training program
|
||||||
|
When I complete each module
|
||||||
|
Then my progress percentage should update automatically
|
||||||
|
And I should see my completion status on the dashboard
|
||||||
|
And next modules should unlock sequentially
|
||||||
|
When I complete all modules with 80% average score
|
||||||
|
Then my status should change to "COMPLETED"
|
||||||
|
And I should be eligible for certification
|
||||||
|
And I should receive a completion certificate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 5: Track Learning Progress**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Monitor my learning journey
|
||||||
|
Given I have multiple trainings in progress
|
||||||
|
When I view my training dashboard
|
||||||
|
Then I should see:
|
||||||
|
- Overall progress percentage for each training
|
||||||
|
- Time spent learning this week
|
||||||
|
- Upcoming deadlines or recommendations
|
||||||
|
- My skill level improvements
|
||||||
|
- Badges or achievements earned
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Certification Management**
|
||||||
|
|
||||||
|
#### **User Story 6: Apply for Certification**
|
||||||
|
```gherkin
|
||||||
|
Feature: Earn and manage certifications
|
||||||
|
|
||||||
|
Scenario: Apply for certification after training
|
||||||
|
Given I have completed "Organic Farming Basics" training
|
||||||
|
And my final score is above 85%
|
||||||
|
When I click "Apply for Certification"
|
||||||
|
Then my certification status should be "PENDING"
|
||||||
|
And an admin should be notified for review
|
||||||
|
And I should see estimated review time (3-5 business days)
|
||||||
|
And I can upload additional supporting documents if required
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 7: View My Certifications**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Manage my certification portfolio
|
||||||
|
Given I have earned certifications
|
||||||
|
When I visit my profile certification section
|
||||||
|
Then I should see all my certifications with:
|
||||||
|
- Certificate name and issuing body
|
||||||
|
- Issue date and expiry date
|
||||||
|
- Digital certificate download link (PDF)
|
||||||
|
- Verification QR code
|
||||||
|
- Renewal requirements and timeline
|
||||||
|
And I should get notifications 30 days before expiry
|
||||||
|
And I can share certifications with buyers or cooperatives
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **🏢 As a Buyer:**
|
||||||
|
|
||||||
|
### **Farmer Qualification Verification**
|
||||||
|
|
||||||
|
#### **User Story 8: Verify Farmer Qualifications**
|
||||||
|
```gherkin
|
||||||
|
Feature: Verify farmer qualifications during procurement
|
||||||
|
|
||||||
|
Scenario: View farmer certifications during procurement
|
||||||
|
Given I am evaluating a farmer for procurement
|
||||||
|
When I view their profile
|
||||||
|
Then I should see their completed trainings and certifications:
|
||||||
|
- Organic farming certifications
|
||||||
|
- Pest management training completion
|
||||||
|
- Quality standards training
|
||||||
|
- Safety and compliance certifications
|
||||||
|
And I can verify certificate authenticity via QR codes
|
||||||
|
And I can see their training scores and completion dates
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 9: Filter Farmers by Certifications**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Find qualified farmers for specific requirements
|
||||||
|
Given I need organic certified produce for export
|
||||||
|
When I search for farmers in the procurement section
|
||||||
|
Then I can filter by:
|
||||||
|
- Certification type (Organic, GAP, Halal, etc.)
|
||||||
|
- Certification validity status
|
||||||
|
- Training completion in specific areas
|
||||||
|
- Skill level and experience
|
||||||
|
And see only farmers meeting my quality requirements
|
||||||
|
And view their certification verification status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **👨💼 As an Administrator:**
|
||||||
|
|
||||||
|
### **Authentication & Access**
|
||||||
|
|
||||||
|
#### **User Story 10: Admin Login**
|
||||||
|
```gherkin
|
||||||
|
Feature: Admin authentication and access control
|
||||||
|
|
||||||
|
Scenario: Admin login to training management system
|
||||||
|
Given I am an authorized administrator
|
||||||
|
When I navigate to the admin login page
|
||||||
|
And I enter my valid credentials
|
||||||
|
Then I should be logged into the admin dashboard
|
||||||
|
And I should see training management options
|
||||||
|
And I should have access to all training-related features
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Training Content Management**
|
||||||
|
|
||||||
|
#### **User Story 11: Create Training Programs**
|
||||||
|
```gherkin
|
||||||
|
Feature: Create and manage training programs
|
||||||
|
|
||||||
|
Scenario: Create comprehensive training program
|
||||||
|
Given I am logged into the admin training management dashboard
|
||||||
|
When I create a new training program
|
||||||
|
Then I should specify:
|
||||||
|
- Title: "Sustainable Pepper Cultivation"
|
||||||
|
- Description and learning objectives
|
||||||
|
- Category: Crop-specific training
|
||||||
|
- Skill level: Beginner/Intermediate/Advanced
|
||||||
|
- Duration: 180 minutes
|
||||||
|
- Prerequisites: Basic farming knowledge
|
||||||
|
- Training modules and content structure
|
||||||
|
- Assessment criteria and passing score
|
||||||
|
- Certification eligibility requirements
|
||||||
|
And I can upload multimedia content (videos, PDFs, images)
|
||||||
|
And set the training as active/inactive
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 12: Edit Training Programs**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Edit existing training program
|
||||||
|
Given I am viewing a training program "Organic Farming Basics"
|
||||||
|
When I click "Edit Training"
|
||||||
|
Then I should be able to modify:
|
||||||
|
- Title and description
|
||||||
|
- Category and skill level
|
||||||
|
- Duration and prerequisites
|
||||||
|
- Training content and modules
|
||||||
|
- Assessment criteria
|
||||||
|
- Active/inactive status
|
||||||
|
And save the changes
|
||||||
|
And notify assigned farmers of updates
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 13: Delete Training Programs**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Delete training program
|
||||||
|
Given I am viewing a training program that needs to be removed
|
||||||
|
When I click "Delete Training"
|
||||||
|
Then I should see a confirmation dialog
|
||||||
|
And I should be warned if farmers are currently enrolled
|
||||||
|
When I confirm deletion
|
||||||
|
Then the training should be removed from the system
|
||||||
|
And enrolled farmers should be notified of cancellation
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 14: View All Training Programs**
|
||||||
|
```gherkin
|
||||||
|
Scenario: View comprehensive training program list
|
||||||
|
Given I am in the admin training management dashboard
|
||||||
|
When I navigate to the training programs section
|
||||||
|
Then I should see all training programs with:
|
||||||
|
- Title and category
|
||||||
|
- Status (active/inactive)
|
||||||
|
- Number of enrolled farmers
|
||||||
|
- Creation and last modified dates
|
||||||
|
- Completion statistics
|
||||||
|
And I can filter by category, status, or date
|
||||||
|
And I can sort by various criteria
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 15: View Individual Training Program**
|
||||||
|
```gherkin
|
||||||
|
Scenario: View detailed training program information
|
||||||
|
Given I am viewing the training programs list
|
||||||
|
When I click on a specific training program
|
||||||
|
Then I should see detailed information:
|
||||||
|
- Complete training description and objectives
|
||||||
|
- All modules and content structure
|
||||||
|
- Assessment criteria and requirements
|
||||||
|
- List of enrolled farmers with their progress
|
||||||
|
- Completion statistics and analytics
|
||||||
|
- Farmer feedback and ratings
|
||||||
|
And I can edit or delete the training from this view
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Farmer Assignment Management**
|
||||||
|
|
||||||
|
#### **User Story 16: Select Farmers for Training**
|
||||||
|
```gherkin
|
||||||
|
Feature: Assign farmers to training programs
|
||||||
|
|
||||||
|
Scenario: Assign farmers to training program
|
||||||
|
Given I am viewing a training program "Integrated Pest Management"
|
||||||
|
When I click "Assign Farmers"
|
||||||
|
Then I should see a list of available farmers with:
|
||||||
|
- Farmer name and location
|
||||||
|
- Crop types and farm details
|
||||||
|
- Previous training history
|
||||||
|
- Skill level and certifications
|
||||||
|
And I can filter farmers by:
|
||||||
|
- Location/region
|
||||||
|
- Crop type
|
||||||
|
- Skill level
|
||||||
|
- Previous training completion
|
||||||
|
And I can select multiple farmers
|
||||||
|
And I can add assignment notes/reasons
|
||||||
|
When I confirm assignment
|
||||||
|
Then selected farmers should be enrolled in the training
|
||||||
|
And farmers should receive assignment notifications
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 17: Monitor Training Effectiveness**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Analyze training program performance
|
||||||
|
Given training programs have been running for 3 months
|
||||||
|
When I view training analytics dashboard
|
||||||
|
Then I should see comprehensive metrics:
|
||||||
|
- Assignment numbers per program and category
|
||||||
|
- Completion rates by farmer demographics
|
||||||
|
- Average scores and assessment results
|
||||||
|
- Time spent per module
|
||||||
|
- Farmer feedback and ratings
|
||||||
|
- Drop-off points in training content
|
||||||
|
- Geographic distribution of participants
|
||||||
|
- ROI impact on farm productivity
|
||||||
|
And I can export reports for stakeholders
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Certification Review & Approval**
|
||||||
|
|
||||||
|
#### **User Story 18: Process Certification Applications**
|
||||||
|
```gherkin
|
||||||
|
Feature: Review and approve certifications efficiently
|
||||||
|
|
||||||
|
Scenario: Review certification applications systematically
|
||||||
|
Given farmers have applied for certifications
|
||||||
|
When I access the certification review queue
|
||||||
|
Then I should see pending applications with:
|
||||||
|
- Farmer profile and farm details
|
||||||
|
- Training completion records and scores
|
||||||
|
- Assessment results and practical evaluations
|
||||||
|
- Supporting documents and evidence
|
||||||
|
- Previous certification history
|
||||||
|
And I can sort by application date, urgency, or type
|
||||||
|
And I can assign applications to specialist reviewers
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **User Story 19: Approve and Issue Certifications**
|
||||||
|
```gherkin
|
||||||
|
Scenario: Complete certification approval process
|
||||||
|
Given I am reviewing a certification application for "Organic Farming"
|
||||||
|
And the farmer has met all requirements:
|
||||||
|
- Training completion with 85% score
|
||||||
|
- Practical assessment passed
|
||||||
|
- Supporting documentation verified
|
||||||
|
When I approve the application
|
||||||
|
Then the farmer's status should change to "APPROVED"
|
||||||
|
And a digital certificate should be auto-generated with:
|
||||||
|
- Unique certificate number
|
||||||
|
- QR code for verification
|
||||||
|
- Expiry date (24 months for organic certification)
|
||||||
|
And the farmer should receive approval notification
|
||||||
|
And the certificate should be available for download
|
||||||
|
And the farmer's profile should reflect the new certification
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **📊 Advanced User Stories:**
|
||||||
|
|
||||||
|
### **Personalized Learning Paths**
|
||||||
|
|
||||||
|
#### **User Story 20: AI-Driven Training Recommendations**
|
||||||
|
```gherkin
|
||||||
|
Feature: Intelligent training recommendations
|
||||||
|
|
||||||
|
As a Farmer
|
||||||
|
I want to receive personalized training recommendations
|
||||||
|
So that I can improve my specific farming challenges
|
||||||
|
|
||||||
|
Scenario: Receive targeted recommendations based on farm data
|
||||||
|
Given my farm profile shows:
|
||||||
|
- Crop: Pepper cultivation
|
||||||
|
- Recent issue: Pest damage reported
|
||||||
|
- Skill level: Intermediate
|
||||||
|
- Location: West Java
|
||||||
|
When I view my dashboard
|
||||||
|
Then I should see recommended trainings:
|
||||||
|
- "Integrated Pest Management for Pepper" (High Priority)
|
||||||
|
- "Organic Pest Control Methods" (Medium Priority)
|
||||||
|
- "Beneficial Insects in Agriculture" (Low Priority)
|
||||||
|
And recommendations should explain why they're relevant
|
||||||
|
And I can see success stories from similar farmers
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Group Training & Community Learning**
|
||||||
|
|
||||||
|
#### **User Story 21: Collaborative Learning Sessions**
|
||||||
|
```gherkin
|
||||||
|
Feature: Group training and peer learning
|
||||||
|
|
||||||
|
As a Farmer
|
||||||
|
I want to join group training sessions with other farmers
|
||||||
|
So that I can learn collaboratively and share experiences
|
||||||
|
|
||||||
|
Scenario: Participate in regional group training
|
||||||
|
Given there's a group training "Sustainable Rice Farming" in my district
|
||||||
|
And 15 other farmers from nearby villages are enrolled
|
||||||
|
When I join the group session
|
||||||
|
Then I should be able to:
|
||||||
|
- Participate in live discussions
|
||||||
|
- Share my farming experiences
|
||||||
|
- Ask questions to trainers and peers
|
||||||
|
- Access group chat and resources
|
||||||
|
- Schedule follow-up practice sessions
|
||||||
|
And I can connect with other farmers for ongoing support
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Mobile Learning & Offline Access**
|
||||||
|
|
||||||
|
#### **User Story 22: Mobile-Optimized Learning**
|
||||||
|
```gherkin
|
||||||
|
Feature: Mobile learning with offline capabilities
|
||||||
|
|
||||||
|
As a Farmer
|
||||||
|
I want to access training on my smartphone during field work
|
||||||
|
So that I can learn flexibly without internet dependency
|
||||||
|
|
||||||
|
Scenario: Offline training access
|
||||||
|
Given I have limited internet connectivity in my farm area
|
||||||
|
When I download training content while connected
|
||||||
|
Then I should be able to:
|
||||||
|
- Access all downloaded materials offline
|
||||||
|
- Complete quizzes and assessments
|
||||||
|
- Take notes and bookmark content
|
||||||
|
- Record my progress locally
|
||||||
|
And when I reconnect to internet:
|
||||||
|
- All progress should sync automatically
|
||||||
|
- New content should be available for download
|
||||||
|
- Notifications should be received
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Training Impact & ROI Tracking**
|
||||||
|
|
||||||
|
#### **User Story 23: Measure Training Effectiveness**
|
||||||
|
```gherkin
|
||||||
|
Feature: Training impact analytics
|
||||||
|
|
||||||
|
As an Administrator
|
||||||
|
I want to track training impact on farm performance
|
||||||
|
So that I can improve training programs and demonstrate ROI
|
||||||
|
|
||||||
|
Scenario: Analyze training return on investment
|
||||||
|
Given farmers have completed productivity training over 6 months
|
||||||
|
When I generate impact analytics reports
|
||||||
|
Then I should see correlations between:
|
||||||
|
- Training completion and yield improvements (% increase)
|
||||||
|
- Certification status and product quality grades
|
||||||
|
- Skill level progression and income increases
|
||||||
|
- Training investment vs. productivity gains
|
||||||
|
- Farmer satisfaction vs. knowledge retention
|
||||||
|
- Regional performance vs. training participation rates
|
||||||
|
And I can identify most effective training content
|
||||||
|
And create evidence-based improvements
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **🎯 Success Metrics & KPIs:**
|
||||||
|
|
||||||
|
### **Engagement Metrics**
|
||||||
|
- **Enrollment Rate**: 75% of active farmers enroll in at least one training annually
|
||||||
|
- **Completion Rate**: 80% of enrolled farmers complete their training programs
|
||||||
|
- **Retention Rate**: 90% of farmers continue learning after first training
|
||||||
|
- **Mobile Usage**: 60% of training consumption happens on mobile devices
|
||||||
|
|
||||||
|
### **Learning Effectiveness**
|
||||||
|
- **Knowledge Retention**: 85% average score on post-training assessments
|
||||||
|
- **Practical Application**: 70% of farmers implement learned techniques
|
||||||
|
- **Certification Rate**: 60% of completed trainings lead to certifications
|
||||||
|
- **Skill Progression**: 50% improvement in skill assessments
|
||||||
|
|
||||||
|
### **Business Impact**
|
||||||
|
- **Productivity Improvement**: 25% average yield increase post-training
|
||||||
|
- **Quality Enhancement**: 30% improvement in product quality grades
|
||||||
|
- **Income Growth**: 20% increase in farmer income within 12 months
|
||||||
|
- **Certification Value**: 15% premium for certified produce
|
||||||
|
|
||||||
|
### **User Satisfaction**
|
||||||
|
- **Training Quality Rating**: 4.5/5 average rating
|
||||||
|
- **Content Relevance**: 85% find training directly applicable
|
||||||
|
- **Platform Usability**: 90% satisfaction with mobile app experience
|
||||||
|
- **Support Quality**: 95% satisfaction with help and guidance
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **📱 Technical Implementation Considerations:**
|
||||||
|
|
||||||
|
### **Platform Requirements**
|
||||||
|
- **Mobile-First Design**: Responsive design optimized for smartphones
|
||||||
|
- **Offline Capability**: Progressive Web App (PWA) with offline content
|
||||||
|
- **Multi-language Support**: Bahasa Indonesia, Javanese, and English
|
||||||
|
- **Low Bandwidth**: Optimized for 2G/3G networks in rural areas
|
||||||
|
|
||||||
|
### **Content Management**
|
||||||
|
- **Rich Media Support**: Videos, interactive presentations, PDF documents
|
||||||
|
- **Progressive Content**: Modular structure with prerequisite management
|
||||||
|
- **Assessment Engine**: Quizzes, practical evaluations, peer assessments
|
||||||
|
- **Analytics Integration**: Detailed learning analytics and progress tracking
|
||||||
|
|
||||||
|
### **Integration Features**
|
||||||
|
- **Farm Data Integration**: Connect training to actual farm performance
|
||||||
|
- **Certification Verification**: QR codes and blockchain verification
|
||||||
|
- **Payment Integration**: Premium training content and certification fees
|
||||||
|
- **Communication Tools**: Chat, forums, and mentorship connections
|
||||||
|
|
||||||
|
### **Security & Compliance**
|
||||||
|
- **Data Privacy**: GDPR compliance for farmer personal data
|
||||||
|
- **Certificate Security**: Tamper-proof digital certificates
|
||||||
|
- **Content Protection**: DRM for premium training content
|
||||||
|
- **Access Control**: Role-based permissions for different user types
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **🚀 Implementation Roadmap:**
|
||||||
|
|
||||||
|
### **Phase 1: Core Training Platform (Months 1-2)**
|
||||||
|
- Basic training content management
|
||||||
|
- Farmer enrollment and progress tracking
|
||||||
|
- Mobile-responsive interface
|
||||||
|
- Basic certification workflow
|
||||||
|
|
||||||
|
### **Phase 2: Enhanced Learning Experience (Months 3-4)**
|
||||||
|
- Offline content access
|
||||||
|
- Interactive assessments and quizzes
|
||||||
|
- Group training capabilities
|
||||||
|
- Advanced progress analytics
|
||||||
|
|
||||||
|
### **Phase 3: Intelligent Features (Months 5-6)**
|
||||||
|
- AI-driven personalized recommendations
|
||||||
|
- Training impact tracking and ROI analysis
|
||||||
|
- Integration with farm management data
|
||||||
|
- Advanced certification verification
|
||||||
|
|
||||||
|
### **Phase 4: Community & Ecosystem (Months 7-8)**
|
||||||
|
- Peer learning and mentorship
|
||||||
|
- Marketplace integration for certified farmers
|
||||||
|
- Third-party training provider integration
|
||||||
|
- Advanced analytics and reporting
|
||||||
Loading…
Reference in New Issue