ya_client_model/payment/
invoice_event.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use strum_macros::Display;
4
5use super::DriverStatusProperty;
6
7#[derive(Debug, Serialize, Deserialize, PartialEq)]
8#[serde(rename_all = "camelCase")]
9pub struct InvoiceEvent {
10    pub invoice_id: String,
11    pub event_date: DateTime<Utc>,
12    #[serde(flatten)]
13    pub event_type: InvoiceEventType,
14}
15
16#[derive(Clone, Debug, Display, Serialize, Deserialize, PartialEq)]
17#[serde(tag = "eventType")]
18pub enum InvoiceEventType {
19    InvoiceReceivedEvent,
20    InvoiceAcceptedEvent,
21    InvoiceRejectedEvent {
22        rejection: crate::payment::Rejection,
23    },
24    InvoiceCancelledEvent,
25    InvoiceSettledEvent,
26    InvoicePaymentStatusEvent {
27        property: DriverStatusProperty,
28    },
29    InvoicePaymentOkEvent,
30}
31
32impl InvoiceEventType {
33    pub fn discriminant(&self) -> &'static str {
34        use InvoiceEventType::*;
35        match self {
36            InvoiceReceivedEvent => "RECEIVED",
37            InvoiceAcceptedEvent => "ACCEPTED",
38            InvoiceRejectedEvent { .. } => "REJECTED",
39            InvoiceCancelledEvent => "CANCELLED",
40            InvoiceSettledEvent => "SETTLED",
41            InvoicePaymentStatusEvent { .. } => "PAYMENT_EVENT",
42            InvoicePaymentOkEvent => "PAYMENT_OK",
43        }
44    }
45
46    pub fn details(&self) -> Option<serde_json::Value> {
47        use serde_json::to_value;
48        use InvoiceEventType::*;
49
50        match self {
51            InvoiceRejectedEvent { rejection } => to_value(rejection).ok(),
52            InvoicePaymentStatusEvent { property } => to_value(property).ok(),
53            _ => None,
54        }
55    }
56
57    pub fn from_discriminant_and_details(
58        discriminant: &str,
59        details: Option<serde_json::Value>,
60    ) -> Option<Self> {
61        use serde_json::from_value;
62        use InvoiceEventType::*;
63
64        Some(match (discriminant, details) {
65            ("RECEIVED", _) => InvoiceReceivedEvent,
66            ("ACCEPTED", _) => InvoiceAcceptedEvent,
67            ("REJECTED", Some(details)) => InvoiceRejectedEvent {
68                rejection: from_value(details).ok()?,
69            },
70            ("CANCELLED", _) => InvoiceCancelledEvent,
71            ("SETTLED", _) => InvoiceSettledEvent,
72            ("PAYMENT_EVENT", Some(details)) => InvoicePaymentStatusEvent {
73                property: from_value(details).ok()?,
74            },
75            ("PAYMENT_OK", _) => InvoicePaymentOkEvent,
76            _ => None?,
77        })
78    }
79}
80
81#[cfg(test)]
82mod test {
83    use super::*;
84    use crate::payment::{Rejection, RejectionReason};
85    use bigdecimal::{BigDecimal, FromPrimitive};
86
87    #[test]
88    fn test_serialize_rejected_event_has_flat_rejection() {
89        let ie = InvoiceEvent {
90            invoice_id: "ajdik".to_string(),
91            event_date: DateTime::parse_from_str("2020-12-21T15:51:21.126645Z", "%+")
92                .unwrap()
93                .with_timezone(&Utc),
94            event_type: InvoiceEventType::InvoiceRejectedEvent {
95                rejection: Rejection {
96                    rejection_reason: RejectionReason::UnsolicitedService,
97                    total_amount_accepted: BigDecimal::from_f32(13.14).unwrap(),
98                    message: None,
99                },
100            },
101        };
102
103        assert_eq!(
104            "{\"invoiceId\":\"ajdik\",\
105                \"eventDate\":\"2020-12-21T15:51:21.126645Z\",\
106                \"eventType\":\"InvoiceRejectedEvent\",\
107                \"rejection\":{\
108                    \"rejectionReason\":\"UNSOLICITED_SERVICE\",\
109                    \"totalAmountAccepted\":\"13.14000\"\
110                }\
111             }",
112            serde_json::to_string(&ie).unwrap()
113        );
114    }
115
116    #[test]
117    fn test_deserialize_event() {
118        let ie: InvoiceEvent = serde_json::from_str(
119            "{\
120                \"invoiceId\":\"ajdik\",\
121                \"eventDate\":\"2020-12-21T15:51:21.126645Z\",\
122                \"eventType\":\"InvoiceAcceptedEvent\"\
123            }",
124        )
125        .unwrap();
126
127        assert_eq!(
128            InvoiceEvent {
129                invoice_id: "ajdik".to_string(),
130                event_date: DateTime::parse_from_str("2020-12-21T15:51:21.126645Z", "%+")
131                    .unwrap()
132                    .with_timezone(&Utc),
133                event_type: InvoiceEventType::InvoiceAcceptedEvent,
134            },
135            ie
136        );
137    }
138
139    #[test]
140    fn test_serialize_event_type() {
141        let iet = InvoiceEventType::InvoiceSettledEvent;
142        assert_eq!(
143            "{\"eventType\":\"InvoiceSettledEvent\"}",
144            serde_json::to_string(&iet).unwrap()
145        );
146    }
147
148    #[test]
149    fn test_deserialize_event_type() {
150        let iet: InvoiceEventType =
151            serde_json::from_str("{\"eventType\":\"InvoiceReceivedEvent\"}").unwrap();
152        assert_eq!(InvoiceEventType::InvoiceReceivedEvent, iet);
153    }
154
155    #[test]
156    fn test_deserialize_event_type_from_str() {
157        let iet = InvoiceEventType::from_discriminant_and_details(
158            "REJECTED",
159            InvoiceEventType::InvoiceRejectedEvent {
160                rejection: Default::default(),
161            }
162            .details(),
163        )
164        .unwrap();
165        assert_eq!(
166            InvoiceEventType::InvoiceRejectedEvent {
167                rejection: Default::default()
168            },
169            iet
170        );
171    }
172
173    #[test]
174    fn test_deserialize_event_type_to_string() {
175        assert_eq!(
176            InvoiceEventType::InvoiceSettledEvent.discriminant(),
177            "SETTLED"
178        );
179    }
180}