// TODO check logic here, it's just been copied from BookOrderItems. Possibly could remove duplication here. protected override async ValueTask ProposeOrderItems(List <OrderItemContext <SessionOpportunity> > orderItemContexts, StoreBookingFlowContext flowContext, OrderStateContext stateContext, OrderTransaction databaseTransaction) { // Check that there are no conflicts between the supplied opportunities // Also take into account spaces requested across OrderItems against total spaces in each opportunity foreach (var ctxGroup in orderItemContexts.GroupBy(x => x.RequestBookableOpportunityOfferId)) { // Check that the Opportunity ID and type are as expected for the store if (ctxGroup.Key.OpportunityType != OpportunityType.ScheduledSession || !ctxGroup.Key.ScheduledSessionId.HasValue) { throw new OpenBookingException(new UnableToProcessOrderItemError(), "Opportunity ID and type are as not expected for the SessionStore, during proposal"); } // Attempt to book for those with the same IDs, which is atomic var(result, bookedOrderItemInfos) = await FakeDatabase.BookOrderItemsForClassOccurrence( databaseTransaction.FakeDatabaseTransaction, flowContext.OrderId.ClientId, flowContext.SellerId.SellerIdLong ?? null /* Hack to allow this to work in Single Seller mode too */, flowContext.OrderId.uuid, ctxGroup.Key.ScheduledSessionId.Value, RenderOpportunityId(ctxGroup.Key), RenderOfferId(ctxGroup.Key), ctxGroup.Count(), true ); switch (result) { case ReserveOrderItemsResult.Success: // Set OrderItemId for each orderItemContext foreach (var(ctx, bookedOrderItemInfo) in ctxGroup.Zip(bookedOrderItemInfos, (ctx, bookedOrderItemInfo) => (ctx, bookedOrderItemInfo))) { ctx.SetOrderItemId(flowContext, bookedOrderItemInfo.OrderItemId); } break; case ReserveOrderItemsResult.SellerIdMismatch: throw new OpenBookingException(new SellerMismatchError(), "An OrderItem SellerID did not match"); case ReserveOrderItemsResult.OpportunityNotFound: throw new OpenBookingException(new UnableToProcessOrderItemError(), "Opportunity not found"); case ReserveOrderItemsResult.NotEnoughCapacity: throw new OpenBookingException(new OpportunityHasInsufficientCapacityError()); case ReserveOrderItemsResult.OpportunityOfferPairNotBookable: throw new OpenBookingException(new UnableToProcessOrderItemError(), "Opportunity and offer pair were not bookable"); default: throw new OpenBookingException(new OrderCreationFailedError(), "Booking failed for an unexpected reason"); } } }
//TODO: This should reuse code of LeaseOrderItem protected override async ValueTask BookOrderItems(List <OrderItemContext <SessionOpportunity> > orderItemContexts, StoreBookingFlowContext flowContext, OrderStateContext stateContext, OrderTransaction databaseTransaction) { // Check that there are no conflicts between the supplied opportunities // Also take into account spaces requested across OrderItems against total spaces in each opportunity // TODO: ENSURE THAT THIS IS CALLED EVERY TIME BY THE STOREBOOKINGENGINE, EVEN WITH ZERO ITEMS // This will ensure that items can be removed from the Order before the booking is confirmed if all items of that type have been removed from the lease // Step 1: Call lease to ensure items are already leased // Step 2: Set OrderItems to booked // Step 3: Write attendee and orderItemIntakeFormResponse to the OrderItem records, for inclusion in P later foreach (var ctxGroup in orderItemContexts.GroupBy(x => x.RequestBookableOpportunityOfferId)) { // Check that the Opportunity ID and type are as expected for the store if (ctxGroup.Key.OpportunityType != OpportunityType.ScheduledSession || !ctxGroup.Key.ScheduledSessionId.HasValue) { throw new OpenBookingException(new UnableToProcessOrderItemError(), "Opportunity ID and type are as not expected for the SessionStore, during booking"); } // Attempt to book for those with the same IDs, which is atomic var(result, bookedOrderItemInfos) = await FakeDatabase.BookOrderItemsForClassOccurrence( databaseTransaction.FakeDatabaseTransaction, flowContext.OrderId.ClientId, flowContext.SellerId.SellerIdLong ?? null /* Hack to allow this to work in Single Seller mode too */, flowContext.OrderId.uuid, ctxGroup.Key.ScheduledSessionId.Value, RenderOpportunityId(ctxGroup.Key), RenderOfferId(ctxGroup.Key), ctxGroup.Count(), false ); switch (result) { case ReserveOrderItemsResult.Success: foreach (var(ctx, bookedOrderItemInfo) in ctxGroup.Zip(bookedOrderItemInfos, (ctx, bookedOrderItemInfo) => (ctx, bookedOrderItemInfo))) { // Set OrderItemId and access properties for each orderItemContext ctx.SetOrderItemId(flowContext, bookedOrderItemInfo.OrderItemId); BookedOrderItemHelper.AddPropertiesToBookedOrderItem(ctx, bookedOrderItemInfo); } break; case ReserveOrderItemsResult.SellerIdMismatch: throw new OpenBookingException(new SellerMismatchError(), "An OrderItem SellerID did not match"); case ReserveOrderItemsResult.OpportunityNotFound: throw new OpenBookingException(new UnableToProcessOrderItemError(), "Opportunity not found"); case ReserveOrderItemsResult.NotEnoughCapacity: throw new OpenBookingException(new OpportunityHasInsufficientCapacityError()); case ReserveOrderItemsResult.OpportunityOfferPairNotBookable: throw new OpenBookingException(new UnableToProcessOrderItemError(), "Opportunity and offer pair were not bookable"); default: throw new OpenBookingException(new OrderCreationFailedError(), "Booking failed for an unexpected reason"); } } }