feat: Add reminder functionality to ContractSigner model
- Added `last_reminder_mail_sent_at` field to track reminder timestamps. - Implemented `can_send_reminder` to check if a reminder can be sent based on a 30-minute cooldown. - Added `reminder_cooldown_remaining` to get remaining cooldown time. - Added `mark_reminder_sent` to update reminder timestamp. - Added example demonstrating reminder functionality in `legal_contract_example.rs`. - Added tests for reminder functionality in `test_reminder_functionality.rs`. - Updated Rhai scripts to include reminder-related functions and tests. - Improved formatting and clarity in example code.
This commit is contained in:
parent
20c075ec51
commit
970299b1a4
@ -70,7 +70,7 @@ fn main() {
|
||||
.add_signer(signer2.clone())
|
||||
.add_revision(revision1.clone())
|
||||
.add_revision(revision2.clone());
|
||||
|
||||
|
||||
// The `#[model]` derive handles `created_at` and `updated_at` in `base_data`.
|
||||
// `base_data.touch()` might be called internally by setters or needs explicit call if fields are set directly.
|
||||
// For builder pattern, the final state of `base_data.updated_at` reflects the time of the last builder call if `touch()` is implicit.
|
||||
@ -87,7 +87,7 @@ fn main() {
|
||||
|
||||
println!("\n--- Contract Details After Signing ---");
|
||||
println!("{:#?}", contract);
|
||||
|
||||
|
||||
println!("\n--- Accessing Specific Fields ---");
|
||||
println!("Contract Title: {}", contract.title);
|
||||
println!("Contract Status: {:?}", contract.status);
|
||||
@ -97,7 +97,10 @@ fn main() {
|
||||
println!("Updated At (timestamp): {}", contract.base_data.modified_at); // From BaseModelData
|
||||
|
||||
if let Some(first_signer_details) = contract.signers.first() {
|
||||
println!("\nFirst Signer: {} ({})", first_signer_details.name, first_signer_details.email);
|
||||
println!(
|
||||
"\nFirst Signer: {} ({})",
|
||||
first_signer_details.name, first_signer_details.email
|
||||
);
|
||||
println!(" Status: {:?}", first_signer_details.status);
|
||||
if let Some(signed_time) = first_signer_details.signed_at {
|
||||
println!(" Signed At: {}", signed_time);
|
||||
@ -110,6 +113,51 @@ fn main() {
|
||||
println!(" Created By: {}", latest_rev.created_by);
|
||||
println!(" Revision Created At: {}", latest_rev.created_at);
|
||||
}
|
||||
|
||||
|
||||
// Demonstrate reminder functionality
|
||||
println!("\n--- Reminder Functionality Demo ---");
|
||||
let current_time = current_timestamp_secs();
|
||||
|
||||
// Check if we can send reminders to signers
|
||||
for (i, signer) in contract.signers.iter().enumerate() {
|
||||
println!("\nSigner {}: {} ({})", i + 1, signer.name, signer.email);
|
||||
println!(" Status: {:?}", signer.status);
|
||||
|
||||
if signer.last_reminder_mail_sent_at.is_none() {
|
||||
println!(" Last reminder: Never sent");
|
||||
} else {
|
||||
println!(
|
||||
" Last reminder: {}",
|
||||
signer.last_reminder_mail_sent_at.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
let can_send = signer.can_send_reminder(current_time);
|
||||
println!(" Can send reminder now: {}", can_send);
|
||||
|
||||
if let Some(remaining) = signer.reminder_cooldown_remaining(current_time) {
|
||||
println!(" Cooldown remaining: {} seconds", remaining);
|
||||
} else {
|
||||
println!(" No cooldown active");
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate sending a reminder to the first signer
|
||||
if let Some(first_signer) = contract.signers.get_mut(0) {
|
||||
if first_signer.can_send_reminder(current_time) {
|
||||
println!("\nSimulating reminder sent to: {}", first_signer.name);
|
||||
first_signer.mark_reminder_sent(current_time);
|
||||
println!(
|
||||
" Reminder timestamp updated to: {}",
|
||||
first_signer.last_reminder_mail_sent_at.unwrap()
|
||||
);
|
||||
|
||||
// Check cooldown after sending
|
||||
if let Some(remaining) = first_signer.reminder_cooldown_remaining(current_time) {
|
||||
println!(" New cooldown: {} seconds (30 minutes)", remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nLegal Contract Model demonstration complete.");
|
||||
}
|
||||
|
@ -39,14 +39,17 @@ let signer1 = new_contract_signer(signer1_id, "Alice Wonderland", "alice@example
|
||||
print(`Signer 1 ID: ${signer1.id}, Name: ${signer1.name}, Email: ${signer1.email}`);
|
||||
print(`Signer 1 Status: ${signer1.status}, Comments: ${format_optional_string(signer1.comments, "N/A")}`);
|
||||
print(`Signer 1 Signed At: ${format_optional_int(signer1.signed_at, "Not signed")}`);
|
||||
print(`Signer 1 Last Reminder: ${format_optional_int(signer1.last_reminder_mail_sent_at, "Never sent")}`);
|
||||
|
||||
let signer2_id = "signer-uuid-002";
|
||||
let signer2 = new_contract_signer(signer2_id, "Bob The Builder", "bob@example.com")
|
||||
.status(SignerStatusConstants::Signed)
|
||||
.signed_at(1678886400) // Example timestamp
|
||||
.comments("Bob has already signed.");
|
||||
.comments("Bob has already signed.")
|
||||
.last_reminder_mail_sent_at(1678880000); // Example reminder timestamp
|
||||
|
||||
print(`Signer 2 ID: ${signer2.id}, Name: ${signer2.name}, Status: ${signer2.status}, Signed At: ${format_optional_int(signer2.signed_at, "N/A")}`);
|
||||
print(`Signer 2 Last Reminder: ${format_optional_int(signer2.last_reminder_mail_sent_at, "Never sent")}`);
|
||||
|
||||
// --- Test ContractRevision Model ---
|
||||
print("\n--- Testing ContractRevision Model ---");
|
||||
@ -116,4 +119,31 @@ print("Updated Contract saved.");
|
||||
let final_retrieved_contract = get_contract_by_id(contract1_base_id);
|
||||
print(`Final Retrieved Contract - Status: ${final_retrieved_contract.status}, Description: '${final_retrieved_contract.description}'`);
|
||||
|
||||
// --- Test Reminder Functionality ---
|
||||
print("\n--- Testing Reminder Functionality ---");
|
||||
let current_time = 1678900000; // Example current timestamp
|
||||
|
||||
// Test reminder functionality on signers
|
||||
if final_retrieved_contract.signers.len() > 0 {
|
||||
let test_signer = final_retrieved_contract.signers[0];
|
||||
print(`Testing reminder for signer: ${test_signer.name}`);
|
||||
|
||||
let can_send = can_send_reminder(test_signer, current_time);
|
||||
print(`Can send reminder: ${can_send}`);
|
||||
|
||||
let cooldown_remaining = reminder_cooldown_remaining(test_signer, current_time);
|
||||
print(`Cooldown remaining: ${format_optional_int(cooldown_remaining, "No cooldown")}`);
|
||||
|
||||
// Simulate sending a reminder
|
||||
if can_send {
|
||||
print("Simulating reminder sent...");
|
||||
mark_reminder_sent(test_signer, current_time);
|
||||
print("Reminder timestamp updated");
|
||||
|
||||
// Check cooldown after sending
|
||||
let new_cooldown = reminder_cooldown_remaining(test_signer, current_time);
|
||||
print(`New cooldown: ${format_optional_int(new_cooldown, "No cooldown")} seconds`);
|
||||
}
|
||||
}
|
||||
|
||||
print("\nLegal Rhai example script finished.");
|
||||
|
108
heromodels/examples/test_reminder_functionality.rs
Normal file
108
heromodels/examples/test_reminder_functionality.rs
Normal file
@ -0,0 +1,108 @@
|
||||
use heromodels::models::legal::{ContractSigner, SignerStatus};
|
||||
|
||||
// Helper function to get current timestamp
|
||||
fn current_timestamp_secs() -> u64 {
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Testing ContractSigner Reminder Functionality");
|
||||
println!("==============================================\n");
|
||||
|
||||
// Test 1: Create a new signer (should have no reminder timestamp)
|
||||
println!("Test 1: New signer creation");
|
||||
let mut signer = ContractSigner::new(
|
||||
"test-signer-001".to_string(),
|
||||
"Test User".to_string(),
|
||||
"test@example.com".to_string(),
|
||||
);
|
||||
|
||||
println!(" Signer created: {}", signer.name);
|
||||
println!(" Last reminder: {:?}", signer.last_reminder_mail_sent_at);
|
||||
assert_eq!(signer.last_reminder_mail_sent_at, None);
|
||||
println!(" ✓ New signer has no reminder timestamp\n");
|
||||
|
||||
// Test 2: Check if reminder can be sent (should be true for new signer)
|
||||
println!("Test 2: Can send reminder check");
|
||||
let current_time = current_timestamp_secs();
|
||||
let can_send = signer.can_send_reminder(current_time);
|
||||
println!(" Can send reminder: {}", can_send);
|
||||
assert!(can_send);
|
||||
println!(" ✓ New signer can receive reminders\n");
|
||||
|
||||
// Test 3: Check cooldown remaining (should be None for new signer)
|
||||
println!("Test 3: Cooldown remaining check");
|
||||
let cooldown = signer.reminder_cooldown_remaining(current_time);
|
||||
println!(" Cooldown remaining: {:?}", cooldown);
|
||||
assert_eq!(cooldown, None);
|
||||
println!(" ✓ New signer has no cooldown\n");
|
||||
|
||||
// Test 4: Mark reminder as sent
|
||||
println!("Test 4: Mark reminder as sent");
|
||||
signer.mark_reminder_sent(current_time);
|
||||
println!(" Reminder marked as sent at: {}", current_time);
|
||||
println!(" Last reminder timestamp: {:?}", signer.last_reminder_mail_sent_at);
|
||||
assert_eq!(signer.last_reminder_mail_sent_at, Some(current_time));
|
||||
println!(" ✓ Reminder timestamp updated correctly\n");
|
||||
|
||||
// Test 5: Check if reminder can be sent immediately after (should be false)
|
||||
println!("Test 5: Immediate retry check");
|
||||
let can_send_again = signer.can_send_reminder(current_time);
|
||||
println!(" Can send reminder immediately: {}", can_send_again);
|
||||
assert!(!can_send_again);
|
||||
println!(" ✓ Cannot send reminder immediately after sending\n");
|
||||
|
||||
// Test 6: Check cooldown remaining (should be 30 minutes)
|
||||
println!("Test 6: Cooldown after sending");
|
||||
let cooldown_after = signer.reminder_cooldown_remaining(current_time);
|
||||
println!(" Cooldown remaining: {:?} seconds", cooldown_after);
|
||||
assert_eq!(cooldown_after, Some(30 * 60)); // 30 minutes = 1800 seconds
|
||||
println!(" ✓ Cooldown is exactly 30 minutes\n");
|
||||
|
||||
// Test 7: Test after cooldown period
|
||||
println!("Test 7: After cooldown period");
|
||||
let future_time = current_time + (31 * 60); // 31 minutes later
|
||||
let can_send_later = signer.can_send_reminder(future_time);
|
||||
let cooldown_later = signer.reminder_cooldown_remaining(future_time);
|
||||
println!(" Time: {} (31 minutes later)", future_time);
|
||||
println!(" Can send reminder: {}", can_send_later);
|
||||
println!(" Cooldown remaining: {:?}", cooldown_later);
|
||||
assert!(can_send_later);
|
||||
assert_eq!(cooldown_later, None);
|
||||
println!(" ✓ Can send reminder after cooldown period\n");
|
||||
|
||||
// Test 8: Test builder pattern with reminder timestamp
|
||||
println!("Test 8: Builder pattern with reminder timestamp");
|
||||
let signer_with_reminder = ContractSigner::new(
|
||||
"test-signer-002".to_string(),
|
||||
"Another User".to_string(),
|
||||
"another@example.com".to_string(),
|
||||
)
|
||||
.status(SignerStatus::Pending)
|
||||
.last_reminder_mail_sent_at(current_time - (20 * 60)) // 20 minutes ago
|
||||
.comments("Test signer with reminder");
|
||||
|
||||
println!(" Signer: {}", signer_with_reminder.name);
|
||||
println!(" Last reminder: {:?}", signer_with_reminder.last_reminder_mail_sent_at);
|
||||
println!(" Can send reminder: {}", signer_with_reminder.can_send_reminder(current_time));
|
||||
|
||||
let remaining = signer_with_reminder.reminder_cooldown_remaining(current_time);
|
||||
println!(" Cooldown remaining: {:?} seconds", remaining);
|
||||
assert_eq!(remaining, Some(10 * 60)); // 10 minutes remaining
|
||||
println!(" ✓ Builder pattern works correctly\n");
|
||||
|
||||
// Test 9: Test clear reminder timestamp
|
||||
println!("Test 9: Clear reminder timestamp");
|
||||
let cleared_signer = signer_with_reminder.clear_last_reminder_mail_sent_at();
|
||||
println!(" Last reminder after clear: {:?}", cleared_signer.last_reminder_mail_sent_at);
|
||||
println!(" Can send reminder: {}", cleared_signer.can_send_reminder(current_time));
|
||||
assert_eq!(cleared_signer.last_reminder_mail_sent_at, None);
|
||||
assert!(cleared_signer.can_send_reminder(current_time));
|
||||
println!(" ✓ Clear reminder timestamp works correctly\n");
|
||||
|
||||
println!("All tests passed! ✅");
|
||||
println!("ContractSigner reminder functionality is working correctly.");
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use heromodels_core::BaseModelData;
|
||||
use heromodels_derive::model;
|
||||
use std::fmt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
// --- Enums ---
|
||||
|
||||
@ -86,6 +86,7 @@ pub struct ContractSigner {
|
||||
pub status: SignerStatus,
|
||||
pub signed_at: Option<u64>, // Timestamp
|
||||
pub comments: Option<String>,
|
||||
pub last_reminder_mail_sent_at: Option<u64>, // Unix timestamp of last reminder sent
|
||||
}
|
||||
|
||||
impl ContractSigner {
|
||||
@ -97,6 +98,7 @@ impl ContractSigner {
|
||||
status: SignerStatus::default(),
|
||||
signed_at: None,
|
||||
comments: None,
|
||||
last_reminder_mail_sent_at: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +111,7 @@ impl ContractSigner {
|
||||
self.signed_at = Some(signed_at);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn clear_signed_at(mut self) -> Self {
|
||||
self.signed_at = None;
|
||||
self
|
||||
@ -124,6 +126,48 @@ impl ContractSigner {
|
||||
self.comments = None;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn last_reminder_mail_sent_at(mut self, timestamp: u64) -> Self {
|
||||
self.last_reminder_mail_sent_at = Some(timestamp);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn clear_last_reminder_mail_sent_at(mut self) -> Self {
|
||||
self.last_reminder_mail_sent_at = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Helper method to check if a reminder can be sent (30-minute rate limiting)
|
||||
pub fn can_send_reminder(&self, current_timestamp: u64) -> bool {
|
||||
match self.last_reminder_mail_sent_at {
|
||||
None => true, // No reminder sent yet
|
||||
Some(last_sent) => {
|
||||
let thirty_minutes_in_seconds = 30 * 60; // 30 minutes = 1800 seconds
|
||||
current_timestamp >= last_sent + thirty_minutes_in_seconds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method to get remaining cooldown time in seconds
|
||||
pub fn reminder_cooldown_remaining(&self, current_timestamp: u64) -> Option<u64> {
|
||||
match self.last_reminder_mail_sent_at {
|
||||
None => None, // No cooldown if no reminder sent yet
|
||||
Some(last_sent) => {
|
||||
let thirty_minutes_in_seconds = 30 * 60; // 30 minutes = 1800 seconds
|
||||
let cooldown_end = last_sent + thirty_minutes_in_seconds;
|
||||
if current_timestamp < cooldown_end {
|
||||
Some(cooldown_end - current_timestamp)
|
||||
} else {
|
||||
None // Cooldown has expired
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method to update the reminder timestamp to current time
|
||||
pub fn mark_reminder_sent(&mut self, current_timestamp: u64) {
|
||||
self.last_reminder_mail_sent_at = Some(current_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Main Contract Model ---
|
||||
@ -139,21 +183,21 @@ pub struct Contract {
|
||||
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
|
||||
|
||||
#[index]
|
||||
pub contract_type: String,
|
||||
|
||||
|
||||
#[index]
|
||||
pub status: crate::models::ContractStatus, // Use re-exported path for #[model] macro
|
||||
|
||||
|
||||
pub created_by: String,
|
||||
pub terms_and_conditions: String,
|
||||
|
||||
|
||||
pub start_date: Option<u64>,
|
||||
pub end_date: Option<u64>,
|
||||
pub renewal_period_days: Option<i32>,
|
||||
pub next_renewal_date: Option<u64>,
|
||||
|
||||
|
||||
pub signers: Vec<ContractSigner>,
|
||||
pub revisions: Vec<ContractRevision>,
|
||||
pub current_version: u32,
|
||||
@ -217,7 +261,7 @@ impl Contract {
|
||||
self.start_date = Some(start_date);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn clear_start_date(mut self) -> Self {
|
||||
self.start_date = None;
|
||||
self
|
||||
@ -257,7 +301,7 @@ impl Contract {
|
||||
self.signers.push(signer);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn signers(mut self, signers: Vec<ContractSigner>) -> Self {
|
||||
self.signers = signers;
|
||||
self
|
||||
@ -272,7 +316,7 @@ impl Contract {
|
||||
self.revisions = revisions;
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn current_version(mut self, version: u32) -> Self {
|
||||
self.current_version = version;
|
||||
self
|
||||
@ -287,7 +331,7 @@ impl Contract {
|
||||
self.last_signed_date = None;
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
// Example methods for state changes
|
||||
pub fn set_status(&mut self, status: crate::models::ContractStatus) {
|
||||
self.status = status;
|
||||
|
@ -1,51 +1,60 @@
|
||||
use rhai::{
|
||||
Dynamic, Engine, EvalAltResult, NativeCallContext, Position, Module, Array,
|
||||
};
|
||||
use rhai::{Array, Dynamic, Engine, EvalAltResult, Module, NativeCallContext, Position};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::db::hero::OurDB; // Updated path based on compiler suggestion
|
||||
// use heromodels_core::BaseModelData; // Removed as fields are accessed via contract.base_data directly
|
||||
use crate::models::legal::{Contract, ContractRevision, ContractSigner, ContractStatus, SignerStatus};
|
||||
use crate::models::legal::{
|
||||
Contract, ContractRevision, ContractSigner, ContractStatus, SignerStatus,
|
||||
};
|
||||
|
||||
use crate::db::Collection; // Import the Collection trait
|
||||
|
||||
// --- Helper Functions for ID and Timestamp Conversion ---
|
||||
fn i64_to_u32(val: i64, context_pos: Position, field_name: &str, object_name: &str) -> Result<u32, Box<EvalAltResult>> {
|
||||
fn i64_to_u32(
|
||||
val: i64,
|
||||
context_pos: Position,
|
||||
field_name: &str,
|
||||
object_name: &str,
|
||||
) -> Result<u32, Box<EvalAltResult>> {
|
||||
val.try_into().map_err(|_e| {
|
||||
Box::new(EvalAltResult::ErrorArithmetic(
|
||||
format!(
|
||||
"Conversion error for field '{}' in object '{}': cannot convert i64 ({}) to u32",
|
||||
field_name,
|
||||
object_name,
|
||||
val
|
||||
field_name, object_name, val
|
||||
),
|
||||
context_pos,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn i64_to_u64(val: i64, context_pos: Position, field_name: &str, object_name: &str) -> Result<u64, Box<EvalAltResult>> {
|
||||
fn i64_to_u64(
|
||||
val: i64,
|
||||
context_pos: Position,
|
||||
field_name: &str,
|
||||
object_name: &str,
|
||||
) -> Result<u64, Box<EvalAltResult>> {
|
||||
val.try_into().map_err(|_e| {
|
||||
Box::new(EvalAltResult::ErrorArithmetic(
|
||||
format!(
|
||||
"Conversion error for field '{}' in object '{}': cannot convert i64 ({}) to u64",
|
||||
field_name,
|
||||
object_name,
|
||||
val
|
||||
field_name, object_name, val
|
||||
),
|
||||
context_pos,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn i64_to_i32(val: i64, context_pos: Position, field_name: &str, object_name: &str) -> Result<i32, Box<EvalAltResult>> {
|
||||
fn i64_to_i32(
|
||||
val: i64,
|
||||
context_pos: Position,
|
||||
field_name: &str,
|
||||
object_name: &str,
|
||||
) -> Result<i32, Box<EvalAltResult>> {
|
||||
val.try_into().map_err(|_e| {
|
||||
Box::new(EvalAltResult::ErrorArithmetic(
|
||||
format!(
|
||||
"Conversion error for field '{}' in object '{}': cannot convert i64 ({}) to i32",
|
||||
field_name,
|
||||
object_name,
|
||||
val
|
||||
field_name, object_name, val
|
||||
),
|
||||
context_pos,
|
||||
))
|
||||
@ -73,193 +82,608 @@ pub fn register_legal_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
|
||||
engine.register_static_module("SignerStatusConstants", signer_status_module.into());
|
||||
engine.register_type_with_name::<SignerStatus>("SignerStatus"); // Expose the type itself
|
||||
|
||||
// --- ContractRevision ---
|
||||
// --- ContractRevision ---
|
||||
engine.register_type_with_name::<ContractRevision>("ContractRevision");
|
||||
engine.register_fn(
|
||||
"new_contract_revision",
|
||||
move |context: NativeCallContext, version_i64: i64, content: String, created_at_i64: i64, created_by: String| -> Result<ContractRevision, Box<EvalAltResult>> {
|
||||
let version = i64_to_u32(version_i64, context.position(), "version", "new_contract_revision")?;
|
||||
let created_at = i64_to_u64(created_at_i64, context.position(), "created_at", "new_contract_revision")?;
|
||||
Ok(ContractRevision::new(version, content, created_at, created_by))
|
||||
}
|
||||
move |context: NativeCallContext,
|
||||
version_i64: i64,
|
||||
content: String,
|
||||
created_at_i64: i64,
|
||||
created_by: String|
|
||||
-> Result<ContractRevision, Box<EvalAltResult>> {
|
||||
let version = i64_to_u32(
|
||||
version_i64,
|
||||
context.position(),
|
||||
"version",
|
||||
"new_contract_revision",
|
||||
)?;
|
||||
let created_at = i64_to_u64(
|
||||
created_at_i64,
|
||||
context.position(),
|
||||
"created_at",
|
||||
"new_contract_revision",
|
||||
)?;
|
||||
Ok(ContractRevision::new(
|
||||
version, content, created_at, created_by,
|
||||
))
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"comments",
|
||||
|mut revision: ContractRevision, comments: String| -> ContractRevision {
|
||||
revision.comments = Some(comments);
|
||||
revision
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"version",
|
||||
|revision: &mut ContractRevision| -> Result<i64, Box<EvalAltResult>> {
|
||||
Ok(revision.version as i64)
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"content",
|
||||
|revision: &mut ContractRevision| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(revision.content.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"created_at",
|
||||
|revision: &mut ContractRevision| -> Result<i64, Box<EvalAltResult>> {
|
||||
Ok(revision.created_at as i64)
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"created_by",
|
||||
|revision: &mut ContractRevision| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(revision.created_by.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"comments",
|
||||
|revision: &mut ContractRevision| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(revision
|
||||
.comments
|
||||
.clone()
|
||||
.map_or(Dynamic::UNIT, Dynamic::from))
|
||||
},
|
||||
);
|
||||
engine.register_fn("comments", |mut revision: ContractRevision, comments: String| -> ContractRevision {
|
||||
revision.comments = Some(comments);
|
||||
revision
|
||||
});
|
||||
engine.register_get("version", |revision: &mut ContractRevision| -> Result<i64, Box<EvalAltResult>> { Ok(revision.version as i64) });
|
||||
engine.register_get("content", |revision: &mut ContractRevision| -> Result<String, Box<EvalAltResult>> { Ok(revision.content.clone()) });
|
||||
engine.register_get("created_at", |revision: &mut ContractRevision| -> Result<i64, Box<EvalAltResult>> { Ok(revision.created_at as i64) });
|
||||
engine.register_get("created_by", |revision: &mut ContractRevision| -> Result<String, Box<EvalAltResult>> { Ok(revision.created_by.clone()) });
|
||||
engine.register_get("comments", |revision: &mut ContractRevision| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(revision.comments.clone().map_or(Dynamic::UNIT, Dynamic::from))
|
||||
});
|
||||
|
||||
// --- ContractSigner ---
|
||||
// --- ContractSigner ---
|
||||
engine.register_type_with_name::<ContractSigner>("ContractSigner");
|
||||
engine.register_fn(
|
||||
"new_contract_signer",
|
||||
|id: String, name: String, email: String| -> ContractSigner {
|
||||
ContractSigner::new(id, name, email)
|
||||
}
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"status",
|
||||
|signer: ContractSigner, status: SignerStatus| -> ContractSigner { signer.status(status) },
|
||||
);
|
||||
engine.register_fn(
|
||||
"signed_at",
|
||||
|context: NativeCallContext,
|
||||
signer: ContractSigner,
|
||||
signed_at_i64: i64|
|
||||
-> Result<ContractSigner, Box<EvalAltResult>> {
|
||||
let signed_at_u64 = i64_to_u64(
|
||||
signed_at_i64,
|
||||
context.position(),
|
||||
"signed_at",
|
||||
"ContractSigner.signed_at",
|
||||
)?;
|
||||
Ok(signer.signed_at(signed_at_u64))
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"clear_signed_at",
|
||||
|signer: ContractSigner| -> ContractSigner { signer.clear_signed_at() },
|
||||
);
|
||||
engine.register_fn(
|
||||
"comments",
|
||||
|signer: ContractSigner, comments: String| -> ContractSigner { signer.comments(comments) },
|
||||
);
|
||||
engine.register_fn(
|
||||
"clear_comments",
|
||||
|signer: ContractSigner| -> ContractSigner { signer.clear_comments() },
|
||||
);
|
||||
engine.register_fn("status", |signer: ContractSigner, status: SignerStatus| -> ContractSigner { signer.status(status) });
|
||||
engine.register_fn("signed_at", |context: NativeCallContext, signer: ContractSigner, signed_at_i64: i64| -> Result<ContractSigner, Box<EvalAltResult>> {
|
||||
let signed_at_u64 = i64_to_u64(signed_at_i64, context.position(), "signed_at", "ContractSigner.signed_at")?;
|
||||
Ok(signer.signed_at(signed_at_u64))
|
||||
});
|
||||
engine.register_fn("clear_signed_at", |signer: ContractSigner| -> ContractSigner { signer.clear_signed_at() });
|
||||
engine.register_fn("comments", |signer: ContractSigner, comments: String| -> ContractSigner { signer.comments(comments) });
|
||||
engine.register_fn("clear_comments", |signer: ContractSigner| -> ContractSigner { signer.clear_comments() });
|
||||
|
||||
engine.register_get("id", |signer: &mut ContractSigner| -> Result<String, Box<EvalAltResult>> { Ok(signer.id.clone()) });
|
||||
engine.register_get("name", |signer: &mut ContractSigner| -> Result<String, Box<EvalAltResult>> { Ok(signer.name.clone()) });
|
||||
engine.register_get("email", |signer: &mut ContractSigner| -> Result<String, Box<EvalAltResult>> { Ok(signer.email.clone()) });
|
||||
engine.register_get("status", |signer: &mut ContractSigner| -> Result<SignerStatus, Box<EvalAltResult>> { Ok(signer.status.clone()) });
|
||||
engine.register_get("signed_at_ts", |signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer.signed_at.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
});
|
||||
engine.register_get("comments", |signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer.comments.clone().map_or(Dynamic::UNIT, Dynamic::from))
|
||||
});
|
||||
engine.register_get("signed_at", |signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer.signed_at.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts)))
|
||||
});
|
||||
// Reminder functionality
|
||||
engine.register_fn(
|
||||
"last_reminder_mail_sent_at",
|
||||
|context: NativeCallContext,
|
||||
signer: ContractSigner,
|
||||
timestamp_i64: i64|
|
||||
-> Result<ContractSigner, Box<EvalAltResult>> {
|
||||
let timestamp_u64 = i64_to_u64(
|
||||
timestamp_i64,
|
||||
context.position(),
|
||||
"timestamp",
|
||||
"ContractSigner.last_reminder_mail_sent_at",
|
||||
)?;
|
||||
Ok(signer.last_reminder_mail_sent_at(timestamp_u64))
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"clear_last_reminder_mail_sent_at",
|
||||
|signer: ContractSigner| -> ContractSigner { signer.clear_last_reminder_mail_sent_at() },
|
||||
);
|
||||
|
||||
// --- Contract ---
|
||||
// Helper methods for reminder logic
|
||||
engine.register_fn(
|
||||
"can_send_reminder",
|
||||
|context: NativeCallContext,
|
||||
signer: &mut ContractSigner,
|
||||
current_timestamp_i64: i64|
|
||||
-> Result<bool, Box<EvalAltResult>> {
|
||||
let current_timestamp = i64_to_u64(
|
||||
current_timestamp_i64,
|
||||
context.position(),
|
||||
"current_timestamp",
|
||||
"ContractSigner.can_send_reminder",
|
||||
)?;
|
||||
Ok(signer.can_send_reminder(current_timestamp))
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn(
|
||||
"reminder_cooldown_remaining",
|
||||
|context: NativeCallContext,
|
||||
signer: &mut ContractSigner,
|
||||
current_timestamp_i64: i64|
|
||||
-> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let current_timestamp = i64_to_u64(
|
||||
current_timestamp_i64,
|
||||
context.position(),
|
||||
"current_timestamp",
|
||||
"ContractSigner.reminder_cooldown_remaining",
|
||||
)?;
|
||||
Ok(signer
|
||||
.reminder_cooldown_remaining(current_timestamp)
|
||||
.map_or(Dynamic::UNIT, |remaining| Dynamic::from(remaining as i64)))
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn(
|
||||
"mark_reminder_sent",
|
||||
|context: NativeCallContext,
|
||||
signer: &mut ContractSigner,
|
||||
current_timestamp_i64: i64|
|
||||
-> Result<(), Box<EvalAltResult>> {
|
||||
let current_timestamp = i64_to_u64(
|
||||
current_timestamp_i64,
|
||||
context.position(),
|
||||
"current_timestamp",
|
||||
"ContractSigner.mark_reminder_sent",
|
||||
)?;
|
||||
signer.mark_reminder_sent(current_timestamp);
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_get(
|
||||
"id",
|
||||
|signer: &mut ContractSigner| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(signer.id.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"name",
|
||||
|signer: &mut ContractSigner| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(signer.name.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"email",
|
||||
|signer: &mut ContractSigner| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(signer.email.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"status",
|
||||
|signer: &mut ContractSigner| -> Result<SignerStatus, Box<EvalAltResult>> {
|
||||
Ok(signer.status.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"signed_at_ts",
|
||||
|signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer
|
||||
.signed_at
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"comments",
|
||||
|signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer.comments.clone().map_or(Dynamic::UNIT, Dynamic::from))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"signed_at",
|
||||
|signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer
|
||||
.signed_at
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts)))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"last_reminder_mail_sent_at",
|
||||
|signer: &mut ContractSigner| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(signer
|
||||
.last_reminder_mail_sent_at
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
},
|
||||
);
|
||||
|
||||
// --- Contract ---
|
||||
engine.register_type_with_name::<Contract>("Contract");
|
||||
engine.register_fn(
|
||||
"new_contract",
|
||||
move |context: NativeCallContext, base_id_i64: i64, contract_id: String| -> Result<Contract, Box<EvalAltResult>> {
|
||||
move |context: NativeCallContext,
|
||||
base_id_i64: i64,
|
||||
contract_id: String|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let base_id = i64_to_u32(base_id_i64, context.position(), "base_id", "new_contract")?;
|
||||
Ok(Contract::new(base_id, contract_id))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Builder methods
|
||||
engine.register_fn("title", |contract: Contract, title: String| -> Contract { contract.title(title) });
|
||||
engine.register_fn("description", |contract: Contract, description: String| -> Contract { contract.description(description) });
|
||||
engine.register_fn("contract_type", |contract: Contract, contract_type: String| -> Contract { contract.contract_type(contract_type) });
|
||||
engine.register_fn("status", |contract: Contract, status: ContractStatus| -> Contract { contract.status(status) });
|
||||
engine.register_fn("created_by", |contract: Contract, created_by: String| -> Contract { contract.created_by(created_by) });
|
||||
engine.register_fn("terms_and_conditions", |contract: Contract, terms: String| -> Contract { contract.terms_and_conditions(terms) });
|
||||
|
||||
engine.register_fn("start_date", |context: NativeCallContext, contract: Contract, start_date_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let start_date_u64 = i64_to_u64(start_date_i64, context.position(), "start_date", "Contract.start_date")?;
|
||||
Ok(contract.start_date(start_date_u64))
|
||||
engine.register_fn("title", |contract: Contract, title: String| -> Contract {
|
||||
contract.title(title)
|
||||
});
|
||||
engine.register_fn("clear_start_date", |contract: Contract| -> Contract { contract.clear_start_date() });
|
||||
engine.register_fn(
|
||||
"description",
|
||||
|contract: Contract, description: String| -> Contract { contract.description(description) },
|
||||
);
|
||||
engine.register_fn(
|
||||
"contract_type",
|
||||
|contract: Contract, contract_type: String| -> Contract {
|
||||
contract.contract_type(contract_type)
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"status",
|
||||
|contract: Contract, status: ContractStatus| -> Contract { contract.status(status) },
|
||||
);
|
||||
engine.register_fn(
|
||||
"created_by",
|
||||
|contract: Contract, created_by: String| -> Contract { contract.created_by(created_by) },
|
||||
);
|
||||
engine.register_fn(
|
||||
"terms_and_conditions",
|
||||
|contract: Contract, terms: String| -> Contract { contract.terms_and_conditions(terms) },
|
||||
);
|
||||
|
||||
engine.register_fn("end_date", |context: NativeCallContext, contract: Contract, end_date_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let end_date_u64 = i64_to_u64(end_date_i64, context.position(), "end_date", "Contract.end_date")?;
|
||||
Ok(contract.end_date(end_date_u64))
|
||||
});
|
||||
engine.register_fn("clear_end_date", |contract: Contract| -> Contract { contract.clear_end_date() });
|
||||
|
||||
engine.register_fn("renewal_period_days", |context: NativeCallContext, contract: Contract, days_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let days_i32 = i64_to_i32(days_i64, context.position(), "renewal_period_days", "Contract.renewal_period_days")?;
|
||||
Ok(contract.renewal_period_days(days_i32))
|
||||
});
|
||||
engine.register_fn("clear_renewal_period_days", |contract: Contract| -> Contract { contract.clear_renewal_period_days() });
|
||||
|
||||
engine.register_fn("next_renewal_date", |context: NativeCallContext, contract: Contract, date_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let date_u64 = i64_to_u64(date_i64, context.position(), "next_renewal_date", "Contract.next_renewal_date")?;
|
||||
Ok(contract.next_renewal_date(date_u64))
|
||||
});
|
||||
engine.register_fn("clear_next_renewal_date", |contract: Contract| -> Contract { contract.clear_next_renewal_date() });
|
||||
|
||||
engine.register_fn("add_signer", |contract: Contract, signer: ContractSigner| -> Contract { contract.add_signer(signer) });
|
||||
engine.register_fn("signers", |contract: Contract, signers_array: Array| -> Contract {
|
||||
let signers_vec = signers_array.into_iter().filter_map(|s| s.try_cast::<ContractSigner>()).collect();
|
||||
contract.signers(signers_vec)
|
||||
engine.register_fn(
|
||||
"start_date",
|
||||
|context: NativeCallContext,
|
||||
contract: Contract,
|
||||
start_date_i64: i64|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let start_date_u64 = i64_to_u64(
|
||||
start_date_i64,
|
||||
context.position(),
|
||||
"start_date",
|
||||
"Contract.start_date",
|
||||
)?;
|
||||
Ok(contract.start_date(start_date_u64))
|
||||
},
|
||||
);
|
||||
engine.register_fn("clear_start_date", |contract: Contract| -> Contract {
|
||||
contract.clear_start_date()
|
||||
});
|
||||
|
||||
engine.register_fn("add_revision", |contract: Contract, revision: ContractRevision| -> Contract { contract.add_revision(revision) });
|
||||
engine.register_fn("revisions", |contract: Contract, revisions_array: Array| -> Contract {
|
||||
let revisions_vec = revisions_array.into_iter().filter_map(|r| r.try_cast::<ContractRevision>()).collect();
|
||||
contract.revisions(revisions_vec)
|
||||
engine.register_fn(
|
||||
"end_date",
|
||||
|context: NativeCallContext,
|
||||
contract: Contract,
|
||||
end_date_i64: i64|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let end_date_u64 = i64_to_u64(
|
||||
end_date_i64,
|
||||
context.position(),
|
||||
"end_date",
|
||||
"Contract.end_date",
|
||||
)?;
|
||||
Ok(contract.end_date(end_date_u64))
|
||||
},
|
||||
);
|
||||
engine.register_fn("clear_end_date", |contract: Contract| -> Contract {
|
||||
contract.clear_end_date()
|
||||
});
|
||||
|
||||
engine.register_fn("current_version", |context: NativeCallContext, contract: Contract, version_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let version_u32 = i64_to_u32(version_i64, context.position(), "current_version", "Contract.current_version")?;
|
||||
Ok(contract.current_version(version_u32))
|
||||
});
|
||||
engine.register_fn(
|
||||
"renewal_period_days",
|
||||
|context: NativeCallContext,
|
||||
contract: Contract,
|
||||
days_i64: i64|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let days_i32 = i64_to_i32(
|
||||
days_i64,
|
||||
context.position(),
|
||||
"renewal_period_days",
|
||||
"Contract.renewal_period_days",
|
||||
)?;
|
||||
Ok(contract.renewal_period_days(days_i32))
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"clear_renewal_period_days",
|
||||
|contract: Contract| -> Contract { contract.clear_renewal_period_days() },
|
||||
);
|
||||
|
||||
engine.register_fn("last_signed_date", |context: NativeCallContext, contract: Contract, date_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let date_u64 = i64_to_u64(date_i64, context.position(), "last_signed_date", "Contract.last_signed_date")?;
|
||||
Ok(contract.last_signed_date(date_u64))
|
||||
engine.register_fn(
|
||||
"next_renewal_date",
|
||||
|context: NativeCallContext,
|
||||
contract: Contract,
|
||||
date_i64: i64|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let date_u64 = i64_to_u64(
|
||||
date_i64,
|
||||
context.position(),
|
||||
"next_renewal_date",
|
||||
"Contract.next_renewal_date",
|
||||
)?;
|
||||
Ok(contract.next_renewal_date(date_u64))
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"clear_next_renewal_date",
|
||||
|contract: Contract| -> Contract { contract.clear_next_renewal_date() },
|
||||
);
|
||||
|
||||
engine.register_fn(
|
||||
"add_signer",
|
||||
|contract: Contract, signer: ContractSigner| -> Contract { contract.add_signer(signer) },
|
||||
);
|
||||
engine.register_fn(
|
||||
"signers",
|
||||
|contract: Contract, signers_array: Array| -> Contract {
|
||||
let signers_vec = signers_array
|
||||
.into_iter()
|
||||
.filter_map(|s| s.try_cast::<ContractSigner>())
|
||||
.collect();
|
||||
contract.signers(signers_vec)
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn(
|
||||
"add_revision",
|
||||
|contract: Contract, revision: ContractRevision| -> Contract {
|
||||
contract.add_revision(revision)
|
||||
},
|
||||
);
|
||||
engine.register_fn(
|
||||
"revisions",
|
||||
|contract: Contract, revisions_array: Array| -> Contract {
|
||||
let revisions_vec = revisions_array
|
||||
.into_iter()
|
||||
.filter_map(|r| r.try_cast::<ContractRevision>())
|
||||
.collect();
|
||||
contract.revisions(revisions_vec)
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn(
|
||||
"current_version",
|
||||
|context: NativeCallContext,
|
||||
contract: Contract,
|
||||
version_i64: i64|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let version_u32 = i64_to_u32(
|
||||
version_i64,
|
||||
context.position(),
|
||||
"current_version",
|
||||
"Contract.current_version",
|
||||
)?;
|
||||
Ok(contract.current_version(version_u32))
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn(
|
||||
"last_signed_date",
|
||||
|context: NativeCallContext,
|
||||
contract: Contract,
|
||||
date_i64: i64|
|
||||
-> Result<Contract, Box<EvalAltResult>> {
|
||||
let date_u64 = i64_to_u64(
|
||||
date_i64,
|
||||
context.position(),
|
||||
"last_signed_date",
|
||||
"Contract.last_signed_date",
|
||||
)?;
|
||||
Ok(contract.last_signed_date(date_u64))
|
||||
},
|
||||
);
|
||||
engine.register_fn("clear_last_signed_date", |contract: Contract| -> Contract {
|
||||
contract.clear_last_signed_date()
|
||||
});
|
||||
engine.register_fn("clear_last_signed_date", |contract: Contract| -> Contract { contract.clear_last_signed_date() });
|
||||
|
||||
// Getters for Contract
|
||||
engine.register_get("id", |contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> { Ok(contract.base_data.id as i64) });
|
||||
engine.register_get("created_at_ts", |contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> { Ok(contract.base_data.created_at as i64) });
|
||||
engine.register_get("updated_at_ts", |contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> { Ok(contract.base_data.modified_at as i64) });
|
||||
engine.register_get("contract_id", |contract: &mut Contract| -> Result<String, Box<EvalAltResult>> { Ok(contract.contract_id.clone()) });
|
||||
engine.register_get("title", |contract: &mut Contract| -> Result<String, Box<EvalAltResult>> { Ok(contract.title.clone()) });
|
||||
engine.register_get("description", |contract: &mut Contract| -> Result<String, Box<EvalAltResult>> { Ok(contract.description.clone()) });
|
||||
engine.register_get("contract_type", |contract: &mut Contract| -> Result<String, Box<EvalAltResult>> { Ok(contract.contract_type.clone()) });
|
||||
engine.register_get("status", |contract: &mut Contract| -> Result<ContractStatus, Box<EvalAltResult>> { Ok(contract.status.clone()) });
|
||||
engine.register_get("created_by", |contract: &mut Contract| -> Result<String, Box<EvalAltResult>> { Ok(contract.created_by.clone()) });
|
||||
engine.register_get("terms_and_conditions", |contract: &mut Contract| -> Result<String, Box<EvalAltResult>> { Ok(contract.terms_and_conditions.clone()) });
|
||||
|
||||
engine.register_get("start_date", |contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract.start_date.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
});
|
||||
engine.register_get("end_date", |contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract.end_date.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
});
|
||||
engine.register_get("renewal_period_days", |contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract.renewal_period_days.map_or(Dynamic::UNIT, |days| Dynamic::from(days as i64)))
|
||||
});
|
||||
engine.register_get("next_renewal_date", |contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract.next_renewal_date.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
});
|
||||
engine.register_get("last_signed_date", |contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract.last_signed_date.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
});
|
||||
engine.register_get(
|
||||
"id",
|
||||
|contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> {
|
||||
Ok(contract.base_data.id as i64)
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"created_at_ts",
|
||||
|contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> {
|
||||
Ok(contract.base_data.created_at as i64)
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"updated_at_ts",
|
||||
|contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> {
|
||||
Ok(contract.base_data.modified_at as i64)
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"contract_id",
|
||||
|contract: &mut Contract| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(contract.contract_id.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"title",
|
||||
|contract: &mut Contract| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(contract.title.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"description",
|
||||
|contract: &mut Contract| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(contract.description.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"contract_type",
|
||||
|contract: &mut Contract| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(contract.contract_type.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"status",
|
||||
|contract: &mut Contract| -> Result<ContractStatus, Box<EvalAltResult>> {
|
||||
Ok(contract.status.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"created_by",
|
||||
|contract: &mut Contract| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(contract.created_by.clone())
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"terms_and_conditions",
|
||||
|contract: &mut Contract| -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(contract.terms_and_conditions.clone())
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_get("current_version", |contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> { Ok(contract.current_version as i64) });
|
||||
engine.register_get(
|
||||
"start_date",
|
||||
|contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract
|
||||
.start_date
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"end_date",
|
||||
|contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract
|
||||
.end_date
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"renewal_period_days",
|
||||
|contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract
|
||||
.renewal_period_days
|
||||
.map_or(Dynamic::UNIT, |days| Dynamic::from(days as i64)))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"next_renewal_date",
|
||||
|contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract
|
||||
.next_renewal_date
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"last_signed_date",
|
||||
|contract: &mut Contract| -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
Ok(contract
|
||||
.last_signed_date
|
||||
.map_or(Dynamic::UNIT, |ts| Dynamic::from(ts as i64)))
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_get("signers", |contract: &mut Contract| -> Result<Array, Box<EvalAltResult>> {
|
||||
let rhai_array = contract.signers.iter().cloned().map(Dynamic::from).collect::<Array>();
|
||||
Ok(rhai_array)
|
||||
});
|
||||
engine.register_get("revisions", |contract: &mut Contract| -> Result<Array, Box<EvalAltResult>> {
|
||||
let rhai_array = contract.revisions.iter().cloned().map(Dynamic::from).collect::<Array>();
|
||||
Ok(rhai_array)
|
||||
});
|
||||
engine.register_get(
|
||||
"current_version",
|
||||
|contract: &mut Contract| -> Result<i64, Box<EvalAltResult>> {
|
||||
Ok(contract.current_version as i64)
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_get(
|
||||
"signers",
|
||||
|contract: &mut Contract| -> Result<Array, Box<EvalAltResult>> {
|
||||
let rhai_array = contract
|
||||
.signers
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Dynamic::from)
|
||||
.collect::<Array>();
|
||||
Ok(rhai_array)
|
||||
},
|
||||
);
|
||||
engine.register_get(
|
||||
"revisions",
|
||||
|contract: &mut Contract| -> Result<Array, Box<EvalAltResult>> {
|
||||
let rhai_array = contract
|
||||
.revisions
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Dynamic::from)
|
||||
.collect::<Array>();
|
||||
Ok(rhai_array)
|
||||
},
|
||||
);
|
||||
|
||||
// Method set_status
|
||||
engine.register_fn("set_contract_status", |contract: &mut Contract, status: ContractStatus| {
|
||||
contract.set_status(status);
|
||||
});
|
||||
engine.register_fn(
|
||||
"set_contract_status",
|
||||
|contract: &mut Contract, status: ContractStatus| {
|
||||
contract.set_status(status);
|
||||
},
|
||||
);
|
||||
|
||||
// --- Database Interaction ---
|
||||
let captured_db_for_set = Arc::clone(&db);
|
||||
engine.register_fn("set_contract",
|
||||
engine.register_fn(
|
||||
"set_contract",
|
||||
move |contract: Contract| -> Result<(), Box<EvalAltResult>> {
|
||||
captured_db_for_set.set(&contract).map(|_| ()).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Failed to set Contract (ID: {}): {}", contract.base_data.id, e).into(),
|
||||
format!(
|
||||
"Failed to set Contract (ID: {}): {}",
|
||||
contract.base_data.id, e
|
||||
)
|
||||
.into(),
|
||||
Position::NONE,
|
||||
))
|
||||
})
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
let captured_db_for_get = Arc::clone(&db);
|
||||
engine.register_fn("get_contract_by_id",
|
||||
engine.register_fn(
|
||||
"get_contract_by_id",
|
||||
move |context: NativeCallContext, id_i64: i64| -> Result<Contract, Box<EvalAltResult>> {
|
||||
let id_u32 = i64_to_u32(id_i64, context.position(), "id", "get_contract_by_id")?;
|
||||
|
||||
captured_db_for_get.get_by_id(id_u32)
|
||||
.map_err(|e| Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Error getting Contract (ID: {}): {}", id_u32, e).into(),
|
||||
Position::NONE,
|
||||
)))?
|
||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Contract with ID {} not found", id_u32).into(),
|
||||
Position::NONE,
|
||||
)))
|
||||
});
|
||||
|
||||
captured_db_for_get
|
||||
.get_by_id(id_u32)
|
||||
.map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Error getting Contract (ID: {}): {}", id_u32, e).into(),
|
||||
Position::NONE,
|
||||
))
|
||||
})?
|
||||
.ok_or_else(|| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Contract with ID {} not found", id_u32).into(),
|
||||
Position::NONE,
|
||||
))
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ pub mut:
|
||||
status SignerStatus
|
||||
signed_at ourtime.OurTime // Optional in Rust, OurTime can be zero
|
||||
comments string // Optional in Rust, string can be empty
|
||||
last_reminder_mail_sent_at ourtime.OurTime // Unix timestamp of last reminder sent
|
||||
}
|
||||
|
||||
// SignerStatus defines the status of a contract signer
|
||||
|
Loading…
Reference in New Issue
Block a user