/// <summary> /// Gets ifnromation about the seat types. /// </summary> /// <remarks> /// Because the seat type contains the number of available seats, and this information can change often, notice /// how we manage the risks associated with displaying data that is very stale by adjusting caching duration /// or not even caching at all if only a few seats remain. /// For more information on the optimizations we did for V3 /// see <see cref="http://go.microsoft.com/fwlink/p/?LinkID=258557"> Journey chapter 7</see>. /// </remarks> public IList <SeatType> GetPublishedSeatTypes(Guid conferenceId) { var key = "ConferenceDao_PublishedSeatTypes_" + conferenceId; var seatTypes = cache.Get(key) as IList <SeatType>; if (seatTypes == null) { seatTypes = decoratedDao.GetPublishedSeatTypes(conferenceId); if (seatTypes != null) { // determine how long to cache depending on criticality of using stale data. TimeSpan timeToCache; if (seatTypes.All(x => x.AvailableQuantity > 200 || x.AvailableQuantity <= 0)) { timeToCache = TimeSpan.FromMinutes(5); } else if (seatTypes.Any(x => x.AvailableQuantity < 30 && x.AvailableQuantity > 0)) { // there are just a few seats remaining. Do not cache. timeToCache = TimeSpan.Zero; } else if (seatTypes.Any(x => x.AvailableQuantity < 100 && x.AvailableQuantity > 0)) { timeToCache = TimeSpan.FromSeconds(20); } else { timeToCache = TimeSpan.FromMinutes(1); } if (timeToCache > TimeSpan.Zero) { cache.Set(key, seatTypes, new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.UtcNow.Add(timeToCache) }); } } } return(seatTypes); }
public OrderTotal CalculateTotal(Guid conferenceId, ICollection <SeatQuantity> seatItems) { var seatTypes = conferenceDao.GetPublishedSeatTypes(conferenceId); var lineItems = new List <OrderLine>(); foreach (var item in seatItems) { var seatType = seatTypes.FirstOrDefault(x => x.Id == item.SeatType); if (seatType == null) { throw new InvalidDataException(string.Format(CultureInfo.InvariantCulture, "Invalid seat type ID '{0}' for conference with ID '{1}'", item.SeatType, conferenceId)); } lineItems.Add(new SeatOrderLine { SeatType = item.SeatType, Quantity = item.Quantity, UnitPrice = seatType.Price, LineTotal = Math.Round(seatType.Price * item.Quantity, 2) }); } return(new OrderTotal { Total = lineItems.Sum(x => x.LineTotal), Lines = lineItems }); }