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

Extend system_pricing_plans.json #252

Merged
merged 12 commits into from
Oct 14, 2020
77 changes: 76 additions & 1 deletion gbfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ Example: `41.890169` for the Colosseum in Rome.
Example: `12.492269` for the Colosseum in Rome.
* Non-negative Integer - An integer greater than or equal to 0.
* Non-negative Float - A floating point number greater than or equal to 0.
* Float - A floating point number.
josee-sabourin marked this conversation as resolved.
Show resolved Hide resolved
* Timezone - TZ timezone from the https://www.iana.org/time-zones. Timezone names never contain the space character but may contain an underscore. Refer to http://en.wikipedia.org/wiki/List_of_tz_zones for a list of valid values.
Example: `Asia/Tokyo`, `America/Los_Angeles` or `Africa/Cairo`.
* URI *(added in v1.1)* - A fully qualified URI that includes the scheme (e.g., `com.abcrental.android://`), and any special characters in the URI must be correctly escaped. See the following http://www.w3.org/Addressing/URL/4_URI_Recommentations.html for a description of how to create fully qualified URI values. Note that URIs may be URLs.
Expand Down Expand Up @@ -468,6 +469,7 @@ Field Name | Required | Type | Defines
\- `vehicle_type_id` <br/>*(added in v2.1-RC)* | Conditionally Required | ID | The vehicle_type_id of this vehicle as described in [vehicle_types.json](#vehicle_typesjson-added-in-v21-rc). This field is required if the [vehicle_types.json](#vehicle_typesjson-added-in-v21-rc) is defined.
\- `last_reported` <br/>*(added in v2.1-RC)* | Optional | Timestamp | The last time this vehicle reported its status to the operator's backend.
\- `current_range_meters` <br/>*(added in v2.1-RC)* | Conditionally Required | Non-negative float | If the corresponding vehicle_type definition for this vehicle has a motor, then this field is required. This value represents the furthest distance in meters that the vehicle can travel without recharging or refueling with the vehicle's current charge or fuel.
\- `pricing_plan_id` | Optional | ID | The `plan_id` of the pricing plan this vehicle is eligible for as described in [system_pricing_plans.json](#system_pricing_plans.json).
Copy link
Contributor

@sfaubert1 sfaubert1 Oct 6, 2020

Choose a reason for hiding this comment

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

I understand that the pricing_plan_id is at the vehicle type level (instead of the vehicle type at the pricing level) to allow for easier dynamic pricing based on location, but based on my comment from September 15th (about the same plan having different pricing based on the vehicle type), this would be confusing.

For example, if vehicle ABC is eligible for plan 123 with a certain per_min_princing and vehicle XYZ is also eligible for plan 123 but with another per_min_princing. Both ABC and XYZ vehicles would be linked to the same pricing_plan_id=123, but there would actually be 2 objects with plan_id=123 in system_pricing_plans including different per_min_princing based on the vehicle type and no way to know which vehicle is linked to which of the plan_id=123 objects in this case (without data manipulation).

I'm curious to know if we are the only ones with this particular case?

(FYI the "vehicle_type_id" is still in the system_pricing_plans.json example)

Copy link
Contributor Author

@josee-sabourin josee-sabourin Oct 6, 2020

Choose a reason for hiding this comment

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

This would effectively be two different pricing plans, and therefore would have two separate plan IDs, for example plan ID 123-ABC and plan ID 123-XYZ, the public name for these can be the same, but in the back end they are different. As a general rule of thumb, even if the public plan name is the same (ex: one-way), if the prices are different, they should be treated as separate plans with separate plan IDs.

Thanks for catching the example error! I'll make sure to fix that!


Example:

Expand Down Expand Up @@ -576,10 +578,83 @@ Field Name | Required | Type | Defines
\-&nbsp;`url` | Optional | URL | URL where the customer can learn more about this pricing plan.
\-&nbsp;`name` | Yes | String | Name of this pricing plan.
\-&nbsp;`currency` | Yes | String | Currency used to pay the fare. <br /><br /> This pricing is in ISO 4217 code: http://en.wikipedia.org/wiki/ISO_4217 <br />(e.g. `CAD` for Canadian dollars, `EUR` for euros, or `JPY` for Japanese yen.)
\-&nbsp;`price` | Yes | Non-negative float OR String | Fare price, in the unit specified by currency. If String, must be in decimal monetary value.
\-&nbsp;`price` | Yes | String | Fare price, in the unit specified by currency. Must be in decimal monetary value.<br /><br />In case of non-rate price, this field is the total price. In case of rate price, this field is the base price that is charged only once per trip (e.g., price for unlocking) in addition to `per_km_pricing` and/or `per_min_pricing`.
\-&nbsp;`is_taxable` | Yes | Boolean | Will additional tax be added to the base price?<br /><br />`true` - Yes.<br /> `false` - No. <br /><br />`false` may be used to indicate that tax is not charged or that tax is included in the base price.
\-&nbsp;`description` | Yes | String | Customer-readable description of the pricing plan. This should include the duration, price, conditions, etc. that the publisher would like users to see.
\-&nbsp;`per_km_pricing` | Optional | Array | Array of segments when the price is a function of distance travelled, displayed in kilometers.<br /><br />Total price is the addition of `price` and all segments in `per_km_pricing` and `per_min_pricing`. If this array is not provided, there are no variable prices based on distance.
&emsp;&emsp;\-&nbsp;`start` | Yes | Non-Negative Integer | Number of kilometers that have to elapse before this segment starts applying.
&emsp;&emsp;\-&nbsp;`rate` | Yes | String | Rate that is charged for each kilometer `interval` after the `start`. Must be in decimal monetary value. Can be a negative number, which indicates that the traveller will receive a discount.
josee-sabourin marked this conversation as resolved.
Show resolved Hide resolved
&emsp;&emsp;\-&nbsp;`interval` | Yes | Non-Negative Integer | Interval in kilometers at which the `rate` of this segment is either reapplied indefinitely, or if defined, up until (but not including) `end` kilometer.<br /><br />An interval of 0 indicates the rate is only charged once.
&emsp;&emsp;\-&nbsp; `end` | Optional | Non-Negative Integer | The kilometer at which the rate will no longer apply.<br /><br /> If this field is empty, the price issued for this segment is charged until the trip ends, in addition to following segments.
\-&nbsp;`per_min_pricing` | Optional | Array | Array of segments when the price is a function of time travelled, displayed in minutes.<br /><br />Total price is the addition of `price` and all segments in `per_km_pricing` and `per_min_pricing`. If this array is not provided, there are no variable prices based on time.
&emsp;&emsp;\-&nbsp;`start` | Yes | Non-Negative Integer | Number of minutes that have to elapse before this segment starts applying.
&emsp;&emsp;\-&nbsp;`rate` | Yes | String | Rate that is charged for each minute `interval` after the `start`. Must be in decimal monetary value. Can be a negative number, which indicates that the traveller will receive a discount.
&emsp;&emsp;\-&nbsp;`interval` | Yes | Non-Negative Integer | Interval in minutes at which the `rate` of this segment is either reapplied indefinitely, or if defined, up until (but not including) `end` minute.<br /><br />An interval of 0 indicates the rate is only charged once.
&emsp;&emsp;\-&nbsp; `end` | Yes | Non-Negative Integer | The minute at which the rate will no longer apply.<br /><br />If this field is empty, the price issued for this segment is charged until the trip ends, in addition to following segments.
\-&nbsp;`surge_pricing` | Optional | Boolean | Is there currently an increase in price in response to increased demand in this pricing plan? If this field is empty, it means these is no surge pricing in effect.<br /><br />`true` - Surge pricing is in effect.<br /> `false` - Surge pricing is not in effect.


Example:

The user does not pay more than the base price for the first 10 km. After 10 km the user pays $1 per km. After 25 km the user pays $0.50 per km and an additional $3 every 5 km, the extension price, in addition to $0.50 per km.

```jsonc
{
"plans": {
"plan_id": "plan2",
"vehicle_type_id": "bike1",
"name": "One-Way",
"currency": "USD",
"price": 2,
"is_taxable": false,
"description": "Includes 10km, overage fees apply after 10km.",
"per_km_pricing": [
{
"start": 10,
"rate": 1,
"interval": 1,
"end": 25
},
{
"start": 25,
"rate": 0.5,
"interval": 1
},
{
"start": 25,
"rate": 3,
"interval": 5
}
]
}
}
```
Example:

This example demonstrates a pricing scheme that has a rate both by minute and by km. The user is charged $0.25 per km as well as $0.50 per minute. Both of these rates happen concurrently and are not dependent on one another.
```jsonc
{
"plans": {
"plan_id": "plan3",
"vehicle_type_id": "scooter1",
"name": "Simple Rate",
"currency": "CAD",
"price": 3,
"is_taxable": true,
"description": "$3 unlock fee, $0.25 per kilometer and 0.50 per minute.",
"per_km_pricing": {
"start": 0,
"rate": 0.25,
"interval": 1,
},
"per_min_pricing": {
"start": 0,
"rate": 0.50,
"interval": 1
}
barbeau marked this conversation as resolved.
Show resolved Hide resolved
}
}
```
### system_alerts.json
This feed is intended to inform customers about changes to the system that do not fall within the normal system operations. For example, system closures due to weather would be listed here, but a system that only operated for part of the year would have that schedule listed in the system_calendar.json feed.<br />
Obsolete alerts should be removed so the client application can safely present to the end user everything present in the feed.
Expand Down