backbone-inventory 0.15.0

Inventory: stock ledger of record (SLE) + moving-average valuation; emits COGS/asset AccountingPost (Delivery/Receipt -> GL)
Documentation
//! Domain Entities
//!
//! Generated by metaphor-schema. Do not edit manually.

pub mod picking_batch;
pub mod delivery_note;
pub mod delivery_note_item;
pub mod inventory_company_setting;
pub mod landed_cost;
pub mod landed_cost_line;
pub mod landed_cost_adjustment_line;
pub mod location;
pub mod stock_move;
pub mod stock_move_line;
pub mod operation_type;
pub mod transfer;
pub mod route;
pub mod route_rule;
pub mod reordering_rule;
pub mod purchase_receipt;
pub mod purchase_receipt_item;
pub mod quant;
pub mod scrap;
pub mod scrap_reason_tag;
pub mod stock_entry;
pub mod stock_entry_item;
pub mod stock_ledger_entry;
pub mod bin;
pub mod stock_reconciliation;
pub mod stock_reconciliation_item;
pub mod package_type;
pub mod storage_category;
pub mod storage_category_capacity;
pub mod putaway_rule;
pub mod lot;
pub mod package;
pub mod warehouse;
pub mod stock_item;
pub mod picking_batch_state;
pub mod inventory_cost_method;
pub mod valuation_policy;
pub mod landed_cost_state;
pub mod landed_cost_split_method;
pub mod location_usage;
pub mod move_state;
pub mod procure_method;
pub mod picking_code;
pub mod reservation_method;
pub mod move_type;
pub mod create_backorder;
pub mod transfer_state;
pub mod priority;
pub mod rule_action;
pub mod rule_auto;
pub mod orderpoint_trigger;
pub mod doc_status;
pub mod gl_posting_state;
pub mod scrap_state;
pub mod stock_entry_type;
pub mod voucher_type;
pub mod stock_ledger_status;
pub mod package_use;
pub mod storage_allow_new_product;
pub mod putaway_sublocation;
pub mod warehouse_type;
pub mod valuation_method;
pub mod service_tracking_type;

