Closed ravi-prakash-v closed 2 years ago
In metro each fulfillment can have a schedule of fulfillment start and end times. So proposing the below structure :
{
"context": {
"domain": "nic2004:60221",
"country": "IND",
"city": "std:080",
"action": "on_search",
"core_version": "0.9.1",
"bap_id": "https://mock_bap.com/",
"bap_uri": "https://mock_bap.com/beckn/",
"bpp_id": "https://mock_bpp.com/",
"bpp_uri": "https://mock_bpp.com/beckn/",
"transaction_id": "1209849124",
"message_id": "12341242343",
"timestamp": "2021-03-23T10:00:40.065Z"
},
"message": {
"catalog": {
"bpp/descriptor": {
"name": "KMRL"
},
"bpp/providers": [
{
"id": "1",
"descriptor": {
"name": "KMRL"
},
"locations": [
{
"id": "station-1",
"descriptor": {
"name": "Station 1",
"code": "STN1"
},
"gps": "12.9349377,77.6055586"
},
{
"id": "station-2",
"gps": "12.9349377,77.6055586",
"descriptor": {
"name": "Station 3",
"code": "STN3"
}
},
{
"id": "station-3",
"gps": "12.9349377,77.6055586",
"descriptor": {
"name": "Station 3",
"code": "STN3"
}
}
],
"items": [
{
"id": "1",
"descriptor": {
"name": "Single Journey Ticket",
"code": "SJT"
},
"location_id": "station-1",
"fulfillment_id": "station-1-to-station-2",
"price": {
"currency": "INR",
"value": "20"
}
},
{
"id": "1",
"descriptor": {
"name": "Single Journey Ticket",
"code": "SJT"
},
"location_id": "station-1",
"fulfillment_id": "station-1-to-station-3",
"price": {
"currency": "INR",
"value": "30"
}
},
{
"id": "1",
"descriptor": {
"name": "Single Journey Ticket",
"code": "SJT"
},
"location_id": "station-2",
"fulfillment_id": "2"
},
{
"id": "1",
"descriptor": {
"name": "Single Journey Ticket",
"code": "SJT"
},
"location_id": "station-3",
"fulfillment_id": "station-3-to-station-2",
"price": {
"currency": "INR",
"value": "20"
}
}
],
"fulfillments": [
{
"id": "station-1-to-station-2",
"start": {
"location": {
"id": "station-1"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:32:19.000Z",
"2021-10-15T01:42:19.000Z",
"2021-10-15T02:57:59.000Z",
"2021-10-15T04:07:59.000Z",
"2021-10-15T05:17:59.000Z",
"2021-10-15T06:27:59.000Z",
"2021-10-15T07:37:59.000Z",
"2021-10-15T08:47:59.000Z",
"2021-10-15T09:57:59.000Z",
"2021-10-15T11:07:59.000Z"
]
}
}
},
"end": {
"location": {
"id": "station-2"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:43:21.000Z",
"2021-10-15T01:53:21.000Z",
"2021-10-15T03:09:01.000Z",
"2021-10-15T04:19:01.000Z",
"2021-10-15T05:29:01.000Z",
"2021-10-15T06:39:01.000Z",
"2021-10-15T07:49:01.000Z",
"2021-10-15T08:59:01.000Z",
"2021-10-15T10:09:01.000Z",
"2021-10-15T11:19:01.000Z"
]
}
}
},
"./komn-mobility-0_9_3.distance": "12 km"
},
{
"id": "station-2-to-station-3",
"start": {
"location": {
"id": "station-2"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:26:36.000Z",
"2021-10-15T01:36:46.000Z",
"2021-10-15T02:51:55.000Z",
"2021-10-15T04:02:26.000Z",
"2021-10-15T05:12:26.000Z",
"2021-10-15T06:22:26.000Z",
"2021-10-15T07:32:26.000Z",
"2021-10-15T08:42:26.000Z",
"2021-10-15T09:52:26.000Z",
"2021-10-15T11:02:26.000Z"
]
}
}
},
"end": {
"location": {
"id": "station-3",
"time": {
"schedule": {
"times": [
"2021-10-15T00:43:21.000Z",
"2021-10-15T01:53:21.000Z",
"2021-10-15T03:09:01.000Z",
"2021-10-15T04:19:01.000Z",
"2021-10-15T05:29:01.000Z",
"2021-10-15T06:39:01.000Z",
"2021-10-15T07:49:01.000Z",
"2021-10-15T08:59:01.000Z",
"2021-10-15T10:09:01.000Z",
"2021-10-15T11:19:01.000Z"
]
}
}
}
},
"./komn-mobility-0_9_3.distance": "10 km"
},
{
"id": "station-1-to-station-3",
"start": {
"location": {
"id": "station-1"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:32:19.000Z",
"2021-10-15T01:42:19.000Z",
"2021-10-15T02:57:59.000Z",
"2021-10-15T04:07:59.000Z",
"2021-10-15T05:17:59.000Z",
"2021-10-15T06:27:59.000Z",
"2021-10-15T07:37:59.000Z",
"2021-10-15T08:47:59.000Z",
"2021-10-15T09:57:59.000Z",
"2021-10-15T11:07:59.000Z"
]
}
}
},
"end": {
"location": {
"id": "station-3"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:43:21.000Z",
"2021-10-15T01:53:21.000Z",
"2021-10-15T03:09:01.000Z",
"2021-10-15T04:19:01.000Z",
"2021-10-15T05:29:01.000Z",
"2021-10-15T06:39:01.000Z",
"2021-10-15T07:49:01.000Z",
"2021-10-15T08:59:01.000Z",
"2021-10-15T10:09:01.000Z",
"2021-10-15T11:19:01.000Z"
]
}
}
},
"./komn-mobility-0_9_3.distance": "22 km"
},
{
"id": "station-3-to-station-2",
"start": {
"location": {
"id": "station-3"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:32:19.000Z",
"2021-10-15T01:42:19.000Z",
"2021-10-15T02:57:59.000Z",
"2021-10-15T04:07:59.000Z",
"2021-10-15T05:17:59.000Z",
"2021-10-15T06:27:59.000Z",
"2021-10-15T07:37:59.000Z",
"2021-10-15T08:47:59.000Z",
"2021-10-15T09:57:59.000Z",
"2021-10-15T11:07:59.000Z"
]
}
}
},
"end": {
"location": {
"id": "station-2"
},
"time": {
"schedule": {
"times": [
"2021-10-15T00:43:21.000Z",
"2021-10-15T01:53:21.000Z",
"2021-10-15T03:09:01.000Z",
"2021-10-15T04:19:01.000Z",
"2021-10-15T05:29:01.000Z",
"2021-10-15T06:39:01.000Z",
"2021-10-15T07:49:01.000Z",
"2021-10-15T08:59:01.000Z",
"2021-10-15T10:09:01.000Z",
"2021-10-15T11:19:01.000Z"
]
}
}
},
"./komn-mobility-0_9_3.distance": "12 km"
}
]
}
]
}
}
}
In metro the use case can be that each ticket for a particular fulfillment can be used at any of the scheduled time and need not be required from the user. So the user is buying a ticket for any one of the scheduled times for trips between the station. In this case as well showing them as one denormalized object in the items array makes sense.
@techframewirk The above structure will not work the mapping of departure and arrival times in the schedules
array is underspecified.
Secondly, all beckn APIs are stateless. A metro BPP catalog may have specific arrival and departure times in its schedule. That doesn't mean that an Order
object will have timings. A complete confirm
request body in the case of metro will look like this.
{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "confirm",
"core_version": "0.9.3",
"transaction_id": "c0c86294-4b47-426e-b752-6db4bd60fa84",
"message_id": "c0c86294-4b47-426e-b752-6db4bd60fa84",
"timestamp": "2021-03-23T10:00:40.065Z"
},
"message": {
"order": {
"items": [
{
"id": "1",
"descriptor" : {
"name" : "Single Journey Ticket",
"code" : "SJT"
},
"location_id": "station-1",
"fulfillment_id" : "station-1-to-station-2",
"price" : {
"currency" : "INR",
"value" : "20"
}
}
],
"fulfillment" : {
"id" : "station-1-to-station-2",
"start" : {
"location" : {
"id": "station-1",
"gps": "12.9349377,77.6055586",
"descriptor" : {
"name" : "Station 1",
"code" : "STN1"
}
}
},
"end" : {
"id": "station-2",
"gps": "12.9349377,77.6055586",
"descriptor" : {
"name" : "Station 3",
"code" : "STN3"
}
},
"./komn-mobility-0_9_3.distance" : "12 km"
},
"quote": {
"price": {
"currency": "INR",
"value": "25"
},
"breakup": [
{
"title": "Fare",
"price": {
"currency": "INR",
"value": "20"
}
},
{
"title": "cgst",
"price": {
"currency": "INR",
"value": "5"
}
},
{
"title": "sgst",
"price": {
"currency": "INR",
"value": "5"
}
}
]
},
"payment": {
"uri": "payto://upi/example@upi?amount=$currency:$value&message=payment_msg",
"tl_method": "PAYTO",
"type": "ON-ORDER",
"status": "PAID",
"params": {
"value": "25",
"currency": "INR",
"transaction_id" : "6db4bd60fa84"
}
}
}
}
}
As you can see, the BAP will use the select
, init
and confirm
calls to get quote, get payment terms and confirm the order respectively.
Lastly, on a different though related note, I feel that the schedules
array may not be required at all as any schedule can be managed via the fulfillments
array in the catalog.
I don't understand the comment about being stateless. In the JSON you have shared as well as the one I have shared time is present in fulfillment. If the response from the BPP has fulfillment array each with its own separate time, then the select call will have to select one of the objects in the fulfillment array which would specify it to a particular time. The item being selected is not just for that time but for all the trips between the stations which is why I feel fulfillment times should be an array.
Made an edit to the first JSON. Did not realize time
was an object. It is fixed.
@techframewirk, by "stateless", I mean the API specification for each endpoint (search
,on_search
, select
, on_select
,...) are independent of each other's state.
That means, in the case of a Metro BPP on a typical mobility network, the required
fields of the select
call is independent of the schema of the previous on_search
callback.
You are absolutely right about the fact that a metro BPP catalog may have specific arrival and departure times in its schedule.
And it is a well known fact that _booking a metro ticket typically, does not need the departure time information_ of a train.
Keeping the above two facts in mind, and the fact that the APIs are stateless, we can conclude that even though the fulfillment.start.time
property in on_search
call is required
, it does not mean that the
fulfillment.start.timeproperty will also be
requiredin the
selectcall. Because, a Metro BPP's policy does _not_ require
fulfillment.start.time` in the select call.
So the statement in your last response that,
If the response from the BPP has fulfillment array each with its own separate time, then the select call will have to select one of the objects in the fulfillment array which would specify it to a particular time
is incorrect. The select
call schema does not have any dependency on the fulfillments
array sent in on_search
.
Furthermore, if you are wondering,
"How will the BAP or BPP know which 'property per schema per endpoint per use case' is
required
?
That will be defined in the network's policy. The JSON schema of each use case a network supports are part of its network policy.
That means before deployment, the BAP and BPP are already aware of the required properties per schema per endpoint per use case and have implemented them as part of their respective business logic.
Fulfillment.start.time is not required, but isn't fulfillment start location (start station) and fulfillment end location (end station) is required to uniquely identify a ticket. So in select call we will need to select one of them (ie from which station to which station we are taking the ticket). So I can't think of how we can represent select without mentioning which fulfillment they are selecting. Can you show an example?
Furthermore this will still be stateless as here fulfillment_id will be as unique as the item id. The select call won't be dependent on the search call.
Made a small correction to the Order
object. The location
object was missing in fulfillment.end
. And the API was on_confirm
, not confirm
.
{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "on_confirm",
"core_version": "0.9.3",
"transaction_id": "c0c86294-4b47-426e-b752-6db4bd60fa84",
"message_id": "c0c86294-4b47-426e-b752-6db4bd60fa84",
"timestamp": "2021-03-23T10:00:40.065Z"
},
"message": {
"order": {
"id" : "example-order-id",
"items": [
{
"id": "1",
"descriptor" : {
"name" : "Single Journey Ticket",
"code" : "SJT"
},
"location_id": "station-1",
"fulfillment_id" : "station-1-to-station-2",
"price" : {
"currency" : "INR",
"value" : "20"
}
}
],
"fulfillment" : {
"id" : "station-1-to-station-2",
"start" : {
"location" : {
"id": "station-1",
"gps": "12.9349377,77.6055586",
"descriptor" : {
"name" : "Station 1",
"code" : "STN1"
}
}
},
"end" : {
"location" : {
"id": "station-2",
"gps": "12.9349377,77.6055586",
"descriptor" : {
"name" : "Station 2",
"code" : "STN2"
}
}
},
"./komn-mobility-0_9_3.distance" : "12 km"
},
"quote": {
"price": {
"currency": "INR",
"value": "25"
},
"breakup": [
{
"title": "Fare",
"price": {
"currency": "INR",
"value": "20"
}
},
{
"title": "CGST",
"price": {
"currency": "INR",
"value": "5"
}
},
{
"title": "SGST",
"price": {
"currency": "INR",
"value": "5"
}
}
]
},
"payment": {
"uri": "payto://upi/example@upi?amount=$currency:$value&message=payment_msg",
"tl_method": "PAYTO",
"type": "ON-ORDER",
"status": "PAID",
"params": {
"value": "25",
"currency": "INR",
"transaction_id" : "6db4bd60fa84"
}
}
}
}
}
How would the corresponding on_search be? We need to provide the schedule timings there right? How to describe them there is the problem I am having. And select would need fulfillment_id right?
I have added a Metro Schedule Catalog that reuses existing components of the core specification for a Metro Schedule as opposed to the current representation of a Metro Catalog.
The current catalog object can be seen here
I propose the following object to represent the same schedule. Shown for 3 stations.
Please note the denormalized
items
array.