TOMP-WG / TOMP-API

Transport Operator to Mobility-as-a-Service Provider-API development for Mobility as a Service
Apache License 2.0
100 stars 41 forks source link

[FEATURE REQUEST] Asset Replacement and Early Asset Return #484

Closed eborremans closed 10 months ago

eborremans commented 1 year ago

Use case - Early Asset Return

As a Transport Operator I want early returned assets to be available immediately for new bookings so that we can achieve optimal asset utilization.

EDIT: I changed actualArrivalTime to actualEndTime as per my discussion with @edwinvandenbelt.

However currently TOMP does not offer a way to indicate that an asset is available earlier than the arrivalTime on the booking. For this we suggest the following change to the booking structure:

One could argue that as soon as all of a bookings legs have been reported FINISHED, the time of the last legs arrival, can be implicitly considered the actualEndTime. However, it is quite cumbersome to retrieve this information via the booking endpoint. The client would have to fetch all legs and inspect their individual arrivalTimes. A new booking field actualEndTime would be much more convenient. In addition this allows for explicitly changing the actualEndTime via the

PUT /bookings/{id}

endpoint which may come in handy as support functionality.

Closely related to this is a feature that some operators want to be able to offer: free asset replacement (for instance because of malfunction).

Use case - In-leg Asset Replacement

As a Transport Operator offering bookings with late asset assignment, I want to enable customers to swap an asset as long as this happens before the bookings arrivalTime.

For example when a bike turns out to have a flat tire or breaks down during the leg, the customer can easily swap it without having to create a new booking (provided assets are available).

EDIT: TOMP already supports asset replacement. For this we can use the trip execution ASSIGN_ASSET event instead of the SET_IN_USE. The sequence diagram has been updated to reflect this.

We can easily implement this use case by adding an additional trip execution event REPLACE_ASSET. This event can be used instead of the FINISH event to indicate that the booking is not FINISHED and the customer intends to swap the asset for a new one. Because ASSIGN_ASSET is intended to be possible without payment consequences for the end customer, we suggest the current leg is reused. We may want to consider maintaining a history of assets used per leg for administration/auditing purposes.

As a side node and possible future extension, some TOs may want to offer swapping to an up(or down)graded asset, in which case a new leg (with its own pricing) may need to be inserted. At this point I cannot oversee the implications of dynamically inserting legs to a booking to provide this functionality because I do not know if a bookings list of legs should be considered immutable. In addition, this would produce a new leg Id that is NOT(!) known to the client. So for this to work we'd need additional changes in the API to communicate this information with the client in a useful way since they'd need a way to know to which booking this new leg belongs.

Note that in combination with the new actualEndTime field, the trip execution behavior could change as follows:

POST /legs/{id}/events FINISH -> sets the actualEndTime to now()

POST /legs/{id}/events ASSIGN_ASSET -> does not change the actualEndTime

Of course the TO is free to use the actualEndTime how they see fit. They can even choose not to use it at all. But at least it offers useful information about the actual trip to both the TO and the MP, while retaining the original booking info.

In case the customer somehow fails to replace the asset after returning it with the intention to replace it, the booking will automatically end when the (planned)arrivalTime passes or when the actualEndTime is explicitly set via the

PUT /bookings/{id}

endpoint.

Furthermore we'd advise the client to always call GET /bookings/{id} after receiving a trip execution event, to ensure they have up to date booking info.

Urgency

Quite urgent as optimal asset utilization is important to our customer TOs.

Additional context

I am currently not aware of possible existing ways to (easily) publish the actual booking end time.

image

@startuml
'https://plantuml.com/sequence-diagram

Title TOMP Replacing Assets and Early Arrival

actor "End User" as user
actor "Service Desk" as support
participant "Moovlr App" as app
participant "MaaS Provider" as MP
participant "Transport Operator" as TO
participant "TO-Back End" as backend

user -> "MP" : books asset
"MP" -> "TO"++ : POST /bookings
TO -> backend: createReservation
"TO" --> "MP"-- : bookingId, status PENDING

"MP" -> "TO"++ : POST /bookings/{bookingId}/events
TO -> backend: confirmReservation
"TO" --> "MP"-- : bookingId, status CONFIRMED

user -> app++: starts using asset
app -> backend++: lockRent
backend -> MP: POST /legs/{bookingId}/events SET_IN_USE
backend --> app--: OK
note over app
    Nazza offers the ability to replace (swap) an asset as long as the
    booking is still valid. This means that the leg can be reused but 
     returning the asset will not cause the booking to be finished. 
     For this we'd need a new trip execution event **REPLACE_ASSET**.
end note

app -> backend++: lockSwap - End user wants to replace (broken)asset
note right of app
  returning the asset for replacement does not require a 
  trip execution event to be sent yet. Instead of sending 
  a SET_IN_USE, a ASSIGN_ASSET can be sent. 
end note
backend --> app--: OK
app -> backend++: lockRent - new Asset, bookingId
backend -> backend: update booking#leg#assetId 
note over backend
  In addition we could add a leg history 
  here to record any replaced asset
end note
backend -> MP: POST /legs/{bookingId}/events ASSIGN_ASSET
note left of backend
  To indicated we replaced the asset we need to send
  an ASSIGN_ASSET event instead of a SET_IN_USE
end note 
backend --> app--: OK
app -> backend++: lockReturn - last leg FINISHED -> reservation is FINISHED
backend -> backend: finishReservation
note right of backend
  (planned)arrivalTime = <unchanged>
  actualEndTime = now()
end note
backend -> MP: POST /legs/{bookingId}/events FINISH
note left of backend
  After the last leg of a booking has been FINISHED 
  the TO should set the booking actualEndTime to now().
  **This enables the TO to make an asset immediately available**
  **after an asset has been returned or the last leg has finished.**
  In addition it is advisable that clients call a 
  **GET /bookings/{bookingId}** immediately after receiving 
  a leg **FINISH** event or even after any trip execution event.
end note
backend --> app--: OK

app --> user--: thanks!

@enduml
edwinvandenbelt commented 1 year ago

Huh? Don't understand this one. When the /legs/{id}/events - FINISH is fired, the asset is returned. Independent on the booked arrival time.

eborremans commented 1 year ago

@edwinvandenbelt I updated this request as per our discussion earlier today.

edwinvandenbelt commented 1 year ago

Added also actualDepartureTime