Implement billing functionality and enhance role management
- Introduced billing capabilities, allowing users to request payments for subscription periods (3/6/12 months) with admin approval via Telegram. - Updated role management to include a `BillingEnabled` property, preventing billing for admin roles. - Enhanced the `CreateRoleCommand` and `UpdateRoleCommand` to accept billing parameters, ensuring proper handling during role creation and updates. - Added new endpoints for billing management and integrated billing checks into VPN config creation to enforce payment requirements. - Updated related services, models, and tests to support the new billing features, ensuring comprehensive coverage and functionality. - Enhanced documentation to reflect the new billing processes and role management changes.
This commit is contained in:
@@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using PnvPanel.Domain.Activation;
|
||||
using PnvPanel.Domain.Apps;
|
||||
using PnvPanel.Domain.Audit;
|
||||
using PnvPanel.Domain.Billing;
|
||||
using PnvPanel.Domain.Configs;
|
||||
using PnvPanel.Domain.Inbounds;
|
||||
using PnvPanel.Domain.Instructions;
|
||||
@@ -48,6 +49,10 @@ public interface IAppDbContext
|
||||
|
||||
DbSet<PricingSettings> PricingSettings { get; }
|
||||
|
||||
DbSet<BillingSettings> BillingSettings { get; }
|
||||
|
||||
DbSet<PaymentRequest> PaymentRequests { get; }
|
||||
|
||||
/// <summary>Нужен для advisory-lock при проверке квоты конфигов (см. CreateVpnConfigCommandHandler).</summary>
|
||||
DatabaseFacade Database { get; }
|
||||
|
||||
|
||||
@@ -13,7 +13,19 @@ public sealed record CurrentUserProfile(
|
||||
bool IsBlocked,
|
||||
int MaxConfigs,
|
||||
int MaxIpLimit,
|
||||
string SubscriptionToken
|
||||
string SubscriptionToken,
|
||||
bool BillingEnabled,
|
||||
DateTimeOffset? BillingPaidUntil,
|
||||
bool BillingSuspended
|
||||
);
|
||||
|
||||
/// <summary>Срез биллинг-полей пользователя — для фоновой джобы приостановки (см. BillingService),
|
||||
/// не требует полного CurrentUserProfile (роль/квоты там не нужны).</summary>
|
||||
public sealed record BillingUserDto(
|
||||
Guid UserId,
|
||||
DateTimeOffset? PaidUntil,
|
||||
bool Suspended,
|
||||
DateTimeOffset? LastWarnedForPaidUntil
|
||||
);
|
||||
|
||||
public sealed record UserSummaryDto(
|
||||
@@ -135,4 +147,27 @@ public interface IIdentityService
|
||||
Guid exceptUserId,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
|
||||
/// <summary>Пользователи с billing-ролью (role.BillingEnabled), не заблокированные — обход для
|
||||
/// BillingService (приостановка за неуплату / предупреждения).</summary>
|
||||
Task<IReadOnlyList<BillingUserDto>> ListBillingUsersAsync(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Гасит конфиги за неуплату на уровне пользователя (BillingSuspended=true) — сами
|
||||
/// конфиги гасит вызывающая сторона (см. BillingService, по образцу BlockUserCommandHandler).</summary>
|
||||
Task<Result> SuspendBillingAsync(Guid userId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Продлевает оплаченный период, снимает приостановку и сбрасывает флаг "предупреждение
|
||||
/// отправлено" (новый срок ещё не близко к истечению). Используется и при подтверждении оплаты,
|
||||
/// и при первичной выдаче грейс-периода.</summary>
|
||||
Task<Result> ExtendBillingPaidUntilAsync(
|
||||
Guid userId,
|
||||
DateTimeOffset paidUntil,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
|
||||
Task<Result> MarkBillingWarningSentAsync(
|
||||
Guid userId,
|
||||
DateTimeOffset paidUntil,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,14 @@ using PnvPanel.Application.Common.Models;
|
||||
|
||||
namespace PnvPanel.Application.Common.Interfaces;
|
||||
|
||||
public sealed record RoleDto(Guid Id, string Name, int MaxConfigs, int MaxIpLimit, bool IsSystem);
|
||||
public sealed record RoleDto(
|
||||
Guid Id,
|
||||
string Name,
|
||||
int MaxConfigs,
|
||||
int MaxIpLimit,
|
||||
bool IsSystem,
|
||||
bool BillingEnabled
|
||||
);
|
||||
|
||||
public interface IRoleService
|
||||
{
|
||||
@@ -10,6 +17,7 @@ public interface IRoleService
|
||||
string name,
|
||||
int maxConfigs,
|
||||
int maxIpLimit,
|
||||
bool billingEnabled,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
|
||||
@@ -17,6 +25,7 @@ public interface IRoleService
|
||||
Guid roleId,
|
||||
int maxConfigs,
|
||||
int maxIpLimit,
|
||||
bool billingEnabled,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using PnvPanel.Domain.Billing;
|
||||
using PnvPanel.Domain.Support;
|
||||
|
||||
namespace PnvPanel.Application.Common.Interfaces;
|
||||
@@ -51,4 +52,14 @@ public interface ITelegramNotifier
|
||||
TicketType type,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
|
||||
/// <summary>Пользователь нажал «Я оплатил» — инлайн-кнопки «Подтвердить/Отклонить», решается
|
||||
/// полностью в Telegram (аналогично заявке на роль).</summary>
|
||||
Task NotifyAdminsPaymentRequestedAsync(
|
||||
Guid requestId,
|
||||
string userName,
|
||||
PaymentPeriod period,
|
||||
int amount,
|
||||
CancellationToken cancellationToken
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user