db/heromodels/src/models/legal/contract.rs
2025-05-22 23:57:33 +03:00

297 lines
7.4 KiB
Rust

use heromodels_core::BaseModelData;
use heromodels_derive::model;
use std::fmt;
use serde::{Deserialize, Serialize};
// --- Enums ---
/// Defines the possible statuses of a contract
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ContractStatus {
Draft,
PendingSignatures,
Signed,
Active,
Expired,
Cancelled,
}
impl Default for ContractStatus {
fn default() -> Self {
ContractStatus::Draft
}
}
impl fmt::Display for ContractStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self) // Outputs the variant name, e.g., "Draft"
}
}
/// Defines the status of a contract signer
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum SignerStatus {
Pending,
Signed,
Rejected,
}
impl Default for SignerStatus {
fn default() -> Self {
SignerStatus::Pending
}
}
impl fmt::Display for SignerStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self) // Outputs the variant name, e.g., "Pending"
}
}
// --- Structs for nested data ---
/// ContractRevision represents a version of the contract content
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ContractRevision {
pub version: u32,
pub content: String,
pub created_at: u64, // Timestamp
pub created_by: String,
pub comments: Option<String>,
}
impl ContractRevision {
pub fn new(version: u32, content: String, created_at: u64, created_by: String) -> Self {
Self {
version,
content,
created_at,
created_by,
comments: None,
}
}
pub fn comments(mut self, comments: impl ToString) -> Self {
self.comments = Some(comments.to_string());
self
}
}
/// ContractSigner represents a party involved in signing a contract
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ContractSigner {
pub id: String, // Unique ID for the signer (UUID string)
pub name: String,
pub email: String,
pub status: SignerStatus,
pub signed_at: Option<u64>, // Timestamp
pub comments: Option<String>,
}
impl ContractSigner {
pub fn new(id: String, name: String, email: String) -> Self {
Self {
id,
name,
email,
status: SignerStatus::default(),
signed_at: None,
comments: None,
}
}
pub fn status(mut self, status: SignerStatus) -> Self {
self.status = status;
self
}
pub fn signed_at(mut self, signed_at: u64) -> Self {
self.signed_at = Some(signed_at);
self
}
pub fn clear_signed_at(mut self) -> Self {
self.signed_at = None;
self
}
pub fn comments(mut self, comments: impl ToString) -> Self {
self.comments = Some(comments.to_string());
self
}
pub fn clear_comments(mut self) -> Self {
self.comments = None;
self
}
}
// --- Main Contract Model ---
/// Represents a legal agreement
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[model]
pub struct Contract {
pub base_data: BaseModelData, // Provides id (u32), created_at (u64), updated_at (u64)
#[index]
pub contract_id: String, // Unique ID for the contract (UUID string)
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,
pub last_signed_date: Option<u64>,
}
impl Contract {
pub fn new(_base_id: u32, contract_id: String) -> Self {
Self {
base_data: BaseModelData::new(),
contract_id,
title: String::new(),
description: String::new(),
contract_type: String::new(),
status: ContractStatus::default(),
created_by: String::new(),
terms_and_conditions: String::new(),
start_date: None,
end_date: None,
renewal_period_days: None,
next_renewal_date: None,
signers: Vec::new(),
revisions: Vec::new(),
current_version: 0,
last_signed_date: None,
}
}
// Builder methods
pub fn title(mut self, title: impl ToString) -> Self {
self.title = title.to_string();
self
}
pub fn description(mut self, description: impl ToString) -> Self {
self.description = description.to_string();
self
}
pub fn contract_type(mut self, contract_type: impl ToString) -> Self {
self.contract_type = contract_type.to_string();
self
}
pub fn status(mut self, status: ContractStatus) -> Self {
self.status = status;
self
}
pub fn created_by(mut self, created_by: impl ToString) -> Self {
self.created_by = created_by.to_string();
self
}
pub fn terms_and_conditions(mut self, terms: impl ToString) -> Self {
self.terms_and_conditions = terms.to_string();
self
}
pub fn start_date(mut self, start_date: u64) -> Self {
self.start_date = Some(start_date);
self
}
pub fn clear_start_date(mut self) -> Self {
self.start_date = None;
self
}
pub fn end_date(mut self, end_date: u64) -> Self {
self.end_date = Some(end_date);
self
}
pub fn clear_end_date(mut self) -> Self {
self.end_date = None;
self
}
pub fn renewal_period_days(mut self, days: i32) -> Self {
self.renewal_period_days = Some(days);
self
}
pub fn clear_renewal_period_days(mut self) -> Self {
self.renewal_period_days = None;
self
}
pub fn next_renewal_date(mut self, date: u64) -> Self {
self.next_renewal_date = Some(date);
self
}
pub fn clear_next_renewal_date(mut self) -> Self {
self.next_renewal_date = None;
self
}
pub fn add_signer(mut self, signer: ContractSigner) -> Self {
self.signers.push(signer);
self
}
pub fn signers(mut self, signers: Vec<ContractSigner>) -> Self {
self.signers = signers;
self
}
pub fn add_revision(mut self, revision: ContractRevision) -> Self {
self.revisions.push(revision);
self
}
pub fn revisions(mut self, revisions: Vec<ContractRevision>) -> Self {
self.revisions = revisions;
self
}
pub fn current_version(mut self, version: u32) -> Self {
self.current_version = version;
self
}
pub fn last_signed_date(mut self, date: u64) -> Self {
self.last_signed_date = Some(date);
self
}
pub fn clear_last_signed_date(mut self) -> Self {
self.last_signed_date = None;
self
}
// Example methods for state changes
pub fn set_status(&mut self, status: crate::models::ContractStatus) {
self.status = status;
// self.base_data.touch(); // Assume #[model] handles timestamp updates
}
}