using EntitlementBLL.Payment; using EntitlementDAL.DTOs; using EntitlementDAL.Enums; using GB5Shared.QueryExecutor; namespace EntitlementBLL.Interfaces; public interface ISubscriptionService { Task GetAsync(int clientId, CancellationToken ct); Task SaveAsync(SaveSubscriptionRequest req, CancellationToken ct); Task ChangePlanAsync(int subscriptionId, int newPlanId, int userId, CancellationToken ct); Task RenewAsync(int subscriptionId, DateTime newValidTill, int userId, CancellationToken ct); Task SetStatusAsync(int subscriptionId, SubscriptionStatusEnum status, CancellationToken ct); /// Additive beyond the core 5 signatures — required by Subscription.svc's /// GetList endpoint (paginated, filters status/planId/clientId; -1 on any filter = any). Task> GetListAsync( int subscriptionStatus, int planId, int clientId, int page, int pageSize, CancellationToken ct); // ── Entitlement↔Payment loose coupling (§9.1) ────────────────────────────── /// Creates a PAY order for this subscription's Plan price and records the /// resulting PayOrderId. Throws if the Plan has no PlanPrice set (a real, legitimate /// state for a custom/enterprise plan — "contact sales" — not something to default /// silently), or if PAY already has an active order for this subscription. Task InitiatePaymentAsync(InitiatePaymentRequest req, int userId, CancellationToken ct); /// Full payment history for one client's subscription, newest first — reads /// PAY's own TPAYORDER directly (SourceDocType+SourceDocId), never a local copy. Task> GetPaymentHistoryAsync(int clientId, CancellationToken ct); /// Called by both PayOrderStatusChangedSubscriber and the reconciliation job — /// the one shared place that decides what a PAY order's terminal status means for the /// subscription it belongs to. No-op for non-terminal OrderStatus values (1=Created, /// 2=Pending) — payment is still in flight, nothing to react to yet. Task HandlePaymentOutcomeAsync(int payOrderId, int orderStatus, CancellationToken ct); } public class InitiatePaymentRequest { public int SubscriptionId { get; set; } public string GatewayCode { get; set; } = string.Empty; public string CustomerName { get; set; } = string.Empty; public string CustomerEmail { get; set; } = string.Empty; public string CustomerPhone { get; set; } = string.Empty; public string CallbackUrl { get; set; } = string.Empty; // Legal/Contract Agreement Consent (tracker §51.10) — the AgreementVersionIds the caller was // shown (via Legal/GetApplicableAgreements?AgreementTypeCodes=SUBSCRIPTIONTERMS) and ticked // to accept. Required whenever a real SUBSCRIPTIONTERMS version is currently Published — // InitiatePaymentAsync rejects the call outright if it's missing or stale, since real money // moves as a direct result of this call. Left empty when nothing is currently configured to // require (never silently blocks payment platform-wide over a missing content seed). public int[] AcceptedAgreementVersionIds { get; set; } = Array.Empty(); }