Collections
Overview
All Firestore collections managed by @frappes/firebase.
This section maps each collection path to the operations provided by FirestoreCoreClient.
Collection map
| Path | Purpose | Main operations |
|---|---|---|
tenants/{tenantId} | Tenant profile/config | upsertTenant |
tenants/{tenantId}/locations/{locationId} | Store/location metadata | upsertLocation |
tenants/{tenantId}/staff/{uid} | Staff roles/status | upsertStaff |
tenants/{tenantId}/products/{productId} | Product catalog | upsertProduct, subscribeProducts |
tenants/{tenantId}/locations/{locationId}/orders/{orderId} | Order aggregate | createOrder, getOrder, listOrders, subscribeOrders, updateOrderStatus |
.../orders/{orderId}/events/{eventId} | Order event log | createOrder, updateOrderStatus, appendOrderEvent |
.../businessDays/{dateKey} | Open/close lifecycle per date | openBusinessDay, closeBusinessDay |
.../dailySummaries/{dateKey} | Daily reporting snapshot | setDailySummary |
Notes
- Operations use tenant-first paths to keep data isolated by tenant.
- Order/business-day/summary operations are location-scoped.
- Retry-safe flows should pass
idempotencyKeyon create/update event methods.
End-to-end example
// Tenant + catalog
await client.upsertTenant({ name: "Frappe Athens", country: "GR", timezone: "Europe/Athens" })
await client.upsertLocation("loc_syntagma", { name: "Syntagma", currency: "EUR" })
await client.upsertStaff("uid_1", { roles: ["manager"], status: "active", locationIds: ["loc_syntagma"] })
await client.upsertProduct("espresso", { name: "Espresso", price: 2.5, taxRate: 0.24, categoryId: "coffee" })
// Orders + events
const { orderId } = await client.createOrder({
source: "in_store",
channel: "pos",
totals: { subtotal: 2.5, tax: 0.6, discounts: 0, total: 3.1 },
items: [{ productId: "espresso", nameSnapshot: "Espresso", qty: 1, unitPriceSnapshot: 2.5 }],
idempotencyKey: "ord-001-create",
})
await client.updateOrderStatus({ orderId, toStatus: "accepted", idempotencyKey: "ord-001-accepted" })
// Day lifecycle + reporting
await client.openBusinessDay("2026-02-24")
await client.setDailySummary("2026-02-24", {
ordersCount: 1,
revenue: 3.1,
topItems: [{ productId: "espresso", qty: 1, revenue: 2.5 }],
channelMix: { pos: 1 },
})
await client.closeBusinessDay("2026-02-24")