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,9 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
/// <summary>Optional branch scope from JWT (staff terminal / POS session).</summary>
|
||||
public interface IBranchContext
|
||||
{
|
||||
string? CafeId { get; }
|
||||
string? BranchId { get; }
|
||||
bool HasBranch { get; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public interface IPlatformRuntimeConfig
|
||||
{
|
||||
Task<string?> GetAsync(string key, CancellationToken cancellationToken = default);
|
||||
Task<IReadOnlyDictionary<string, string>> GetByPrefixAsync(string prefix, CancellationToken cancellationToken = default);
|
||||
void InvalidateCache();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public interface ISmsService
|
||||
{
|
||||
Task SendOtpAsync(string phone, string otp, CancellationToken cancellationToken = default);
|
||||
Task SendMessageAsync(string phone, string message, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public record SnappPayInitResult(bool Success, string? PaymentToken, string? PaymentUrl, string? ErrorMessage);
|
||||
|
||||
public record SnappPayVerifyResult(bool Success, string? RefId, string? ErrorMessage);
|
||||
|
||||
public interface ISnappPayGateway
|
||||
{
|
||||
Task<bool> IsEnabledAsync(CancellationToken cancellationToken = default);
|
||||
Task<SnappPayInitResult> RequestPaymentAsync(
|
||||
long amountRials,
|
||||
string transactionId,
|
||||
string returnUrl,
|
||||
CancellationToken cancellationToken = default);
|
||||
Task<SnappPayVerifyResult> VerifyAndSettleAsync(
|
||||
string paymentToken,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public interface ISnappfoodClient
|
||||
{
|
||||
Task AcknowledgeOrderAsync(string snappfoodOrderId, CancellationToken cancellationToken = default);
|
||||
Task NotifyOrderDeliveredAsync(string snappfoodOrderId, CancellationToken cancellationToken = default);
|
||||
Task NotifyOrderStatusAsync(
|
||||
string snappfoodOrderId,
|
||||
string status,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public interface ITap30Client
|
||||
{
|
||||
Task AcknowledgeOrderAsync(string tap30OrderId, CancellationToken cancellationToken = default);
|
||||
Task NotifyOrderStatusAsync(
|
||||
string tap30OrderId,
|
||||
string status,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public record TaraInitResult(bool Success, string? TraceNumber, string? PaymentUrl, string? ErrorMessage);
|
||||
|
||||
public record TaraVerifyResult(bool Success, string? RefId, string? ErrorMessage);
|
||||
|
||||
public interface ITaraPaymentGateway
|
||||
{
|
||||
Task<bool> IsEnabledAsync(CancellationToken cancellationToken = default);
|
||||
Task<TaraInitResult> RequestPaymentAsync(
|
||||
long amountRials,
|
||||
string invoiceNumber,
|
||||
string callbackUrl,
|
||||
CancellationToken cancellationToken = default);
|
||||
Task<TaraVerifyResult> VerifyPaymentAsync(
|
||||
string traceNumber,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public record TarazSubmitResult(bool Success, string? TrackingCode, string? Message);
|
||||
|
||||
public interface ITarazTaxService
|
||||
{
|
||||
Task<TarazSubmitResult> SubmitDailyInvoicesAsync(string cafeId, DateTime dateUtc, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Meezi.Core.Enums;
|
||||
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public interface ITenantContext
|
||||
{
|
||||
string? UserId { get; }
|
||||
string? CafeId { get; }
|
||||
EmployeeRole? Role { get; }
|
||||
PlanTier? PlanTier { get; }
|
||||
string? Language { get; }
|
||||
/// <summary>Active branch from JWT when employee is branch-scoped.</summary>
|
||||
string? BranchId { get; }
|
||||
bool IsSystemAdmin { get; }
|
||||
bool IsAuthenticated { get; }
|
||||
bool IsCafeOwner => Role == EmployeeRole.Owner;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public interface IWebsiteService
|
||||
{
|
||||
Task<(IReadOnlyList<object> Posts, int Total)> GetPostsAsync(
|
||||
string locale, int page, int limit, CancellationToken ct = default);
|
||||
Task<object?> GetPostAsync(string slug, string locale, CancellationToken ct = default);
|
||||
Task<IReadOnlyList<object>> GetCommentsAsync(string slug, CancellationToken ct = default);
|
||||
Task<object> AddCommentAsync(string slug, string authorName, string? email,
|
||||
string content, string? ip, CancellationToken ct = default);
|
||||
Task<object> CreateDemoRequestAsync(string contactName, string businessName,
|
||||
string phone, string? email, string branchCount, string? notes, string source,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Meezi.Core.Interfaces;
|
||||
|
||||
public record ZarinPalRequestResult(bool Success, string? Authority, string? PaymentUrl, string? ErrorMessage);
|
||||
|
||||
public record ZarinPalVerifyResult(bool Success, string? RefId, string? ErrorMessage);
|
||||
|
||||
public interface IZarinPalGateway
|
||||
{
|
||||
Task<bool> IsEnabledAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
Task<ZarinPalRequestResult> RequestPaymentAsync(
|
||||
long amountRials,
|
||||
string description,
|
||||
string callbackUrl,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<ZarinPalVerifyResult> VerifyPaymentAsync(
|
||||
string authority,
|
||||
long amountRials,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
Reference in New Issue
Block a user