feat(orders): recent orders view with receipt / kitchen / bar reprint
CI/CD / CI · API (dotnet build + test) (push) Successful in 41s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 30s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m10s
CI/CD / CI · Admin Web (tsc) (push) Successful in 38s
CI/CD / CI · Website (tsc) (push) Successful in 46s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 3m34s

Adds a "سفارش‌ها" (Orders) nav page listing closed orders by day (date +
branch filter, paged), each with reprint actions:
- چاپ فاکتور  → customer receipt
- فیش آشپزخانه → kitchen ticket (all stations)
- one button per print station (e.g. Bar) → reprints only that station's items

Backend: the kitchen print endpoint gains an optional ?stationId= to reprint a
single station; PrintKitchenTicketAsync filters its station groups accordingly
(NO_STATION_ITEMS when that station has nothing on the order). Nav gated by
ViewOrders (visible to branch staff too). fa/en/ar strings added.

Note: local backend build couldn't run (NU1301 — NuGet restore network timeout);
dashboard typecheck is clean and the C# changes are minimal — CI builds via the
Nexus mirror.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-21 23:15:34 +03:30
parent 1264606410
commit c360fbb068
10 changed files with 321 additions and 6 deletions
@@ -19,6 +19,7 @@ public interface IPrinterService
Task<PrintResult> PrintKitchenTicketAsync(
string cafeId,
string orderId,
string? stationId = null,
CancellationToken ct = default);
Task<PrintResult> TestPrintAsync(string printerIp, int port, CancellationToken ct = default);
}
@@ -62,6 +63,7 @@ public class NetworkPrinterService : IPrinterService
public async Task<PrintResult> PrintKitchenTicketAsync(
string cafeId,
string orderId,
string? stationId = null,
CancellationToken ct = default)
{
var ctx = await BuildContextAsync(cafeId, orderId, ct);
@@ -102,6 +104,14 @@ public class NetworkPrinterService : IPrinterService
})
.ToList();
// Optionally reprint a single station only (e.g. just the bar ticket).
if (!string.IsNullOrEmpty(stationId))
{
groups = groups.Where(g => g.Key == stationId).ToList();
if (groups.Count == 0)
return PrintResult.Fail("NO_STATION_ITEMS");
}
PrintResult? lastFail = null;
var anyPrinted = false;
@@ -243,7 +253,7 @@ public static class PrinterBackgroundJobs
try
{
var printer = scope.ServiceProvider.GetRequiredService<IPrinterService>();
var result = await printer.PrintKitchenTicketAsync(cafeId, orderId, CancellationToken.None);
var result = await printer.PrintKitchenTicketAsync(cafeId, orderId, null, CancellationToken.None);
if (!result.Success)
logger.LogWarning("Kitchen print failed for {OrderId}: {Code}", orderId, result.ErrorCode);
}