add flow and contract models

This commit is contained in:
timurgordon 2025-05-20 21:59:45 +03:00
parent bd4770b99b
commit aa8ef90f9f
6 changed files with 466 additions and 0 deletions

View File

@ -0,0 +1,47 @@
use heromodels_core::BaseModelData;
use heromodels_derive::model;
use serde::{Deserialize, Serialize};
/// Represents a signing flow.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[model]
pub struct Flow {
/// Base model data (id, created_at, updated_at).
pub base_data: BaseModelData,
/// A unique UUID for the flow, for external reference.
#[index]
pub flow_uuid: String,
/// Name of the flow.
#[index]
pub name: String,
/// Current status of the flow (e.g., "Pending", "InProgress", "Completed", "Failed").
pub status: String,
}
impl Flow {
/// Create a new flow.
/// The `id` is the database primary key.
/// The `flow_uuid` should be a Uuid::new_v4().to_string().
pub fn new(id: u32, flow_uuid: impl ToString, name: impl ToString, status: impl ToString) -> Self {
Self {
base_data: BaseModelData::new(id),
flow_uuid: flow_uuid.to_string(),
name: name.to_string(),
status: status.to_string(),
}
}
// Builder methods for optional fields or to change initial values can be added here if needed.
// For example:
// pub fn name(mut self, name: impl ToString) -> Self {
// self.name = name.to_string();
// self
// }
// pub fn status(mut self, status: impl ToString) -> Self {
// self.status = status.to_string();
// self
// }
}

View File

@ -0,0 +1,49 @@
use heromodels_core::BaseModelData;
use heromodels_derive::model;
use serde::{Deserialize, Serialize};
/// Represents a step within a signing flow.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[model]
pub struct FlowStep {
/// Base model data.
pub base_data: BaseModelData,
/// Foreign key to the Flow this step belongs to.
#[index]
pub flow_id: u32,
/// Optional description for the step.
pub description: Option<String>,
/// Order of this step within the flow.
#[index]
pub step_order: u32,
/// Current status of the flow step (e.g., "Pending", "InProgress", "Completed", "Failed").
pub status: String,
}
impl FlowStep {
/// Create a new flow step.
pub fn new(id: u32, flow_id: u32, step_order: u32, status: impl ToString) -> Self {
Self {
base_data: BaseModelData::new(id),
flow_id,
description: None,
step_order,
status: status.to_string(),
}
}
/// Sets the description for the flow step.
pub fn description(mut self, description: impl ToString) -> Self {
self.description = Some(description.to_string());
self
}
// pub fn status(mut self, status: impl ToString) -> Self {
// self.status = status.to_string();
// self
// }
}

View File

@ -0,0 +1,9 @@
// Export flowbroker model submodules
pub mod flow;
pub mod flow_step;
pub mod signature_requirement;
// Re-export key types for convenience
pub use flow::Flow;
pub use flow_step::FlowStep;
pub use signature_requirement::SignatureRequirement;

View File

@ -0,0 +1,62 @@
use heromodels_core::BaseModelData;
use heromodels_derive::model;
use serde::{Deserialize, Serialize};
/// Represents a signature requirement for a flow step.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[model]
pub struct SignatureRequirement {
/// Base model data.
pub base_data: BaseModelData,
/// Foreign key to the FlowStep this requirement belongs to.
#[index]
pub flow_step_id: u32,
/// The public key required to sign the message.
pub public_key: String,
/// The plaintext message to be signed.
pub message: String,
/// The public key of the entity that signed the message, if signed.
pub signed_by: Option<String>,
/// The signature, if signed.
pub signature: Option<String>,
/// Current status of the signature requirement (e.g., "Pending", "SentToClient", "Signed", "Failed", "Error").
pub status: String,
}
impl SignatureRequirement {
/// Create a new signature requirement.
pub fn new(id: u32, flow_step_id: u32, public_key: impl ToString, message: impl ToString, status: impl ToString) -> Self {
Self {
base_data: BaseModelData::new(id),
flow_step_id,
public_key: public_key.to_string(),
message: message.to_string(),
signed_by: None,
signature: None,
status: status.to_string(),
}
}
/// Sets the public key of the signer.
pub fn signed_by(mut self, signed_by: impl ToString) -> Self {
self.signed_by = Some(signed_by.to_string());
self
}
/// Sets the signature.
pub fn signature(mut self, signature: impl ToString) -> Self {
self.signature = Some(signature.to_string());
self
}
// pub fn status(mut self, status: impl ToString) -> Self {
// self.status = status.to_string();
// self
// }
}

View File

@ -0,0 +1,296 @@
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(base_id),
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
}
}

View File

@ -0,0 +1,3 @@
pub mod contract;
pub use contract::{Contract, ContractRevision, ContractSigner, ContractStatus, SignerStatus};