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}