ya_client_model/payment/
invoice_event.rs1use 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}