paystack/models/
virtual_terminal.rs

1use std::fmt;
2
3use derive_builder::Builder;
4use serde::{Deserialize, Serialize};
5
6use super::Currency;
7
8#[derive(Debug, Serialize, Deserialize, Clone, Builder, Default)]
9pub struct VirtualTerminalRequestData {
10    /// Name of the virtual terminal
11    pub name: String,
12    /// An array of objects containing the notification recipients for payments to the Virtual Terminal.
13    /// Create with the `DestinationRequestDataBuilder` struct.
14    pub destinations: Vec<DestinationRequest>,
15    /// Stringified JSON object of custom data.
16    /// Kindly check the Paystack API Metadata page for more information
17    #[builder(setter(strip_option), default)]
18    pub metadata: Option<String>,
19    /// The transaction currency for the Virtual Terminal. Defaults to your integration currency
20    #[builder(setter(strip_option), default)]
21    pub currency: Option<Vec<Currency>>,
22    /// An array of objects representing custom fields to display on the form.
23    /// Create with `CustomFieldBuilder` struct.
24    #[builder(setter(strip_option), default)]
25    pub custom_field: Option<Vec<CustomField>>,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone, Builder, Default)]
29pub struct DestinationRequest {
30    /// The Whatsapp phone number to send notifications to.
31    pub target: String,
32    /// A descriptive label
33    pub name: String,
34}
35
36#[derive(Debug, Serialize, Deserialize, Clone, Builder, Default)]
37pub struct CustomField {
38    /// What will be displayed on the Virtual Terminal page
39    pub display_name: String,
40    /// Parameter for referencing the custom field programmatically
41    pub variable_name: String,
42}
43
44#[derive(Debug, Deserialize, Serialize, Clone, Default)]
45#[serde(rename_all = "camelCase")]
46pub struct VirtualTerminalResponseData {
47    pub id: u64,
48    pub name: String,
49    pub integration: u64,
50    pub domain: String,
51    pub code: String,
52    pub payment_methods: Option<Vec<String>>,
53    pub active: bool,
54    pub metadata: Option<String>,
55    pub connect_account_id: Option<String>,
56    pub destinations: Option<Vec<DestinationResponse>>,
57    pub currency: Option<String>,
58    pub created_at: Option<String>,
59}
60
61#[derive(Debug, Deserialize, Clone, Serialize, Default)]
62pub struct DestinationResponse {
63    pub integration: Option<u32>,
64    pub target: Option<String>,
65    pub name: Option<String>,
66    #[serde(rename = "type")]
67    pub destination_type: Option<String>,
68    pub id: Option<u32>,
69    #[serde(rename = "createdAt")]
70    pub created_at: Option<String>,
71    #[serde(rename = "updatedAt")]
72    pub updated_at: Option<String>,
73}
74
75#[derive(Debug, Serialize, Deserialize, Clone)]
76pub enum VirtualTerminalStatus {
77    Active,
78    Inactive,
79}
80
81impl fmt::Display for VirtualTerminalStatus {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        let lowercase_string = match self {
84            VirtualTerminalStatus::Active => "active",
85            VirtualTerminalStatus::Inactive => "inactive",
86        };
87        write!(f, "{}", lowercase_string)
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn create_virtual_terminal_request() {
97        let destinations = vec![
98            DestinationRequestBuilder::default()
99                .target("Whatsapp-phone-number".to_string())
100                .name("Test-name".to_string())
101                .build()
102                .expect("unable to build destination request"),
103            DestinationRequestBuilder::default()
104                .target("Whatsapp-phone-number-2".to_string())
105                .name("Test-name-2".to_string())
106                .build()
107                .expect("unable to build destination request"),
108        ];
109        let currencies = vec![Currency::NGN, Currency::USD];
110        let custom_field = vec![
111            CustomFieldBuilder::default()
112                .display_name("display-name".to_string())
113                .variable_name("variable-name".to_string())
114                .build()
115                .expect("unable to build custome field"),
116            CustomFieldBuilder::default()
117                .display_name("display-name-2".to_string())
118                .variable_name("variable-name-2".to_string())
119                .build()
120                .expect("unable to build custome field"),
121        ];
122
123        let request = VirtualTerminalRequestDataBuilder::default()
124            .name("Some name".to_string())
125            .destinations(destinations)
126            .currency(currencies)
127            .custom_field(custom_field)
128            .build()
129            .expect("unable to build virtual terminal request");
130
131        assert_eq!(request.name, "Some name");
132        assert!(request.destinations.len() > 0);
133        assert!(request.currency.is_some());
134        assert!(request.custom_field.is_some());
135        assert!(request.metadata.is_none());
136    }
137
138    #[test]
139    fn cannot_create_virtual_terminal_request_without_compulsory_field() {
140        let request = VirtualTerminalRequestDataBuilder::default()
141            .currency(vec![Currency::GHS, Currency::NGN])
142            .build();
143
144        assert!(request.is_err());
145    }
146}