Understanding the core data models and their relationships in Greenhouse Admin
Greenhouse Admin manages a hierarchical data structure that mirrors the physical organization of greenhouse facilities. Understanding this model is essential for working with the application.
@Serializabledata class Sector( val id: Long, val code: String, // Auto-generated unique code val tenantId: Long, // Foreign key to Client val greenhouseId: Long, // Foreign key to Greenhouse val greenhouseCode: String? = null, // Denormalized for display val name: String? = null // Optional custom name) { val initial: String get() = name?.firstOrNull()?.uppercaseChar()?.toString() ?: "S" val displayName: String get() = name ?: "Sector"}
Sectors can have optional custom names. If no name is provided, they’re identified by their auto-generated code.
@Serializabledata class GreenhouseResponse( val id: Long, val code: String, val name: String, val tenantId: Long, val location: Location? = null, val areaM2: Double? = null, val timezone: String? = null, val isActive: Boolean = true, val createdAt: String, val updatedAt: String)
@Serializabledata class Greenhouse( val id: Long, val code: String, val name: String, val tenantId: Long, val location: Location? = null, val areaM2: Double? = null, val timezone: String? = "Europe/Madrid", val isActive: Boolean = true, val createdAt: String? = null, val updatedAt: String? = null) { // Additional computed properties for UI}
@Serializabledata class GreenhouseCreateRequest( val name: String, val location: Location? = null, val areaM2: Double? = null, val timezone: String? = "Europe/Madrid", val isActive: Boolean? = true)@Serializabledata class GreenhouseUpdateRequest( val name: String? = null, val location: Location? = null, val areaM2: Double? = null, val timezone: String? = null, val isActive: Boolean? = null)
Update requests use nullable fields to support partial updates - only changed fields are sent to the API.
data class DeviceCatalogType( val id: Short, val name: String, // "Temperature", "Humidity", etc. val description: String?, val categoryId: Short, // References category val defaultUnitId: Short?, // Default measurement unit val defaultUnitSymbol: String?, // e.g., "°C" val controlType: String? // For actuators: "ON_OFF", "ANALOG", etc.)
data class DeviceCatalogUnit( val id: Short, val symbol: String, // "°C", "%", "lux", "ppm" val name: String, // "Celsius", "Percent", "Lux", "Parts per million" val description: String?, val isActive: Boolean = true)
data class ActuatorState( val id: Short, val name: String, // "ON", "OFF", "STANDBY" val description: String?, val isOperational: Boolean, // Whether this state means the device is working val displayOrder: Short, val color: String? // Hex color for UI display)