// Re-exports
pub use picking_batch::PickingBatch;
pub use picking_batch::PickingBatchBuilder;
pub use picking_batch::PickingBatchId;
pub use delivery_note::DeliveryNote;
pub use delivery_note::DeliveryNoteBuilder;
pub use delivery_note::DeliveryNoteId;
pub use delivery_note_item::DeliveryNoteItem;
pub use delivery_note_item::DeliveryNoteItemBuilder;
pub use delivery_note_item::DeliveryNoteItemId;
pub use inventory_company_setting::InventoryCompanySetting;
pub use inventory_company_setting::InventoryCompanySettingBuilder;
pub use inventory_company_setting::InventoryCompanySettingId;
pub use landed_cost::LandedCost;
pub use landed_cost::LandedCostBuilder;
pub use landed_cost::LandedCostId;
pub use landed_cost_line::LandedCostLine;
pub use landed_cost_line::LandedCostLineBuilder;
pub use landed_cost_line::LandedCostLineId;
pub use landed_cost_adjustment_line::LandedCostAdjustmentLine;
pub use landed_cost_adjustment_line::LandedCostAdjustmentLineBuilder;
pub use landed_cost_adjustment_line::LandedCostAdjustmentLineId;
pub use location::Location;
pub use location::LocationBuilder;
pub use location::LocationId;
pub use stock_move::StockMove;
pub use stock_move::StockMoveBuilder;
pub use stock_move::StockMoveId;
pub use stock_move_line::StockMoveLine;
pub use stock_move_line::StockMoveLineBuilder;
pub use stock_move_line::StockMoveLineId;
pub use operation_type::OperationType;
pub use operation_type::OperationTypeBuilder;
pub use operation_type::OperationTypeId;
pub use transfer::Transfer;
pub use transfer::TransferBuilder;
pub use transfer::TransferId;
pub use route::Route;
pub use route::RouteBuilder;
pub use route::RouteId;
pub use route_rule::RouteRule;
pub use route_rule::RouteRuleBuilder;
pub use route_rule::RouteRuleId;
pub use reordering_rule::ReorderingRule;
pub use reordering_rule::ReorderingRuleBuilder;
pub use reordering_rule::ReorderingRuleId;
pub use purchase_receipt::PurchaseReceipt;
pub use purchase_receipt::PurchaseReceiptBuilder;
pub use purchase_receipt::PurchaseReceiptId;
pub use purchase_receipt_item::PurchaseReceiptItem;
pub use purchase_receipt_item::PurchaseReceiptItemBuilder;
pub use purchase_receipt_item::PurchaseReceiptItemId;
pub use quant::Quant;
pub use quant::QuantBuilder;
pub use quant::QuantId;
pub use scrap::Scrap;
pub use scrap::ScrapBuilder;
pub use scrap::ScrapId;
pub use scrap_reason_tag::ScrapReasonTag;
pub use scrap_reason_tag::ScrapReasonTagBuilder;
pub use scrap_reason_tag::ScrapReasonTagId;
pub use stock_entry::StockEntry;
pub use stock_entry::StockEntryBuilder;
pub use stock_entry::StockEntryId;
pub use stock_entry_item::StockEntryItem;
pub use stock_entry_item::StockEntryItemBuilder;
pub use stock_entry_item::StockEntryItemId;
pub use stock_ledger_entry::StockLedgerEntry;
pub use stock_ledger_entry::StockLedgerEntryBuilder;
pub use stock_ledger_entry::StockLedgerEntryId;
pub use bin::Bin;
pub use bin::BinBuilder;
pub use bin::BinId;
pub use stock_reconciliation::StockReconciliation;
pub use stock_reconciliation::StockReconciliationBuilder;
pub use stock_reconciliation::StockReconciliationId;
pub use stock_reconciliation_item::StockReconciliationItem;
pub use stock_reconciliation_item::StockReconciliationItemBuilder;
pub use stock_reconciliation_item::StockReconciliationItemId;
pub use package_type::PackageType;
pub use package_type::PackageTypeBuilder;
pub use package_type::PackageTypeId;
pub use storage_category::StorageCategory;
pub use storage_category::StorageCategoryBuilder;
pub use storage_category::StorageCategoryId;
pub use storage_category_capacity::StorageCategoryCapacity;
pub use storage_category_capacity::StorageCategoryCapacityBuilder;
pub use storage_category_capacity::StorageCategoryCapacityId;
pub use putaway_rule::PutawayRule;
pub use putaway_rule::PutawayRuleBuilder;
pub use putaway_rule::PutawayRuleId;
pub use lot::Lot;
pub use lot::LotBuilder;
pub use lot::LotId;
pub use package::Package;
pub use package::PackageBuilder;
pub use package::PackageId;
pub use warehouse::Warehouse;
pub use warehouse::WarehouseBuilder;
pub use warehouse::WarehouseId;
pub use stock_item::StockItem;
pub use stock_item::StockItemBuilder;
pub use stock_item::StockItemId;
pub use picking_batch_state::PickingBatchState;
pub use inventory_cost_method::InventoryCostMethod;
pub use valuation_policy::ValuationPolicy;
pub use landed_cost_state::LandedCostState;
pub use landed_cost_split_method::LandedCostSplitMethod;
pub use location_usage::LocationUsage;
pub use move_state::MoveState;
pub use procure_method::ProcureMethod;
pub use picking_code::PickingCode;
pub use reservation_method::ReservationMethod;
pub use move_type::MoveType;
pub use create_backorder::CreateBackorder;
pub use transfer_state::TransferState;
pub use priority::Priority;
pub use rule_action::RuleAction;
pub use rule_auto::RuleAuto;
pub use orderpoint_trigger::OrderpointTrigger;
pub use doc_status::DocStatus;
pub use gl_posting_state::GlPostingState;
pub use scrap_state::ScrapState;
pub use stock_entry_type::StockEntryType;
pub use voucher_type::VoucherType;
pub use stock_ledger_status::StockLedgerStatus;
pub use package_use::PackageUse;
pub use storage_allow_new_product::StorageAllowNewProduct;
pub use putaway_sublocation::PutawaySublocation;
pub use warehouse_type::WarehouseType;
pub use valuation_method::ValuationMethod;
pub use service_tracking_type::ServiceTrackingType;

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