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:
|
||||
- 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
|
||||
- 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
|
||||
|
||||
@ -316,10 +316,9 @@ public sealed class DefaultKitchenWorkflowPort : IKitchenWorkflowPort
|
||||
|
||||
private static PersistedKitchenWorkItemRecord BuildDerivedWorkItem(PersistedRestaurantLifecycleRecord order)
|
||||
{
|
||||
var numericSuffix = new string(order.OrderId.Where(char.IsDigit).ToArray());
|
||||
var workItemId = string.IsNullOrWhiteSpace(numericSuffix)
|
||||
? $"WK-{order.OrderId}"
|
||||
: $"WK-{numericSuffix}";
|
||||
// Use the full order identity when deriving kitchen IDs so distinct orders
|
||||
// cannot collide just because they share a numeric suffix.
|
||||
var workItemId = $"WK-{order.OrderId}";
|
||||
|
||||
return new PersistedKitchenWorkItemRecord(
|
||||
order.ContextId,
|
||||
|
||||
@ -56,6 +56,53 @@ public class KitchenWorkflowUseCasesTests
|
||||
|
||||
Assert.Equal("hot-line", derivedItem.Station);
|
||||
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]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user