orb_billing/client/
plans.rs

1// Copyright Materialize, Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License in the LICENSE file at the
6// root of this repository, or online at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::collections::BTreeMap;
17
18use futures_core::Stream;
19use reqwest::Method;
20use serde::{Deserialize, Serialize};
21use time::OffsetDateTime;
22
23use crate::client::Client;
24use crate::config::ListParams;
25use crate::error::Error;
26use crate::util::StrIteratorExt;
27
28const PLANS_PATH: [&str; 1] = ["plans"];
29
30/// A plan ID.
31#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
32pub enum PlanId<'a> {
33    /// An Orb plan ID.
34    #[serde(rename = "plan_id")]
35    Orb(&'a str),
36    /// An external plan ID.
37    #[serde(rename = "external_plan_id")]
38    External(&'a str),
39}
40
41impl<'a> Default for PlanId<'a> {
42    fn default() -> PlanId<'a> {
43        PlanId::Orb("")
44    }
45}
46
47/// An Orb plan.
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
49pub struct Plan {
50    /// The Orb-assigned unique identifier for the plan.
51    pub id: String,
52    /// An optional user-defined ID for this plan resource, used throughout
53    /// the system as an alias for this plan.
54    #[serde(rename = "external_plan_id")]
55    pub external_id: Option<String>,
56    /// A human-readable name for the plan.
57    pub name: Option<String>,
58    /// A human-readable description of the plan.
59    pub description: String,
60    /// The time at which the plan was created.
61    #[serde(with = "time::serde::rfc3339")]
62    pub created_at: OffsetDateTime,
63    /// The parent plan id if the given plan was created by overriding one or more of the parent's
64    /// prices.
65    pub base_plan_id: Option<String>,
66    /// Arbitrary metadata that is attached to the plan. Cannot be nested, must have string values.
67    #[serde(default)]
68    pub metadata: BTreeMap<String, String>,
69    // TODO: many missing fields.
70}
71
72impl Client {
73    /// Lists all plans.
74    ///
75    /// The underlying API call is paginated. The returned stream will fetch
76    /// additional pages as it is consumed.
77    pub fn list_plans(&self, params: &ListParams) -> impl Stream<Item = Result<Plan, Error>> + '_ {
78        let req = self.build_request(Method::GET, PLANS_PATH);
79        self.stream_paginated_request(params, req)
80    }
81
82    /// Gets a plan by ID.
83    pub async fn get_plan(&self, id: &str) -> Result<Plan, Error> {
84        let req = self.build_request(Method::GET, PLANS_PATH.chain_one(id));
85        let res = self.send_request(req).await?;
86        Ok(res)
87    }
88
89    /// Gets a plan by external ID.
90    pub async fn get_plan_by_external_id(&self, external_id: &str) -> Result<Plan, Error> {
91        let req = self.build_request(
92            Method::GET,
93            PLANS_PATH
94                .chain_one("external_plan_id")
95                .chain_one(external_id),
96        );
97        let res = self.send_request(req).await?;
98        Ok(res)
99    }
100}