Skip to main content

Overview

This page documents the two key enumerations in the FoodTech Kitchen domain model: Station and TaskStatus. These enums define the fixed set of kitchen stations and the lifecycle states a task can be in.
Enums are used instead of strings to provide compile-time type safety and prevent invalid values from entering the system.

Station Enum

The Station enum represents the physical kitchen stations where food and beverages are prepared. Each station is responsible for specific types of products.

Definition

package com.foodtech.kitchen.domain.model;

public enum Station {
    BAR,
    HOT_KITCHEN,
    COLD_KITCHEN
}

Station Types

BAR
Station
The bar station handles all beverage preparation including alcoholic drinks, cocktails, soft drinks, and coffee.
HOT_KITCHEN
Station
The hot kitchen station prepares all cooked and heated dishes such as grilled meats, pasta, soups, and hot appetizers.
COLD_KITCHEN
Station
The cold kitchen station handles cold dishes including salads, cold appetizers, ceviche, sushi, and desserts.

Station Responsibilities

StationProduct TypesTypical Products
BARDRINKMojito, Beer, Wine, Coffee, Lemonade, Cocktails
HOT_KITCHENHOT_DISHGrilled Steak, Pasta, Soup, Pizza, Stir-fry
COLD_KITCHENCOLD_DISHCaesar Salad, Ceviche, Sushi, Carpaccio, Cold Appetizers

Usage Examples

// Using Station in task creation
Task task = new Task(
    orderId,
    Station.BAR,        // Assign to bar
    "T-15",
    drinkProducts,
    LocalDateTime.now()
);

// Checking station assignment
if (task.getStation() == Station.HOT_KITCHEN) {
    // Handle hot kitchen specific logic
}

// Getting station from product type
Product drink = new Product("Mojito", ProductType.DRINK);
Station station = drink.getType().getStation(); // Returns Station.BAR

Station-ProductType Mapping

Each ProductType is automatically associated with its corresponding station:
ProductType.DRINK.getStation()      // Returns Station.BAR
ProductType.HOT_DISH.getStation()   // Returns Station.HOT_KITCHEN
ProductType.COLD_DISH.getStation()  // Returns Station.COLD_KITCHEN
The mapping between ProductType and Station is encapsulated within the ProductType enum, following the Open-Closed Principle.

TaskStatus Enum

The TaskStatus enum represents the lifecycle states of a kitchen task. Tasks transition through these states as they are processed by kitchen staff.

Definition

package com.foodtech.kitchen.domain.model;

public enum TaskStatus {
    PENDING,
    IN_PREPARATION,
    COMPLETED
}

Status Descriptions

PENDING
TaskStatus
Initial state when a task is created. The task is waiting to be started by kitchen staff.
IN_PREPARATION
TaskStatus
The task has been started and is currently being prepared by kitchen staff.
COMPLETED
TaskStatus
The task has been finished. All products in the task are ready.

State Machine

Tasks follow a strict linear state machine:

Valid State Transitions

FromToMethodValidation
PENDINGIN_PREPARATIONtask.start()Must be in PENDING status
IN_PREPARATIONCOMPLETEDtask.complete()Must be in IN_PREPARATION status
Invalid state transitions will throw IllegalStateException. You cannot skip states or transition backwards.

Usage Examples

Basic Task Lifecycle

// Create new task (status is PENDING)
Task task = new Task(orderId, Station.BAR, "T-15", products, LocalDateTime.now());
assert task.getStatus() == TaskStatus.PENDING;

// Start the task
task.start();
assert task.getStatus() == TaskStatus.IN_PREPARATION;
assert task.getStartedAt() != null;

// Complete the task
task.complete();
assert task.getStatus() == TaskStatus.COMPLETED;
assert task.getCompletedAt() != null;

Invalid State Transitions

Task task = new Task(orderId, station, "T-15", products, LocalDateTime.now());

// Try to complete without starting
try {
    task.complete(); // Will throw IllegalStateException
} catch (IllegalStateException e) {
    // "Task must be in IN_PREPARATION status to complete"
}

// Try to start twice
task.start();
try {
    task.start(); // Will throw IllegalStateException
} catch (IllegalStateException e) {
    // "Task must be in PENDING status to start"
}

Checking Task Status

// Query current status
switch (task.getStatus()) {
    case PENDING:
        System.out.println("Task is waiting to be started");
        break;
    case IN_PREPARATION:
        System.out.println("Task is being prepared");
        break;
    case COMPLETED:
        System.out.println("Task is finished");
        break;
}

// Filter tasks by status
List<Task> pendingTasks = allTasks.stream()
    .filter(t -> t.getStatus() == TaskStatus.PENDING)
    .collect(Collectors.toList());

Status with Timestamps

Task task = new Task(orderId, station, "T-15", products, LocalDateTime.now());

// PENDING: only createdAt is set
assert task.getCreatedAt() != null;
assert task.getStartedAt() == null;
assert task.getCompletedAt() == null;

task.start();

// IN_PREPARATION: createdAt and startedAt are set
assert task.getCreatedAt() != null;
assert task.getStartedAt() != null;
assert task.getCompletedAt() == null;

task.complete();

// COMPLETED: all timestamps are set
assert task.getCreatedAt() != null;
assert task.getStartedAt() != null;
assert task.getCompletedAt() != null;

// Calculate preparation time
Duration prepTime = Duration.between(
    task.getStartedAt(), 
    task.getCompletedAt()
);

Design Considerations

Why Enums?

Type Safety

Enums provide compile-time type safety. It’s impossible to assign invalid station or status values.

Exhaustiveness Checking

When using enums in switch statements, the compiler can warn you if you haven’t handled all cases.

Self-Documenting

Enum values clearly communicate the limited set of valid options without documentation.

Refactoring Safety

Renaming or removing enum values will cause compilation errors, making refactoring safer.

Extensibility

Adding new stations or status values requires code changes. This is intentional—station and status values are core to the business logic and should be carefully controlled.
To add a new station:
  1. Add the new enum value to Station
  2. Add a corresponding ProductType value
  3. Update the ProductType to map to the new station
  4. Update any UI or API documentation
// Example: Adding a dessert station
public enum Station {
    BAR,
    HOT_KITCHEN,
    COLD_KITCHEN,
    DESSERT_STATION  // New station
}

public enum ProductType {
    DRINK(Station.BAR),
    HOT_DISH(Station.HOT_KITCHEN),
    COLD_DISH(Station.COLD_KITCHEN),
    DESSERT(Station.DESSERT_STATION);  // New product type
    
    // ... rest of implementation
}

Integration Points

REST API

Both enums are typically serialized as strings in JSON:
{
  "station": "HOT_KITCHEN",
  "status": "IN_PREPARATION"
}

Database Persistence

Enums are usually persisted as strings or ordinal values:
@Entity
public class TaskEntity {
    @Enumerated(EnumType.STRING)
    private Station station;
    
    @Enumerated(EnumType.STRING)
    private TaskStatus status;
}
Use EnumType.STRING rather than EnumType.ORDINAL for database persistence. This makes the database more readable and prevents issues when reordering enum values.
  • Task - Uses both Station and TaskStatus
  • Product - ProductType maps to Station
  • ProductType - Contains station mappings

Build docs developers (and LLMs) love