Skip to main content

tap_node/storage/
models.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::str::FromStr;
4use tap_msg::utils::NameHashable;
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum TransactionType {
9    Transfer,
10    Payment,
11}
12
13impl fmt::Display for TransactionType {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        match self {
16            TransactionType::Transfer => write!(f, "transfer"),
17            TransactionType::Payment => write!(f, "payment"),
18        }
19    }
20}
21
22impl TryFrom<&str> for TransactionType {
23    type Error = String;
24
25    fn try_from(value: &str) -> Result<Self, Self::Error> {
26        match value {
27            "transfer" => Ok(TransactionType::Transfer),
28            "payment" => Ok(TransactionType::Payment),
29            _ => Err(format!("Invalid transaction type: {}", value)),
30        }
31    }
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub enum TransactionStatus {
37    Pending,
38    Confirmed,
39    Failed,
40    Cancelled,
41    Reverted,
42}
43
44impl fmt::Display for TransactionStatus {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            TransactionStatus::Pending => write!(f, "pending"),
48            TransactionStatus::Confirmed => write!(f, "confirmed"),
49            TransactionStatus::Failed => write!(f, "failed"),
50            TransactionStatus::Cancelled => write!(f, "cancelled"),
51            TransactionStatus::Reverted => write!(f, "reverted"),
52        }
53    }
54}
55
56impl TryFrom<&str> for TransactionStatus {
57    type Error = String;
58
59    fn try_from(value: &str) -> Result<Self, Self::Error> {
60        match value {
61            "pending" => Ok(TransactionStatus::Pending),
62            "confirmed" => Ok(TransactionStatus::Confirmed),
63            "failed" => Ok(TransactionStatus::Failed),
64            "cancelled" => Ok(TransactionStatus::Cancelled),
65            "reverted" => Ok(TransactionStatus::Reverted),
66            _ => Err(format!("Invalid transaction status: {}", value)),
67        }
68    }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct Transaction {
73    pub id: i64,
74    pub transaction_type: TransactionType,
75    pub reference_id: String,
76    pub from_did: Option<String>,
77    pub to_did: Option<String>,
78    pub thread_id: Option<String>,
79    pub message_type: String,
80    pub status: TransactionStatus,
81    pub message_json: serde_json::Value,
82    pub created_at: String,
83    pub updated_at: String,
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
87#[serde(rename_all = "snake_case")]
88pub enum MessageDirection {
89    Incoming,
90    Outgoing,
91}
92
93impl fmt::Display for MessageDirection {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        match self {
96            MessageDirection::Incoming => write!(f, "incoming"),
97            MessageDirection::Outgoing => write!(f, "outgoing"),
98        }
99    }
100}
101
102impl TryFrom<&str> for MessageDirection {
103    type Error = String;
104
105    fn try_from(value: &str) -> Result<Self, Self::Error> {
106        match value {
107            "incoming" => Ok(MessageDirection::Incoming),
108            "outgoing" => Ok(MessageDirection::Outgoing),
109            _ => Err(format!("Invalid message direction: {}", value)),
110        }
111    }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct Message {
116    pub id: i64,
117    pub message_id: String,
118    pub message_type: String,
119    pub from_did: Option<String>,
120    pub to_did: Option<String>,
121    pub thread_id: Option<String>,
122    pub parent_thread_id: Option<String>,
123    pub direction: MessageDirection,
124    pub message_json: serde_json::Value,
125    pub created_at: String,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129#[serde(rename_all = "snake_case")]
130pub enum DeliveryStatus {
131    Pending,
132    Success,
133    Failed,
134}
135
136impl fmt::Display for DeliveryStatus {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        match self {
139            DeliveryStatus::Pending => write!(f, "pending"),
140            DeliveryStatus::Success => write!(f, "success"),
141            DeliveryStatus::Failed => write!(f, "failed"),
142        }
143    }
144}
145
146impl TryFrom<&str> for DeliveryStatus {
147    type Error = String;
148
149    fn try_from(value: &str) -> Result<Self, Self::Error> {
150        match value {
151            "pending" => Ok(DeliveryStatus::Pending),
152            "success" => Ok(DeliveryStatus::Success),
153            "failed" => Ok(DeliveryStatus::Failed),
154            _ => Err(format!("Invalid delivery status: {}", value)),
155        }
156    }
157}
158
159impl FromStr for DeliveryStatus {
160    type Err = String;
161
162    fn from_str(s: &str) -> Result<Self, Self::Err> {
163        Self::try_from(s)
164    }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
168#[serde(rename_all = "snake_case")]
169pub enum DeliveryType {
170    /// HTTP/HTTPS delivery to external endpoints
171    Https,
172    /// Internal delivery to agents within the same node
173    Internal,
174    /// Return path delivery for future implementation
175    ReturnPath,
176    /// Pickup delivery for future implementation
177    Pickup,
178}
179
180impl fmt::Display for DeliveryType {
181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182        match self {
183            DeliveryType::Https => write!(f, "https"),
184            DeliveryType::Internal => write!(f, "internal"),
185            DeliveryType::ReturnPath => write!(f, "return_path"),
186            DeliveryType::Pickup => write!(f, "pickup"),
187        }
188    }
189}
190
191impl TryFrom<&str> for DeliveryType {
192    type Error = String;
193
194    fn try_from(value: &str) -> Result<Self, Self::Error> {
195        match value {
196            "https" => Ok(DeliveryType::Https),
197            "internal" => Ok(DeliveryType::Internal),
198            "return_path" => Ok(DeliveryType::ReturnPath),
199            "pickup" => Ok(DeliveryType::Pickup),
200            _ => Err(format!("Invalid delivery type: {}", value)),
201        }
202    }
203}
204
205impl FromStr for DeliveryType {
206    type Err = String;
207
208    fn from_str(s: &str) -> Result<Self, Self::Err> {
209        Self::try_from(s)
210    }
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct Delivery {
215    pub id: i64,
216    pub message_id: String,
217    pub message_text: String,
218    pub recipient_did: String,
219    pub delivery_url: Option<String>,
220    pub delivery_type: DeliveryType,
221    pub status: DeliveryStatus,
222    pub retry_count: i32,
223    pub last_http_status_code: Option<i32>,
224    pub error_message: Option<String>,
225    pub created_at: String,
226    pub updated_at: String,
227    pub delivered_at: Option<String>,
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
231#[serde(rename_all = "snake_case")]
232pub enum SourceType {
233    /// HTTP/HTTPS delivery from external endpoints
234    Https,
235    /// Internal delivery from agents within the same node
236    Internal,
237    /// WebSocket connection
238    WebSocket,
239    /// Return path delivery
240    ReturnPath,
241    /// Pickup delivery
242    Pickup,
243}
244
245impl fmt::Display for SourceType {
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247        match self {
248            SourceType::Https => write!(f, "https"),
249            SourceType::Internal => write!(f, "internal"),
250            SourceType::WebSocket => write!(f, "websocket"),
251            SourceType::ReturnPath => write!(f, "return_path"),
252            SourceType::Pickup => write!(f, "pickup"),
253        }
254    }
255}
256
257impl TryFrom<&str> for SourceType {
258    type Error = String;
259
260    fn try_from(value: &str) -> Result<Self, Self::Error> {
261        match value {
262            "https" => Ok(SourceType::Https),
263            "internal" => Ok(SourceType::Internal),
264            "websocket" => Ok(SourceType::WebSocket),
265            "return_path" => Ok(SourceType::ReturnPath),
266            "pickup" => Ok(SourceType::Pickup),
267            _ => Err(format!("Invalid source type: {}", value)),
268        }
269    }
270}
271
272impl FromStr for SourceType {
273    type Err = String;
274
275    fn from_str(s: &str) -> Result<Self, Self::Err> {
276        Self::try_from(s)
277    }
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
281#[serde(rename_all = "snake_case")]
282pub enum ReceivedStatus {
283    Pending,
284    Processed,
285    Failed,
286}
287
288impl fmt::Display for ReceivedStatus {
289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290        match self {
291            ReceivedStatus::Pending => write!(f, "pending"),
292            ReceivedStatus::Processed => write!(f, "processed"),
293            ReceivedStatus::Failed => write!(f, "failed"),
294        }
295    }
296}
297
298impl TryFrom<&str> for ReceivedStatus {
299    type Error = String;
300
301    fn try_from(value: &str) -> Result<Self, Self::Error> {
302        match value {
303            "pending" => Ok(ReceivedStatus::Pending),
304            "processed" => Ok(ReceivedStatus::Processed),
305            "failed" => Ok(ReceivedStatus::Failed),
306            _ => Err(format!("Invalid received status: {}", value)),
307        }
308    }
309}
310
311impl FromStr for ReceivedStatus {
312    type Err = String;
313
314    fn from_str(s: &str) -> Result<Self, Self::Err> {
315        Self::try_from(s)
316    }
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct Received {
321    pub id: i64,
322    pub message_id: Option<String>,
323    pub raw_message: String,
324    pub source_type: SourceType,
325    pub source_identifier: Option<String>,
326    pub status: ReceivedStatus,
327    pub error_message: Option<String>,
328    pub received_at: String,
329    pub processed_at: Option<String>,
330    pub processed_message_id: Option<String>,
331}
332
333#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
334#[serde(rename_all = "snake_case")]
335pub enum SchemaType {
336    Person,
337    Organization,
338    Thing,
339}
340
341impl fmt::Display for SchemaType {
342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343        match self {
344            SchemaType::Person => write!(f, "Person"),
345            SchemaType::Organization => write!(f, "Organization"),
346            SchemaType::Thing => write!(f, "Thing"),
347        }
348    }
349}
350
351impl TryFrom<&str> for SchemaType {
352    type Error = String;
353
354    fn try_from(value: &str) -> Result<Self, Self::Error> {
355        match value {
356            "Person" => Ok(SchemaType::Person),
357            "Organization" => Ok(SchemaType::Organization),
358            "Thing" => Ok(SchemaType::Thing),
359            _ => Err(format!("Invalid schema type: {}", value)),
360        }
361    }
362}
363
364impl FromStr for SchemaType {
365    type Err = String;
366
367    fn from_str(s: &str) -> Result<Self, Self::Err> {
368        Self::try_from(s)
369    }
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct Customer {
374    pub id: String,
375    pub agent_did: String,
376    pub schema_type: SchemaType,
377
378    // Core fields for natural persons
379    pub given_name: Option<String>,
380    pub family_name: Option<String>,
381    pub display_name: Option<String>,
382
383    // Core fields for organizations
384    pub legal_name: Option<String>,
385    pub lei_code: Option<String>,
386    pub mcc_code: Option<String>,
387
388    // Address fields
389    pub address_country: Option<String>,
390    pub address_locality: Option<String>,
391    pub postal_code: Option<String>,
392    pub street_address: Option<String>,
393
394    // Full schema.org JSON-LD profile
395    pub profile: serde_json::Value,
396
397    // Cached IVMS101 data
398    pub ivms101_data: Option<serde_json::Value>,
399
400    // Metadata
401    pub verified_at: Option<String>,
402    pub created_at: String,
403    pub updated_at: String,
404}
405
406#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
407#[serde(rename_all = "snake_case")]
408pub enum IdentifierType {
409    Did,
410    Email,
411    Phone,
412    Url,
413    Account,
414    Other,
415}
416
417impl fmt::Display for IdentifierType {
418    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419        match self {
420            IdentifierType::Did => write!(f, "did"),
421            IdentifierType::Email => write!(f, "email"),
422            IdentifierType::Phone => write!(f, "phone"),
423            IdentifierType::Url => write!(f, "url"),
424            IdentifierType::Account => write!(f, "account"),
425            IdentifierType::Other => write!(f, "other"),
426        }
427    }
428}
429
430impl TryFrom<&str> for IdentifierType {
431    type Error = String;
432
433    fn try_from(value: &str) -> Result<Self, Self::Error> {
434        match value {
435            "did" => Ok(IdentifierType::Did),
436            "email" => Ok(IdentifierType::Email),
437            "phone" => Ok(IdentifierType::Phone),
438            "url" => Ok(IdentifierType::Url),
439            "account" => Ok(IdentifierType::Account),
440            "other" => Ok(IdentifierType::Other),
441            _ => Err(format!("Invalid identifier type: {}", value)),
442        }
443    }
444}
445
446impl FromStr for IdentifierType {
447    type Err = String;
448
449    fn from_str(s: &str) -> Result<Self, Self::Err> {
450        Self::try_from(s)
451    }
452}
453
454#[derive(Debug, Clone, Serialize, Deserialize)]
455pub struct CustomerIdentifier {
456    pub id: String, // The IRI itself
457    pub customer_id: String,
458    pub identifier_type: IdentifierType,
459    pub verified: bool,
460    pub verification_method: Option<String>,
461    pub verified_at: Option<String>,
462    pub created_at: String,
463}
464
465#[derive(Debug, Clone, Serialize, Deserialize)]
466pub struct CustomerRelationship {
467    pub id: String,
468    pub customer_id: String,
469    pub relationship_type: String,
470    pub related_identifier: String,
471    pub proof: Option<serde_json::Value>,
472    pub confirmed_at: Option<String>,
473    pub created_at: String,
474}
475
476#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
477#[serde(rename_all = "snake_case")]
478pub enum DecisionStatus {
479    Pending,
480    Delivered,
481    Resolved,
482    Expired,
483}
484
485impl fmt::Display for DecisionStatus {
486    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487        match self {
488            DecisionStatus::Pending => write!(f, "pending"),
489            DecisionStatus::Delivered => write!(f, "delivered"),
490            DecisionStatus::Resolved => write!(f, "resolved"),
491            DecisionStatus::Expired => write!(f, "expired"),
492        }
493    }
494}
495
496impl TryFrom<&str> for DecisionStatus {
497    type Error = String;
498
499    fn try_from(value: &str) -> Result<Self, Self::Error> {
500        match value {
501            "pending" => Ok(DecisionStatus::Pending),
502            "delivered" => Ok(DecisionStatus::Delivered),
503            "resolved" => Ok(DecisionStatus::Resolved),
504            "expired" => Ok(DecisionStatus::Expired),
505            _ => Err(format!("Invalid decision status: {}", value)),
506        }
507    }
508}
509
510impl FromStr for DecisionStatus {
511    type Err = String;
512
513    fn from_str(s: &str) -> Result<Self, Self::Err> {
514        Self::try_from(s)
515    }
516}
517
518#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
519#[serde(rename_all = "snake_case")]
520pub enum DecisionType {
521    AuthorizationRequired,
522    PolicySatisfactionRequired,
523    SettlementRequired,
524}
525
526impl fmt::Display for DecisionType {
527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528        match self {
529            DecisionType::AuthorizationRequired => write!(f, "authorization_required"),
530            DecisionType::PolicySatisfactionRequired => {
531                write!(f, "policy_satisfaction_required")
532            }
533            DecisionType::SettlementRequired => write!(f, "settlement_required"),
534        }
535    }
536}
537
538impl TryFrom<&str> for DecisionType {
539    type Error = String;
540
541    fn try_from(value: &str) -> Result<Self, Self::Error> {
542        match value {
543            "authorization_required" => Ok(DecisionType::AuthorizationRequired),
544            "policy_satisfaction_required" => Ok(DecisionType::PolicySatisfactionRequired),
545            "settlement_required" => Ok(DecisionType::SettlementRequired),
546            _ => Err(format!("Invalid decision type: {}", value)),
547        }
548    }
549}
550
551impl FromStr for DecisionType {
552    type Err = String;
553
554    fn from_str(s: &str) -> Result<Self, Self::Err> {
555        Self::try_from(s)
556    }
557}
558
559#[derive(Debug, Clone, Serialize, Deserialize)]
560pub struct DecisionLogEntry {
561    pub id: i64,
562    pub transaction_id: String,
563    pub agent_did: String,
564    pub decision_type: DecisionType,
565    pub context_json: serde_json::Value,
566    pub status: DecisionStatus,
567    pub resolution: Option<String>,
568    pub resolution_detail: Option<serde_json::Value>,
569    pub created_at: String,
570    pub delivered_at: Option<String>,
571    pub resolved_at: Option<String>,
572}
573
574// Implement NameHashable for Customer
575impl NameHashable for Customer {}
576
577impl Customer {
578    /// Generate a name hash based on the customer's name
579    pub fn generate_name_hash(&self) -> Option<String> {
580        match self.schema_type {
581            SchemaType::Person => {
582                // For persons, combine given name and family name
583                if let (Some(given), Some(family)) = (&self.given_name, &self.family_name) {
584                    Some(Self::hash_name(&format!("{} {}", given, family)))
585                } else {
586                    self.display_name
587                        .as_ref()
588                        .map(|display| Self::hash_name(display))
589                }
590            }
591            SchemaType::Organization => {
592                // For organizations, use legal name
593                self.legal_name.as_ref().map(|name| Self::hash_name(name))
594            }
595            _ => None,
596        }
597    }
598
599    /// Add name hash to the profile metadata
600    pub fn add_name_hash_to_profile(&mut self) {
601        if let Some(hash) = self.generate_name_hash() {
602            if let serde_json::Value::Object(ref mut map) = self.profile {
603                map.insert("nameHash".to_string(), serde_json::Value::String(hash));
604            }
605        }
606    }
607
608    /// Get name hash from profile if present
609    pub fn get_name_hash(&self) -> Option<String> {
610        if let serde_json::Value::Object(map) = &self.profile {
611            map.get("nameHash")
612                .and_then(|v| v.as_str())
613                .map(|s| s.to_string())
614        } else {
615            None
616        }
617    }
618}