示例#1
0
        public static SubscriptionPayment Buy(
            PayerId payerId,
            SubscriptionPeriod period,
            string countryCode,
            MoneyValue priceOffer,
            PriceList priceList)
        {
            var priceInPriceList = priceList.GetPrice(countryCode, period, PriceListItemCategory.New);

            CheckRule(new PriceOfferMustMatchPriceInPriceListRule(priceOffer, priceInPriceList));

            var subscriptionPayment = new SubscriptionPayment();

            var subscriptionPaymentCreated = new SubscriptionPaymentCreatedDomainEvent(
                Guid.NewGuid(),
                payerId.Value,
                period.Code,
                countryCode,
                SubscriptionPaymentStatus.WaitingForPayment.Code,
                priceOffer.Value,
                priceOffer.Currency);

            subscriptionPayment.Apply(subscriptionPaymentCreated);
            subscriptionPayment.AddDomainEvent(subscriptionPaymentCreated);

            return(subscriptionPayment);
        }
 private void When(PriceListItemAttributesChangedDomainEvent @event)
 {
     this._countryCode        = @event.CountryCode;
     this._subscriptionPeriod = SubscriptionPeriod.Of(@event.SubscriptionPeriodCode);
     this._category           = PriceListItemCategory.Of(@event.CategoryCode);
     this._price = MoneyValue.Of(@event.Price, @event.Currency);
 }
        public async Task <Guid> Handle(BuySubscriptionRenewalCommand command, CancellationToken cancellationToken)
        {
            var priceList = await PriceListProvider.GetPriceList(_sqlConnectionFactory.GetOpenConnection());

            var subscriptionId = new SubscriptionId(command.SubscriptionId);

            var subscription = await _aggregateStore.Load(new SubscriptionId(command.SubscriptionId));

            if (subscription == null)
            {
                throw new InvalidCommandException(new List <string> {
                    "Subscription for renewal must exist."
                });
            }

            var subscriptionRenewalPayment = SubscriptionRenewalPayment.Buy(
                _payerContext.PayerId,
                subscriptionId,
                SubscriptionPeriod.Of(command.SubscriptionTypeCode),
                command.CountryCode,
                MoneyValue.Of(command.Value, command.Currency),
                priceList);

            _aggregateStore.AppendChanges(subscriptionRenewalPayment);

            return(subscriptionRenewalPayment.Id);
        }
示例#4
0
        public MoneyValue GetPrice(string countryCode, SubscriptionPeriod subscriptionPeriod, PriceListItemCategory category)
        {
            var priceListItem = _items.Single(x =>
                                              x.CountryCode == countryCode && x.SubscriptionPeriod == subscriptionPeriod &&
                                              x.Category == category);

            return(priceListItem.Value - _discountValue);
        }
 private void When(PriceListItemCreatedDomainEvent @event)
 {
     this.Id             = @event.PriceListItemId;
     _countryCode        = @event.CountryCode;
     _subscriptionPeriod = SubscriptionPeriod.Of(@event.SubscriptionPeriodCode);
     _category           = PriceListItemCategory.Of(@event.CategoryCode);
     _price    = MoneyValue.Of(@event.Price, @event.Currency);
     _isActive = true;
 }
示例#6
0
 public PriceForSubscriptionMustBeDefined(
     string countryCode,
     SubscriptionPeriod subscriptionPeriod,
     IList <PriceListItemData> priceListItems)
 {
     _countryCode        = countryCode;
     _subscriptionPeriod = subscriptionPeriod;
     _priceListItems     = priceListItems;
 }
示例#7
0
 private void When(SubscriptionPaymentCreatedDomainEvent @event)
 {
     this.Id                    = @event.SubscriptionPaymentId;
     _payerId                   = new PayerId(@event.PayerId);
     _subscriptionPeriod        = SubscriptionPeriod.Of(@event.SubscriptionPeriodCode);
     _countryCode               = @event.CountryCode;
     _subscriptionPaymentStatus = SubscriptionPaymentStatus.Of(@event.Status);
     _value = MoneyValue.Of(@event.Value, @event.Currency);
 }
