backbone-banking 0.7.1

Cash & bank — bank/account master, statement import, reconciliation, and clearing postings (5th GL producer)
Documentation
//! Domain Entities
//!
//! Generated by metaphor-schema. Do not edit manually.

pub mod bank;
pub mod bank_account;
pub mod bank_clearance;
pub mod bank_reconciliation;
pub mod bank_statement_import;
pub mod bank_transaction;
pub mod fx_gain_loss;
pub mod reconcile_preset;
pub mod bank_status;
pub mod bank_account_status;
pub mod bank_account_type;
pub mod matched_source_type;
pub mod match_method;
pub mod recon_status;
pub mod source_format;
pub mod import_status;
pub mod txn_status;
pub mod fx_direction;
pub mod match_on;
pub mod preset_status;

// Re-exports
pub use bank::Bank;
pub use bank::BankBuilder;
pub use bank::BankId;
pub use bank_account::BankAccount;
pub use bank_account::BankAccountBuilder;
pub use bank_account::BankAccountId;
pub use bank_clearance::BankClearance;
pub use bank_clearance::BankClearanceBuilder;
pub use bank_clearance::BankClearanceId;
pub use bank_reconciliation::BankReconciliation;
pub use bank_reconciliation::BankReconciliationBuilder;
pub use bank_reconciliation::BankReconciliationId;
pub use bank_statement_import::BankStatementImport;
pub use bank_statement_import::BankStatementImportBuilder;
pub use bank_statement_import::BankStatementImportId;
pub use bank_transaction::BankTransaction;
pub use bank_transaction::BankTransactionBuilder;
pub use bank_transaction::BankTransactionId;
pub use fx_gain_loss::FxGainLoss;
pub use fx_gain_loss::FxGainLossBuilder;
pub use fx_gain_loss::FxGainLossId;
pub use reconcile_preset::ReconcilePreset;
pub use reconcile_preset::ReconcilePresetBuilder;
pub use reconcile_preset::ReconcilePresetId;
pub use bank_status::BankStatus;
pub use bank_account_status::BankAccountStatus;
pub use bank_account_type::BankAccountType;
pub use matched_source_type::MatchedSourceType;
pub use match_method::MatchMethod;
pub use recon_status::ReconStatus;
pub use source_format::SourceFormat;
pub use import_status::ImportStatus;
pub use txn_status::TxnStatus;
pub use fx_direction::FxDirection;
pub use match_on::MatchOn;
pub use preset_status::PresetStatus;

// ==========================================================================
// Entity Trait
// ==========================================================================

use std::fmt::Debug;

/// Trait for domain entities
///
/// All generated entities implement this trait, providing
/// a common interface for working with domain objects.
pub trait Entity: Debug + Clone {
    /// The type of the entity's unique identifier
    type Id: Debug + Clone + PartialEq;

    /// Get the entity's unique identifier
    fn entity_id(&self) -> &Self::Id;

    /// Get the entity type name
    fn entity_type() -> &'static str;
}

// ==========================================================================
// Audit Metadata
// ==========================================================================

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[cfg(feature = "openapi")]
use utoipa::ToSchema;

/// Audit metadata stored as JSONB in the database
///
/// This struct consolidates audit fields (timestamps and actors) into a single
/// JSONB column for efficient storage and flexible querying.
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct AuditMetadata {
    /// Timestamp when the record was created
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created_at: Option<DateTime<Utc>>,

    /// Timestamp when the record was last updated
    #[serde(skip_serializing_if = "Option::is_none")]
    pub updated_at: Option<DateTime<Utc>>,

    /// Timestamp when the record was soft-deleted
    #[serde(skip_serializing_if = "Option::is_none")]
    pub deleted_at: Option<DateTime<Utc>>,

    /// User ID who created the record
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created_by: Option<Uuid>,

    /// User ID who last updated the record
    #[serde(skip_serializing_if = "Option::is_none")]
    pub updated_by: Option<Uuid>,

    /// User ID who deleted the record
    #[serde(skip_serializing_if = "Option::is_none")]
    pub deleted_by: Option<Uuid>,
}

impl AuditMetadata {
    /// Create new audit metadata with created_at set to now
    pub fn new() -> Self {
        Self {
            created_at: Some(Utc::now()),
            ..Default::default()
        }
    }

    /// Create with creator ID
    pub fn with_creator(creator_id: Uuid) -> Self {
        Self {
            created_at: Some(Utc::now()),
            created_by: Some(creator_id),
            ..Default::default()
        }
    }

    /// Touch the record (update updated_at)
    pub fn touch(&mut self) {
        self.updated_at = Some(Utc::now());
    }

    /// Touch with updater ID
    pub fn touch_by(&mut self, updater_id: Uuid) {
        self.updated_at = Some(Utc::now());
        self.updated_by = Some(updater_id);
    }

    /// Soft delete the record
    pub fn soft_delete(&mut self) {
        self.deleted_at = Some(Utc::now());
    }

    /// Soft delete with deleter ID
    pub fn soft_delete_by(&mut self, deleter_id: Uuid) {
        self.deleted_at = Some(Utc::now());
        self.deleted_by = Some(deleter_id);
    }

    /// Restore a soft-deleted record
    pub fn restore(&mut self) {
        self.deleted_at = None;
        self.deleted_by = None;
    }

    /// Check if record is deleted
    pub fn is_deleted(&self) -> bool {
        self.deleted_at.is_some()
    }

    /// Check if record is active (not deleted)
    pub fn is_active(&self) -> bool {
        self.deleted_at.is_none()
    }
}