Skip to main content
Greenhouse models represent individual greenhouse facilities within a client’s account. Each greenhouse can contain multiple sectors and devices.

Greenhouse

Domain model representing a greenhouse facility. Used internally in the app for business logic.
@Serializable
data 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
)

Fields

id
Long
required
Unique identifier for the greenhouse
code
String
required
Unique code assigned to the greenhouse
name
String
required
Greenhouse display name
tenantId
Long
required
ID of the tenant/client that owns this greenhouse
location
Location
default:"null"
Geographic coordinates of the greenhouse. See Location for details.
areaM2
Double
default:"null"
Total area of the greenhouse in square meters
timezone
String
default:"Europe/Madrid"
IANA timezone identifier for the greenhouse location
isActive
Boolean
default:"true"
Whether the greenhouse is currently active
createdAt
String
default:"null"
ISO 8601 timestamp when the greenhouse was created
updatedAt
String
default:"null"
ISO 8601 timestamp when the greenhouse was last updated

Computed Properties

The Greenhouse class provides computed properties for display purposes:
initial
String
Returns the first letter of the greenhouse name in uppercase, or ”?” if name is empty.
val initial: String
    get() = name.firstOrNull()?.uppercaseChar()?.toString() ?: "?"
Example: “North Greenhouse” → “N”
areaDisplay
String
Returns the formatted area string with units, or ”-” if not set.
val areaDisplay: String
    get() = areaM2?.let { "$it m²" } ?: "-"
Example: “500.0 m²” or ”-”
locationDisplay
String
Returns the location display string, or ”-” if not set.
val locationDisplay: String
    get() = location?.displayString?.takeIf { it.isNotBlank() } ?: "-"
Example: “36.8381, -2.4597” or ”-“

Extension Properties

status
GreenhouseStatus
Derives the greenhouse status from the isActive field.
val Greenhouse.status: GreenhouseStatus
    get() = if (isActive) GreenhouseStatus.ACTIVE else GreenhouseStatus.INACTIVE

GreenhouseStatus

Enum representing the operational status of a greenhouse.
@Serializable
enum class GreenhouseStatus {
    ACTIVE,
    INACTIVE
}

Values

  • ACTIVE: Greenhouse is active and operational
  • INACTIVE: Greenhouse is inactive or disabled

Computed Properties

displayName
String
Returns a human-readable display name for the status.
val displayName: String
    get() = name.lowercase().replaceFirstChar { it.uppercase() }
Example: ACTIVE → “Active”, INACTIVE → “Inactive”

API DTOs

GreenhouseResponse

Response DTO from the API representing a greenhouse. Matches the GreenhouseResponse structure from the API.
@Serializable
data 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
)
toGreenhouse
() -> Greenhouse
Converts GreenhouseResponse to Greenhouse domain model.
fun GreenhouseResponse.toGreenhouse() = Greenhouse(
    id = id,
    code = code,
    name = name,
    tenantId = tenantId,
    location = location,
    areaM2 = areaM2,
    timezone = timezone,
    isActive = isActive,
    createdAt = createdAt,
    updatedAt = updatedAt
)

GreenhouseCreateRequest

Request DTO for creating a new greenhouse.
@Serializable
data class GreenhouseCreateRequest(
    val name: String,
    val location: Location? = null,
    val areaM2: Double? = null,
    val timezone: String? = "Europe/Madrid",
    val isActive: Boolean? = true
)
name
String
required
Name of the greenhouse to create
location
Location
default:"null"
Geographic coordinates of the greenhouse
areaM2
Double
default:"null"
Total area in square meters
timezone
String
default:"Europe/Madrid"
IANA timezone identifier
isActive
Boolean
default:"true"
Whether the greenhouse should be active upon creation

GreenhouseUpdateRequest

Request DTO for updating an existing greenhouse. All fields are optional for partial updates.
@Serializable
data class GreenhouseUpdateRequest(
    val name: String? = null,
    val location: Location? = null,
    val areaM2: Double? = null,
    val timezone: String? = null,
    val isActive: Boolean? = null
)
name
String
default:"null"
Updated name for the greenhouse
location
Location
default:"null"
Updated geographic coordinates
areaM2
Double
default:"null"
Updated area in square meters
timezone
String
default:"null"
Updated timezone identifier
isActive
Boolean
default:"null"
Updated active status

Usage Examples

Creating a Greenhouse

val greenhouse = Greenhouse(
    id = 1L,
    code = "GH001",
    name = "North Greenhouse",
    tenantId = 1L,
    location = Location(lat = 36.8381, lon = -2.4597),
    areaM2 = 500.0,
    timezone = "Europe/Madrid",
    isActive = true,
    createdAt = "2024-01-15T10:30:00Z",
    updatedAt = "2024-01-15T10:30:00Z"
)

println(greenhouse.initial) // "N"
println(greenhouse.areaDisplay) // "500.0 m²"
println(greenhouse.status) // GreenhouseStatus.ACTIVE

Creating a Greenhouse via API

val createRequest = GreenhouseCreateRequest(
    name = "South Greenhouse",
    location = Location(lat = 36.8381, lon = -2.4597),
    areaM2 = 750.0,
    timezone = "Europe/Madrid",
    isActive = true
)

val response: GreenhouseResponse = apiClient.createGreenhouse(
    tenantId = 1L,
    request = createRequest
)

val greenhouse: Greenhouse = response.toGreenhouse()

Updating a Greenhouse

val updateRequest = GreenhouseUpdateRequest(
    name = "North Greenhouse (Renovated)",
    areaM2 = 600.0
)

val response: GreenhouseResponse = apiClient.updateGreenhouse(
    tenantId = 1L,
    greenhouseId = 1L,
    request = updateRequest
)

Checking Status

val greenhouse = getGreenhouse(1L)

when (greenhouse.status) {
    GreenhouseStatus.ACTIVE -> println("Greenhouse is operational")
    GreenhouseStatus.INACTIVE -> println("Greenhouse is offline")
}

println(greenhouse.status.displayName) // "Active" or "Inactive"

Build docs developers (and LLMs) love