示例#8
0
        public MoneyValue GetPrice(
            string countryCode,
            SubscriptionPeriod subscriptionPeriod,
            PriceListItemCategory category)
        {
            CheckRule(new PriceForSubscriptionMustBeDefinedRule(countryCode, subscriptionPeriod, _items, category));

            return(_pricingStrategy.GetPrice(countryCode, subscriptionPeriod, category));
        }
 public SubscriptionRenewalPaymentSnapshot(
     SubscriptionRenewalPaymentId id,
     PayerId payerId,
     SubscriptionPeriod subscriptionPeriod,
     string countryCode)
 {
     PayerId            = payerId;
     SubscriptionPeriod = subscriptionPeriod;
     CountryCode        = countryCode;
     Id = id;
 }
 public PriceForSubscriptionMustBeDefinedRule(
     string countryCode,
     SubscriptionPeriod subscriptionPeriod,
     IList <PriceListItemData> priceListItems,
     PriceListItemCategory category)
 {
     _countryCode        = countryCode;
     _subscriptionPeriod = subscriptionPeriod;
     _priceListItems     = priceListItems;
     _category           = category;
 }
        public void ChangeAttributes(
            string countryCode,
            SubscriptionPeriod subscriptionPeriod,
            PriceListItemCategory category,
            MoneyValue price)
        {
            var priceListItemChangedDomainEvent = new PriceListItemAttributesChangedDomainEvent(this.Id, countryCode, subscriptionPeriod.Code, category.Code, price.Value, price.Currency);

            this.Apply(priceListItemChangedDomainEvent);
            this.AddDomainEvent(priceListItemChangedDomainEvent);
        }
 public PriceListItemData(
     string countryCode,
     SubscriptionPeriod subscriptionPeriod,
     MoneyValue value,
     PriceListItemCategory category)
 {
     CountryCode        = countryCode;
     Value              = value;
     Category           = category;
     SubscriptionPeriod = subscriptionPeriod;
 }
        public Task <Guid> Handle(CreatePriceListItemCommand command, CancellationToken cancellationToken)
        {
            var priceListItem = PriceListItem.Create(
                command.CountryCode,
                SubscriptionPeriod.Of(command.SubscriptionPeriodCode),
                PriceListItemCategory.Of(command.CategoryCode),
                MoneyValue.Of(command.PriceValue, command.PriceCurrency));

            _aggregateStore.AppendChanges(priceListItem);

            return(Task.FromResult(priceListItem.Id));
        }
        public MoneyValue GetPrice(
            string countryCode,
            SubscriptionPeriod subscriptionPeriod,
            PriceListItemCategory category)
        {
            CheckRule(new PriceForSubscriptionMustBeDefined(countryCode, subscriptionPeriod, _items, category));

            var priceListItem = _items.Single(x =>
                                              x.CountryCode == countryCode && x.SubscriptionPeriod == subscriptionPeriod &&
                                              x.Category == category);

            return(priceListItem.Value);
        }
        public async Task <Unit> Handle(ChangePriceListItemAttributesCommand command, CancellationToken cancellationToken)
        {
            var priceListItem = await _aggregateStore.Load(new PriceListItemId(command.PriceListItemId));

            priceListItem.ChangeAttributes(
                command.CountryCode,
                SubscriptionPeriod.Of(command.SubscriptionPeriodCode),
                PriceListItemCategory.Of(command.CategoryCode),
                MoneyValue.Of(command.PriceValue, command.PriceCurrency));

            _aggregateStore.AppendChanges(priceListItem);
            return(Unit.Value);
        }
        public void CalculateForNew_WhenPeriodHalfYearIsSelected_Test()
        {
            // Arrange
            SubscriptionPeriod period = SubscriptionPeriod.HalfYear;

            SystemClock.Set(new DateTime(2020, 5, 11));

            // Act
            DateTime expirationDate = SubscriptionDateExpirationCalculator.CalculateForNew(period);

            // Assert
            Assert.That(expirationDate, Is.EqualTo(new DateTime(2020, 11, 11)));
        }
        public static async Task <PriceList> GetPriceList(IDbConnection connection)
        {
            var priceListItemList = await GetPriceListItems(connection);

            return(PriceList.CreateFromItems(
                       priceListItemList
                       .Select(x =>
                               new PriceListItemData(
                                   x.CountryCode,
                                   SubscriptionPeriod.Of(x.SubscriptionPeriodCode),
                                   MoneyValue.Of(x.MoneyValue, x.MoneyCurrency),
                                   PriceListItemCategory.Of(x.CategoryCode)))
                       .ToList()));
        }
        public void CalculateForRenewal_WhenPeriodMonthIsSelected_AndExpireDatePassed_ThenMonthsAreAddedToNow()
        {
            // Arrange
            SubscriptionPeriod period = SubscriptionPeriod.Month;

            SystemClock.Set(new DateTime(2020, 5, 11));
            DateTime expirationDate = new DateTime(2020, 4, 1);

            // Act
            expirationDate = SubscriptionDateExpirationCalculator.CalculateForRenewal(expirationDate, period);

            // Assert
            Assert.That(expirationDate, Is.EqualTo(new DateTime(2020, 6, 11)));
        }
        public async Task <Guid> Handle(BuySubscriptionCommand command, CancellationToken cancellationToken)
        {
            var priceList = await PriceListProvider.GetPriceList(_sqlConnectionFactory.GetOpenConnection());

            var subscription = SubscriptionPayment.Buy(
                _payerContext.PayerId,
                SubscriptionPeriod.Of(command.SubscriptionTypeCode),
                command.CountryCode,
                MoneyValue.Of(command.Value, command.Currency),
                priceList);

            _aggregateStore.AppendChanges(subscription);

            return(subscription.Id);
        }
