backbone-pos 0.8.0

Point of sale — cashier session, ticket + multi-tender; orchestrates billing (revenue) + payment (settlement), posts no GL directly
Documentation
//! Domain Entities
//!
//! Generated by metaphor-schema. Do not edit manually.

pub mod pos_closing_entry;
pub mod pos_invoice;
pub mod pos_invoice_item;
pub mod pos_payment;
pub mod pos_profile;
pub mod pos_opening_entry;
pub mod pos_cash_movement;
pub mod pos_discount;
pub mod pos_manager_pin;
pub mod pos_floor_plan;
pub mod pos_table;
pub mod pos_closing_status;
pub mod pos_invoice_status;
pub mod pos_payment_method;
pub mod pos_cash_rounding_strategy;
pub mod pos_profile_status;
pub mod pos_session_status;
pub mod pos_cash_movement_type;

// Re-exports
pub use pos_closing_entry::PosClosingEntry;
pub use pos_closing_entry::PosClosingEntryBuilder;
pub use pos_closing_entry::PosClosingEntryId;
pub use pos_invoice::PosInvoice;
pub use pos_invoice::PosInvoiceBuilder;
pub use pos_invoice::PosInvoiceId;
pub use pos_invoice_item::PosInvoiceItem;
pub use pos_invoice_item::PosInvoiceItemBuilder;
pub use pos_invoice_item::PosInvoiceItemId;
pub use pos_payment::PosPayment;
pub use pos_payment::PosPaymentBuilder;
pub use pos_payment::PosPaymentId;
pub use pos_profile::PosProfile;
pub use pos_profile::PosProfileBuilder;
pub use pos_profile::PosProfileId;
pub use pos_opening_entry::PosOpeningEntry;
pub use pos_opening_entry::PosOpeningEntryBuilder;
pub use pos_opening_entry::PosOpeningEntryId;
pub use pos_cash_movement::PosCashMovement;
pub use pos_cash_movement::PosCashMovementBuilder;
pub use pos_cash_movement::PosCashMovementId;
pub use pos_discount::PosDiscount;
pub use pos_discount::PosDiscountBuilder;
pub use pos_discount::PosDiscountId;
pub use pos_manager_pin::PosManagerPin;
pub use pos_manager_pin::PosManagerPinBuilder;
pub use pos_manager_pin::PosManagerPinId;
pub use pos_floor_plan::PosFloorPlan;
pub use pos_floor_plan::PosFloorPlanBuilder;
pub use pos_floor_plan::PosFloorPlanId;
pub use pos_table::PosTable;
pub use pos_table::PosTableBuilder;
pub use pos_table::PosTableId;
pub use pos_closing_status::PosClosingStatus;
pub use pos_invoice_status::PosInvoiceStatus;
pub use pos_payment_method::PosPaymentMethod;
pub use pos_cash_rounding_strategy::PosCashRoundingStrategy;
pub use pos_profile_status::PosProfileStatus;
pub use pos_session_status::PosSessionStatus;
pub use pos_cash_movement_type::PosCashMovementType;

// ==========================================================================
// 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()
    }
}