-
Notifications
You must be signed in to change notification settings - Fork 0
/
account_activity.rs
136 lines (119 loc) · 5.5 KB
/
account_activity.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use crate::dispute::DisputeCase;
use crate::transaction::{Transaction, TransactionID};
use crate::ClientID;
use rust_decimal::Decimal;
use std::fmt::{Display, Formatter};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AccountActivityError {
/// Indicates that the payload of a transaction is invalid.
#[error("invalid transaction: {0}")]
InvalidTransaction(String),
/// Indicates that a transaction could not be executed.
///
/// This covers cases such as an attempt of a withdrawal with insufficient funds or an internal
/// processing error.
#[error("failed transaction: {0}")]
FailedTransaction(String),
/// Indicates that a dispute case could not be executed.
///
/// This covers cases such as a dispute being initiated on an already disputed transaction.
#[error("failed dispute case: {0}")]
FailedDisputeCase(String),
}
pub type AccountActivityResult<T> = Result<T, AccountActivityError>;
/// Account activities are events that influence an [`Account`]s balance. These events could either
/// be [`Transaction`]s or [`DisputeCase`]s.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum AccountActivity {
/// A [`Transaction`] where funds are added to an account, increasing the available and total
/// balance of the account.
///
/// Deposits can be made in various ways, such as transferring money from another account,
/// depositing cash, or receiving payments.
Deposit(Transaction),
/// A [`Transaction`] where funds are removed from an account, reducing the available and total
/// account balance.
///
/// Withdrawals can be made in various ways, such as cash withdrawals, bank transfers to other
/// accounts, or using checks or debit cards for purchases.
Withdrawal(Transaction),
/// A dispute is the initiation of a [`DisputeCase`].
///
/// It is a formal objection raised by a customer regarding a particular [`Transaction`].
///
/// This typically occurs when the customer believes the transaction is unauthorized,
/// fraudulent, or processed incorrectly (e.g., an incorrect amount or duplicate charge).
///
/// The dispute triggers an investigation by the bank or financial institution to determine the
/// validity of the claim.
Dispute(DisputeCase),
/// A resolve or resolution is the continuation of a [`DisputeCase`].
///
/// It is the process of addressing and concluding a [`Dispute`]. During the resolution process,
/// the financial institution investigates the disputed transaction, reviews evidence, and makes
/// a decision on whether the claim is valid.
///
/// A resolution can result in the dispute being upheld (leading to a refund or chargeback) or
/// denied.
///
/// [`Dispute`]: AccountActivity::Dispute
Resolve(DisputeCase),
/// A chargeback is the continuation of a [`DisputeCase`].
///
/// It is a refund issued to a customer after a [`Dispute`] is resolved in their favor,
/// reversing the funds transferred in the disputed transaction back to the claimant's account.
///
/// Chargebacks are typically initiated by the bank or payment processor and are used to protect
/// customers from fraudulent or erroneous charges.
///
/// [`Dispute`]: AccountActivity::Dispute
Chargeback(DisputeCase),
}
impl AccountActivity {
pub fn deposit(transaction_id: TransactionID, client_id: ClientID, amount: Decimal) -> Self {
Self::Deposit(Transaction::new(transaction_id, client_id, amount))
}
pub fn withdrawal(transaction_id: TransactionID, client_id: ClientID, amount: Decimal) -> Self {
Self::Withdrawal(Transaction::new(transaction_id, client_id, amount))
}
pub fn dispute(transaction_id: TransactionID, client_id: ClientID) -> Self {
Self::Dispute(DisputeCase::new(transaction_id, client_id))
}
pub fn resolve(transaction_id: TransactionID, client_id: ClientID) -> Self {
Self::Resolve(DisputeCase::new(transaction_id, client_id))
}
pub fn chargeback(transaction_id: TransactionID, client_id: ClientID) -> Self {
Self::Chargeback(DisputeCase::new(transaction_id, client_id))
}
pub fn transaction_id(&self) -> TransactionID {
match self {
AccountActivity::Deposit(transaction) => transaction.id(),
AccountActivity::Withdrawal(transaction) => transaction.id(),
AccountActivity::Dispute(transaction) => transaction.id(),
AccountActivity::Resolve(transaction) => transaction.id(),
AccountActivity::Chargeback(transaction) => transaction.id(),
}
}
pub fn client_id(&self) -> ClientID {
match self {
AccountActivity::Deposit(transaction) => transaction.client_id(),
AccountActivity::Withdrawal(transaction) => transaction.client_id(),
AccountActivity::Dispute(transaction) => transaction.client_id(),
AccountActivity::Resolve(transaction) => transaction.client_id(),
AccountActivity::Chargeback(transaction) => transaction.client_id(),
}
}
}
impl Display for AccountActivity {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let kind = match self {
AccountActivity::Deposit(_) => "deposit",
AccountActivity::Withdrawal(_) => "withdrawal",
AccountActivity::Dispute(_) => "dispute",
AccountActivity::Resolve(_) => "resolve",
AccountActivity::Chargeback(_) => "chargeback",
};
write!(f, "{}", kind)
}
}