fix(kitchen-service): harden derived ticket identities
This commit is contained in:
parent
0dc1f39dd2
commit
5564c06dd6
@ -18,6 +18,7 @@ This repo now orchestrates kitchen progression over persisted kitchen tickets fr
|
|||||||
|
|
||||||
That means:
|
That means:
|
||||||
- board and queue reads come from persisted kitchen tickets plus lifecycle-derived ticket materialization for newly accepted restaurant orders
|
- board and queue reads come from persisted kitchen tickets plus lifecycle-derived ticket materialization for newly accepted restaurant orders
|
||||||
|
- derived kitchen IDs now use the full order identity so runtime projections stay collision-safe across similar order numbers
|
||||||
- claim and priority changes update persisted kitchen ticket state
|
- claim and priority changes update persisted kitchen ticket state
|
||||||
- ticket transitions update both kitchen tickets and the linked restaurant order lifecycle
|
- ticket transitions update both kitchen tickets and the linked restaurant order lifecycle
|
||||||
- accepted orders can become kitchen-visible without waiting for a stack reset or a second write path
|
- accepted orders can become kitchen-visible without waiting for a stack reset or a second write path
|
||||||
|
|||||||
@ -316,10 +316,9 @@ public sealed class DefaultKitchenWorkflowPort : IKitchenWorkflowPort
|
|||||||
|
|
||||||
private static PersistedKitchenWorkItemRecord BuildDerivedWorkItem(PersistedRestaurantLifecycleRecord order)
|
private static PersistedKitchenWorkItemRecord BuildDerivedWorkItem(PersistedRestaurantLifecycleRecord order)
|
||||||
{
|
{
|
||||||
var numericSuffix = new string(order.OrderId.Where(char.IsDigit).ToArray());
|
// Use the full order identity when deriving kitchen IDs so distinct orders
|
||||||
var workItemId = string.IsNullOrWhiteSpace(numericSuffix)
|
// cannot collide just because they share a numeric suffix.
|
||||||
? $"WK-{order.OrderId}"
|
var workItemId = $"WK-{order.OrderId}";
|
||||||
: $"WK-{numericSuffix}";
|
|
||||||
|
|
||||||
return new PersistedKitchenWorkItemRecord(
|
return new PersistedKitchenWorkItemRecord(
|
||||||
order.ContextId,
|
order.ContextId,
|
||||||
|
|||||||
@ -56,6 +56,53 @@ public class KitchenWorkflowUseCasesTests
|
|||||||
|
|
||||||
Assert.Equal("hot-line", derivedItem.Station);
|
Assert.Equal("hot-line", derivedItem.Station);
|
||||||
Assert.Equal("Queued", derivedItem.State);
|
Assert.Equal("Queued", derivedItem.State);
|
||||||
|
Assert.Equal("WK-ORD-1099", derivedItem.WorkItemId);
|
||||||
|
Assert.Equal("KT-ORD-1099", derivedItem.TicketId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetKitchenBoardUseCase_DerivesCollisionSafeIdsForSimilarNumericSuffixes()
|
||||||
|
{
|
||||||
|
await restaurantLifecycle.UpsertOrderAsync(
|
||||||
|
new Kitchen.Service.Application.State.PersistedRestaurantLifecycleRecord(
|
||||||
|
"demo-context",
|
||||||
|
"ORD-STAGE49-001",
|
||||||
|
"CHK-ORD-STAGE49-001",
|
||||||
|
"T-31",
|
||||||
|
"Accepted",
|
||||||
|
"Open",
|
||||||
|
2,
|
||||||
|
false,
|
||||||
|
25.00m,
|
||||||
|
"USD",
|
||||||
|
"customer-orders",
|
||||||
|
new[] { "ITEM-101", "ITEM-102" },
|
||||||
|
DateTime.UtcNow),
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
await restaurantLifecycle.UpsertOrderAsync(
|
||||||
|
new Kitchen.Service.Application.State.PersistedRestaurantLifecycleRecord(
|
||||||
|
"demo-context",
|
||||||
|
"ORD-STAGE49-WAITER-001",
|
||||||
|
"CHK-ORD-STAGE49-WAITER-001",
|
||||||
|
"T-32",
|
||||||
|
"Accepted",
|
||||||
|
"Open",
|
||||||
|
3,
|
||||||
|
false,
|
||||||
|
37.50m,
|
||||||
|
"USD",
|
||||||
|
"waiter-floor",
|
||||||
|
new[] { "ITEM-201", "ITEM-202", "ITEM-203" },
|
||||||
|
DateTime.UtcNow.AddSeconds(1)),
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
var useCase = new GetKitchenBoardUseCase(workflowPort);
|
||||||
|
var response = await useCase.HandleAsync(new GetKitchenBoardRequest("demo-context"), CancellationToken.None);
|
||||||
|
var queuedLane = Assert.Single(response.Lanes, lane => lane.Lane == "queued");
|
||||||
|
|
||||||
|
Assert.Contains(queuedLane.Items, item => item.WorkItemId == "WK-ORD-STAGE49-001" && item.TicketId == "KT-ORD-STAGE49-001");
|
||||||
|
Assert.Contains(queuedLane.Items, item => item.WorkItemId == "WK-ORD-STAGE49-WAITER-001" && item.TicketId == "KT-ORD-STAGE49-WAITER-001");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user