feat: Add new Rhai example demonstrating payment flow
- 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.
This commit is contained in:
313
heromodels/tests/payment.rs
Normal file
313
heromodels/tests/payment.rs
Normal file
@@ -0,0 +1,313 @@
|
||||
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());
|
||||
}
|
Reference in New Issue
Block a user