Compare commits

...

2 Commits

Author SHA1 Message Date
José René White Enciso
6d4251b3b3 docs(kitchen-ops-bff): align lifecycle board reads 2026-03-31 19:59:32 -06:00
José René White Enciso
b6b6c8fcf6 feat(kitchen-ops-bff): bridge kitchen state into shared flow 2026-03-31 18:53:28 -06:00
6 changed files with 43 additions and 15 deletions

View File

@ -30,4 +30,7 @@ This BFF exposes kitchen board, claim or release, transition, and priority workf
## Notes
- `kitchen-service` currently exposes claim but not a dedicated release contract, so the release route reuses the claim validation path and projects a release-oriented response for the BFF edge.
- Transition requests now forward `ContextId` to `kitchen-service` so kitchen actions land in the correct shared restaurant lifecycle context.
- Board reads now rely on the lifecycle-driven kitchen ticket materialization in `kitchen-service`, which means newly accepted restaurant orders can appear without a stack reset.
- The BFF keeps temporary edge-state compatibility for existing web clients by translating `Cooking|Ready|Served` to the canonical kitchen-service states `Preparing|ReadyForPickup|Delivered`.
- Correlation IDs are preserved through Thalos session checks and kitchen-service calls.

View File

@ -9,11 +9,10 @@ kitchen-ops-bff
- Epic 3: Improve observability and operational readiness for demo compose environments.
## Domain-Specific Candidate Features
- Order lifecycle consistency and state transitions.
- Kitchen queue and dispatch optimization hooks.
- Kitchen work-item claim, release, transition, and priority workflows aligned with kitchen-service.
- Kitchen board projection over linked restaurant tickets.
- Kitchen work-item claim, release, transition, and priority workflows aligned with canonical kitchen-service state transitions.
- Cross-app state continuity from customer or waiter submission through kitchen execution and POS readiness.
- Operations control-plane policies (flags, service windows, overrides).
- POS closeout and settlement summary alignment.
## Documentation Contract
Any code change in this repository must include docs updates in the same branch.

View File

@ -39,5 +39,6 @@ docker run --rm -p 8080:8080 --name kitchen-ops-bff agilewebs/kitchen-ops-bff:de
- Integration artifact path: `greenfield/demo/restaurant/docker-compose.yml`
## Known Limitations
- Kitchen-ops now delegates dashboard and work-item actions to `kitchen-service`, but the upstream kitchen workflow adapter still serves deterministic demo data rather than database-backed state.
- Kitchen-ops now delegates dashboard and work-item actions to `kitchen-service`, which projects persisted kitchen ticket state and syncs order progression back into the shared restaurant lifecycle.
- Temporary edge-state translation remains in place for existing web clients until the Stage 47 kitchen web task adopts the canonical kitchen-service states directly.
- Demo PostgreSQL seeds validate integration contracts and smoke determinism, but do not yet imply full persistence implementation parity.

View File

@ -75,7 +75,11 @@ public sealed class KitchenWorkflowServiceClient(HttpClient httpClient) : IKitch
{
using var response = await httpClient.PostAsJsonAsync(
"internal/kitchen/orders/transition",
new TransitionKitchenWorkItemPayload(request.OrderId, request.TicketId, request.TargetState),
new TransitionKitchenWorkItemPayload(
request.OrderId,
request.TicketId,
MapKitchenServiceState(request.TargetState),
request.ContextId ?? "demo-context"),
cancellationToken);
response.EnsureSuccessStatusCode();
@ -88,8 +92,8 @@ public sealed class KitchenWorkflowServiceClient(HttpClient httpClient) : IKitch
return new TransitionKitchenWorkItemResponse(
payload.OrderId,
payload.TicketId,
payload.PreviousState,
payload.CurrentState,
MapEdgeState(payload.PreviousState),
MapEdgeState(payload.CurrentState),
payload.Transitioned,
payload.Error);
}
@ -155,7 +159,27 @@ public sealed class KitchenWorkflowServiceClient(HttpClient httpClient) : IKitch
string ClaimedBy,
string Message);
private sealed record TransitionKitchenWorkItemPayload(string OrderId, string TicketId, string TargetState);
private static string MapKitchenServiceState(string edgeState) => edgeState switch
{
"Cooking" => "Preparing",
"Ready" => "ReadyForPickup",
"Served" => "Delivered",
_ => edgeState
};
private static string MapEdgeState(string serviceState) => serviceState switch
{
"Preparing" => "Cooking",
"ReadyForPickup" => "Ready",
"Delivered" => "Served",
_ => serviceState
};
private sealed record TransitionKitchenWorkItemPayload(
string OrderId,
string TicketId,
string TargetState,
string ContextId);
private sealed record TransitionKitchenWorkItemResponsePayload(
string OrderId,

View File

@ -4,4 +4,5 @@ public sealed record TransitionKitchenWorkItemRequest(
string OrderId,
string TicketId,
string TargetState,
string UpdatedBy);
string UpdatedBy,
string? ContextId = null);

View File

@ -65,7 +65,7 @@ public sealed class KitchenWorkflowServiceClientTests
{
var adapter = new KitchenWorkflowServiceClient(CreateClient("""
{
"orderId": "CO-1001",
"orderId": "ORD-1001",
"ticketId": "KT-1001",
"previousState": "Queued",
"currentState": "Preparing",
@ -75,11 +75,11 @@ public sealed class KitchenWorkflowServiceClientTests
"""));
var response = await adapter.TransitionWorkItemAsync(
new TransitionKitchenWorkItemRequest("CO-1001", "KT-1001", "Preparing", "chef-maya"),
new TransitionKitchenWorkItemRequest("ORD-1001", "KT-1001", "Cooking", "chef-maya", "demo-context"),
CancellationToken.None);
Assert.True(response.Transitioned);
Assert.Equal("Preparing", response.CurrentState);
Assert.Equal("Cooking", response.CurrentState);
}
[Fact]
@ -124,14 +124,14 @@ public sealed class KitchenWorkflowServiceClientTests
private const string BoardPayload = """
{
"contextId": "demo-context",
"summary": "Kitchen board shows queued, preparing, and ready lanes for the current service context.",
"summary": "Kitchen board now reflects persisted tickets linked to shared restaurant orders.",
"lanes": [
{
"lane": "queued",
"items": [
{
"workItemId": "WK-1001",
"orderId": "CO-1001",
"orderId": "ORD-1001",
"ticketId": "KT-1001",
"tableId": "T-08",
"station": "hot-line",