Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/luisumit/LaPreviaRestobar/llms.txt

Use this file to discover all available pages before exploring further.

Every order in La Previa Restobar begins the moment a waiter selects a table and adds items to a cart. From that point, the order travels through up to eight distinct statuses, each owned by a different role — waiter, chef, or system — and every change is persisted to Firebase Realtime Database and simultaneously stored in the local Room database for offline resilience.

The Order Data Class

The Order data class is the central record that moves through the entire system. It is serialized to a flat Firebase map for remote storage and mapped to OrderEntity for local Room persistence.
data class Order(
    val id: String = UUID.randomUUID().toString(),
    val tableId: Int = 0,
    val tableNumber: Int = 0,
    val items: List<OrderItem> = emptyList(),
    val status: OrderStatus = OrderStatus.PENDING,
    val createdAt: Long = System.currentTimeMillis(),
    val updatedAt: Long = System.currentTimeMillis(),
    val total: Double = 0.0,
    val waiterId: String? = null,
    val waiterName: String? = null,
    val notes: String? = null,
    val version: Long = 0,
    val syncStatus: String = "PENDING"
)

Identity

id — UUID generated at creation. Used as the Firebase node key and Room primary key.

Table Link

tableId + tableNumber — both stored for quick display without a join. tableId also drives the assignOrderToTable call.

Financial

total is computed via calculateTotal(), which sums all OrderItem.subtotal values.

Sync

syncStatus starts as "PENDING" and is flipped to "SYNCED" by SyncManager once the record reaches Firebase.

OrderItem Structure

Each line on an order is an OrderItem. The fields are flat (no nested objects) so Firebase can serialize them without custom adapters.
data class OrderItem(
    val productId: String = "",
    val productName: String = "",
    val productDescription: String = "",
    val productPrice: Double = 0.0,
    val productCategory: String = "",
    val trackInventory: Boolean = false,
    val quantity: Int = 0,
    val unitPrice: Double = 0.0,
    val subtotal: Double = 0.0
)
The convenience constructor OrderItem(product: Product, quantity: Int) copies all denormalized fields from the Product at the moment the order is placed, including the trackInventory flag. When an order is later confirmed, this flag signals the inventory system to deduct stock automatically.

OrderStatus Enum

The eight statuses map directly to the operational stages of the restaurant floor.
enum class OrderStatus {
    PENDING,
    ENVIADO,
    ACEPTADO,
    EN_PREPARACION,
    LISTO,
    ENTREGADO,      // Food delivered, table still occupied
    COMPLETED,
    CANCELLED;

    companion object {
        fun fromString(status: String): OrderStatus {
            return when (status.uppercase()) {
                "PENDING", "PENDIENTE"                    -> PENDING
                "ENVIADO", "ENVIADA"                      -> ENVIADO
                "ACEPTADO", "ACEPTADA", "CONFIRMADO"      -> ACEPTADO
                "EN_PREPARACION", "PREPARACION", "PREPARANDO" -> EN_PREPARACION
                "LISTO", "LISTA", "READY"                 -> LISTO
                "ENTREGADO", "ENTREGADA", "DELIVERED"     -> ENTREGADO
                "COMPLETED", "COMPLETADA", "TERMINADO"    -> COMPLETED
                "CANCELLED", "CANCELADA", "CANCELADO"     -> CANCELLED
                else                                      -> PENDING
            }
        }
    }
}
fromString() handles legacy Spanish variants and English aliases, making the system resilient to old records stored with different string values. If an unknown string is encountered, it defaults to PENDING rather than throwing.

Order Lifecycle

The lifecycle below shows every status transition, who performs it, and what side-effects are triggered.
1

PENDING — Order created by waiter

The waiter selects a table, picks items from the product catalog, and taps Enviar Pedido. CreateOrderUseCase calls orderRepository.createOrder(order) and then tableRepository.assignOrderToTable(order.tableId, order.id), atomically creating the order and linking it to the table.
2

ENVIADO — Order sent to kitchen screen

The waiter confirms the order. The status is updated to ENVIADO via UpdateOrderStatusUseCase. The kitchen’s chef panel observes the Firebase node in real time and the new order appears immediately on the ChefNotificationPanel.
3

ACEPTADO — Chef acknowledges the order

The chef taps Aceptar on the kitchen screen. UpdateOrderStatusUseCase writes ACEPTADO to Firebase. The waiter’s screen reflects the change, confirming the kitchen has the ticket.
4

EN_PREPARACION — Kitchen is cooking

The chef moves the order to active preparation. Status becomes EN_PREPARACION. At this point inventory deduction is triggered for all OrderItem entries where trackInventory = true.
5

LISTO — Order is ready for pickup

The chef marks the order ready. Status becomes LISTO. The waiter receives a notification and the order card highlights on their panel.
6

ENTREGADO — Food delivered to table

The waiter picks up the food and delivers it to the table. Status becomes ENTREGADO. The table remains OCUPADA because the guests are still seated and may order more or request the bill.
7

COMPLETED — Bill paid, table freed

The waiter closes the order after payment. Status becomes COMPLETED. The table status reverts to LIBRE and currentOrderId is cleared.
8

CANCELLED — Order voided

Either role can cancel before preparation begins. Status becomes CANCELLED. No inventory deduction occurs; any deduction already made is reversed.
ENTREGADO was added specifically to model the gap between food leaving the kitchen and the bill being paid. Without this status, the waiter had no way to distinguish “food on the table” from “table free.”

Use Cases

CreateOrderUseCase

class CreateOrderUseCase @Inject constructor(
    private val orderRepository: OrderRepository,
    private val tableRepository: TableRepository
) {
    suspend operator fun invoke(order: Order) {
        orderRepository.createOrder(order)
        tableRepository.assignOrderToTable(order.tableId, order.id)
    }
}
Two repository calls are made in sequence: the order is persisted first, then the table record is updated with currentOrderId. This ensures the table is never linked to an order that failed to save.

UpdateOrderStatusUseCase

class UpdateOrderStatusUseCase @Inject constructor(
    private val orderRepository: OrderRepository
) {
    suspend operator fun invoke(orderId: String, status: OrderStatus) {
        orderRepository.updateOrderStatus(orderId, status.name)
    }
}
The status enum is converted to its .name string before being sent to Firebase. FirebaseOrderRepositoryImpl.updateOrderStatus writes a partial update containing status and updatedAt, so only those two fields change in the database node rather than the entire document.

Local Persistence: OrderDao

The Room DAO mirrors the full Firebase schema. The syncStatus column drives the sync queue.
@Dao
interface OrderDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(order: OrderEntity)

    @Query("SELECT * FROM orders")
    fun getAllFlow(): Flow<List<OrderEntity>>

    @Query("SELECT * FROM orders WHERE syncStatus = 'PENDING'")
    suspend fun getPending(): List<OrderEntity>

    @Query("UPDATE orders SET syncStatus = :status WHERE id = :id")
    suspend fun updateStatus(id: String, status: String)

    @Query("UPDATE orders SET syncStatus = :status, version = :newVersion, lastModified = :lastModified WHERE id = :id AND version < :newVersion")
    suspend fun updateStatusIfNewer(id: String, status: String, newVersion: Long, lastModified: Long)

    @Query("SELECT * FROM orders WHERE id = :id")
    suspend fun getById(id: String): OrderEntity?

    @Query("DELETE FROM orders WHERE id = :orderId")
    suspend fun deleteOrder(orderId: String)
}
Use getAllFlow() in ViewModels that need to react to live updates, and getPending() inside SyncManager to batch-push local changes to Firebase when network is available.

Build docs developers (and LLMs) love