use payrix_macros::PayrixEntity;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use super::{bool_from_int_default_false, PayrixId};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ChargebackCycle {
#[default]
Retrieval,
First,
Arbitration,
Reversal,
Representment,
PreArbitration,
ArbitrationLost,
ArbitrationSplit,
ArbitrationWon,
IssuerAcceptPreArbitration,
IssuerDeclinedPreArbitration,
ResponseToIssuerPreArbitration,
MerchantAcceptedPreArbitration,
MerchantDeclinedPreArbitration,
PreCompliance,
Compliance,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChargebackStatusValue {
#[default]
Open,
Closed,
Won,
Lost,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum ChargebackPlatform {
#[serde(rename = "VCORE")]
VCore,
Tsys,
#[serde(rename = "FIRSTDATA")]
FirstData,
Elavon,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize_repr, Deserialize_repr)]
#[repr(i32)]
pub enum ChargebackPaymentMethod {
#[default]
None = 0,
AmericanExpress = 1,
Visa = 2,
Mastercard = 3,
DinersClub = 4,
Discover = 5,
PayPal = 6,
Debit = 7,
Checking = 8,
Savings = 9,
CorporateChecking = 10,
CorporateSavings = 11,
GiftCard = 12,
Ebt = 13,
Wic = 14,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChargebackMessageStatus {
#[default]
Requested,
Processing,
Failed,
Denied,
Processed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ChargebackMessageType {
#[default]
Assign,
Notate,
AcceptLiability,
CreatePreArbitration,
Represent,
Respond,
RequestArbitration,
CreateArbitration,
RequestPreArbitration,
RequestResolutionToPreArbitration,
RespondToDispute,
RespondToPreArbitration,
Unaccept,
FilePreArbitration,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChargebackMessageResultType {
#[default]
General,
Platform,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChargebackDocumentStatus {
#[default]
Created,
Processed,
Failed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum ChargebackDocumentSource {
#[default]
Merchant,
Issuer,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChargebackDocumentType {
#[default]
Image,
Pdf,
Text,
Tiff,
Png,
Jpg,
Other,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize_repr, Deserialize_repr)]
#[repr(i32)]
pub enum MessageDirection {
#[default]
Inbound = 1,
Outbound = 2,
}
#[derive(Debug, Clone, Serialize, Deserialize, PayrixEntity)]
#[payrix(update = UpdateChargeback)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct Chargeback {
#[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 merchant: Option<PayrixId>,
#[serde(default)]
pub txn: Option<PayrixId>,
#[serde(default)]
pub mid: Option<String>,
#[payrix(mutable)]
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub total: Option<i64>,
#[serde(default)]
pub represented_total: Option<i64>,
#[serde(default)]
pub cycle: Option<ChargebackCycle>,
#[serde(default)]
pub currency: Option<String>,
#[serde(default)]
pub platform: Option<ChargebackPlatform>,
#[serde(default)]
pub payment_method: Option<ChargebackPaymentMethod>,
#[serde(default, rename = "ref")]
pub reference: Option<String>,
#[serde(default)]
pub reason: Option<String>,
#[serde(default)]
pub reason_code: Option<String>,
#[serde(default)]
pub issued: Option<i32>,
#[serde(default)]
pub received: Option<i32>,
#[serde(default)]
pub reply: Option<i32>,
#[serde(default)]
pub bank_ref: Option<String>,
#[serde(default)]
pub chargeback_ref: Option<String>,
#[serde(default)]
pub status: Option<ChargebackStatusValue>,
#[serde(default)]
pub last_status_change: Option<PayrixId>,
#[serde(default, with = "bool_from_int_default_false")]
pub actionable: bool,
#[serde(default, with = "bool_from_int_default_false")]
pub shadow: bool,
#[payrix(mutable)]
#[serde(default, with = "bool_from_int_default_false")]
pub inactive: bool,
#[payrix(mutable)]
#[serde(default, with = "bool_from_int_default_false")]
pub frozen: bool,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub assessments: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub chargeback_documents: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub chargeback_messages: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub chargeback_statuses: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub entries: Option<Vec<serde_json::Value>>,
#[cfg(not(feature = "sqlx"))]
#[serde(default)]
pub pending_entry: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PayrixEntity)]
#[payrix(create = CreateChargebackMessage)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct ChargebackMessage {
#[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>,
#[payrix(create_only, create_required, create_type = "String")]
pub chargeback: PayrixId,
#[payrix(readonly)]
#[serde(default)]
pub login: Option<PayrixId>,
#[payrix(create_only)]
#[serde(default, rename = "type")]
pub message_type: Option<ChargebackMessageType>,
#[payrix(readonly)]
#[serde(default)]
pub status: Option<ChargebackMessageStatus>,
#[payrix(create_only)]
#[serde(default)]
pub subject: Option<String>,
#[payrix(create_only)]
#[serde(default)]
pub message: Option<String>,
#[payrix(readonly)]
#[serde(default)]
pub sender: Option<String>,
#[payrix(readonly)]
#[serde(default)]
pub direction: Option<MessageDirection>,
#[payrix(readonly)]
#[serde(default, with = "bool_from_int_default_false")]
pub read: bool,
#[payrix(readonly)]
#[serde(default, with = "bool_from_int_default_false")]
pub inactive: bool,
#[payrix(readonly)]
#[serde(default, with = "bool_from_int_default_false")]
pub frozen: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PayrixEntity)]
#[payrix(create = CreateChargebackDocument)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct ChargebackDocument {
#[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>,
#[payrix(create_only, create_required, create_type = "String")]
pub chargeback: PayrixId,
#[payrix(create_only, create_type = "String")]
#[serde(default)]
pub chargeback_message: Option<PayrixId>,
#[payrix(readonly)]
#[serde(default)]
pub login: Option<PayrixId>,
#[payrix(create_only)]
#[serde(default)]
pub name: Option<String>,
#[payrix(create_only)]
#[serde(default, rename = "type")]
pub document_type: Option<ChargebackDocumentType>,
#[payrix(create_only)]
#[serde(default)]
pub mime_type: Option<String>,
#[payrix(readonly)]
#[serde(default)]
pub size: Option<i64>,
#[payrix(readonly)]
#[serde(default)]
pub url: Option<String>,
#[payrix(create_only)]
#[serde(default)]
pub description: Option<String>,
#[payrix(create_only)]
#[serde(default, skip_deserializing)]
pub data: Option<String>,
#[payrix(readonly)]
#[serde(default, with = "bool_from_int_default_false")]
pub inactive: bool,
#[payrix(readonly)]
#[serde(default, with = "bool_from_int_default_false")]
pub frozen: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct ChargebackMessageResult {
pub id: PayrixId,
#[serde(default)]
pub created: Option<String>,
#[serde(default)]
pub modified: Option<String>,
#[serde(default)]
pub chargeback: Option<PayrixId>,
#[serde(default)]
pub chargeback_message: Option<PayrixId>,
#[serde(default, rename = "type")]
pub result_type: Option<ChargebackMessageResultType>,
#[serde(default)]
pub message: Option<String>,
#[serde(default)]
pub response: Option<String>,
#[serde(default, with = "bool_from_int_default_false")]
pub inactive: bool,
#[serde(default, with = "bool_from_int_default_false")]
pub frozen: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
#[serde(rename_all = "camelCase")]
pub struct ChargebackStatus {
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 chargeback: Option<PayrixId>,
#[serde(default)]
pub status: Option<ChargebackStatusValue>,
#[serde(default)]
pub chargeback_message: Option<PayrixId>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chargeback_cycle_default() {
assert_eq!(ChargebackCycle::default(), ChargebackCycle::Retrieval);
}
#[test]
fn chargeback_cycle_serialize_all_variants() {
let test_cases = [
(ChargebackCycle::Retrieval, "\"retrieval\""),
(ChargebackCycle::First, "\"first\""),
(ChargebackCycle::Arbitration, "\"arbitration\""),
(ChargebackCycle::Reversal, "\"reversal\""),
(ChargebackCycle::Representment, "\"representment\""),
(ChargebackCycle::PreArbitration, "\"preArbitration\""),
(ChargebackCycle::ArbitrationLost, "\"arbitrationLost\""),
(ChargebackCycle::ArbitrationSplit, "\"arbitrationSplit\""),
(ChargebackCycle::ArbitrationWon, "\"arbitrationWon\""),
(ChargebackCycle::IssuerAcceptPreArbitration, "\"issuerAcceptPreArbitration\""),
(ChargebackCycle::IssuerDeclinedPreArbitration, "\"issuerDeclinedPreArbitration\""),
(ChargebackCycle::ResponseToIssuerPreArbitration, "\"responseToIssuerPreArbitration\""),
(ChargebackCycle::MerchantAcceptedPreArbitration, "\"merchantAcceptedPreArbitration\""),
(ChargebackCycle::MerchantDeclinedPreArbitration, "\"merchantDeclinedPreArbitration\""),
(ChargebackCycle::PreCompliance, "\"preCompliance\""),
(ChargebackCycle::Compliance, "\"compliance\""),
];
for (variant, expected_json) in test_cases {
let json = serde_json::to_string(&variant).unwrap();
assert_eq!(json, expected_json);
}
}
#[test]
fn chargeback_cycle_deserialize_all_variants() {
let test_cases = [
("\"retrieval\"", ChargebackCycle::Retrieval),
("\"first\"", ChargebackCycle::First),
("\"arbitration\"", ChargebackCycle::Arbitration),
("\"reversal\"", ChargebackCycle::Reversal),
("\"representment\"", ChargebackCycle::Representment),
("\"preArbitration\"", ChargebackCycle::PreArbitration),
("\"arbitrationLost\"", ChargebackCycle::ArbitrationLost),
("\"arbitrationSplit\"", ChargebackCycle::ArbitrationSplit),
("\"arbitrationWon\"", ChargebackCycle::ArbitrationWon),
("\"issuerAcceptPreArbitration\"", ChargebackCycle::IssuerAcceptPreArbitration),
("\"issuerDeclinedPreArbitration\"", ChargebackCycle::IssuerDeclinedPreArbitration),
("\"responseToIssuerPreArbitration\"", ChargebackCycle::ResponseToIssuerPreArbitration),
("\"merchantAcceptedPreArbitration\"", ChargebackCycle::MerchantAcceptedPreArbitration),
("\"merchantDeclinedPreArbitration\"", ChargebackCycle::MerchantDeclinedPreArbitration),
("\"preCompliance\"", ChargebackCycle::PreCompliance),
("\"compliance\"", ChargebackCycle::Compliance),
];
for (json, expected_variant) in test_cases {
let variant: ChargebackCycle = serde_json::from_str(json).unwrap();
assert_eq!(variant, expected_variant);
}
}
#[test]
fn chargeback_status_value_default() {
assert_eq!(ChargebackStatusValue::default(), ChargebackStatusValue::Open);
}
#[test]
fn chargeback_status_value_serialize_all_variants() {
let test_cases = [
(ChargebackStatusValue::Open, "\"open\""),
(ChargebackStatusValue::Closed, "\"closed\""),
(ChargebackStatusValue::Won, "\"won\""),
(ChargebackStatusValue::Lost, "\"lost\""),
];
for (variant, expected_json) in test_cases {
let json = serde_json::to_string(&variant).unwrap();
assert_eq!(json, expected_json);
}
}
#[test]
fn chargeback_status_value_deserialize_all_variants() {
let test_cases = [
("\"open\"", ChargebackStatusValue::Open),
("\"closed\"", ChargebackStatusValue::Closed),
("\"won\"", ChargebackStatusValue::Won),
("\"lost\"", ChargebackStatusValue::Lost),
];
for (json, expected_variant) in test_cases {
let variant: ChargebackStatusValue = serde_json::from_str(json).unwrap();
assert_eq!(variant, expected_variant);
}
}
#[test]
fn chargeback_payment_method_default() {
assert_eq!(ChargebackPaymentMethod::default(), ChargebackPaymentMethod::None);
}
#[test]
fn chargeback_payment_method_serialize_all_variants() {
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::None).unwrap(), "0");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::AmericanExpress).unwrap(), "1");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Visa).unwrap(), "2");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Mastercard).unwrap(), "3");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::DinersClub).unwrap(), "4");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Discover).unwrap(), "5");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::PayPal).unwrap(), "6");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Debit).unwrap(), "7");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Checking).unwrap(), "8");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Savings).unwrap(), "9");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::CorporateChecking).unwrap(), "10");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::CorporateSavings).unwrap(), "11");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::GiftCard).unwrap(), "12");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Ebt).unwrap(), "13");
assert_eq!(serde_json::to_string(&ChargebackPaymentMethod::Wic).unwrap(), "14");
}
#[test]
fn chargeback_deserialize_full() {
let json = r#"{
"id": "t1_chb_12345678901234567890123",
"created": "2024-01-01 10:00:00.0000",
"modified": "2024-01-01 15:30:00.0000",
"creator": "t1_lgn_creator1234567890123456",
"modifier": "t1_lgn_modifier123456789012345",
"merchant": "t1_mer_12345678901234567890123",
"txn": "t1_txn_12345678901234567890123",
"mid": "123456789012345",
"description": "Disputed transaction",
"total": 10000,
"representedTotal": 10000,
"cycle": "first",
"currency": "USD",
"platform": "VCORE",
"paymentMethod": 2,
"ref": "REF123456",
"reason": "Cardholder Dispute",
"reasonCode": "4853",
"issued": 20240101,
"received": 20240102,
"reply": 20240115,
"bankRef": "BANK123",
"chargebackRef": "CB123",
"status": "open",
"lastStatusChange": "t1_chs_12345678901234567890123",
"actionable": 1,
"shadow": 0,
"inactive": 0,
"frozen": 1
}"#;
let chargeback: Chargeback = serde_json::from_str(json).unwrap();
assert_eq!(chargeback.id.as_str(), "t1_chb_12345678901234567890123");
assert_eq!(chargeback.creator.as_ref().unwrap().as_str(), "t1_lgn_creator1234567890123456");
assert_eq!(chargeback.modifier.as_ref().unwrap().as_str(), "t1_lgn_modifier123456789012345");
assert_eq!(chargeback.merchant.as_ref().unwrap().as_str(), "t1_mer_12345678901234567890123");
assert_eq!(chargeback.txn.as_ref().unwrap().as_str(), "t1_txn_12345678901234567890123");
assert_eq!(chargeback.mid.as_deref(), Some("123456789012345"));
assert_eq!(chargeback.description.as_deref(), Some("Disputed transaction"));
assert_eq!(chargeback.total, Some(10000));
assert_eq!(chargeback.represented_total, Some(10000));
assert_eq!(chargeback.cycle, Some(ChargebackCycle::First));
assert_eq!(chargeback.currency.as_deref(), Some("USD"));
assert_eq!(chargeback.platform, Some(ChargebackPlatform::VCore));
assert_eq!(chargeback.payment_method, Some(ChargebackPaymentMethod::Visa));
assert_eq!(chargeback.reference.as_deref(), Some("REF123456"));
assert_eq!(chargeback.reason.as_deref(), Some("Cardholder Dispute"));
assert_eq!(chargeback.reason_code.as_deref(), Some("4853"));
assert_eq!(chargeback.issued, Some(20240101));
assert_eq!(chargeback.received, Some(20240102));
assert_eq!(chargeback.reply, Some(20240115));
assert_eq!(chargeback.bank_ref.as_deref(), Some("BANK123"));
assert_eq!(chargeback.chargeback_ref.as_deref(), Some("CB123"));
assert_eq!(chargeback.status, Some(ChargebackStatusValue::Open));
assert_eq!(chargeback.last_status_change.as_ref().unwrap().as_str(), "t1_chs_12345678901234567890123");
assert!(chargeback.actionable);
assert!(!chargeback.shadow);
assert!(!chargeback.inactive);
assert!(chargeback.frozen);
}
#[test]
fn chargeback_deserialize_minimal() {
let json = r#"{"id": "t1_chb_12345678901234567890123"}"#;
let chargeback: Chargeback = serde_json::from_str(json).unwrap();
assert_eq!(chargeback.id.as_str(), "t1_chb_12345678901234567890123");
assert!(chargeback.creator.is_none());
assert!(chargeback.merchant.is_none());
assert!(chargeback.txn.is_none());
assert!(chargeback.total.is_none());
assert!(chargeback.cycle.is_none());
assert!(chargeback.status.is_none());
assert!(!chargeback.actionable);
assert!(!chargeback.shadow);
assert!(!chargeback.inactive);
assert!(!chargeback.frozen);
}
#[test]
fn chargeback_bool_from_int() {
let json = r#"{
"id": "t1_chb_12345678901234567890123",
"actionable": 1,
"shadow": 1,
"inactive": 0,
"frozen": 1
}"#;
let chargeback: Chargeback = serde_json::from_str(json).unwrap();
assert!(chargeback.actionable);
assert!(chargeback.shadow);
assert!(!chargeback.inactive);
assert!(chargeback.frozen);
}
#[test]
fn chargeback_message_status_default() {
assert_eq!(ChargebackMessageStatus::default(), ChargebackMessageStatus::Requested);
}
#[test]
fn chargeback_message_type_default() {
assert_eq!(ChargebackMessageType::default(), ChargebackMessageType::Assign);
}
#[test]
fn create_chargeback_message_serialize() {
let msg = CreateChargebackMessage {
chargeback: "t1_chb_12345678901234567890123".to_string(),
message_type: Some(ChargebackMessageType::Represent),
subject: Some("Response".to_string()),
message: Some("We are representing this transaction".to_string()),
};
let json = serde_json::to_string(&msg).unwrap();
assert!(json.contains("\"chargeback\":\"t1_chb_12345678901234567890123\""));
assert!(json.contains("\"type\":\"represent\""));
assert!(json.contains("\"subject\":\"Response\""));
}
#[test]
fn chargeback_document_status_default() {
assert_eq!(ChargebackDocumentStatus::default(), ChargebackDocumentStatus::Created);
}
#[test]
fn chargeback_document_type_default() {
assert_eq!(ChargebackDocumentType::default(), ChargebackDocumentType::Image);
}
#[test]
fn create_chargeback_document_serialize() {
let doc = CreateChargebackDocument {
chargeback: "t1_chb_12345678901234567890123".to_string(),
chargeback_message: Some("t1_cbm_12345678901234567890123".to_string()),
name: Some("evidence.pdf".to_string()),
document_type: Some(ChargebackDocumentType::Pdf),
mime_type: Some("application/pdf".to_string()),
description: Some("Supporting evidence".to_string()),
data: Some("SGVsbG8gV29ybGQ=".to_string()), };
let json = serde_json::to_string(&doc).unwrap();
assert!(json.contains("\"chargeback\":\"t1_chb_12345678901234567890123\""));
assert!(json.contains("\"type\":\"pdf\""));
assert!(json.contains("\"name\":\"evidence.pdf\""));
assert!(json.contains("\"data\":\"SGVsbG8gV29ybGQ=\""));
}
#[test]
fn chargeback_message_result_type_default() {
assert_eq!(ChargebackMessageResultType::default(), ChargebackMessageResultType::General);
}
#[cfg(not(feature = "sqlx"))]
#[test]
fn chargeback_deserialize_with_nested_relations() {
let json = r#"{
"id": "t1_chb_12345678901234567890123",
"assessments": [{"id": "assess_1", "amount": 500}],
"chargebackDocuments": [{"id": "t1_cbd_12345678901234567890123", "name": "evidence.pdf"}],
"chargebackMessages": [{"id": "t1_chm_12345678901234567890123", "type": "represent"}],
"chargebackStatuses": [{"id": "t1_chs_12345678901234567890123", "status": "open"}],
"entries": [{"id": "t1_ent_12345678901234567890123", "amount": 10000}],
"pendingEntry": {"id": "t1_pen_12345678901234567890123", "amount": 5000}
}"#;
let cb: Chargeback = serde_json::from_str(json).unwrap();
assert_eq!(cb.assessments.as_ref().unwrap().len(), 1);
assert_eq!(cb.chargeback_documents.as_ref().unwrap().len(), 1);
assert_eq!(cb.chargeback_messages.as_ref().unwrap().len(), 1);
assert_eq!(cb.chargeback_statuses.as_ref().unwrap().len(), 1);
assert_eq!(cb.entries.as_ref().unwrap().len(), 1);
assert!(cb.pending_entry.is_some());
}
#[cfg(not(feature = "sqlx"))]
#[test]
fn chargeback_deserialize_nested_relations_absent() {
let json = r#"{"id": "t1_chb_12345678901234567890123"}"#;
let cb: Chargeback = serde_json::from_str(json).unwrap();
assert!(cb.assessments.is_none());
assert!(cb.chargeback_documents.is_none());
assert!(cb.chargeback_messages.is_none());
assert!(cb.chargeback_statuses.is_none());
assert!(cb.entries.is_none());
assert!(cb.pending_entry.is_none());
}
#[test]
fn message_direction_default() {
assert_eq!(MessageDirection::default(), MessageDirection::Inbound);
}
#[test]
fn message_direction_serialize() {
assert_eq!(serde_json::to_string(&MessageDirection::Inbound).unwrap(), "1");
assert_eq!(serde_json::to_string(&MessageDirection::Outbound).unwrap(), "2");
}
}