示例#20
0
        private PeriodType ToPeriodType(SubscriptionPeriod periodType)
        {
            switch (periodType)
            {
            case SubscriptionPeriod.Monthly:
                return(PeriodType.Month);

            case SubscriptionPeriod.Daily:
                return(PeriodType.Day);

            case SubscriptionPeriod.Yearly:
                return(PeriodType.Year);

            default: throw new InvalidOperationException($"Can't convert {nameof(SubscriptionPeriod)} to {nameof(PeriodType)}");
            }
        }
示例#21
0
        private async Task When(SubscriptionCreatedDomainEvent subscriptionCreated)
        {
            var period = SubscriptionPeriod.GetName(subscriptionCreated.SubscriptionPeriodCode);

            await _connection.ExecuteScalarAsync("INSERT INTO payments.SubscriptionDetails " +
                                                 "([Id], [Period], [Status], [CountryCode], [ExpirationDate]) " +
                                                 "VALUES (@SubscriptionId, @Period, @Status, @CountryCode, @ExpirationDate)",
                                                 new
            {
                subscriptionCreated.SubscriptionId,
                period,
                subscriptionCreated.Status,
                subscriptionCreated.CountryCode,
                subscriptionCreated.ExpirationDate
            });
        }
示例#22
0
        private async Task When(SubscriptionRenewedDomainEvent subscriptionRenewed)
        {
            var period = SubscriptionPeriod.GetName(subscriptionRenewed.SubscriptionPeriodCode);

            await _connection.ExecuteScalarAsync("UPDATE payments.SubscriptionDetails " +
                                                 "SET " +
                                                 "[Status] = @Status, " +
                                                 "[ExpirationDate] = @ExpirationDate, " +
                                                 "[Period] = @Period " +
                                                 "WHERE [Id] = @SubscriptionId",
                                                 new
            {
                subscriptionRenewed.SubscriptionId,
                subscriptionRenewed.Status,
                subscriptionRenewed.ExpirationDate,
                period
            });
        }
        public async Task <Unit> Handle(ChangePriceListItemAttributesCommand command, CancellationToken cancellationToken)
        {
            var priceListItem = await _aggregateStore.Load(new PriceListItemId(command.PriceListItemId));

            if (priceListItem == null)
            {
                throw new InvalidCommandException(new List <string> {
                    "Pricelist item for changing must exist."
                });
            }

            priceListItem.ChangeAttributes(
                command.CountryCode,
                SubscriptionPeriod.Of(command.SubscriptionPeriodCode),
                PriceListItemCategory.Of(command.CategoryCode),
                MoneyValue.Of(command.PriceValue, command.PriceCurrency));

            _aggregateStore.AppendChanges(priceListItem);
            return(Unit.Value);
        }
        public static async Task <PriceList> CreatePriceList(IDbConnection connection)
        {
            var priceListItemList = await GetPriceListItems(connection);

            var priceListItems = priceListItemList
                                 .Select(x =>
                                         new PriceListItemData(
                                             x.CountryCode,
                                             SubscriptionPeriod.Of(x.SubscriptionPeriodCode),
                                             MoneyValue.Of(x.MoneyValue, x.MoneyCurrency),
                                             PriceListItemCategory.Of(x.CategoryCode)))
                                 .ToList();

            // This is place for selecting pricing strategy based on provided data and the system state.
            IPricingStrategy pricingStrategy = new DirectValueFromPriceListPricingStrategy(priceListItems);

            return(PriceList.Create(
                       priceListItems,
                       pricingStrategy));
        }
