public static decimal GetRefundableAmount(this Booking booking, DateTime forDate)
        {
            var refundableAmount = booking.Rooms.Sum(room => room.Price.Amount *
                                                     (decimal)room.DeadlineDetails.GetRefundableFraction(forDate));

            return(MoneyRounder.Ceil(refundableAmount, booking.Currency));
        }
        public static RoomContractSet AlignPrices(RoomContractSet roomContractSet)
        {
            var totalFinalPrice = MoneyRounder.Ceil(roomContractSet.Rate.FinalPrice);
            var roomFinalPrices = roomContractSet.Rooms
                                  .Select(r => MoneyRounder.Ceil(r.Rate.FinalPrice))
                                  .ToList();

            var(alignedFinalPrice, alignedRoomFinalPrices) = PriceAligner.AlignAggregateValues(totalFinalPrice, roomFinalPrices);

            var totalGrossPrice = MoneyRounder.Ceil(roomContractSet.Rate.Gross);
            var roomGrossPrices = roomContractSet.Rooms
                                  .Select(r => MoneyRounder.Ceil(r.Rate.Gross))
                                  .ToList();

            var(alignedGrossPrice, alignedRoomGrossRates) = PriceAligner.AlignAggregateValues(totalGrossPrice, roomGrossPrices);

            var roomContracts = new List <RoomContract>(roomContractSet.Rooms.Count);

            for (var i = 0; i < roomContractSet.Rooms.Count; i++)
            {
                var room            = roomContractSet.Rooms[i];
                var totalPriceNet   = alignedRoomFinalPrices[i];
                var totalPriceGross = alignedRoomGrossRates[i];
                var totalRate       = new Rate(totalPriceNet, totalPriceGross);

                roomContracts.Add(BuildRoomContracts(room, room.DailyRoomRates, totalRate));
            }

            var roomContractSetRate = new Rate(alignedFinalPrice, alignedGrossPrice);

            return(BuildRoomContractSet(roomContractSet, roomContractSetRate, roomContracts));
        }
Beispiel #3
0
        public static MoneyAmount Calculate(Booking booking, DateTime cancellationDate)
        {
            var penaltyAmount = booking.Rooms
                                .Sum(room => room.Price.Amount * (decimal)GetPenaltyFraction(room.DeadlineDetails, room.IsAdvancePurchaseRate, cancellationDate));

            penaltyAmount = MoneyRounder.Ceil(penaltyAmount, booking.Currency);

            return(new MoneyAmount(penaltyAmount, booking.Currency));
Beispiel #4
0
        public async Task <DataWithMarkup <TDetails> > ApplyMarkups <TDetails>(AgentContext agent, TDetails details,
                                                                               Func <TDetails, PriceProcessFunction, ValueTask <TDetails> > priceProcessFunc)
        {
            var markup = await _markupService.Get(agent, MarkupPolicyTarget.AccommodationAvailability);

            var responseWithMarkup = await priceProcessFunc(details, markup.Function);

            var ceiledResponse = await priceProcessFunc(responseWithMarkup, price =>
                                                        new ValueTask <MoneyAmount>(MoneyRounder.Ceil(price)));

            return(DataWithMarkup.Create(ceiledResponse, markup.Policies));
        }
        public static async Task <RoomContractSet> ProcessPrices(RoomContractSet sourceRoomContractSet, PriceProcessFunction priceProcessFunction)
        {
            var roomContracts    = new List <RoomContract>(sourceRoomContractSet.Rooms.Count);
            var sourceTotalPrice = sourceRoomContractSet.Rate.FinalPrice;

            if (sourceTotalPrice.Amount == 0)
            {
                throw new NotSupportedException("Room contract set price cannot be 0");
            }

            var processedTotalPrice = await priceProcessFunction(sourceRoomContractSet.Rate.FinalPrice);

            var roomContractSetGross = ChangeProportionally(sourceRoomContractSet.Rate.Gross);
            var roomContractSetRate  = new Rate(finalPrice: processedTotalPrice,
                                                gross: roomContractSetGross,
                                                discounts: sourceRoomContractSet.Rate.Discounts,
                                                type: sourceRoomContractSet.Rate.Type,
                                                description: sourceRoomContractSet.Rate.Description);

            foreach (var room in sourceRoomContractSet.Rooms)
            {
                var dailyRates = new List <DailyRate>(room.DailyRoomRates.Count);
                foreach (var dailyRate in room.DailyRoomRates)
                {
                    var roomGross      = MoneyRounder.Ceil(ChangeProportionally(dailyRate.Gross));
                    var roomFinalPrice = MoneyRounder.Ceil(ChangeProportionally(dailyRate.FinalPrice));

                    dailyRates.Add(BuildDailyPrice(dailyRate, roomFinalPrice, roomGross));
                }

                var totalPriceNet   = ChangeProportionally(room.Rate.FinalPrice);
                var totalPriceGross = ChangeProportionally(room.Rate.Gross);
                var totalRate       = new Rate(totalPriceNet, totalPriceGross);

                roomContracts.Add(BuildRoomContracts(room, dailyRates, totalRate));
            }

            return(BuildRoomContractSet(sourceRoomContractSet, roomContractSetRate, roomContracts));


            MoneyAmount ChangeProportionally(MoneyAmount price)
            {
                var ratio = (price / sourceTotalPrice).Amount;

                return(new MoneyAmount(processedTotalPrice.Amount * ratio, processedTotalPrice.Currency));
            }
        }
Beispiel #6
0
        public async Task <Result <TData> > ConvertPricesInData <TData>(TData data,
                                                                        Func <TData, PriceProcessFunction, ValueTask <TData> > changePricesFunc, Func <TData, Currencies?> getCurrencyFunc)
        {
            var currentCurrency = getCurrencyFunc(data);

            if (!currentCurrency.HasValue)
            {
                return(Result.Success(data));
            }

            if (currentCurrency == TargetCurrency)
            {
                return(Result.Success(data));
            }

            if (currentCurrency == Currencies.NotSpecified)
            {
                return(Result.Failure <TData>($"Cannot convert from '{Currencies.NotSpecified}' currency"));
            }

            var(_, isFailure, rate, error) = await _rateService.Get(currentCurrency.Value, TargetCurrency);

            if (isFailure)
            {
                return(Result.Failure <TData>(error));
            }

            var converter        = _converterFactory.Create(in rate, currentCurrency.Value, TargetCurrency);
            var convertedDetails = await changePricesFunc(data, price =>
            {
                var convertedAmount = converter.Convert(price);
                var ceiledAmount    = MoneyRounder.Ceil(convertedAmount);

                return(new ValueTask <MoneyAmount>(ceiledAmount));
            });

            return(Result.Success(convertedDetails));
        }
Beispiel #7
0
 private MoneyAmount CalculatePercentPenaltyPrice(double percentToCharge, PaymentDetails paymentDetails)
 => new MoneyAmount(MoneyRounder.Ceil(paymentDetails.TotalAmount.Amount * (decimal)percentToCharge / 100, paymentDetails.TotalAmount.Currency), paymentDetails.TotalAmount.Currency);