Compare commits

..

No commits in common. "6d4251b3b3219b0a3423a98a55eb6e574ade1d26" and "fcaa7e0d91b8eb78fcb9f2f18f9babf508035afa" have entirely different histories.

6 changed files with 15 additions and 43 deletions

View File

@ -30,7 +30,4 @@ This BFF exposes kitchen board, claim or release, transition, and priority workf
## Notes ## 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. - `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. - Correlation IDs are preserved through Thalos session checks and kitchen-service calls.

View File

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

View File

@ -39,6 +39,5 @@ docker run --rm -p 8080:8080 --name kitchen-ops-bff agilewebs/kitchen-ops-bff:de
- Integration artifact path: `greenfield/demo/restaurant/docker-compose.yml` - Integration artifact path: `greenfield/demo/restaurant/docker-compose.yml`
## Known Limitations ## Known Limitations
- 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. - 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.
- 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. - Demo PostgreSQL seeds validate integration contracts and smoke determinism, but do not yet imply full persistence implementation parity.

View File

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

View File

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

View File

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