コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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));
            });
        }
コード例 #3
0
        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;
        }
コード例 #4
0
        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"));
            }
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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);
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        public Task <Dictionary <string, string> > GetAdditionalPaymentData(SubscribableEdition edition)
        {
            Dictionary <string, string> additionalData = new Dictionary <string, string>();

            return(Task.FromResult(additionalData));
        }