示例#25
0
        private async Task When(SubscriptionPaymentCreatedDomainEvent subscriptionPaymentCreated)
        {
            string period = SubscriptionPeriod.GetName(subscriptionPaymentCreated.SubscriptionPeriodCode);

            await _connection.ExecuteScalarAsync(
                "INSERT INTO payments.SubscriptionPayments " +
                "([PaymentId], [PayerId], [Type], [Status], [Period], [Date], " +
                "[SubscriptionId], [MoneyValue], [MoneyCurrency]) " +
                "VALUES (@SubscriptionPaymentId, @PayerId, @Type, @Status, @Period, " +
                "@OccurredOn, NULL, @Value, @Currency)",
                new
            {
                subscriptionPaymentCreated.SubscriptionPaymentId,
                subscriptionPaymentCreated.PayerId,
                Type = "Initial Payment",
                subscriptionPaymentCreated.Status,
                period,
                subscriptionPaymentCreated.OccurredOn,
                subscriptionPaymentCreated.Value,
                subscriptionPaymentCreated.Currency
            });
        }
        public static PriceListItem Create(
            string countryCode,
            SubscriptionPeriod subscriptionPeriod,
            PriceListItemCategory category,
            MoneyValue price)
        {
            var priceListItem = new PriceListItem();

            var priceListItemCreatedEvent = new PriceListItemCreatedDomainEvent(
                Guid.NewGuid(),
                countryCode,
                subscriptionPeriod.Code,
                category.Code,
                price.Value,
                price.Currency,
                isActive: true);

            priceListItem.Apply(priceListItemCreatedEvent);
            priceListItem.AddDomainEvent(priceListItemCreatedEvent);

            return(priceListItem);
        }
 public MoneyValue GetPrice(string countryCode, SubscriptionPeriod subscriptionPeriod, PriceListItemCategory category)
 {
     return(_directValue);
 }
