- Add a new Rhai example showcasing complete payment flow for company registration. This includes company creation, payment record creation, successful payment processing, status updates, and handling failed and refunded payments. - Add new example demonstrating payment integration in Rhai scripting. This example showcases the usage of various payment status methods and verifies data from the database after processing payments. - Add new examples to Cargo.toml to facilitate building and running the examples. This makes it easier to integrate and test payment functionality using Rhai scripting.
314 lines
9.1 KiB
Rust
314 lines
9.1 KiB
Rust
use heromodels::db::Collection;
|
|
use heromodels::db::hero::OurDB;
|
|
use heromodels::models::biz::{BusinessType, Company, CompanyStatus, Payment, PaymentStatus};
|
|
use heromodels_core::Model;
|
|
use std::sync::Arc;
|
|
|
|
fn create_test_db() -> Arc<OurDB> {
|
|
let timestamp = std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_nanos();
|
|
let path = format!("/tmp/payment_test_{}", timestamp);
|
|
|
|
// Clean up any existing database at this path
|
|
let _ = std::fs::remove_dir_all(&path);
|
|
|
|
Arc::new(OurDB::new(path, true).expect("Failed to create test database"))
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_creation() {
|
|
let payment = Payment::new(
|
|
"pi_test_123".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
100.0,
|
|
50.0,
|
|
150.0,
|
|
);
|
|
|
|
assert_eq!(payment.payment_intent_id, "pi_test_123");
|
|
assert_eq!(payment.company_id, 1);
|
|
assert_eq!(payment.payment_plan, "monthly");
|
|
assert_eq!(payment.setup_fee, 100.0);
|
|
assert_eq!(payment.monthly_fee, 50.0);
|
|
assert_eq!(payment.total_amount, 150.0);
|
|
assert_eq!(payment.currency, "usd");
|
|
assert_eq!(payment.status, PaymentStatus::Pending);
|
|
assert_eq!(payment.stripe_customer_id, None);
|
|
assert!(payment.created_at > 0);
|
|
assert_eq!(payment.completed_at, None);
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_status_default() {
|
|
let payment = Payment::new(
|
|
"pi_test".to_string(),
|
|
1,
|
|
"yearly".to_string(),
|
|
500.0,
|
|
99.0,
|
|
1688.0,
|
|
);
|
|
|
|
assert_eq!(payment.status, PaymentStatus::Pending);
|
|
assert!(payment.is_pending());
|
|
assert!(!payment.is_processing());
|
|
assert!(!payment.is_completed());
|
|
assert!(!payment.has_failed());
|
|
assert!(!payment.is_refunded());
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_processing() {
|
|
let payment = Payment::new(
|
|
"pi_processing_test".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
150.0,
|
|
60.0,
|
|
210.0,
|
|
);
|
|
|
|
let processing_payment = payment.process_payment();
|
|
|
|
assert_eq!(processing_payment.status, PaymentStatus::Processing);
|
|
assert!(processing_payment.is_processing());
|
|
assert!(!processing_payment.is_pending());
|
|
assert!(!processing_payment.is_completed());
|
|
assert!(!processing_payment.has_failed());
|
|
assert!(!processing_payment.is_refunded());
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_completion() {
|
|
let payment = Payment::new(
|
|
"pi_complete_test".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
200.0,
|
|
75.0,
|
|
275.0,
|
|
);
|
|
|
|
let stripe_customer_id = Some("cus_test_123".to_string());
|
|
let completed_payment = payment.complete_payment(stripe_customer_id.clone());
|
|
|
|
assert_eq!(completed_payment.status, PaymentStatus::Completed);
|
|
assert_eq!(completed_payment.stripe_customer_id, stripe_customer_id);
|
|
assert!(completed_payment.is_completed());
|
|
assert!(!completed_payment.is_pending());
|
|
assert!(!completed_payment.has_failed());
|
|
assert!(!completed_payment.is_refunded());
|
|
assert!(completed_payment.completed_at.is_some());
|
|
assert!(completed_payment.completed_at.unwrap() > 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_failure() {
|
|
let payment = Payment::new(
|
|
"pi_fail_test".to_string(),
|
|
1,
|
|
"yearly".to_string(),
|
|
300.0,
|
|
60.0,
|
|
1020.0,
|
|
);
|
|
|
|
let failed_payment = payment.fail_payment();
|
|
|
|
assert_eq!(failed_payment.status, PaymentStatus::Failed);
|
|
assert!(failed_payment.has_failed());
|
|
assert!(!failed_payment.is_completed());
|
|
assert!(!failed_payment.is_pending());
|
|
assert!(!failed_payment.is_refunded());
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_refund() {
|
|
let payment = Payment::new(
|
|
"pi_refund_test".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
150.0,
|
|
45.0,
|
|
195.0,
|
|
);
|
|
|
|
// First complete the payment
|
|
let completed_payment = payment.complete_payment(Some("cus_refund_test".to_string()));
|
|
assert!(completed_payment.is_completed());
|
|
|
|
// Then refund it
|
|
let refunded_payment = completed_payment.refund_payment();
|
|
|
|
assert_eq!(refunded_payment.status, PaymentStatus::Refunded);
|
|
assert!(refunded_payment.is_refunded());
|
|
assert!(!refunded_payment.is_completed());
|
|
assert!(!refunded_payment.is_pending());
|
|
assert!(!refunded_payment.has_failed());
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_builder_pattern() {
|
|
let custom_timestamp = 1640995200; // Jan 1, 2022
|
|
let payment = Payment::new(
|
|
"pi_builder_test".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
100.0,
|
|
50.0,
|
|
150.0,
|
|
)
|
|
.payment_plan("yearly".to_string())
|
|
.setup_fee(500.0)
|
|
.monthly_fee(99.0)
|
|
.total_amount(1688.0)
|
|
.currency("eur".to_string())
|
|
.stripe_customer_id(Some("cus_builder_test".to_string()))
|
|
.created_at(custom_timestamp)
|
|
.completed_at(Some(custom_timestamp + 3600));
|
|
|
|
assert_eq!(payment.payment_plan, "yearly");
|
|
assert_eq!(payment.setup_fee, 500.0);
|
|
assert_eq!(payment.monthly_fee, 99.0);
|
|
assert_eq!(payment.total_amount, 1688.0);
|
|
assert_eq!(payment.currency, "eur");
|
|
assert_eq!(
|
|
payment.stripe_customer_id,
|
|
Some("cus_builder_test".to_string())
|
|
);
|
|
assert_eq!(payment.created_at, custom_timestamp);
|
|
assert_eq!(payment.completed_at, Some(custom_timestamp + 3600));
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_database_persistence() {
|
|
let db = create_test_db();
|
|
|
|
let payment = Payment::new(
|
|
"pi_db_test".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
200.0,
|
|
60.0,
|
|
260.0,
|
|
);
|
|
|
|
// Save payment
|
|
let (payment_id, saved_payment) = db.set(&payment).expect("Failed to save payment");
|
|
assert!(payment_id > 0);
|
|
assert_eq!(saved_payment.payment_intent_id, "pi_db_test");
|
|
|
|
// Retrieve payment
|
|
let retrieved_payment: Payment = db
|
|
.get_by_id(payment_id)
|
|
.expect("Failed to get payment")
|
|
.unwrap();
|
|
assert_eq!(retrieved_payment.payment_intent_id, "pi_db_test");
|
|
assert_eq!(retrieved_payment.company_id, 1);
|
|
assert_eq!(retrieved_payment.status, PaymentStatus::Pending);
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_status_transitions() {
|
|
let db = create_test_db();
|
|
|
|
let payment = Payment::new(
|
|
"pi_transition_test".to_string(),
|
|
1,
|
|
"yearly".to_string(),
|
|
400.0,
|
|
80.0,
|
|
1360.0,
|
|
);
|
|
|
|
let (payment_id, mut payment) = db.set(&payment).expect("Failed to save payment");
|
|
|
|
// Test pending -> completed
|
|
payment = payment.complete_payment(Some("cus_transition_test".to_string()));
|
|
let (_, mut payment) = db.set(&payment).expect("Failed to update payment");
|
|
assert!(payment.is_completed());
|
|
|
|
// Test completed -> refunded
|
|
payment = payment.refund_payment();
|
|
let (_, payment) = db.set(&payment).expect("Failed to update payment");
|
|
assert!(payment.is_refunded());
|
|
|
|
// Verify final state in database
|
|
let final_payment: Payment = db
|
|
.get_by_id(payment_id)
|
|
.expect("Failed to get payment")
|
|
.unwrap();
|
|
assert_eq!(final_payment.status, PaymentStatus::Refunded);
|
|
}
|
|
|
|
#[test]
|
|
fn test_payment_timestamps() {
|
|
let payment = Payment::new(
|
|
"pi_timestamp_test".to_string(),
|
|
1,
|
|
"monthly".to_string(),
|
|
100.0,
|
|
50.0,
|
|
150.0,
|
|
);
|
|
|
|
let initial_created_at = payment.base_data.created_at;
|
|
let initial_modified_at = payment.base_data.modified_at;
|
|
|
|
// Complete payment (should update modified_at)
|
|
let completed_payment = payment.complete_payment(Some("cus_timestamp_test".to_string()));
|
|
|
|
assert_eq!(completed_payment.base_data.created_at, initial_created_at);
|
|
assert!(completed_payment.base_data.modified_at >= initial_modified_at);
|
|
}
|
|
|
|
#[test]
|
|
fn test_company_payment_integration() {
|
|
let db = create_test_db();
|
|
|
|
// Create company with default PendingPayment status
|
|
let company = Company::new(
|
|
"Integration Test Corp".to_string(),
|
|
"ITC-001".to_string(),
|
|
chrono::Utc::now().timestamp(),
|
|
)
|
|
.email("test@integration.com".to_string())
|
|
.business_type(BusinessType::Starter);
|
|
|
|
let (company_id, company) = db.set(&company).expect("Failed to save company");
|
|
assert_eq!(company.status, CompanyStatus::PendingPayment);
|
|
|
|
// Create payment for the company
|
|
let payment = Payment::new(
|
|
"pi_integration_test".to_string(),
|
|
company_id,
|
|
"monthly".to_string(),
|
|
250.0,
|
|
55.0,
|
|
305.0,
|
|
);
|
|
|
|
let (_payment_id, payment) = db.set(&payment).expect("Failed to save payment");
|
|
assert_eq!(payment.company_id, company_id);
|
|
|
|
// Complete payment
|
|
let completed_payment = payment.complete_payment(Some("cus_integration_test".to_string()));
|
|
let (_, completed_payment) = db
|
|
.set(&completed_payment)
|
|
.expect("Failed to update payment");
|
|
|
|
// Update company status to Active
|
|
let active_company = company.status(CompanyStatus::Active);
|
|
let (_, active_company) = db.set(&active_company).expect("Failed to update company");
|
|
|
|
// Verify final states
|
|
assert!(completed_payment.is_completed());
|
|
assert_eq!(active_company.status, CompanyStatus::Active);
|
|
|
|
// Verify relationship
|
|
assert_eq!(completed_payment.company_id, active_company.get_id());
|
|
}
|