Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: elaborate TODOs #227

Merged
merged 4 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public async Task<User> FindByUsername(string username)
return GetUserFromSellerUser(await _fakeBookingSystem.Database.GetSellerUser(username));
}

// TODO: Make this an extension method
// TODO: Make this an extension method to Claim class
private static void AddClaimIfNotNull(List<Claim> claims, string key, string value)
{
if (!string.IsNullOrEmpty(value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,13 @@ public static void AddPropertiesToBookedOrderItem(IOrderItemContext ctx, BookedO
}
}

public static void RemovePropertiesFromBookedOrderItem(IOrderItemContext ctx)
{
// Set RemainingAttendeeCapacity and MaximumAttendeeCapacity to null as the do not belong in the B and P responses.
// For more information see: https://github.com/openactive/open-booking-api/issues/156#issuecomment-926643733
ctx.ResponseOrderItem.OrderedItem.Object.RemainingAttendeeCapacity = null;
ctx.ResponseOrderItem.OrderedItem.Object.MaximumAttendeeCapacity = null;
}

}
}
10 changes: 8 additions & 2 deletions Examples/BookingSystem.AspNetCore/Stores/FacilityStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ protected override async Task GetOrderItems(List<OrderItemContext<FacilityOpport
OrderItem = new OrderItem
{
// TODO: The static example below should come from the database (which doesn't currently support tax)
// This is because it can be different for each Seller and needs to calculated at the time of booking
Comment on lines 360 to +361
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this cause any bugs at present? If yes then maybe should be a GH issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not yet I think

UnitTaxSpecification = GetUnitTaxSpecification(flowContext, slot),
AcceptedOffer = new Offer
{
Expand Down Expand Up @@ -512,7 +513,8 @@ protected override async ValueTask LeaseOrderItems(Lease lease, List<OrderItemCo
}
}

//TODO: This should reuse code of LeaseOrderItem
// TODO: This should reuse code of LeaseOrderItem to be DRY. Similar logic is also used in ProposeOrderItems as well as
// in LeaseOrderItems, BookOrderItems, and ProposeOrderItems in the FacilityStore. The issue for this is: https://github.com/openactive/OpenActive.Server.NET/issues/226
protected override async ValueTask BookOrderItems(List<OrderItemContext<FacilityOpportunity>> orderItemContexts, StoreBookingFlowContext flowContext, OrderStateContext stateContext, OrderTransaction databaseTransaction)
{
// Check that there are no conflicts between the supplied opportunities
Expand Down Expand Up @@ -558,6 +560,8 @@ protected override async ValueTask BookOrderItems(List<OrderItemContext<Facility
// Set OrderItemId and access properties for each orderItemContext
ctx.SetOrderItemId(flowContext, bookedOrderItemInfo.OrderItemId);
BookedOrderItemHelper.AddPropertiesToBookedOrderItem(ctx, bookedOrderItemInfo);
// Remove attendee capacity information from the OrderedItem. For more information see: https://github.com/openactive/open-booking-api/issues/156#issuecomment-926643733
BookedOrderItemHelper.RemovePropertiesFromBookedOrderItem(ctx);
}
break;
case ReserveOrderItemsResult.SellerIdMismatch:
Expand All @@ -574,7 +578,7 @@ protected override async ValueTask BookOrderItems(List<OrderItemContext<Facility
}
}

// TODO check logic here, it's just been copied from BookOrderItems. Possibly could remove duplication here.
// TODO check logic here, it's just been copied from BookOrderItems. Possibly could remove duplication here. Common logic between this, BookOrderItems, and LeaseOrderItems should be pulled out.
protected override async ValueTask ProposeOrderItems(List<OrderItemContext<FacilityOpportunity>> orderItemContexts, StoreBookingFlowContext flowContext, OrderStateContext stateContext, OrderTransaction databaseTransaction)
{
// Check that there are no conflicts between the supplied opportunities
Expand Down Expand Up @@ -619,6 +623,8 @@ protected override async ValueTask ProposeOrderItems(List<OrderItemContext<Facil
foreach (var (ctx, bookedOrderItemInfo) in ctxGroup.Zip(bookedOrderItemInfos, (ctx, bookedOrderItemInfo) => (ctx, bookedOrderItemInfo)))
{
ctx.SetOrderItemId(flowContext, bookedOrderItemInfo.OrderItemId);
// Remove attendee capacity information from the OrderedItem. For more information see: https://github.com/openactive/open-booking-api/issues/156#issuecomment-926643733
BookedOrderItemHelper.RemovePropertiesFromBookedOrderItem(ctx);
}
break;
case ReserveOrderItemsResult.SellerIdMismatch:
Expand Down
2 changes: 1 addition & 1 deletion Examples/BookingSystem.AspNetCore/Stores/OrderStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ public override async Task<bool> CreateOrderFromOrderProposal(OrderIdComponents
sellerId.IdLong ?? null /* Hack to allow this to work in Single Seller mode too */,
orderId.uuid,
version);
// TODO return enum to allow errors cases to be handled in the engine
// TODO return enum (something like CreateOrderStatus) to allow errors cases to be handled in the engine
switch (result)
{
case FakeDatabaseBookOrderProposalResult.OrderSuccessfullyBooked:
Expand Down
11 changes: 8 additions & 3 deletions Examples/BookingSystem.AspNetCore/Stores/SessionStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ protected override async Task GetOrderItems(List<OrderItemContext<SessionOpportu
OrderItem = new OrderItem
{
// TODO: The static example below should come from the database (which doesn't currently support tax)
// This is because it can be different for each Seller and needs to calculated at the time of booking
UnitTaxSpecification = GetUnitTaxSpecification(flowContext, @class),
AcceptedOffer = new Offer
{
Expand Down Expand Up @@ -523,8 +524,8 @@ protected override async ValueTask LeaseOrderItems(
}
}
}

//TODO: This should reuse code of LeaseOrderItem
// TODO: This should reuse code of LeaseOrderItem to be DRY. Similar logic is also used in ProposeOrderItems as well as
// in LeaseOrderItems, BookOrderItems, and ProposeOrderItems in the SessionStore. The issue for this is: https://github.com/openactive/OpenActive.Server.NET/issues/226
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
Expand Down Expand Up @@ -580,6 +581,8 @@ protected override async ValueTask BookOrderItems(List<OrderItemContext<SessionO
// Set OrderItemId and access properties for each orderItemContext
ctx.SetOrderItemId(flowContext, bookedOrderItemInfo.OrderItemId);
BookedOrderItemHelper.AddPropertiesToBookedOrderItem(ctx, bookedOrderItemInfo);
// Remove attendee capacity information from the OrderedItem. For more information see: https://github.com/openactive/open-booking-api/issues/156#issuecomment-926643733
BookedOrderItemHelper.RemovePropertiesFromBookedOrderItem(ctx);
}
break;
case ReserveOrderItemsResult.SellerIdMismatch:
Expand All @@ -596,7 +599,7 @@ protected override async ValueTask BookOrderItems(List<OrderItemContext<SessionO
}
}

// TODO check logic here, it's just been copied from BookOrderItems. Possibly could remove duplication here.
// TODO check logic here, it's just been copied from BookOrderItems. Possibly could remove duplication here. Common logic between this, BookOrderItems, and LeaseOrderItems should be pulled out.
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
Expand Down Expand Up @@ -642,6 +645,8 @@ protected override async ValueTask ProposeOrderItems(List<OrderItemContext<Sessi
foreach (var (ctx, bookedOrderItemInfo) in ctxGroup.Zip(bookedOrderItemInfos, (ctx, bookedOrderItemInfo) => (ctx, bookedOrderItemInfo)))
{
ctx.SetOrderItemId(flowContext, bookedOrderItemInfo.OrderItemId);
// Remove attendee capacity information from the OrderedItem. For more information see: https://github.com/openactive/open-booking-api/issues/156#issuecomment-926643733
BookedOrderItemHelper.RemovePropertiesFromBookedOrderItem(ctx);
}
break;
case ReserveOrderItemsResult.SellerIdMismatch:
Expand Down
5 changes: 2 additions & 3 deletions Fakes/OpenActive.FakeDatabase.NET/FakeBookingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static FakeDatabase()
int.TryParse(Environment.GetEnvironmentVariable("OPPORTUNITY_COUNT"), out var opportunityCount) ? opportunityCount : 2000;

/// <summary>
/// TODO: Call this on a schedule from both .NET Core and .NET Framework reference implementations
/// TODO: Call this on a schedule from both .NET Core and .NET Framework reference implementations to ensure database is not cluttered
/// </summary>
public async Task CleanupExpiredLeases()
{
Expand Down Expand Up @@ -1316,7 +1316,6 @@ public static async Task RecalculateSlotUses(IDbConnection db, SlotTable slot)
slot.RemainingUses = slot.MaximumUses - totalUsesTaken;

// Push the change into the future to avoid it getting lost in the feed (see race condition transaction challenges https://developer.openactive.io/publishing-data/data-feeds/implementing-rpde-feeds#preventing-the-race-condition)
// TODO: Document this!
slot.Modified = DateTimeOffset.Now.UtcTicks;
await db.UpdateAsync(slot);
}
Expand All @@ -1343,7 +1342,7 @@ public static async Task RecalculateSpaces(IDbConnection db, OccurrenceTable occ
var totalSpacesTaken = (await db.LoadSelectAsync<OrderItemsTable>(x => x.OrderTable.OrderMode == OrderMode.Booking && x.OccurrenceId == occurrence.Id && (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent))).Count();
occurrence.RemainingSpaces = occurrence.TotalSpaces - totalSpacesTaken;

// Push the change into the future to avoid it getting lost in the feed (see race condition transaction challenges https://developer.openactive.io/publishing-data/data-feeds/implementing-rpde-feeds#preventing-the-race-condition) // TODO: Document this!
// Push the change into the future to avoid it getting lost in the feed (see race condition transaction challenges https://developer.openactive.io/publishing-data/data-feeds/implementing-rpde-feeds#preventing-the-race-condition)
occurrence.Modified = DateTimeOffset.Now.UtcTicks;
await db.UpdateAsync(occurrence);
}
Expand Down
18 changes: 10 additions & 8 deletions OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;

Check warning on line 1 in OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs

View workflow job for this annotation

GitHub Actions / framework (controlled, no-auth)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [D:\a\OpenActive.Server.NET\OpenActive.Server.NET\server\OpenActive.Server.NET\OpenActive.Server.NET.csproj]

Check warning on line 1 in OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs

View workflow job for this annotation

GitHub Actions / framework (controlled, no-auth)

Consider calling ConfigureAwait on the awaited task [D:\a\OpenActive.Server.NET\OpenActive.Server.NET\server\OpenActive.Server.NET\OpenActive.Server.NET.csproj]

Check warning on line 1 in OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs

View workflow job for this annotation

GitHub Actions / framework (controlled, no-auth)

Consider calling ConfigureAwait on the awaited task [D:\a\OpenActive.Server.NET\OpenActive.Server.NET\server\OpenActive.Server.NET\OpenActive.Server.NET.csproj]

Check warning on line 1 in OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs

View workflow job for this annotation

GitHub Actions / framework (random, no-auth)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [D:\a\OpenActive.Server.NET\OpenActive.Server.NET\server\OpenActive.Server.NET\OpenActive.Server.NET.csproj]

Check warning on line 1 in OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs

View workflow job for this annotation

GitHub Actions / framework (random, no-auth)

Consider calling ConfigureAwait on the awaited task [D:\a\OpenActive.Server.NET\OpenActive.Server.NET\server\OpenActive.Server.NET\OpenActive.Server.NET.csproj]
using System.Collections.Generic;
using System.Linq;
using System.Net;
Expand Down Expand Up @@ -70,8 +70,7 @@
if (settings.CustomerAccountIdTemplate != null) settings.CustomerAccountIdTemplate.RequiredBaseUrl = settings.CustomerAccountIdBaseUrl;

// Create a lookup of each IdTemplate to pass into the appropriate RpdeGenerator
// TODO: Output better error if there is a feed assigned across two templates
// (there should never be, as each template represents everyting you need in one feed)
// TODO: Output better error if there is a feed assigned across two templates (there should never be, as each template represents everyting you need in one feed)
this.feedAssignedTemplates = settings.IdConfiguration.SelectMany(t => t.IdConfigurations.Select(x => new
{
assignedFeed = x.AssignedFeed,
Expand Down Expand Up @@ -151,7 +150,7 @@
/// Handler for Dataset Site endpoint
/// </summary>
/// <returns></returns>
public async Task<ResponseContent> RenderDatasetSite()

Check warning on line 153 in OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs

View workflow job for this annotation

GitHub Actions / test-server

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
if (datasetSettings == null || supportedFeeds == null) throw new NotSupportedException("RenderDatasetSite is only supported if DatasetSiteGeneratorSettings are supplied to the IBookingEngine");
// TODO add caching layer in front of dataset site rendering
Expand Down Expand Up @@ -375,7 +374,8 @@
if (Guid.TryParse(uuidString, out Guid result))
{
return result;
} else
}
else
{
throw new OpenBookingException(new OpenBookingError(), "Invalid format for Order UUID");
}
Expand Down Expand Up @@ -424,7 +424,7 @@
{
// Attempt to use idempotency cache if it exists
var cachedResponse = await GetResponseFromIdempotencyStoreIfExists(settings, orderId, orderJson);
if (cachedResponse != null)
if (cachedResponse != null)
{
return cachedResponse;
}
Expand All @@ -449,7 +449,7 @@
{
// Attempt to use idempotency cache if it exists
var cachedResponse = await GetResponseFromIdempotencyStoreIfExists(settings, orderId, orderJson);
if (cachedResponse != null)
if (cachedResponse != null)
{
return cachedResponse;
}
Expand All @@ -462,7 +462,7 @@

private async Task<ResponseContent> GetResponseFromIdempotencyStoreIfExists(BookingEngineSettings settings, OrderIdComponents orderId, string orderJson)
{
// Attempt to use idempotency cache if it exists
// Attempt to use idempotency cache if it exists
if (settings.IdempotencyStore != null)
{
var cachedResponse = await settings.IdempotencyStore.GetSuccessfulOrderCreationResponse(orderId, orderJson);
Expand All @@ -474,7 +474,8 @@
return null;
}

private async Task<ResponseContent> CreateResponseViaIdempotencyStoreIfExists(BookingEngineSettings settings, OrderIdComponents orderId, string orderJson, Order response) {
private async Task<ResponseContent> CreateResponseViaIdempotencyStoreIfExists(BookingEngineSettings settings, OrderIdComponents orderId, string orderJson, Order response)
{
// Return a 409 status code if any OrderItem level errors exist
var httpStatusCode = response.OrderedItem.Exists(x => x.Error?.Count > 0) ? HttpStatusCode.Conflict : HttpStatusCode.Created;
var responseJson = OpenActiveSerializer.Serialize(response);
Expand Down Expand Up @@ -730,6 +731,7 @@
throw new OpenBookingException(new OpenBookingError(), "Only bookable opportunities are permitted in the test interface");

// TODO: add this error class to the library
// CS: Does this mean add a new specific error to OpenActive.Net, something like OnlyBookableOpportunitesPermittedInTestInterfaceError
}

if (!genericEvent.TestOpportunityCriteria.HasValue)
Expand Down Expand Up @@ -868,7 +870,7 @@

// Throw error if TotalPaymentDue is not specified at B or P
if (order.TotalPaymentDue?.Price.HasValue != true && (stage == FlowStage.B || stage == FlowStage.P))
// TODO replace this with a more specific error
// TODO replace this with a more specific error ie a subclass of OpenBookingException like TotalPaymentMissingAtBOrPError
throw new OpenBookingException(new OpenBookingError(), "TotalPaymentDue must have a price set");

var payer = order.BrokerRole == BrokerType.ResellerBroker ? order.Broker : order.Customer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,20 +417,24 @@ public Uri RenderOrderId(OrderType orderType, Guid uuid)
return this.RenderOrderId(new OrderIdComponents { OrderType = orderType, uuid = uuid });
}

//TODO reduce duplication of the strings / logic below
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented

public Uri RenderOrderItemId(OrderType orderType, Guid uuid, Guid orderItemId)
private void ValidateOrderType(OrderType orderType)
{
if (orderType != OrderType.Order) throw new ArgumentOutOfRangeException(nameof(orderType), "The Open Booking API 1.0 specification only permits OrderItem Ids to exist within Orders, not OrderQuotes or OrderProposals.");
}

public Uri RenderOrderItemId(OrderType orderType, Guid uuid, Guid orderItemId)
{
ValidateOrderType(orderType);
return this.RenderOrderItemId(new OrderIdComponents { OrderType = orderType, uuid = uuid, OrderItemIdGuid = orderItemId });
}
public Uri RenderOrderItemId(OrderType orderType, Guid uuid, string orderItemId)
{
if (orderType != OrderType.Order) throw new ArgumentOutOfRangeException(nameof(orderType), "The Open Booking API 1.0 specification only permits OrderItem Ids to exist within Orders, not OrderQuotes or OrderProposals.");
ValidateOrderType(orderType);
return this.RenderOrderItemId(new OrderIdComponents { OrderType = orderType, uuid = uuid, OrderItemIdString = orderItemId });
}
public Uri RenderOrderItemId(OrderType orderType, Guid uuid, long orderItemId)
{
if (orderType != OrderType.Order) throw new ArgumentOutOfRangeException(nameof(orderType), "The Open Booking API 1.0 specification only permits OrderItem Ids to exist within Orders, not OrderQuotes or OrderProposals.");
ValidateOrderType(orderType);
return this.RenderOrderItemId(new OrderIdComponents { OrderType = orderType, uuid = uuid, OrderItemIdLong = orderItemId });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ protected Uri RenderOrderId(OrderType orderType, Guid uuid)
return this.OrderIdTemplate.RenderOrderId(orderType, uuid);
}

//TODO reduce duplication of the strings / logic below
protected Uri RenderOrderItemId(OrderType orderType, Guid uuid, Guid orderItemId)
{
return this.OrderIdTemplate.RenderOrderItemId(orderType, uuid, orderItemId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public static List<OpenBookingError> ValidateAdditionalDetails(OrderItem respons

public static Event RenderOpportunityWithOnlyId(OpportunityType opportunityType, Uri id)
{
// TODO: Create an extra prop in DatasetSite lib so that we don't need to parse the URL here
// TODO: Create an extra property in DatasetSite library called DatasetOpportunityType so that we don't need to parse the URL here
switch (OpportunityTypes.Configurations[opportunityType].SameAs.AbsolutePath.Trim('/'))
{
case nameof(Event):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace OpenActive.Server.NET.StoreBooking
{
//TODO: Refactor to inherrit from BookingFlowContext (using constructor to copy params? Use Automapper?)
//TODO: Refactor to inherit from BookingFlowContext (using constructor to copy params? Use Automapper?)
public class StoreBookingFlowContext : BookingFlowContext
{
public StoreBookingFlowContext(BookingFlowContext bookingFlowContext)
Expand Down
Loading