konduto/types/analysis_layer/
status.rs

1use crate::supports::enums;
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4
5/// Status da camada de análise (Segunda Camada)
6///
7/// A Konduto trabalha com camadas de análise, o que permite agregar serviços terceiros
8/// ao parecer de fraude e enriquecendo assim a base para a decisão de risco.
9#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
10#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
11pub enum AnalysisLayerStatus {
12    /// FRAUD: Sinaliza o recebimento de um chargeback ou fraude confirmada na primeira camada.
13    /// (Primeira camada)
14    Fraud,
15
16    /// FRAUD_REVIEW: Em situações onde a primeira camada retorne a recomendação de REVIEW.
17    /// (Segunda camada)
18    FraudReview,
19
20    /// FRAUD_APPROVE: Em situações onde a primeira camada retorne a recomendação de APPROVE.
21    /// (Segunda camada)
22    FraudApprove,
23
24    /// FRAUD_DECLINE: Em situações onde a primeira camada retorne a recomendação de DECLINE.
25    /// (Segunda camada)
26    FraudDecline,
27}
28
29impl<'de> Deserialize<'de> for AnalysisLayerStatus {
30    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31    where
32        D: serde::Deserializer<'de>,
33    {
34        let s = String::deserialize(deserializer)?;
35        match s.to_uppercase().as_str() {
36            "FRAUD" => Ok(AnalysisLayerStatus::Fraud),
37            "FRAUD_REVIEW" => Ok(AnalysisLayerStatus::FraudReview),
38            "FRAUD_APPROVE" => Ok(AnalysisLayerStatus::FraudApprove),
39            "FRAUD_DECLINE" => Ok(AnalysisLayerStatus::FraudDecline),
40            _ => Err(serde::de::Error::custom(format!(
41                "Invalid analysis layer status: {}",
42                s
43            ))),
44        }
45    }
46}
47
48impl AnalysisLayerStatus {
49    pub fn name(&self) -> String {
50        enums::to_string_infallible(self)
51    }
52
53    /// Retorna true se o status é da primeira camada
54    pub fn is_first_layer(&self) -> bool {
55        matches!(self, AnalysisLayerStatus::Fraud)
56    }
57
58    /// Retorna true se o status é da segunda camada
59    pub fn is_second_layer(&self) -> bool {
60        !self.is_first_layer()
61    }
62}
63
64impl Display for AnalysisLayerStatus {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        write!(f, "{}", self.name())
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use serde_json::json;
74
75    #[test]
76    fn test_status_deserialization_case_insensitive() {
77        // Testa uppercase
78        let status: AnalysisLayerStatus = serde_json::from_value(json!("FRAUD")).unwrap();
79        assert_eq!(status, AnalysisLayerStatus::Fraud);
80
81        // Testa lowercase
82        let status: AnalysisLayerStatus = serde_json::from_value(json!("fraud")).unwrap();
83        assert_eq!(status, AnalysisLayerStatus::Fraud);
84
85        // Testa mixed case
86        let status: AnalysisLayerStatus = serde_json::from_value(json!("Fraud")).unwrap();
87        assert_eq!(status, AnalysisLayerStatus::Fraud);
88    }
89
90    #[test]
91    fn test_all_statuses() {
92        let test_cases = vec![
93            ("FRAUD", AnalysisLayerStatus::Fraud),
94            ("FRAUD_REVIEW", AnalysisLayerStatus::FraudReview),
95            ("FRAUD_APPROVE", AnalysisLayerStatus::FraudApprove),
96            ("FRAUD_DECLINE", AnalysisLayerStatus::FraudDecline),
97        ];
98
99        for (input, expected) in test_cases {
100            let status: AnalysisLayerStatus = serde_json::from_value(json!(input)).unwrap();
101            assert_eq!(status, expected);
102        }
103    }
104
105    #[test]
106    fn test_status_serialization() {
107        let status = AnalysisLayerStatus::Fraud;
108        let json = serde_json::to_value(&status).unwrap();
109        assert_eq!(json, json!("FRAUD"));
110
111        let status = AnalysisLayerStatus::FraudReview;
112        let json = serde_json::to_value(&status).unwrap();
113        assert_eq!(json, json!("FRAUD_REVIEW"));
114    }
115
116    #[test]
117    fn test_invalid_status() {
118        let result: Result<AnalysisLayerStatus, _> =
119            serde_json::from_value(json!("invalid_status"));
120        assert!(result.is_err());
121    }
122
123    #[test]
124    fn test_layer_detection() {
125        assert!(AnalysisLayerStatus::Fraud.is_first_layer());
126        assert!(!AnalysisLayerStatus::Fraud.is_second_layer());
127
128        assert!(AnalysisLayerStatus::FraudReview.is_second_layer());
129        assert!(!AnalysisLayerStatus::FraudReview.is_first_layer());
130
131        assert!(AnalysisLayerStatus::FraudApprove.is_second_layer());
132        assert!(AnalysisLayerStatus::FraudDecline.is_second_layer());
133    }
134}