feat(api): .NET 10 multi-tenant REST API
Full backend implementation: - Multi-tenant cafe/restaurant management (menus, orders, tables, staff) - POS order flow with ZarinPal and Snappfood payment integration - OTP authentication via Kavenegar SMS - QR digital menu with public discover/finder endpoints - Customer loyalty, coupons, CRM - PostgreSQL via EF Core, Redis for caching/sessions - Background jobs, webhook handlers - Full migration history Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using Meezi.API.Models.Orders;
|
||||
using Meezi.API.Services.Printing;
|
||||
using Meezi.Core.Enums;
|
||||
using Xunit;
|
||||
|
||||
namespace Meezi.API.Tests;
|
||||
|
||||
public class PrintingTests
|
||||
{
|
||||
private static OrderDto SampleOrder() => new(
|
||||
"order-abc12345",
|
||||
"cafe-1",
|
||||
"branch-1",
|
||||
"table-1",
|
||||
"5",
|
||||
"Ali",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
OrderType.DineIn,
|
||||
OrderSource.Pos,
|
||||
OrderStatus.Pending,
|
||||
200_000m,
|
||||
18_000m,
|
||||
0m,
|
||||
218_000m,
|
||||
0m,
|
||||
DateTime.UtcNow,
|
||||
[
|
||||
new OrderItemDto("i1", "m1", "Espresso", 2, 100_000m, null),
|
||||
new OrderItemDto("i2", "m2", "Void Latte", 1, 50_000m, null, true)
|
||||
],
|
||||
[new PaymentDto("p1", PaymentMethod.Cash, 218_000m, PaymentStatus.Completed, null)]);
|
||||
|
||||
private static ReceiptPrintContext Ctx(int paper = 80) => new(
|
||||
SampleOrder(),
|
||||
"کافه دمو",
|
||||
"شعبه اصلی",
|
||||
"خوش آمدید",
|
||||
"با تشکر",
|
||||
"wifi1234",
|
||||
paper,
|
||||
true);
|
||||
|
||||
[Fact]
|
||||
public void ReceiptBuilder_ExcludesVoidedItems()
|
||||
{
|
||||
var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
|
||||
var text = System.Text.Encoding.UTF8.GetString(bytes);
|
||||
Assert.Contains("Espresso", text);
|
||||
Assert.DoesNotContain("Void Latte", text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReceiptBuilder_AppliesPersianCalendarDate()
|
||||
{
|
||||
var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
|
||||
var text = System.Text.Encoding.UTF8.GetString(bytes);
|
||||
Assert.Contains("تاریخ:", text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReceiptBuilder_ShowsTaxLine_WhenTaxNonZero()
|
||||
{
|
||||
var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
|
||||
var text = System.Text.Encoding.UTF8.GetString(bytes);
|
||||
Assert.Contains("مالیات", text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReceiptBuilder_80mm_Uses48CharWidth()
|
||||
{
|
||||
var sep = new EscPosBuilder().Separator(48).Build();
|
||||
var receipt = new ReceiptBuilder().BuildReceipt(Ctx(80));
|
||||
Assert.NotEmpty(receipt);
|
||||
Assert.Contains(sep, receipt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReceiptBuilder_58mm_Uses32CharWidth()
|
||||
{
|
||||
var sep = new EscPosBuilder().Separator(32).Build();
|
||||
var receipt = new ReceiptBuilder().BuildReceipt(Ctx(58));
|
||||
Assert.Contains(sep, receipt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KitchenTicket_IncludesItemNotes()
|
||||
{
|
||||
var order = SampleOrder() with
|
||||
{
|
||||
Items =
|
||||
[
|
||||
new OrderItemDto("i1", "m1", "Burger", 1, 100_000m, "بدون پیاز")
|
||||
]
|
||||
};
|
||||
var ctx = Ctx() with { Order = order };
|
||||
var text = System.Text.Encoding.UTF8.GetString(new ReceiptBuilder().BuildKitchenTicket(ctx));
|
||||
Assert.Contains("بدون پیاز", text);
|
||||
Assert.Contains("آشپزخانه", text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EscPosBuilder_Cut_AppendsCorrectBytes()
|
||||
{
|
||||
var bytes = new EscPosBuilder().Cut().Build();
|
||||
Assert.Equal([0x1D, 0x56, 0x42, 0x03], bytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EscPosBuilder_TwoColumns_PadsCorrectly()
|
||||
{
|
||||
var bytes = new EscPosBuilder().TwoColumns("کالا", "1000", 10).Build();
|
||||
var line = System.Text.Encoding.UTF8.GetString(bytes).TrimEnd('\n');
|
||||
Assert.Equal(10, line.Length);
|
||||
Assert.EndsWith("1000", line);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user