示例#28
0
        public async Task Subscription_Buy_ThenRenew_ThenExpire_Test()
        {
            await PriceListHelper.AddPriceListItems(PaymentsModule);

            DateTime referenceDate = new DateTime(2020, 6, 15);

            SystemClock.Set(referenceDate);

            var subscriptionPaymentId = await PaymentsModule.ExecuteCommandAsync(
                new BuySubscriptionCommand(
                    "Month",
                    "PL",
                    60,
                    "PLN"));

            var subscriptionPayments = await GetEventually(
                new GetSubscriptionPaymentsProbe(PaymentsModule, ExecutionContext.UserId,
                                                 x => true),
                10000);

            var subscriptionPayment = subscriptionPayments.Single(x => x.PaymentId == subscriptionPaymentId);

            Assert.That(subscriptionPayment.Status, Is.EqualTo(SubscriptionPaymentStatus.WaitingForPayment.Code));

            await PaymentsModule.ExecuteCommandAsync(
                new MarkSubscriptionPaymentAsPaidCommand(subscriptionPaymentId));

            subscriptionPayments = await GetEventually(
                new GetSubscriptionPaymentsProbe(PaymentsModule, ExecutionContext.UserId,
                                                 x => x.Any(y => y.Status == SubscriptionPaymentStatus.Paid.Code &&
                                                            y.SubscriptionId.HasValue)),
                10000);

            subscriptionPayment = subscriptionPayments.Single(x => x.PaymentId == subscriptionPaymentId);

            var subscriptionId = subscriptionPayment.SubscriptionId.GetValueOrDefault();

            var subscription = await GetEventually(
                new GetSubscriptionDetailsProbe(
                    PaymentsModule,
                    subscriptionId,
                    x => x.SubscriptionId == subscriptionId &&
                    x.Status == SubscriptionStatus.Active.Code &&
                    x.Period == SubscriptionPeriod.Month.Code), 5000);

            Assert.That(subscriptionPayments[0].Status, Is.EqualTo(SubscriptionPaymentStatus.Paid.Code));
            Assert.That(subscription.ExpirationDate, Is.EqualTo(referenceDate.AddMonths(1)));

            var subscriptionRenewalPaymentId = await PaymentsModule.ExecuteCommandAsync(
                new BuySubscriptionRenewalCommand(
                    subscriptionId,
                    "HalfYear",
                    "PL",
                    320,
                    "PLN"));

            subscriptionPayments = await GetEventually(
                new GetSubscriptionPaymentsProbe(PaymentsModule, ExecutionContext.UserId,
                                                 x => true),
                10000);

            var renewalPayment = subscriptionPayments
                                 .Single(x => x.PaymentId == subscriptionRenewalPaymentId);

            Assert.That(renewalPayment.Status, Is.EqualTo(SubscriptionRenewalPaymentStatus.WaitingForPayment.Code));

            await PaymentsModule.ExecuteCommandAsync(
                new MarkSubscriptionRenewalPaymentAsPaidCommand(subscriptionRenewalPaymentId));

            subscriptionPayments = await GetEventually(
                new GetSubscriptionPaymentsProbe(PaymentsModule, ExecutionContext.UserId,
                                                 x => x.Any(y => y.PaymentId == subscriptionRenewalPaymentId)),
                10000);

            renewalPayment = subscriptionPayments
                             .Single(x => x.PaymentId == subscriptionRenewalPaymentId);

            subscription = await GetEventually(
                new GetSubscriptionDetailsProbe(
                    PaymentsModule,
                    subscriptionId,
                    x => x.SubscriptionId == subscriptionId &&
                    x.Period == SubscriptionPeriod.GetName(SubscriptionPeriod.HalfYear.Code) &&
                    x.Status == SubscriptionStatus.Active.Code
                    ), 5000);

            Assert.That(renewalPayment.Status, Is.EqualTo(SubscriptionRenewalPaymentStatus.Paid.Code));
            Assert.That(subscription.ExpirationDate, Is.EqualTo(referenceDate.AddMonths(7)));

            SystemClock.Set(referenceDate.AddMonths(7).AddDays(1));

            await PaymentsModule.ExecuteCommandAsync(new ExpireSubscriptionsCommand());

            subscription = await GetEventually(
                new GetSubscriptionDetailsProbe(
                    PaymentsModule,
                    subscriptionId,
                    x => x.SubscriptionId == subscriptionId &&
                    x.Status == SubscriptionStatus.Expired.Code),
                10000);

            Assert.That(subscription, Is.Not.Null);
        }