beckn / metro-bpp

0 stars 1 forks source link

Incorrect Representation of Catalog Object for Representing Metro Schedule. #1

Closed ravi-prakash-v closed 2 years ago

ravi-prakash-v commented 2 years ago

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.

{
    "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" : "10:00"
                            },
                            "end" : {
                                "location" : {
                                    "id" : "station-2"
                                }
                            },
                            "./komn-mobility-0_9_3.distance" : "12 km"
                        },
                        {
                            "id" : "station-2-to-station-3",
                            "start" : {
                                "location" : {
                                    "id" : "station-2"
                                },
                                "time" : "10:10"
                            },
                            "end" : {
                                "location" : {
                                    "id" : "station-3"
                                }
                            },
                            "./komn-mobility-0_9_3.distance" : "10 km"
                        },
                        {
                            "id" : "station-1-to-station-3",
                            "start" : {
                                "location" : {
                                    "id" : "station-1"
                                },
                                "time" : "10:00"
                            },
                            "end" : {
                                "location" : {
                                    "id" : "station-3"
                                }
                            },
                            "./komn-mobility-0_9_3.distance" : "22 km"
                        },
                        {
                            "id" : "station-3-to-station-2",
                            "start" : {
                                "location" : {
                                    "id" : "station-3"
                                },
                                "time" : "10:20"
                            },
                            "end" : {
                                "location" : {
                                    "id" : "station-2"
                                }
                            },
                            "./komn-mobility-0_9_3.distance" : "12 km"
                        }
                    ]
                }
            ]
        }
    }
}

Please note the denormalized items array.

techframewirk commented 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.

ravi-prakash-v commented 2 years ago

@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.

techframewirk commented 2 years ago

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.

ravi-prakash-v commented 2 years ago

Made an edit to the first JSON. Did not realize time was an object. It is fixed.

ravi-prakash-v commented 2 years ago

@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 thefulfillment.start.timeproperty will also berequiredin theselectcall. Because, a Metro BPP's policy does _not_ requirefulfillment.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.

techframewirk commented 2 years ago

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.

ravi-prakash-v commented 2 years ago

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"
                }
            }
        }
    }
}
techframewirk commented 2 years ago

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?