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:
soroush.asadi
2026-05-27 21:33:48 +03:30
parent 03376b3ea1
commit ef15fd6247
472 changed files with 120358 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
namespace Meezi.API.Models.Auth;
public record SendOtpRequest(string Phone);
public record VerifyOtpRequest(string Phone, string Code, string? CafeId = null);
public record RefreshTokenRequest(string RefreshToken);
public record AuthTokenResponse(
string AccessToken,
string RefreshToken,
DateTime ExpiresAt,
string UserId,
string CafeId,
string Role,
string PlanTier,
string Language,
string Actor = Meezi.Core.Constants.MeeziActorKinds.Merchant,
string? BranchId = null);
public record SendOtpResponse(bool Sent, int ExpiresInSeconds);
@@ -0,0 +1,27 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Billing;
public record SubscribeRequest(PlanTier PlanTier, int Months, string? PaymentMethod = null);
public record PaymentMethodDto(string Id, string DisplayNameFa, bool IsDefault);
public record SubscribeResponse(string PaymentId, string PaymentUrl);
public record BillingStatusDto(
PlanTier PlanTier,
DateTime? PlanExpiresAt,
int OrdersToday,
int? OrdersDailyLimit,
int CustomersCount,
int? CustomersLimit,
int SmsUsedThisMonth,
int SmsMonthlyLimit,
bool Menu3dEnabled,
bool MenuAi3dEnabled,
int MenuAi3dUsedThisMonth,
int MenuAi3dMonthlyLimit,
bool DiscoverProfileEnabled,
bool IsPlanExpired);
public record BillingVerifyResult(bool Success, string RedirectUrl);
@@ -0,0 +1,35 @@
namespace Meezi.API.Models.Branches;
public record BranchDto(
string Id,
string Name,
string? Address,
string? City,
string? Phone,
bool IsActive,
string? LoginPhone = null,
string? ManagerName = null,
bool IsPendingDeletion = false,
DateTime? DeletedAt = null,
DateTime? ScheduledPermanentDeleteAt = null,
int? DaysUntilPermanentDelete = null);
public record CreateBranchRequest(
string Name,
string LoginPhone,
string? ManagerName,
string? Address,
string? City,
string? Phone);
public record PatchBranchRequest(
string? Name,
string? Address,
string? City,
string? Phone,
bool? IsActive,
string? LogoUrl,
string? WelcomeText,
string? AccentColor,
string? WifiPassword,
decimal? TaxRate);
@@ -0,0 +1,31 @@
namespace Meezi.API.Models.Cafes;
public record CafeSettingsDto(
string Id,
string Name,
string Slug,
string? Phone,
string? Address,
string? City,
string? Description,
string? LogoUrl,
string? CoverImageUrl,
string? SnappfoodVendorId,
string PlanTier,
DateTime? PlanExpiresAt,
CafeThemeDto Theme,
decimal DefaultTaxRate,
bool AllowBranchTaxOverride);
public record PatchCafeSettingsRequest(
string? Name,
string? Phone,
string? Address,
string? City,
string? Description,
string? LogoUrl,
string? CoverImageUrl,
string? SnappfoodVendorId,
CafeThemeDto? Theme,
decimal? DefaultTaxRate,
bool? AllowBranchTaxOverride);
@@ -0,0 +1,30 @@
namespace Meezi.API.Models.Cafes;
public record CafeThemeCustomColorsDto(
string? Primary,
string? Secondary,
string? Accent,
string? Background,
string? Surface,
string? Text,
string? TextMuted,
string? Destructive,
string? Success,
int? PrimaryOpacity = null,
int? SecondaryOpacity = null,
int? AccentOpacity = null,
int? BackgroundOpacity = null,
int? SurfaceOpacity = null,
int? TextOpacity = null,
int? TextMutedOpacity = null,
int? DestructiveOpacity = null,
int? SuccessOpacity = null);
public record CafeThemeDto(
string PaletteId,
string PanelStyle,
string MenuStyle,
string MenuTexture,
string Density,
string Radius,
CafeThemeCustomColorsDto? Custom);
@@ -0,0 +1,23 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Consumer;
public record ConsumerAuthTokenResponse(
string AccessToken,
string RefreshToken,
DateTime ExpiresAt,
string UserId,
string Phone,
string Language);
public record ConsumerOrderHistoryDto(
string Id,
string CafeId,
string CafeName,
string CafeSlug,
OrderStatus Status,
decimal Total,
int DisplayNumber,
DateTime CreatedAt,
string? TableNumber,
int ItemCount);
+50
View File
@@ -0,0 +1,50 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Crm;
public record CouponDto(
string Id,
string Code,
CouponType Type,
decimal Value,
decimal? MinOrderAmount,
decimal? MaxDiscount,
int? UsageLimit,
int UsedCount,
CustomerGroup? TargetGroup,
DateTime? StartsAt,
DateTime? ExpiresAt,
bool IsActive);
public record CreateCouponRequest(
string Code,
CouponType Type,
decimal Value,
decimal? MinOrderAmount,
decimal? MaxDiscount,
int? UsageLimit,
CustomerGroup? TargetGroup,
DateTime? StartsAt,
DateTime? ExpiresAt,
bool IsActive = true);
public record ValidateCouponRequest(string Code, decimal Subtotal);
public record ValidateCouponResult(
string CouponId,
string Code,
CouponType Type,
decimal Value,
decimal DiscountAmount);
public record UpdateCouponRequest(
string? Code,
CouponType? Type,
decimal? Value,
decimal? MinOrderAmount,
decimal? MaxDiscount,
int? UsageLimit,
CustomerGroup? TargetGroup,
DateTime? StartsAt,
DateTime? ExpiresAt,
bool? IsActive);
+31
View File
@@ -0,0 +1,31 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Crm;
public record CustomerDto(
string Id,
string Name,
string Phone,
string? NationalId,
string? BirthDateJalali,
CustomerGroup Group,
int LoyaltyPoints,
string? ReferredBy,
DateTime CreatedAt);
public record CreateCustomerRequest(
string Name,
string Phone,
string? NationalId,
string? BirthDateJalali,
CustomerGroup Group = CustomerGroup.Regular,
string? ReferredBy = null);
public record UpdateCustomerRequest(
string? Name,
string? Phone,
string? NationalId,
string? BirthDateJalali,
CustomerGroup? Group,
int? LoyaltyPoints,
string? ReferredBy);
+12
View File
@@ -0,0 +1,12 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Crm;
public record SendSmsCampaignRequest(
string Message,
CustomerGroup? TargetGroup,
IReadOnlyList<string>? Phones);
public record SmsCampaignResult(int SentCount, int FailedCount);
public record SmsUsageDto(int UsedThisMonth, int MonthlyLimit, string Month);
@@ -0,0 +1,20 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Delivery;
public record PlatformRevenueDto(
DeliveryPlatform Platform,
string PlatformName,
int OrderCount,
decimal GrossRevenue,
decimal Commission,
decimal NetRevenue);
public record DeliveryRevenueReportDto(
string PeriodLabel,
DateTime UtcFrom,
DateTime UtcTo,
IReadOnlyList<PlatformRevenueDto> Platforms,
decimal TotalGross,
decimal TotalCommission,
decimal TotalNet);
@@ -0,0 +1,31 @@
namespace Meezi.API.Models.Discover;
public record CafeDiscoverProfileDto(
IReadOnlyList<string> Themes,
string? Size,
string? Floors,
IReadOnlyList<string> Vibes,
IReadOnlyList<string> Occasions,
IReadOnlyList<string> SpaceFeatures,
string? NoiseLevel,
string? PriceTier);
public record UpsertCafeDiscoverProfileRequest(
IReadOnlyList<string>? Themes,
string? Size,
string? Floors,
IReadOnlyList<string>? Vibes,
IReadOnlyList<string>? Occasions,
IReadOnlyList<string>? SpaceFeatures,
string? NoiseLevel,
string? PriceTier);
public record DiscoverProfileTaxonomyDto(
IReadOnlyList<string> Themes,
IReadOnlyList<string> Sizes,
IReadOnlyList<string> Floors,
IReadOnlyList<string> Vibes,
IReadOnlyList<string> Occasions,
IReadOnlyList<string> SpaceFeatures,
IReadOnlyList<string> NoiseLevels,
IReadOnlyList<string> PriceTiers);
@@ -0,0 +1,25 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Expenses;
public record CreateExpenseRequest(
string BranchId,
string? ShiftId,
ExpenseCategory Category,
decimal Amount,
string? Note,
string? ReceiptImageUrl);
public record ExpenseDto(
string Id,
string CafeId,
string BranchId,
string? ShiftId,
ExpenseCategory Category,
decimal Amount,
string? Note,
string? ReceiptImageUrl,
string CreatedByUserId,
DateTime CreatedAt);
public record ExpenseListResult(IReadOnlyList<ExpenseDto> Items, int Total);
+61
View File
@@ -0,0 +1,61 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Hr;
public record EmployeeSummaryDto(
string Id,
string Name,
string Phone,
EmployeeRole Role,
decimal BaseSalary);
public record AttendanceDto(
string Id,
string EmployeeId,
string EmployeeName,
DateOnly Date,
DateTime? ClockIn,
DateTime? ClockOut,
string? Notes);
public record ShiftDto(int DayOfWeek, ShiftType ShiftType);
public record UpsertShiftsRequest(IReadOnlyList<ShiftDto> Shifts);
public record LeaveRequestDto(
string Id,
string EmployeeId,
string EmployeeName,
DateOnly StartDate,
DateOnly EndDate,
string? Reason,
LeaveStatus Status,
string? ReviewedBy,
DateTime CreatedAt);
public record CreateLeaveRequest(
DateOnly StartDate,
DateOnly EndDate,
string? Reason);
public record ReviewLeaveRequest(LeaveStatus Status);
public record EmployeeSalaryDto(
string Id,
string EmployeeId,
string EmployeeName,
string MonthYear,
decimal BaseSalary,
decimal OvertimePay,
decimal Deductions,
decimal NetSalary,
bool IsPaid);
public record CreateSalaryRequest(
string EmployeeId,
string MonthYear,
decimal BaseSalary,
decimal OvertimePay,
decimal Deductions);
public record TodayShiftDto(ShiftType ShiftType, string Label);
@@ -0,0 +1,24 @@
namespace Meezi.API.Models.Kitchen;
public record KitchenStationDto(
string Id,
string? BranchId,
string Name,
string? PrinterIp,
int PrinterPort,
int SortOrder,
int CategoryCount);
public record CreateKitchenStationRequest(
string Name,
string? BranchId,
string? PrinterIp,
int PrinterPort = 9100,
int SortOrder = 0);
public record UpdateKitchenStationRequest(
string? Name,
string? BranchId,
string? PrinterIp,
int? PrinterPort,
int? SortOrder);
@@ -0,0 +1,29 @@
namespace Meezi.API.Models.Menu;
public record BranchMenuItemDto(
string Id,
string CategoryId,
string Name,
string? NameAr,
string? NameEn,
string? Description,
decimal MasterPrice,
decimal EffectivePrice,
decimal DiscountPercent,
string? ImageUrl,
string? VideoUrl,
string? Model3dUrl,
bool IsAvailable,
bool IsOverridden,
bool HasPriceOverride);
public record UpsertBranchMenuOverrideRequest(
bool IsAvailable,
decimal? PriceOverride);
public record BranchMenuOverrideDto(
string MenuItemId,
string BranchId,
bool IsAvailable,
decimal? PriceOverride,
DateTime UpdatedAt);
+86
View File
@@ -0,0 +1,86 @@
namespace Meezi.API.Models.Menu;
public record MenuCategoryDto(
string Id,
string Name,
string? NameAr,
string? NameEn,
int SortOrder,
string? TaxId,
decimal DiscountPercent,
string? Icon,
string? IconPresetId,
string? IconStyle,
string? ImageUrl,
bool IsActive,
string? KitchenStationId);
public record CreateMenuCategoryRequest(
string Name,
string? NameAr,
string? NameEn,
int SortOrder,
string? TaxId,
decimal DiscountPercent,
string? Icon = null,
string? IconPresetId = null,
string? IconStyle = null,
string? ImageUrl = null,
bool IsActive = true,
string? KitchenStationId = null);
public record UpdateMenuCategoryRequest(
string? Name,
string? NameAr,
string? NameEn,
int? SortOrder,
string? TaxId,
decimal? DiscountPercent,
string? Icon,
string? IconPresetId,
string? IconStyle,
string? ImageUrl,
bool? IsActive,
string? KitchenStationId);
public record MenuItemDto(
string Id,
string CategoryId,
string Name,
string? NameAr,
string? NameEn,
string? Description,
decimal Price,
decimal DiscountPercent,
string? ImageUrl,
string? VideoUrl,
string? Model3dUrl,
bool IsAvailable);
public record CreateMenuItemRequest(
string CategoryId,
string Name,
string? NameAr,
string? NameEn,
string? Description,
decimal Price,
decimal DiscountPercent = 0,
string? ImageUrl = null,
string? VideoUrl = null,
string? Model3dUrl = null,
bool IsAvailable = true);
public record UpdateMenuItemRequest(
string? CategoryId,
string? Name,
string? NameAr,
string? NameEn,
string? Description,
decimal? Price,
decimal? DiscountPercent,
string? ImageUrl,
string? VideoUrl,
string? Model3dUrl,
bool? IsAvailable);
public record UpdateMenuItemAvailabilityRequest(bool IsAvailable);
@@ -0,0 +1,19 @@
namespace Meezi.API.Models.Notifications;
public record CafeNotificationDto(
string Id,
string Type,
string Title,
string? Body,
string? ReferenceId,
string? TableNumber,
bool IsRead,
DateTime CreatedAt);
public record NotificationListDto(
IReadOnlyList<CafeNotificationDto> Items,
int UnreadCount);
public record MarkNotificationsReadRequest(
IReadOnlyList<string>? Ids,
bool All = false);
+81
View File
@@ -0,0 +1,81 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Orders;
public record OrderItemDto(
string Id,
string MenuItemId,
string MenuItemName,
int Quantity,
decimal UnitPrice,
string? Notes,
bool IsVoided = false,
DateTime? VoidedAt = null);
public record TransferTableRequest(string TargetTableId);
public record OrderDto(
string Id,
string CafeId,
string? BranchId,
string? TableId,
string? TableNumber,
string? GuestName,
string? GuestPhone,
string? CustomerName,
string? CustomerPhone,
string? CustomerId,
string? EmployeeId,
OrderType OrderType,
OrderSource Source,
OrderStatus Status,
decimal Subtotal,
decimal TaxTotal,
decimal DiscountAmount,
decimal Total,
decimal PaidAmount,
DateTime CreatedAt,
int DisplayNumber,
IReadOnlyList<OrderItemDto> Items,
IReadOnlyList<PaymentDto> Payments);
public record AppendOrderItemsRequest(IReadOnlyList<CreateOrderItemRequest> Items);
public record UpdateOrderSessionRequest(
string? GuestName,
string? GuestPhone,
string? CustomerId);
public record CreateOrderItemRequest(string MenuItemId, int Quantity, string? Notes);
public record CreateOrderRequest(
OrderType OrderType,
string? BranchId,
string? TableId,
string? ReservationId,
string? GuestName,
string? GuestPhone,
string? CustomerId,
string? CouponId,
IReadOnlyList<CreateOrderItemRequest> Items);
public record UpdateOrderStatusRequest(OrderStatus Status);
public record CreatePaymentRequest(PaymentMethod Method, decimal Amount, string? Reference);
public record RecordPaymentsRequest(
IReadOnlyList<CreatePaymentRequest> Payments,
int? LoyaltyPointsToRedeem = null);
public record PaymentDto(string Id, PaymentMethod Method, decimal Amount, PaymentStatus Status, string? Reference);
public record LiveOrderDto(
string Id,
int DisplayNumber,
OrderStatus Status,
string? TableNumber,
OrderType OrderType,
decimal Total,
DateTime CreatedAt,
IReadOnlyList<OrderItemDto> Items);
@@ -0,0 +1,36 @@
namespace Meezi.API.Models.Printing;
public record BranchPrintSettingsDto(
string BranchId,
string? ReceiptPrinterIp,
int? ReceiptPrinterPort,
string? KitchenPrinterIp,
int? KitchenPrinterPort,
int PaperWidthMm,
bool AutoCutEnabled,
string? ReceiptHeader,
string? ReceiptFooter,
string? WifiPassword,
string? PosDeviceIp,
int? PosDevicePort);
public record PatchBranchPrintSettingsRequest(
string? ReceiptPrinterIp,
int? ReceiptPrinterPort,
string? KitchenPrinterIp,
int? KitchenPrinterPort,
int? PaperWidthMm,
bool? AutoCutEnabled,
string? ReceiptHeader,
string? ReceiptFooter,
string? WifiPassword,
string? PosDeviceIp,
int? PosDevicePort);
public record PosPaymentRequest(string OrderId, decimal Amount);
public record PosPaymentResultDto(bool Sent, bool Skipped, string? Message);
public record TestPrintRequest(string PrinterIp, int Port = 9100);
public record PrintJobResultDto(bool Printed, string? ErrorCode, string? Message);
@@ -0,0 +1,9 @@
namespace Meezi.API.Models.Public;
public record CoffeeAdvisorRequest(string Purpose, string? CafeSlug = null);
public record CoffeeAdvisorPickDto(string Name, string Reason, string? MenuItemId);
public record CoffeeAdvisorResultDto(
string Summary,
IReadOnlyList<CoffeeAdvisorPickDto> Picks);
+187
View File
@@ -0,0 +1,187 @@
using Meezi.API.Models.Cafes;
using Meezi.API.Models.Discover;
using Meezi.API.Models.Orders;
using Meezi.Core.Enums;
namespace Meezi.API.Models.Public;
// ── Working hours (read-only, for public display) ────────────────────────────
public record DaySchedulePublicDto(bool IsOpen, string? Open, string? Close);
public record WorkingHoursPublicDto(
DaySchedulePublicDto? Sat,
DaySchedulePublicDto? Sun,
DaySchedulePublicDto? Mon,
DaySchedulePublicDto? Tue,
DaySchedulePublicDto? Wed,
DaySchedulePublicDto? Thu,
DaySchedulePublicDto? Fri);
// ── NLP parse result (returned by /api/public/discover/nlp-parse) ────────────
public record DiscoverNlpHintsDto(
IReadOnlyList<string> Themes,
IReadOnlyList<string> Vibes,
IReadOnlyList<string> Occasions,
IReadOnlyList<string> SpaceFeatures,
string? NoiseLevel,
string? PriceTier,
string? Size)
{
public static readonly DiscoverNlpHintsDto Empty =
new([], [], [], [], null, null, null);
}
public record CafeBadgePublicDto(string Key, string Label, string Icon);
public record CafeDiscoverDto(
string Id,
string Name,
string Slug,
string? City,
string? Address,
string? LogoUrl,
string? CoverImageUrl,
bool IsVerified,
double AverageRating,
int ReviewCount,
CafeDiscoverProfileDto DiscoverProfile,
IReadOnlyList<CafeBadgePublicDto> Badges,
IReadOnlyList<string> GalleryUrls,
bool IsOpenNow,
string? InstagramHandle,
string? WebsiteUrl,
double RelevanceScore);
public record CafePublicDto(
string Id,
string Name,
string? NameAr,
string? NameEn,
string Slug,
string? City,
string? Address,
string? Phone,
string? LogoUrl,
string? CoverImageUrl,
string? Description,
bool IsVerified,
double AverageRating,
int ReviewCount,
CafeDiscoverProfileDto DiscoverProfile,
IReadOnlyList<CafeBadgePublicDto> Badges,
IReadOnlyList<string> GalleryUrls,
bool IsOpenNow,
string? InstagramHandle,
string? WebsiteUrl,
WorkingHoursPublicDto? WorkingHours);
public record PublicMenuItemDto(
string Id,
string CategoryId,
string Name,
string? NameAr,
string? NameEn,
string? Description,
decimal Price,
decimal DiscountPercent,
string? ImageUrl,
string? VideoUrl,
string? Model3dUrl,
bool IsAvailable);
public record PublicMenuCategoryDto(
string Id,
string Name,
string? NameAr,
string? NameEn,
string? Icon,
string? IconPresetId,
string? IconStyle,
string? ImageUrl,
IReadOnlyList<PublicMenuItemDto> Items);
public record PublicMenuDto(
string CafeId,
string CafeName,
string Slug,
CafeThemeDto Theme,
IReadOnlyList<PublicMenuCategoryDto> Categories);
public record GuestCreateOrderRequest(
OrderType OrderType,
string? TableId,
string? GuestPhone,
string? GuestName,
string? CouponCode,
IReadOnlyList<CreateOrderItemRequest> Items,
string? CaptchaToken = null);
public record GuestOrderPlacedDto(
string OrderId,
OrderStatus Status,
decimal Total,
string? TableNumber);
public record PlaceGuestOrderRequest(
string TableId,
string? GuestName,
string? GuestPhone,
IReadOnlyList<CreateOrderItemRequest> Items,
string? CaptchaToken = null);
public record PublicSecurityConfigDto(
bool AbuseProtectionEnabled,
string? TurnstileSiteKey,
bool CaptchaRequired);
public record GuestQrOrderPlacedDto(
string OrderId,
string OrderNumber,
decimal TotalAmount,
int ItemCount,
OrderStatus Status,
string TrackingToken);
public record OrderTrackingStepDto(
string Key,
string LabelKey,
bool IsComplete,
bool IsCurrent);
public record OrderTrackDto(
string Id,
string OrderNumber,
OrderStatus Status,
string StatusLabelKey,
decimal Total,
string? TableNumber,
DateTime CreatedAt,
DateTime StatusUpdatedAt,
string TrackingToken,
IReadOnlyList<OrderTrackingStepDto> Steps,
IReadOnlyList<OrderItemDto> Items);
public record CreateReservationRequest(
string GuestName,
string GuestPhone,
DateOnly Date,
TimeOnly Time,
int PartySize,
string? Notes,
string? TableId,
string? CaptchaToken = null);
public record ReservationDto(
string Id,
string CafeId,
string? TableId,
string? TableNumber,
string GuestName,
string GuestPhone,
DateOnly Date,
TimeOnly Time,
int PartySize,
ReservationStatus Status,
string? Notes);
+22
View File
@@ -0,0 +1,22 @@
namespace Meezi.API.Models.Public;
public record CafeReviewDto(
string Id,
string AuthorName,
int Rating,
string? Comment,
string? OwnerReply,
DateTime CreatedAt,
IReadOnlyList<string> PhotoUrls,
bool IsHidden = false);
public record CreateCafeReviewRequest(
string AuthorName,
string? AuthorPhone,
int Rating,
string? Comment,
string? CaptchaToken = null);
public record ReplyCafeReviewRequest(string Reply);
public record HideCafeReviewRequest(bool IsHidden);
+27
View File
@@ -0,0 +1,27 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Queue;
public record QueueTicketDto(
string Id,
string? BranchId,
DateOnly ServiceDate,
int Number,
string? CustomerLabel,
string? OrderId,
QueueTicketStatus Status,
DateTime IssuedAt);
public record QueueBoardDto(
DateOnly ServiceDate,
int? NowServing,
int LastIssued,
int WaitingCount,
IReadOnlyList<QueueTicketDto> Tickets);
public record IssueQueueTicketRequest(
string? BranchId,
string? CustomerLabel,
string? OrderId);
public record UpdateQueueTicketStatusRequest(QueueTicketStatus Status);
@@ -0,0 +1,35 @@
namespace Meezi.API.Models.Reports;
public record TopProductSnapshotDto(string ProductId, string Name, int Quantity, decimal Revenue);
public record DailyReportSnapshotDto(
string Id,
string CafeId,
string BranchId,
string Date,
decimal TotalRevenue,
decimal CashRevenue,
decimal CardRevenue,
decimal CreditRevenue,
int TotalOrders,
decimal AvgOrderValue,
int TotalVoids,
decimal VoidAmount,
decimal TotalExpenses,
decimal NetIncome,
IReadOnlyList<TopProductSnapshotDto> TopProducts,
DateTime GeneratedAt);
public record DailyReportSummaryDto(
int Days,
decimal TotalRevenue,
decimal CashRevenue,
decimal CardRevenue,
decimal CreditRevenue,
int TotalOrders,
decimal AvgOrderValue,
int TotalVoids,
decimal VoidAmount,
decimal TotalExpenses,
decimal NetIncome,
IReadOnlyList<DailyReportSnapshotDto> ByBranch);
@@ -0,0 +1,26 @@
namespace Meezi.API.Models.Reports;
public record TopItemDto(string MenuItemId, string Name, int Quantity, decimal Revenue);
public record DailyReportDto(
string DateJalali,
int TotalOrders,
int NewCustomers,
int ReturningCustomers,
decimal Revenue,
decimal TaxTotal,
decimal DiscountTotal,
IReadOnlyList<TopItemDto> TopItems);
public record DailyBreakdownDto(string DateJalali, decimal Revenue, decimal Cost);
public record MonthlyReportDto(
string MonthJalali,
IReadOnlyList<DailyBreakdownDto> DailyBreakdown,
decimal TotalRevenue,
decimal TotalCosts,
decimal SalaryCosts,
decimal OtherCosts,
decimal NetProfit);
public record TrendDayDto(string DateJalali, decimal Revenue, decimal Cost);
+33
View File
@@ -0,0 +1,33 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Shifts;
public record ShiftDto(
string Id,
string CafeId,
string BranchId,
string OpenedByUserId,
string? ClosedByUserId,
DateTime OpenedAt,
DateTime? ClosedAt,
decimal OpeningCash,
decimal? ClosingCash,
decimal ExpectedCash,
decimal? Discrepancy,
ShiftStatus Status);
public record CashTransactionDto(
string Id,
string ShiftId,
string? BranchId,
CashTransactionType Type,
PaymentMethod Method,
decimal Amount,
string? ReferenceId,
string? Note,
string CreatedByUserId,
DateTime CreatedAt);
public record OpenShiftRequest(decimal OpeningCash);
public record CloseShiftRequest(decimal ClosingCash);
@@ -0,0 +1,14 @@
namespace Meezi.API.Models.Snappfood;
public record SnappfoodWebhookOrder(
string OrderId,
string VendorId,
string? CustomerName,
string? CustomerPhone,
decimal Total,
IReadOnlyList<SnappfoodWebhookItem> Items);
public record SnappfoodWebhookItem(
string Name,
int Quantity,
decimal UnitPrice);
+210
View File
@@ -0,0 +1,210 @@
using Meezi.Core.Enums;
namespace Meezi.API.Models.Tables;
public record TableDto(
string Id,
string BranchId,
string? SectionId,
string? SectionName,
int SortOrder,
string Number,
int Capacity,
string? Floor,
string QrCode,
string QrCodeUrl,
string? ImageUrl,
string? VideoUrl,
bool IsActive);
public record CreateTableRequest(
string? BranchId,
string Number,
int Capacity = 4,
string? Floor = null,
bool IsActive = true);
public record CreateBranchTableRequest(
string Number,
int Capacity = 4,
string? Floor = null,
string? SectionId = null,
int SortOrder = 0,
bool IsActive = true);
public record PatchTableRequest(
string? Number,
int? Capacity,
string? Floor,
string? BranchId,
string? ImageUrl,
string? VideoUrl,
bool? IsActive,
bool? IsCleaning);
public record PatchBranchTableRequest(
string? Number,
int? Capacity,
string? Floor,
string? SectionId,
int? SortOrder,
string? ImageUrl,
string? VideoUrl,
bool? IsActive,
bool? IsCleaning);
public record TableSectionDto(
string Id,
string BranchId,
string Name,
int SortOrder,
bool IsActive,
int TableCount);
public record CreateTableSectionRequest(string Name, int SortOrder = 0);
public record PatchTableSectionRequest(
string? Name,
int? SortOrder,
bool? IsActive);
public record SetTableCleaningRequest(bool IsCleaning);
public record QrResolveResponse(
string CafeId,
string CafeSlug,
string TableId,
string TableNumber,
string TableName,
string BranchId,
string BranchName,
string CafeName,
string PrimaryColor,
string? LogoUrl,
string WelcomeText,
string? WifiPassword,
string? Address,
bool IsCleaning);
public record TableCurrentOrderSummary(
string OrderId,
OrderStatus Status,
decimal Total,
string? GuestLabel,
OrderSource? Source = null);
public record TableBoardDto(
string Id,
string BranchId,
string? SectionId,
string? SectionName,
int SortOrder,
string Number,
int Capacity,
string? Floor,
string QrCode,
string QrCodeUrl,
string? ImageUrl,
string? VideoUrl,
bool IsActive,
TableBoardStatus Status,
TableCurrentOrderSummary? CurrentOrder,
bool IsCleaning);
public record BranchTableOperationResult<T>(bool Success, T? Data, string? ErrorCode, string? Message);
+30
View File
@@ -0,0 +1,30 @@
namespace Meezi.API.Models.Tap30;
public record Tap30WebhookOrder(
string OrderId,
string VendorId,
Tap30Customer? Customer,
decimal Total,
string? PaymentMethod,
bool? IsPaid,
decimal? Commission,
string? DeliveryType,
int? EstimatedMinutes,
string? DriverName,
string? DriverPhone,
string? Status,
IReadOnlyList<Tap30WebhookItem>? Items);
public record Tap30Customer(
string? Name,
string? Phone,
string? Address,
double? Lat,
double? Lng);
public record Tap30WebhookItem(
string? Sku,
string Name,
int Quantity,
decimal UnitPrice,
string? Notes);
+23
View File
@@ -0,0 +1,23 @@
namespace Meezi.API.Models.Taxes;
public record TaxDto(
string Id,
string Name,
decimal Rate,
bool IsDefault,
bool IsRequired,
bool IsCompound);
public record CreateTaxRequest(
string Name,
decimal Rate,
bool IsDefault = false,
bool IsRequired = true,
bool IsCompound = false);
public record UpdateTaxRequest(
string? Name,
decimal? Rate,
bool? IsDefault,
bool? IsRequired,
bool? IsCompound);