using PnvPanel.Domain.Billing; using PnvPanel.Domain.Pricing; using Xunit; namespace PnvPanel.Domain.Tests.Billing; public class RoleChangeTopUpTests { private static readonly DateTimeOffset Now = new(2026, 1, 1, 0, 0, 0, TimeSpan.Zero); [Fact] public void Compute_WhenNewRoleCheaper_ReturnsNull() { var amount = RoleChangeTopUp.Compute( pricePerConfigPerMonth: 200, oldMaxConfigs: 10, newMaxConfigs: 3, discountTiers: [], paidUntil: Now.AddDays(30), now: Now ); Assert.Null(amount); } [Fact] public void Compute_WhenPaidUntilAlreadyExpired_ReturnsNull() { var amount = RoleChangeTopUp.Compute( pricePerConfigPerMonth: 200, oldMaxConfigs: 3, newMaxConfigs: 10, discountTiers: [], paidUntil: Now.AddDays(-1), now: Now ); Assert.Null(amount); } [Fact] public void Compute_WhenEitherRoleUnlimited_ReturnsNull() { var amount = RoleChangeTopUp.Compute( pricePerConfigPerMonth: 200, oldMaxConfigs: 3, newMaxConfigs: -1, discountTiers: [], paidUntil: Now.AddDays(30), now: Now ); Assert.Null(amount); } [Fact] public void Compute_WhenUpgrading_ReturnsProratedDifference() { // Старая роль: 200 * 3 = 600 ₽/мес. Новая: 200 * 10 = 2000 ₽/мес. Разница 1400 ₽/мес, // за 30 дней (ровно месяц) — 1400 ₽. var amount = RoleChangeTopUp.Compute( pricePerConfigPerMonth: 200, oldMaxConfigs: 3, newMaxConfigs: 10, discountTiers: [], paidUntil: Now.AddDays(30), now: Now ); Assert.Equal(1400, amount); } [Fact] public void Compute_ProratesToRemainingDaysOnly() { // Та же разница 1400 ₽/мес, но остаётся только 15 из 30 дней — половина. var amount = RoleChangeTopUp.Compute( pricePerConfigPerMonth: 200, oldMaxConfigs: 3, newMaxConfigs: 10, discountTiers: [], paidUntil: Now.AddDays(15), now: Now ); Assert.Equal(700, amount); } [Fact] public void Compute_AppliesDiscountTiersToBothRoles() { var tiers = new[] { PricingDiscountTier.Create(Guid.NewGuid(), minConfigs: 10, discountPercent: 10) }; // Старая роль (3 конфига, без скидки): 200*3 = 600. Новая (10 конфигов, порог скидки достигнут): // 200*10 = 2000, -10% = 1800. Разница 1200 ₽/мес, за 30 дней — 1200 ₽. var amount = RoleChangeTopUp.Compute( pricePerConfigPerMonth: 200, oldMaxConfigs: 3, newMaxConfigs: 10, discountTiers: tiers, paidUntil: Now.AddDays(30), now: Now ); Assert.Equal(1200, amount); } }