private void CreateEditions() { var defaultEdition = _context.Editions.IgnoreQueryFilters().FirstOrDefault(e => e.Name == EditionManager.DefaultEditionName); if (defaultEdition == null) { defaultEdition = new SubscribableEdition { Name = EditionManager.DefaultEditionName, DisplayName = EditionManager.DefaultEditionName }; _context.Editions.Add(defaultEdition); _context.SaveChanges(); /* Add desired features to the standard edition, if wanted... */ } if (defaultEdition.Id > 0) { CreateFeatureIfNotExists(defaultEdition.Id, AppFeatures.ChatFeature, true); CreateFeatureIfNotExists(defaultEdition.Id, AppFeatures.TenantToTenantChatFeature, true); CreateFeatureIfNotExists(defaultEdition.Id, AppFeatures.TenantToHostChatFeature, true); } }
public async Task Should_Subscribe_To_Edition_As_Trial_If_Trial_Is_Available() { //Arrange var utcNow = Clock.Now.ToUniversalTime(); var trialDayCount = 10; var edition = new SubscribableEdition { DisplayName = "Standard Edition", TrialDayCount = trialDayCount, MonthlyPrice = 9, AnnualPrice = 99 }; await UsingDbContextAsync(async context => { context.SubscribableEditions.Add(edition); await context.SaveChangesAsync(); }); var result = await _tenantRegistrationAppService.RegisterTenant(new RegisterTenantInput { EditionId = edition.Id, AdminEmailAddress = "*****@*****.**", AdminPassword = "******", Name = "Volosoft", SubscriptionStartType = SubscriptionStartType.Trial, TenancyName = "Volosoft" }); //Assert await UsingDbContextAsync(async context => { var tenant = await context.Tenants.FirstOrDefaultAsync(t => t.Id == result.TenantId); tenant.ShouldNotBe(null); tenant.SubscriptionEndDateUtc.ShouldNotBe(null); tenant.SubscriptionEndDateUtc?.Date.ShouldBe(utcNow.Date.AddDays(trialDayCount)); }); }
public async Task<EndSubscriptionResult> EndSubscriptionAsync(Tenant tenant, SubscribableEdition edition, DateTime nowUtc) { if (tenant.EditionId == null || tenant.HasUnlimitedTimeSubscription()) { throw new Exception($"Can not end tenant {tenant.TenancyName} subscription for {edition.DisplayName} tenant has unlimited time subscription!"); } Debug.Assert(tenant.SubscriptionEndDateUtc != null, "tenant.SubscriptionEndDateUtc != null"); var subscriptionEndDateUtc = tenant.SubscriptionEndDateUtc.Value; if (!tenant.IsInTrialPeriod) { subscriptionEndDateUtc = tenant.SubscriptionEndDateUtc.Value.AddDays(edition.WaitingDayAfterExpire ?? 0); } if (subscriptionEndDateUtc >= nowUtc) { throw new Exception($"Can not end tenant {tenant.TenancyName} subscription for {edition.DisplayName} since subscription has not expired yet!"); } if (!tenant.IsInTrialPeriod && edition.ExpiringEditionId.HasValue) { tenant.EditionId = edition.ExpiringEditionId.Value; tenant.SubscriptionEndDateUtc = null; await UpdateAsync(tenant); return EndSubscriptionResult.AssignedToAnotherEdition; } tenant.IsActive = false; tenant.IsInTrialPeriod = false; await UpdateAsync(tenant); return EndSubscriptionResult.TenantSetInActive; }
private void CheckPaymentCache(SubscribableEdition edition, SubscriptionStartType subscriptionStartType, SubscriptionPaymentGatewayType?gateway, string paymentId) { if (edition.IsFree || subscriptionStartType != SubscriptionStartType.Paid) { return; } if (!gateway.HasValue) { throw new Exception("Gateway cannot be empty !"); } if (paymentId.IsNullOrEmpty()) { throw new Exception("PaymentId cannot be empty !"); } var paymentCacheItem = _paymentCache.GetCacheItemOrNull(gateway.Value, paymentId); if (paymentCacheItem == null) { throw new UserFriendlyException(L("PaymentMightBeExpiredWarning")); } }
public void Calculate_Upgrade_To_Edition_Price(int remainingDaysCount, decimal upgradePrice) { var currentEdition = new SubscribableEdition() { DisplayName = "Standard", Name = "Standard", AnnualPrice = (int)PaymentPeriodType.Annual, MonthlyPrice = (int)PaymentPeriodType.Monthly }; var targetEdition = new SubscribableEdition() { DisplayName = "Premium", Name = "Premium", AnnualPrice = (int)PaymentPeriodType.Annual * 2, MonthlyPrice = (int)PaymentPeriodType.Monthly * 2 }; decimal price; price = _tenantManager.GetUpgradePrice(currentEdition, targetEdition, remainingDaysCount); price.ShouldBe(upgradePrice); }
public async Task Should_Get_Daily_Income_Statistics_Data_For_Missing_Days() { var now = DateTime.Now; var utcNow = DateTime.Now.ToUniversalTime(); //Arrange UsingDbContext( context => { var specialEdition = new SubscribableEdition { Name = "Special Edition", DisplayName = "Special", AnnualPrice = 100, MonthlyPrice = 10, TrialDayCount = 30, WaitingDayAfterExpire = 10 }; context.SubscribableEditions.Add(specialEdition); context.SaveChanges(); context.SubscriptionPayments.Add(new SubscriptionPayment { Amount = 100, DayCount = 365, Status = SubscriptionPaymentStatus.Completed, EditionId = specialEdition.Id, CreationTime = now.AddDays(-3), TenantId = 1 }); context.SubscriptionPayments.Add(new SubscriptionPayment { Amount = 200, DayCount = 365, Status = SubscriptionPaymentStatus.Completed, EditionId = specialEdition.Id, CreationTime = now.AddDays(-3), TenantId = 1 }); context.SubscriptionPayments.Add(new SubscriptionPayment { Amount = 200, DayCount = 730, Status = SubscriptionPaymentStatus.Completed, EditionId = specialEdition.Id, CreationTime = now.AddDays(-1), TenantId = 1 }); context.Tenants.Add(new Tenant("MyTenant", "My Tenant") { SubscriptionEndDateUtc = utcNow.AddDays(1), CreationTime = now.AddMinutes(-1) }); }); //Act var output = await _hostDashboardService.GetDashboardStatisticsData(new GetDashboardDataInput { StartDate = now.AddDays(-4), EndDate = now, IncomeStatisticsDateInterval = ChartDateInterval.Daily }); output.IncomeStatistics.Count.ShouldBe(5); output.IncomeStatistics[0].Amount.ShouldBe(0); output.IncomeStatistics[1].Amount.ShouldBe(300); output.IncomeStatistics[2].Amount.ShouldBe(0); output.IncomeStatistics[3].Amount.ShouldBe(200); output.IncomeStatistics[4].Amount.ShouldBe(0); }
public async Task Should_Get_Edition_Statistics() { var now = DateTime.Now; var utcNow = DateTime.Now.ToUniversalTime(); //Arrange UsingDbContext( context => { context.SubscribableEditions.RemoveRange(context.SubscribableEditions); var newSpecialEdition = new SubscribableEdition { DisplayName = "Special Edition" }; context.SubscribableEditions.Add(newSpecialEdition); var newPremiumEdition = new SubscribableEdition { DisplayName = "Premium Edition" }; context.SubscribableEditions.Add(newPremiumEdition); context.SaveChanges(); context.Tenants.Add(new Tenant("SpecialEditionTenant", "Special Tenant") { CreationTime = now.AddDays(-1), SubscriptionEndDateUtc = utcNow.AddDays(1), EditionId = newSpecialEdition.Id }); context.Tenants.Add(new Tenant("PremiumEditionTenant", "Premium Tenant") { SubscriptionEndDateUtc = utcNow.AddDays(1), CreationTime = now.AddDays(-1), EditionId = newPremiumEdition.Id }); }); //Act var output = await _hostDashboardService.GetEditionTenantStatistics(new GetEditionTenantStatisticsInput { StartDate = now.AddDays(-1), EndDate = now }); output.EditionStatistics.Count.ShouldBe(2); output.EditionStatistics.Any(e => e.Label == "Special Edition").ShouldBe(true); var specialEdition = output.EditionStatistics.FirstOrDefault(e => e.Label == "Special Edition"); specialEdition.ShouldNotBe(null); specialEdition.Value.ShouldBe(1); var hasPremiumEdition = output.EditionStatistics.Any(e => e.Label == "Premium Edition"); hasPremiumEdition.ShouldBe(true); var premiumEdition = output.EditionStatistics.FirstOrDefault(e => e.Label == "Premium Edition"); premiumEdition.ShouldNotBe(null); premiumEdition.Value.ShouldBe(1); }
public async Task Should_Get_Dashboard_Statistics_Data() { var now = DateTime.Now; var utcNow = DateTime.Now.ToUniversalTime(); //Arrange UsingDbContext( context => { var specialEdition = new SubscribableEdition { Name = "Special Edition", DisplayName = "Special", AnnualPrice = 100, MonthlyPrice = 10, TrialDayCount = 30, WaitingDayAfterExpire = 10 }; context.SubscribableEditions.Add(specialEdition); context.SaveChanges(); CreatePaidPayment(context, new SubscriptionPayment { Amount = 100, DayCount = 365, EditionId = specialEdition.Id, CreationTime = now.AddDays(-2), TenantId = 1 }); CreatePaidPayment(context, new SubscriptionPayment { Amount = 200, DayCount = 730, EditionId = specialEdition.Id, CreationTime = now.AddDays(-1), TenantId = 1 }); context.Tenants.Add(new Tenant("MyTenant", "My Tenant") { SubscriptionEndDateUtc = utcNow.AddDays(1), CreationTime = now.AddMinutes(-1) }); }); //Act var output = await _hostDashboardService.GetDashboardStatisticsData(new GetDashboardDataInput { StartDate = now.AddDays(-3), EndDate = now, IncomeStatisticsDateInterval = ChartDateInterval.Daily }); output.NewSubscriptionAmount.ShouldBe(300); output.NewTenantsCount.ShouldBe(2); output.IncomeStatistics.Count.ShouldBe(4); output.IncomeStatistics.Sum(x => x.Amount).ShouldBe(300); output.EditionStatistics.Count.ShouldBe(1); output.ExpiringTenants.Count.ShouldBe(1); output.ExpiringTenants.First().RemainingDayCount.ShouldBe(1); output.RecentTenants.Count.ShouldBe(2); }
private static decimal GetAnnualCalculatedPrice(SubscribableEdition currentEdition, SubscribableEdition upgradeEdition, int remainingYearsCount) { var currentUnusedPrice = (currentEdition.AnnualPrice ?? 0) * remainingYearsCount; var upgradeUnusedPrice = (upgradeEdition.AnnualPrice ?? 0) * remainingYearsCount; var additionalPrice = upgradeUnusedPrice - currentUnusedPrice; return(additionalPrice); }
private static decimal GetMonthlyCalculatedPrice(SubscribableEdition currentEdition, SubscribableEdition upgradeEdition, int remainingDaysCount) { decimal currentUnusedPrice = 0; decimal upgradeUnusedPrice = 0; if (currentEdition.MonthlyPrice.HasValue) { currentUnusedPrice = (currentEdition.MonthlyPrice.Value / (int)PaymentPeriodType.Monthly) * remainingDaysCount; } if (upgradeEdition.MonthlyPrice.HasValue) { upgradeUnusedPrice = (upgradeEdition.MonthlyPrice.Value / (int)PaymentPeriodType.Monthly) * remainingDaysCount; } var additionalPrice = upgradeUnusedPrice - currentUnusedPrice; return(additionalPrice); }
private static decimal GetAnnualCalculatedPrice(SubscribableEdition currentEdition, SubscribableEdition upgradeEdition, int remainingYearsCount) { if (!currentEdition.AnnualPrice.HasValue) { throw new Exception("AnnualPrice is null for edition: " + currentEdition.DisplayName); } if (!upgradeEdition.AnnualPrice.HasValue) { throw new Exception("AnnualPrice is null for edition: " + upgradeEdition.DisplayName); } var currentUnusedPrice = currentEdition.AnnualPrice.Value * remainingYearsCount; var upgradeUnusedPrice = upgradeEdition.AnnualPrice.Value * remainingYearsCount; var additionalPrice = upgradeUnusedPrice - currentUnusedPrice; return(additionalPrice); }
private static decimal GetMonthlyCalculatedPrice(SubscribableEdition currentEdition, SubscribableEdition upgradeEdition, int remainingDaysCount) { if (!currentEdition.MonthlyPrice.HasValue) { throw new Exception("MonthlyPrice is null for edition: " + currentEdition.DisplayName); } if (!upgradeEdition.MonthlyPrice.HasValue) { throw new Exception("MonthlyPrice is null for edition: " + upgradeEdition.DisplayName); } var currentUnusedPrice = (currentEdition.MonthlyPrice.Value / (int)PaymentPeriodType.Monthly) * remainingDaysCount; var upgradeUnusedPrice = (upgradeEdition.MonthlyPrice.Value / (int)PaymentPeriodType.Monthly) * remainingDaysCount; var additionalPrice = upgradeUnusedPrice - currentUnusedPrice; return(additionalPrice); }
private async Task <EditionWithFeaturesForSelectDto> CreateEditionWithFeaturesDto(SubscribableEdition edition, Dictionary <string, Feature> featureDictionary) { var editionWithFeatures = new EditionWithFeaturesForSelectDto { Edition = ObjectMapper.Map <EditionSelectDto>(edition), FeatureValues = await GetFeatureValues(edition, featureDictionary) }; foreach (var paymentGateway in Enum.GetValues(typeof(SubscriptionPaymentGatewayType)).Cast <SubscriptionPaymentGatewayType>()) { var paymentGatewayManager = _paymentGatewayProviderFactory.Create(paymentGateway); var additionalData = await paymentGatewayManager.GetAdditionalPaymentData(edition); editionWithFeatures.Edition.AdditionalData.Add(paymentGateway, additionalData); } return(editionWithFeatures); }
public Task <Dictionary <string, string> > GetAdditionalPaymentData(SubscribableEdition edition) { Dictionary <string, string> additionalData = new Dictionary <string, string>(); return(Task.FromResult(additionalData)); }