diff --git a/CHANGELOG.md b/CHANGELOG.md index a1859b6..711baec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ Versioning]. ## [Unreleased] +* Add `invoice_number`, `currency`, `issued_at`, and `metadata` fields to the + `Invoice`. +* Fix issue where `get_customer_costs` queries would fail when provided + timeframe filters with non-UTC offsets. + ## [0.9.0] - 2024-01-17 * Support `additional_emails` field on `Customer`. diff --git a/src/client/customers.rs b/src/client/customers.rs index 7432379..35728fe 100644 --- a/src/client/customers.rs +++ b/src/client/customers.rs @@ -21,7 +21,7 @@ use reqwest::{Method, RequestBuilder}; use serde::{Deserialize, Serialize}; use serde_enum_str::{Deserialize_enum_str, Serialize_enum_str}; use time::format_description::well_known::Rfc3339; -use time::OffsetDateTime; +use time::{OffsetDateTime, UtcOffset}; use crate::client::taxes::{TaxId, TaxIdRequest}; use crate::client::Client; @@ -481,10 +481,24 @@ impl Filterable> for RequestBuilder { self = self.query(&[("group_by", group_by)]); } if let Some(timeframe_start) = &filter.timeframe_start { - self = self.query(&[("timeframe_start", timeframe_start.format(&Rfc3339).unwrap())]); + self = self.query(&[( + "timeframe_start", + timeframe_start + // Orb requires supplied datetimes be in UTC + .to_offset(UtcOffset::UTC) + .format(&Rfc3339) + .unwrap(), + )]); } if let Some(timeframe_end) = &filter.timeframe_end { - self = self.query(&[("timeframe_end", timeframe_end.format(&Rfc3339).unwrap())]); + self = self.query(&[( + "timeframe_end", + timeframe_end + // Orb requires supplied datetimes be in UTC + .to_offset(UtcOffset::UTC) + .format(&Rfc3339) + .unwrap(), + )]); } self } diff --git a/src/client/invoices.rs b/src/client/invoices.rs index b3fb1cd..7ee9ab3 100644 --- a/src/client/invoices.rs +++ b/src/client/invoices.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::collections::BTreeMap; + use futures_core::Stream; use reqwest::Method; use serde::{Deserialize, Serialize}; @@ -38,8 +40,12 @@ pub struct Invoice { /// The issue date of the invoice. #[serde(with = "time::serde::rfc3339")] pub invoice_date: OffsetDateTime, + /// An automatically generated number to help track and reconcile invoices. + pub invoice_number: String, /// The link to download the PDF representation of the invoice. pub invoice_pdf: Option, + /// An ISO 4217 currency string, or "credits" + pub currency: String, /// The total after any minimums, discounts, and taxes have been applied. pub total: String, /// This is the final amount required to be charged to the @@ -49,10 +55,17 @@ pub struct Invoice { /// The time at which the invoice was created. #[serde(with = "time::serde::rfc3339")] pub created_at: OffsetDateTime, + /// The time at which the invoice was issued. + #[serde(with = "time::serde::rfc3339::option")] + pub issued_at: Option, /// The link to the hosted invoice pub hosted_invoice_url: Option, /// The status (see [`InvoiceStatusFilter`] for details) pub status: String, + /// Arbitrary metadata that is attached to the invoice. Cannot be nested, must have string + /// values. + #[serde(default)] + pub metadata: BTreeMap, // TODO: many missing fields. }