/// <summary>
        /// If order passes midnight their might be two rows of same pricetype, merge these to one
        /// Also check if two duplicate rows have less or equal compensation time together. Then it should be reduced, e.g. 23:45-00:45 (should be two 30 min periods not three)
        /// </summary>
        public static IEnumerable <PriceRowBase> MergePriceListRowsAndReduceForMealBreak(IEnumerable <PriceRowBase> pricePerType, IDictionary <PriceListRowType, int> mealbreakDictionary = null)
        {
            int newQuantity             = 0;
            var duplicatesPriceListrows = pricePerType.GroupBy(x => x.PriceListRow.PriceListRowId)
                                          .Where(g => g.Count() > 1)
                                          .Select(g => g.Key)
                                          .Distinct().ToList();

            if (!duplicatesPriceListrows.Any())
            {
                if (mealbreakDictionary != null)
                {
                    List <PriceRowBase> pl = pricePerType.Where(pr => pr.PriceListRow.PriceListRowType != PriceListRowType.BigHolidayWeekendIWH && pr.PriceListRow.PriceListRowType != PriceListRowType.WeekendIWH && pr.PriceListRow.PriceListRowType != PriceListRowType.InconvenientWorkingHours).ToList();
                    foreach (PriceRowBase pricerow in pricePerType.Where(pr => pr.PriceListRow.PriceListRowType == PriceListRowType.BigHolidayWeekendIWH || pr.PriceListRow.PriceListRowType == PriceListRowType.WeekendIWH || pr.PriceListRow.PriceListRowType == PriceListRowType.InconvenientWorkingHours))
                    {
                        //reduce quantity with mealbreaks, check if quantity > 0 before adding
                        newQuantity = GetReducedQuantityForMealbreak(pricerow, mealbreakDictionary[pricerow.PriceListRow.PriceListRowType]);
                        if (newQuantity > 0)
                        {
                            pricerow.Quantity = newQuantity;
                            pl.Add(pricerow);
                        }
                    }
                    return(pl);
                }
                else
                {
                    return(pricePerType);
                }
            }
            else
            {
                List <PriceRowBase> mergedList = new List <PriceRowBase>();
                foreach (int priceListRowId in duplicatesPriceListrows)
                {
                    PriceRowBase newPriceRow = pricePerType.OrderBy(pr => pr.StartAt).First(pr => pr.PriceListRow.PriceListRowId == priceListRowId);
                    var          noOfMinutes = pricePerType.Where(pr => pr.PriceListRow.PriceListRowId == priceListRowId).Sum(pr => pr.Minutes);

                    //reduce noOfMinutes with mealbreak minutes
                    if (mealbreakDictionary != null && mealbreakDictionary.ContainsKey(newPriceRow.PriceListRow.PriceListRowType))
                    {
                        noOfMinutes -= mealbreakDictionary[newPriceRow.PriceListRow.PriceListRowType];
                    }
                    var compensationPeriod = newPriceRow.PriceListRow.MaxMinutes;
                    newQuantity          = compensationPeriod == 0 ? newPriceRow.Quantity : noOfMinutes % compensationPeriod > 0 ? (noOfMinutes / compensationPeriod) + 1 : noOfMinutes / compensationPeriod;
                    newPriceRow.Quantity = newQuantity;
                    newPriceRow.EndAt    = pricePerType.OrderBy(pr => pr.EndAt).Last(pr => pr.PriceListRow.PriceListRowId == priceListRowId).EndAt;
                    if (newQuantity > 0)
                    {
                        newPriceRow.Quantity = newQuantity;
                        mergedList.Add(newPriceRow);
                    }
                }
                mergedList.AddRange(pricePerType.Where(pri => !duplicatesPriceListrows.Contains(pri.PriceListRow.PriceListRowId)));
                return(mergedList);
            }
        }
        private static PriceRowBase GetPriceInformation(DateTimeOffset startAt, DateTimeOffset endAt, PriceListRowType rowType, List <PriceListRow> prices)
        {
            PriceListRow priceInfo = prices.Single(r => r.PriceListRowType == rowType);
            var          priceTime = new PriceRowBase
            {
                StartAt      = startAt,
                EndAt        = endAt,
                PriceRowType = PriceRowType.InterpreterCompensation
            };

            priceTime.Quantity = priceTime.Minutes / priceInfo.MaxMinutes;
            if (priceTime.Minutes % priceInfo.MaxMinutes > 0)
            {
                priceTime.Quantity++;
            }
            priceTime.PriceListRow = priceInfo;
            priceTime.Price        = priceInfo.Price;
            return(priceTime);
        }
        private PriceInformation CompletePricesWithExtraCharges(DateTimeOffset startAt, DateTimeOffset endAt, CompetenceLevel competenceLevel, List <PriceRowBase> priceListRowsPerPriceType, int rankingId, decimal?travelCost, DateTimeOffset orderCreatedDate, decimal?outlay = null, PriceRowBase requestBrokerFeeForRequisition = null)
        {
            List <PriceRowBase> allPriceRows = new List <PriceRowBase>
            {
                GetPriceRowSocialInsuranceCharge(startAt, endAt, priceListRowsPerPriceType),
                GetPriceRowAdministrativeCharge(startAt, endAt, priceListRowsPerPriceType),
                GetPriceRowBrokerFee(startAt, endAt, competenceLevel, rankingId, requestBrokerFeeForRequisition, orderCreatedDate)
            };

            allPriceRows.AddRange(priceListRowsPerPriceType);
            if (travelCost != null && travelCost > 0)
            {
                allPriceRows.Add(GetTravelCostRow(startAt.Date, startAt.Date.AddDays(1).ToDateTimeOffsetSweden(), travelCost, PriceRowType.TravelCost));
            }
            if (outlay != null && outlay > 0)
            {
                allPriceRows.Add(GetTravelCostRow(startAt.Date, startAt.Date.AddDays(1).ToDateTimeOffsetSweden(), outlay, PriceRowType.Outlay));
            }

            allPriceRows.Add(GetRoundedPriceRow(startAt, endAt, allPriceRows));

            var priceInformation = new PriceInformation
            {
                PriceRows = allPriceRows
            };

            return(priceInformation);
        }
        private PriceRowBase GetPriceRowBrokerFee(DateTimeOffset startAt, DateTimeOffset endAt, CompetenceLevel competenceLevel, int rankingId, PriceRowBase brokerFeeToUse, DateTimeOffset orderCreatedDate)
        {
            if (brokerFeeToUse != null)
            {
                return(brokerFeeToUse);
            }
            else
            {
                //One broker fee per day
                int days = GetNoOfDays(startAt, endAt);
                //if there is no priceRowBrokerFee for the orderStart, try to get if for the orderCreatedDate (contract has ended, but order was created when contract/ranking was valid)
                var priceRow = _cacheService.BrokerFeePriceList.Where(br => br.RankingId == rankingId && br.CompetenceLevel == competenceLevel && br.StartDate.Date <= startAt.Date && br.EndDate.Date >= startAt.Date).Count() == 1 ?
                               _cacheService.BrokerFeePriceList.Single(br => br.RankingId == rankingId && br.CompetenceLevel == competenceLevel && br.StartDate.Date <= startAt.Date && br.EndDate.Date >= startAt.Date) :
                               _cacheService.BrokerFeePriceList.Single(br => br.RankingId == rankingId && br.CompetenceLevel == competenceLevel && br.StartDate.Date <= orderCreatedDate.Date && br.EndDate.Date >= orderCreatedDate.Date);

                return(new PriceRowBase
                {
                    StartAt = startAt.Date.ToDateTimeOffsetSweden(),
                    EndAt = endAt.Date.ToDateTimeOffsetSweden(),
                    PriceRowType = PriceRowType.BrokerFee,
                    Quantity = days,
                    Price = priceRow.PriceToUse,
                    PriceListRowId = priceRow.PriceListRowId
                });
            }
        }
        private static int GetReducedQuantityForMealbreak(PriceRowBase newPriceRow, int mealbreakMinutes)
        {
            int reducedMinutes = newPriceRow.Minutes - mealbreakMinutes;

            return(reducedMinutes > 0 ? reducedMinutes % newPriceRow.PriceListRow.MaxMinutes > 0 ? (reducedMinutes / newPriceRow.PriceListRow.MaxMinutes) + 1 : reducedMinutes / newPriceRow.PriceListRow.MaxMinutes : 0);
        }