versa 1.9.0-rc1

Versa types and utilities for developing Versa client applications in Rust
Documentation
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;

// Feature flagged imports

#[cfg(feature = "diesel")]
use std::io::Write;

#[cfg(feature = "diesel")]
use diesel::deserialize::{self, FromSql, FromSqlRow};
#[cfg(feature = "diesel")]
use diesel::prelude::*;
#[cfg(feature = "diesel")]
use diesel::serialize::{self, IsNull, Output, ToSql};
#[cfg(feature = "diesel")]
use diesel::{expression::AsExpression, sql_types::Text};

#[cfg(feature = "diesel")]
use diesel::mysql::{Mysql, MysqlValue};

////////////////////////////////////////////////////////////////////
///
/// TransactionEvent
/// A subset of webhook event types indicating the protocol events
/// that are orchestrated directly between senders and receivers.
///
////////////////////////////////////////////////////////////////////

#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[cfg_attr(
  feature = "diesel",
  derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow)
)]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
pub enum TransactionEvent {
  #[serde(rename = "booking")]
  Booking,
  #[serde(rename = "invoice")]
  Invoice,
  #[serde(rename = "itinerary")]
  Itinerary,
  #[serde(rename = "receipt")]
  Receipt,
}

impl fmt::Display for TransactionEvent {
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    let serialized = serde_json::to_string(self).unwrap().replace("\"", "");
    write!(f, "{}", serialized)
  }
}

impl FromStr for TransactionEvent {
  type Err = String;

  fn from_str(s: &str) -> Result<Self, Self::Err> {
    match s {
      "booking" => Ok(TransactionEvent::Booking),
      "invoice" => Ok(TransactionEvent::Invoice),
      "itinerary" => Ok(TransactionEvent::Itinerary),
      "receipt" => Ok(TransactionEvent::Receipt),
      _ => Err("Unrecognized TransactionEvent enum variant".to_string()),
    }
  }
}

impl Into<WebhookEventType> for TransactionEvent {
  fn into(self) -> WebhookEventType {
    match self {
      TransactionEvent::Booking => WebhookEventType::Booking,
      TransactionEvent::Invoice => WebhookEventType::Invoice,
      TransactionEvent::Itinerary => WebhookEventType::Itinerary,
      TransactionEvent::Receipt => WebhookEventType::Receipt,
    }
  }
}

impl TryFrom<WebhookEventType> for TransactionEvent {
  type Error = String;

  fn try_from(value: WebhookEventType) -> Result<Self, Self::Error> {
    match value {
      WebhookEventType::Itinerary => Ok(TransactionEvent::Itinerary),
      WebhookEventType::Receipt => Ok(TransactionEvent::Receipt),
      _ => Err(format!(
        "TransactionEvent cannot be created from WebhookEventType::{}",
        value
      )),
    }
  }
}

#[cfg(feature = "diesel")]
impl ToSql<Text, Mysql> for TransactionEvent {
  fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
    out.write_all(&*self.to_string().as_bytes())?;
    Ok(IsNull::No)
  }
}

#[cfg(feature = "diesel")]
impl FromSql<Text, Mysql> for TransactionEvent {
  fn from_sql(bytes: MysqlValue<'_>) -> deserialize::Result<Self> {
    match bytes.as_bytes() {
      b"itinerary" => Ok(TransactionEvent::Itinerary),
      b"receipt" => Ok(TransactionEvent::Receipt),
      _ => Err("Unrecognized misuse_code enum variant".into()),
    }
  }
}

////////////////////////////////////////////////////////////////////
///
/// WebhookEventType
/// The superset of webhook event types supported by Versa services.
///
////////////////////////////////////////////////////////////////////

#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[cfg_attr(
  feature = "diesel",
  derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow)
)]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
pub enum WebhookEventType {
  #[serde(rename = "booking")]
  Booking,
  #[serde(rename = "booking.decrypted")]
  BookingDecrypted,
  #[serde(rename = "customer.deregistered_by_sender")]
  CustomerDeregisteredBySender,
  #[serde(rename = "customer.registered_by_sender")]
  CustomerRegisteredBySender,
  #[serde(rename = "invoice")]
  Invoice,
  #[serde(rename = "invoice.decrypted")]
  InvoiceDecrypted,
  #[serde(rename = "itinerary")]
  Itinerary,
  #[serde(rename = "itinerary.decrypted")]
  ItineraryDecrypted,
  #[serde(rename = "receipt")]
  Receipt,
  #[serde(rename = "receipt.decrypted")]
  ReceiptDecrypted,
  #[serde(rename = "transit_route.status.updated")]
  TransitRouteStatusUpdated,
  #[serde(rename = "transit_route.location.updated")]
  TransitRouteLocationUpdated,
}

impl fmt::Display for WebhookEventType {
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    let serialized = serde_json::to_string(self).unwrap().replace("\"", "");
    write!(f, "{}", serialized)
  }
}

impl FromStr for WebhookEventType {
  type Err = String;

  fn from_str(s: &str) -> Result<Self, Self::Err> {
    match s {
      "customer.deregistered_by_sender" => Ok(WebhookEventType::CustomerDeregisteredBySender),
      "customer.registered_by_sender" => Ok(WebhookEventType::CustomerRegisteredBySender),
      "itinerary" => Ok(WebhookEventType::Itinerary),
      "itinerary.decrypted" => Ok(WebhookEventType::ItineraryDecrypted),
      "receipt" => Ok(WebhookEventType::Receipt),
      "receipt.decrypted" => Ok(WebhookEventType::ReceiptDecrypted),
      "transit_route.status.updated" => Ok(WebhookEventType::TransitRouteStatusUpdated),
      "transit_route.location.updated" => Ok(WebhookEventType::TransitRouteLocationUpdated),
      _ => Err("Unrecognized WebhookEventType enum variant".to_string()),
    }
  }
}

#[cfg(feature = "diesel")]
impl ToSql<Text, Mysql> for WebhookEventType {
  fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
    out.write_all(&*self.to_string().as_bytes())?;
    Ok(IsNull::No)
  }
}

#[cfg(feature = "diesel")]
impl FromSql<Text, Mysql> for WebhookEventType {
  fn from_sql(bytes: MysqlValue<'_>) -> deserialize::Result<Self> {
    match bytes.as_bytes() {
      b"customer.deregistered_by_sender" => Ok(WebhookEventType::CustomerDeregisteredBySender),
      b"customer.registered_by_sender" => Ok(WebhookEventType::CustomerRegisteredBySender),
      b"itinerary" => Ok(WebhookEventType::Itinerary),
      b"itinerary.decrypted" => Ok(WebhookEventType::ItineraryDecrypted),
      b"receipt" => Ok(WebhookEventType::Receipt),
      b"receipt.decrypted" => Ok(WebhookEventType::ReceiptDecrypted),
      b"transit_route.status.updated" => Ok(WebhookEventType::TransitRouteStatusUpdated),
      b"transit_route.location.updated" => Ok(WebhookEventType::TransitRouteLocationUpdated),
      _ => Err("Unrecognized misuse_code enum variant".into()),
    }
  }
}

////////////////////////////////////////////////////////////////////
///
/// WebhookEvent
/// The standard object structure for all webhook events sent
/// over the Versa network.
///
////////////////////////////////////////////////////////////////////

#[derive(Deserialize, Serialize)]
pub struct WebhookEvent<T> {
  pub event: WebhookEventType,
  pub event_id: Option<String>,
  pub event_at: Option<i64>,
  pub delivery_id: Option<String>,
  pub delivery_at: Option<i64>,
  pub data: T,
}