Added PlantTouchPoint and IPMSchedule models. Implemented touch-points and IPM controllers/routes. Updated frontend with Dashboard feed and IPM widgets.
392 lines
9.1 KiB
Text
392 lines
9.1 KiB
Text
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
enum RoleEnum {
|
|
OWNER
|
|
MANAGER
|
|
GROWER
|
|
STAFF
|
|
}
|
|
|
|
enum RoomType {
|
|
VEG
|
|
FLOWER
|
|
DRY
|
|
CURE
|
|
MOTHER
|
|
CLONE
|
|
FACILITY
|
|
}
|
|
|
|
enum TaskStatus {
|
|
PENDING
|
|
IN_PROGRESS
|
|
COMPLETED
|
|
BLOCKED
|
|
}
|
|
|
|
// Daily Walkthrough Enums
|
|
enum WalkthroughStatus {
|
|
IN_PROGRESS
|
|
COMPLETED
|
|
INCOMPLETE
|
|
}
|
|
|
|
enum TankType {
|
|
VEG
|
|
FLOWER
|
|
}
|
|
|
|
enum TankStatus {
|
|
OK
|
|
LOW
|
|
CRITICAL
|
|
}
|
|
|
|
enum HealthStatus {
|
|
GOOD
|
|
FAIR
|
|
NEEDS_ATTENTION
|
|
}
|
|
|
|
enum AccessStatus {
|
|
OK
|
|
ISSUES
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
email String @unique
|
|
passwordHash String
|
|
name String?
|
|
role RoleEnum @default(STAFF) // Kept for legacy/fallback, but relying on roleId usually
|
|
|
|
roleId String?
|
|
userRole Role? @relation(fields: [roleId], references: [id])
|
|
|
|
rate Decimal? @map("hourly_rate")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tasks Task[]
|
|
timeLogs TimeLog[]
|
|
walkthroughs DailyWalkthrough[]
|
|
touchPoints PlantTouchPoint[]
|
|
|
|
@@map("users")
|
|
}
|
|
|
|
model Role {
|
|
id String @id @default(uuid())
|
|
name String @unique
|
|
description String?
|
|
permissions Json // Store permissions as JSON: { users: { read: true, write: true }, ... }
|
|
isSystem Boolean @default(false) // System roles cannot be deleted
|
|
|
|
users User[]
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("roles")
|
|
}
|
|
|
|
model Room {
|
|
id String @id @default(uuid())
|
|
name String
|
|
type RoomType
|
|
sqft Float?
|
|
width Float?
|
|
length Float?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
batches Batch[]
|
|
tasks Task[]
|
|
|
|
@@map("rooms")
|
|
}
|
|
|
|
model Batch {
|
|
id String @id @default(uuid())
|
|
name String // e.g., "B-2023-10-15-GG4"
|
|
strain String
|
|
startDate DateTime
|
|
harvestDate DateTime?
|
|
status String @default("ACTIVE") // ACTIVE, HARVESTED, COMPLETED
|
|
|
|
roomId String?
|
|
room Room? @relation(fields: [roomId], references: [id])
|
|
|
|
tasks Task[]
|
|
touchPoints PlantTouchPoint[]
|
|
ipmSchedule IPMSchedule?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("batches")
|
|
}
|
|
|
|
model TaskTemplate {
|
|
id String @id @default(uuid())
|
|
title String
|
|
description String? // Instructions/SOP
|
|
roomType RoomType?
|
|
estimatedMinutes Int?
|
|
materials String[] // Array of material names
|
|
recurrence Json? // Cron or custom pattern
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tasks Task[]
|
|
|
|
@@map("task_templates")
|
|
}
|
|
|
|
model Task {
|
|
id String @id @default(uuid())
|
|
title String
|
|
description String?
|
|
status TaskStatus @default(PENDING)
|
|
priority String @default("MEDIUM")
|
|
|
|
templateId String?
|
|
template TaskTemplate? @relation(fields: [templateId], references: [id])
|
|
|
|
assignedToId String?
|
|
assignedTo User? @relation(fields: [assignedToId], references: [id])
|
|
|
|
batchId String?
|
|
batch Batch? @relation(fields: [batchId], references: [id])
|
|
|
|
roomId String?
|
|
room Room? @relation(fields: [roomId], references: [id])
|
|
|
|
dueDate DateTime?
|
|
completedAt DateTime?
|
|
|
|
notes String?
|
|
photos String[]
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("tasks")
|
|
}
|
|
|
|
model TimeLog {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id])
|
|
|
|
startTime DateTime
|
|
endTime DateTime?
|
|
activityType String? // e.g. "Trimming", "Feeding", "Cleaning"
|
|
notes String?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("time_logs")
|
|
}
|
|
|
|
// Daily Walkthrough Models
|
|
model DailyWalkthrough {
|
|
id String @id @default(uuid())
|
|
date DateTime @default(now())
|
|
completedBy String
|
|
user User @relation(fields: [completedBy], references: [id])
|
|
startTime DateTime @default(now())
|
|
endTime DateTime?
|
|
status WalkthroughStatus @default(IN_PROGRESS)
|
|
|
|
reservoirChecks ReservoirCheck[]
|
|
irrigationChecks IrrigationCheck[]
|
|
plantHealthChecks PlantHealthCheck[]
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("daily_walkthroughs")
|
|
}
|
|
|
|
model WalkthroughSettings {
|
|
id String @id @default("default")
|
|
|
|
// Photo Requirements
|
|
reservoirPhotos PhotoRequirement @default(OPTIONAL)
|
|
irrigationPhotos PhotoRequirement @default(OPTIONAL)
|
|
plantHealthPhotos PhotoRequirement @default(REQUIRED)
|
|
|
|
// Enabled Sections
|
|
enableReservoirs Boolean @default(true)
|
|
enableIrrigation Boolean @default(true)
|
|
enablePlantHealth Boolean @default(true)
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("walkthrough_settings")
|
|
}
|
|
|
|
enum PhotoRequirement {
|
|
REQUIRED
|
|
OPTIONAL
|
|
WEEKLY
|
|
ON_DEMAND
|
|
}
|
|
|
|
model ReservoirCheck {
|
|
id String @id @default(uuid())
|
|
walkthroughId String
|
|
walkthrough DailyWalkthrough @relation(fields: [walkthroughId], references: [id], onDelete: Cascade)
|
|
|
|
tankName String
|
|
tankType TankType
|
|
levelPercent Int
|
|
status TankStatus
|
|
photoUrl String?
|
|
notes String?
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("reservoir_checks")
|
|
}
|
|
|
|
model IrrigationCheck {
|
|
id String @id @default(uuid())
|
|
walkthroughId String
|
|
walkthrough DailyWalkthrough @relation(fields: [walkthroughId], references: [id], onDelete: Cascade)
|
|
|
|
zoneName String // "Veg Upstairs", "Veg Downstairs", "Flower Upstairs", "Flower Downstairs"
|
|
drippersTotal Int
|
|
drippersWorking Int
|
|
drippersFailed String? // JSON array of failed dripper IDs
|
|
waterFlow Boolean
|
|
nutrientsMixed Boolean
|
|
scheduleActive Boolean
|
|
photoUrl String? // Photo of working system
|
|
issues String?
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("irrigation_checks")
|
|
}
|
|
|
|
model PlantHealthCheck {
|
|
id String @id @default(uuid())
|
|
walkthroughId String
|
|
walkthrough DailyWalkthrough @relation(fields: [walkthroughId], references: [id], onDelete: Cascade)
|
|
|
|
zoneName String
|
|
healthStatus HealthStatus
|
|
pestsObserved Boolean
|
|
pestType String?
|
|
waterAccess AccessStatus
|
|
foodAccess AccessStatus
|
|
flaggedForAttention Boolean @default(false)
|
|
issuePhotoUrl String?
|
|
referencePhotoUrl String? // Photo of healthy system
|
|
notes String?
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("plant_health_checks")
|
|
}
|
|
// Supply/Shopping List models
|
|
model SupplyItem {
|
|
id String @id @default(uuid())
|
|
name String
|
|
category SupplyCategory
|
|
quantity Int @default(0)
|
|
minThreshold Int @default(0)
|
|
unit String // "each", "box", "roll", "gallon", etc.
|
|
location String? // "Storage Room", "Bathroom", etc.
|
|
vendor String? // "Amazon", "Local", etc.
|
|
productUrl String? // Link to reorder
|
|
lastOrdered DateTime?
|
|
notes String?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("supply_items")
|
|
}
|
|
|
|
enum SupplyCategory {
|
|
FILTER // Air filters, water filters
|
|
CLEANING // Cleaning supplies
|
|
PPE // Gloves, masks, suits
|
|
OFFICE // Paper, pens, etc.
|
|
BATHROOM // Toilet paper, soap, etc.
|
|
KITCHEN // Coffee, snacks, etc.
|
|
MAINTENANCE // Tools, parts, etc.
|
|
OTHER
|
|
}
|
|
|
|
// Plant Touch Points
|
|
model PlantTouchPoint {
|
|
id String @id @default(uuid())
|
|
type TouchType
|
|
notes String?
|
|
photoUrls String[] // Changed from single photoUrl to array
|
|
|
|
// Measurements
|
|
heightCm Float?
|
|
widthCm Float?
|
|
|
|
// IPM specific
|
|
ipmProduct String? // e.g., "Pyganic 5.0"
|
|
ipmDosage String? // e.g., "1 oz per gallon"
|
|
|
|
// Issues
|
|
issuesObserved Boolean @default(false)
|
|
issueType String?
|
|
|
|
batchId String
|
|
batch Batch @relation(fields: [batchId], references: [id])
|
|
|
|
createdBy String
|
|
user User @relation(fields: [createdBy], references: [id])
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("plant_touch_points")
|
|
}
|
|
|
|
enum TouchType {
|
|
WATER
|
|
FEED
|
|
PRUNE
|
|
TRAIN
|
|
INSPECT
|
|
IPM
|
|
TRANSPLANT
|
|
HARVEST
|
|
OTHER
|
|
}
|
|
|
|
model IPMSchedule {
|
|
id String @id @default(uuid())
|
|
batchId String @unique // One schedule per batch
|
|
batch Batch @relation(fields: [batchId], references: [id])
|
|
|
|
product String // "Pyganic 5.0"
|
|
intervalDays Int // 10
|
|
lastTreatment DateTime?
|
|
nextTreatment DateTime? // Calculated
|
|
|
|
isActive Boolean @default(true)
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("ipm_schedules")
|
|
}
|