gistools/readers/gtfs/schedule/
fare_products.rs

1use crate::readers::csv::parse_csv_as_record;
2use alloc::{collections::BTreeMap, string::String};
3use s2json::MValueCompatible;
4
5/// # Fare Products
6///
7/// **Optional**
8/// Describes different fare products riders can purchase.
9/// Used by GTFS-Fares V2 to model fare product costs, media, and potential discounts for multi-leg journeys.
10///
11/// Multiple rows with the same `fare_product_id` can exist, each paired with a different `fare_media_id`.
12#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
13pub struct GTFSFareProduct {
14    /// **Required**
15    /// Identifies a fare product or set of fare products.
16    pub fare_product_id: String,
17    /// **Optional**
18    /// The name of the fare product as displayed to riders.
19    pub fare_product_name: Option<String>,
20    /// **Optional**
21    /// Identifies a rider category eligible for the fare product.
22    ///
23    /// If fare_products.rider_category_id is empty, the fare product is eligible for any
24    /// rider_category_id.
25    ///
26    /// When multiple rider categories are eligible for a single fare product specified by a
27    /// fare_product_id, there must be only one of these rider categories indicated as the default
28    /// rider category (is_default_fare_category = 1).
29    pub rider_category_id: Option<String>,
30    /// **Optional**
31    /// Identifies a fare media (`fare_media.fare_media_id`) that can be employed to use this fare product.
32    /// When empty, the fare media is unknown.
33    pub fare_media_id: Option<String>,
34    /// **Required**
35    /// The cost of the fare product. May be:
36    /// - Negative: Transfer discount
37    /// - Zero: Free fare
38    /// - Positive: Standard fare cost
39    pub amount: f64,
40    /// **Required**
41    /// Currency code (e.g., "USD", "EUR") for the cost of this product.
42    pub currency: String,
43}
44impl GTFSFareProduct {
45    /// Create a new GTFSFareProduct
46    pub fn new(source: &str) -> BTreeMap<String, GTFSFareProduct> {
47        let mut res = BTreeMap::new();
48        for record in parse_csv_as_record::<GTFSFareProduct>(source, None, None) {
49            res.insert(record.fare_product_id.clone(), record);
50        }
51        res
52    }
53}