use payrix_macros::PayrixEntity;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use super::PayrixId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize_repr, Deserialize_repr)]
#[repr(i32)]
pub enum EventType {
#[default]
Days = 1,
Weeks = 2,
Months = 3,
Years = 4,
Single = 5,
Authorization = 6,
Capture = 7,
Refund = 8,
Boarded = 9,
Payout = 10,
Chargeback = 11,
Overdraft = 12,
Interchange = 13,
Processor = 14,
AchFail = 15,
AccountVerification = 16,
Sift = 17,
Adjustment = 18,
Retrieval = 19,
Arbitration = 20,
ECheckSale = 21,
ECheckRefund = 22,
ECheckReturn = 23,
Settlement = 24,
Misuse = 25,
ProfitShare = 26,
Unauthorized = 27,
AchNotificationOfChange = 28,
ECheckNotificationOfChange = 29,
ECheckFail = 30,
ECheckNonSufficientFunds = 31,
CurrencyConversion = 32,
TerminalTransaction = 33,
ReversePayout = 34,
PartialReversePayout = 35,
ReserveEntry = 36,
ReserveEntryRelease = 37,
PendingEntry = 38,
PendingPaid = 39,
Remainder = 40,
RemainderUsed = 41,
PendingRefundCancelled = 42,
PaymentCheck = 43,
PaymentUpdate = 44,
PaymentGroupCheck = 45,
PaymentGroupUpdate = 46,
EntryRefund = 47,
Statement = 51,
MerchantCreation = 52,
RealtimeBusinessSearch = 53,
RealtimeMemberSearch = 54,
MasterCardMatch = 55,
BusinessInstantId = 56,
ConsumerInstantId = 57,
ThreatMetrix = 58,
LegitScriptRegister = 59,
EquifaxConsumerReport = 60,
GuideStar = 61,
PayloadAttribute = 62,
TinCheck = 63,
EquifaxCommercialReport = 64,
LegitScriptCheckMerchant = 65,
Plaid = 66,
StatementReversal = 67,
GiactEcheck = 68,
GiactBankAccount = 69,
BoardDecision = 70,
TxnRiskDecision = 71,
Fanf = 72,
McLocation = 73,
VisaIntegrity = 74,
SaferPaymentsBasic = 75,
SaferPaymentsManaged = 76,
SaferPaymentsPciNonvalidation = 77,
OmnitokensVolume = 78,
PayoutReturn = 79,
PayoutPartialReturn = 80,
RevShare = 81,
CardSettlement = 82,
EcheckSettlement = 83,
RevShareCard = 84,
RevShareEcheck = 85,
RevShareDbm = 86,
Prearbitration = 87,
PlaidIdentityMatch = 88,
TxnPlaidIdentityMatch = 89,
PlaidGetIdentity = 90,
TxnPlaidGetIdentity = 91,
PlaidGetAuth = 92,
TxnPlaidGetAuth = 93,
Reversal = 94,
Representment = 95,
OmnitokensMonthly = 96,
IcRetainPassthruRefund = 101,
}
#[derive(Debug, Clone, Serialize, Deserialize, PayrixEntity)]
#[payrix(update = UpdateEntry)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct Entry {
#[payrix(readonly)]
pub id: PayrixId,
#[payrix(readonly)]
#[serde(default)]
pub created: Option<String>,
#[payrix(readonly)]
#[serde(default)]
pub modified: Option<String>,
#[payrix(readonly)]
#[serde(default)]
pub creator: Option<PayrixId>,
#[payrix(readonly)]
#[serde(default)]
pub modifier: Option<PayrixId>,
#[serde(default)]
pub entity: Option<PayrixId>,
#[serde(default)]
pub onentity: Option<PayrixId>,
#[serde(default)]
pub fromentity: Option<PayrixId>,
#[serde(default)]
pub opposing_entry: Option<PayrixId>,
#[serde(default)]
pub fund: Option<PayrixId>,
#[serde(default)]
pub fee: Option<PayrixId>,
#[serde(default)]
pub disbursement: Option<PayrixId>,
#[serde(default)]
pub refund: Option<PayrixId>,
#[serde(default)]
pub settlement: Option<PayrixId>,
#[serde(default)]
pub txn: Option<PayrixId>,
#[serde(default)]
pub chargeback: Option<PayrixId>,
#[serde(default)]
pub adjustment: Option<PayrixId>,
#[serde(default)]
pub profit_share: Option<PayrixId>,
#[serde(default)]
pub statement: Option<PayrixId>,
#[serde(default)]
pub event: Option<EventType>,
#[serde(default)]
pub event_id: Option<PayrixId>,
#[serde(default)]
pub rev_share_statement: Option<PayrixId>,
#[serde(default)]
pub original_event_id: Option<String>,
#[serde(default)]
pub original_event: Option<EventType>,
#[payrix(mutable)]
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub original_currency: Option<String>,
#[serde(default)]
pub currency_rate: Option<f64>,
#[serde(default)]
pub amount: Option<f64>,
#[serde(default)]
pub pending: Option<i32>,
#[serde(default)]
pub is_fee: Option<i32>,
#[serde(default)]
pub archive_summary: Option<i32>,
#[serde(default)]
pub pending_entry: Option<PayrixId>,
#[serde(default)]
pub pending_entry_created: Option<String>,
#[serde(default, rename = "isEFE")]
pub is_efe: Option<i32>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub cancellation: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub disbursement_entries: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub entry_origins: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub last_negative_of_disbursement: Option<serde_json::Value>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub last_positive_of_disbursement: Option<serde_json::Value>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub opposing_entries: Option<serde_json::Value>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub profit_share_results: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub refunds: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub reserve_entries: Option<Vec<serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct PendingEntry {
pub id: PayrixId,
#[serde(default)]
pub created: Option<String>,
#[serde(default)]
pub modified: Option<String>,
#[serde(default)]
pub creator: Option<PayrixId>,
#[serde(default)]
pub modifier: Option<PayrixId>,
#[serde(default)]
pub entity: Option<PayrixId>,
#[serde(default)]
pub onentity: Option<PayrixId>,
#[serde(default)]
pub fromentity: Option<PayrixId>,
#[serde(default)]
pub fund: Option<PayrixId>,
#[serde(default)]
pub opposing_entry: Option<PayrixId>,
#[serde(default)]
pub entry: Option<PayrixId>,
#[serde(default)]
pub adjustment: Option<PayrixId>,
#[serde(default)]
pub chargeback: Option<PayrixId>,
#[serde(default)]
pub disbursement: Option<PayrixId>,
#[serde(default)]
pub fee: Option<PayrixId>,
#[serde(default)]
pub refund: Option<PayrixId>,
#[serde(default)]
pub txn: Option<PayrixId>,
#[serde(default)]
pub event: Option<EventType>,
#[serde(default)]
pub amount: Option<f64>,
#[serde(default)]
pub description: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn event_type_default() {
assert_eq!(EventType::default(), EventType::Days);
}
#[test]
fn event_type_common_variants_serialize() {
let test_cases = [
(EventType::Days, "1"),
(EventType::Weeks, "2"),
(EventType::Months, "3"),
(EventType::Years, "4"),
(EventType::Single, "5"),
(EventType::Authorization, "6"),
(EventType::Capture, "7"),
(EventType::Refund, "8"),
(EventType::Boarded, "9"),
(EventType::Payout, "10"),
(EventType::Chargeback, "11"),
(EventType::Settlement, "24"),
(EventType::RevShare, "81"),
];
for (variant, expected_json) in test_cases {
let json = serde_json::to_string(&variant).unwrap();
assert_eq!(json, expected_json);
}
}
#[test]
fn event_type_common_variants_deserialize() {
let test_cases = [
("1", EventType::Days),
("2", EventType::Weeks),
("3", EventType::Months),
("4", EventType::Years),
("5", EventType::Single),
("6", EventType::Authorization),
("7", EventType::Capture),
("8", EventType::Refund),
("9", EventType::Boarded),
("10", EventType::Payout),
("11", EventType::Chargeback),
("24", EventType::Settlement),
("81", EventType::RevShare),
];
for (json, expected_variant) in test_cases {
let variant: EventType = serde_json::from_str(json).unwrap();
assert_eq!(variant, expected_variant);
}
}
#[test]
fn entry_deserialize_full() {
let json = r#"{
"id": "t1_ent_12345678901234567890123",
"created": "2024-01-01 10:00:00.0000",
"modified": "2024-01-01 15:30:00.0000",
"creator": "t1_lgn_12345678901234567890123",
"modifier": "t1_lgn_12345678901234567890124",
"entity": "t1_ety_12345678901234567890123",
"onentity": "t1_ety_12345678901234567890124",
"fromentity": "t1_ety_12345678901234567890125",
"opposingEntry": "t1_ent_12345678901234567890124",
"fund": "t1_fnd_12345678901234567890123",
"fee": "t1_fee_12345678901234567890123",
"disbursement": "t1_dis_12345678901234567890123",
"txn": "t1_txn_12345678901234567890123",
"event": 7,
"description": "Capture transaction",
"originalCurrency": "USD",
"currencyRate": 1.0,
"amount": 10000.0,
"pending": 0,
"isFee": 0,
"isEFE": 0
}"#;
let entry: Entry = serde_json::from_str(json).unwrap();
assert_eq!(entry.id.as_str(), "t1_ent_12345678901234567890123");
assert_eq!(entry.creator.as_ref().map(|c| c.as_str()), Some("t1_lgn_12345678901234567890123"));
assert_eq!(entry.entity.as_ref().map(|e| e.as_str()), Some("t1_ety_12345678901234567890123"));
assert_eq!(entry.onentity.as_ref().map(|o| o.as_str()), Some("t1_ety_12345678901234567890124"));
assert_eq!(entry.fromentity.as_ref().map(|f| f.as_str()), Some("t1_ety_12345678901234567890125"));
assert_eq!(entry.event, Some(EventType::Capture));
assert_eq!(entry.amount, Some(10000.0));
assert_eq!(entry.pending, Some(0));
assert_eq!(entry.is_fee, Some(0));
assert_eq!(entry.is_efe, Some(0));
}
#[test]
fn entry_deserialize_minimal() {
let json = r#"{"id": "t1_ent_12345678901234567890123"}"#;
let entry: Entry = serde_json::from_str(json).unwrap();
assert_eq!(entry.id.as_str(), "t1_ent_12345678901234567890123");
assert!(entry.creator.is_none());
assert!(entry.entity.is_none());
assert!(entry.event.is_none());
assert!(entry.amount.is_none());
}
#[test]
fn entry_event_values() {
let test_cases = [
(1, EventType::Days),
(7, EventType::Capture),
(11, EventType::Chargeback),
(24, EventType::Settlement),
];
for (event_val, expected_type) in test_cases {
let json = format!(r#"{{"id": "t1_ent_12345678901234567890123", "event": {}}}"#, event_val);
let entry: Entry = serde_json::from_str(&json).unwrap();
assert_eq!(entry.event, Some(expected_type));
}
}
#[test]
fn pending_entry_deserialize_full() {
let json = r#"{
"id": "t1_pen_12345678901234567890123",
"created": "2024-01-01 10:00:00.0000",
"modified": "2024-01-01 15:30:00.0000",
"creator": "t1_lgn_12345678901234567890123",
"modifier": "t1_lgn_12345678901234567890124",
"entity": "t1_ety_12345678901234567890123",
"onentity": "t1_ety_12345678901234567890124",
"fund": "t1_fnd_12345678901234567890123",
"entry": "t1_ent_12345678901234567890123",
"txn": "t1_txn_12345678901234567890123",
"event": 6,
"amount": 5000.0,
"description": "Pending authorization"
}"#;
let pending: PendingEntry = serde_json::from_str(json).unwrap();
assert_eq!(pending.id.as_str(), "t1_pen_12345678901234567890123");
assert_eq!(pending.creator.as_ref().map(|c| c.as_str()), Some("t1_lgn_12345678901234567890123"));
assert_eq!(pending.entity.as_ref().map(|e| e.as_str()), Some("t1_ety_12345678901234567890123"));
assert_eq!(pending.event, Some(EventType::Authorization));
assert_eq!(pending.amount, Some(5000.0));
assert_eq!(pending.description, Some("Pending authorization".to_string()));
}
#[test]
fn pending_entry_deserialize_minimal() {
let json = r#"{"id": "t1_pen_12345678901234567890123"}"#;
let pending: PendingEntry = serde_json::from_str(json).unwrap();
assert_eq!(pending.id.as_str(), "t1_pen_12345678901234567890123");
assert!(pending.creator.is_none());
assert!(pending.entity.is_none());
assert!(pending.event.is_none());
}
}