backbone-events 0.3.30

Events core + the sale/booth/crm/sms/desk overlay — registrations under one authoritative seat counter, the sale seam (order-minted registrations, forward-only paid heal, SO-cancel mirror cascade), booth bookings with the DB exclusivity wall, closed-vocabulary lead rules through a host sink port, the dual-channel (mail/sms) self-arming scheduler, and the exact-match desk verb (Odoo event port, core + overlay)
//! Domain Entities
//!
//! Generated by metaphor-schema. Do not edit manually.

pub mod booth_category;
pub mod booth;
pub mod type_booth;
pub mod booth_booking;
pub mod event;
pub mod event_type;
pub mod lead_provenance;
pub mod lead_provenance_registration;
pub mod lead_request;
pub mod lead_rule;
pub mod lead_rule_predicate;
pub mod mail;
pub mod mail_registration;
pub mod mail_slot;
pub mod question;
pub mod question_answer;
pub mod registration_question;
pub mod registration;
pub mod registration_answer;
pub mod slot;
pub mod stage;
pub mod tag_category;
pub mod tag;
pub mod ticket;
pub mod type_mail;
pub mod event_booth_state;
pub mod event_booth_booking_status;
pub mod event_kanban_state;
pub mod event_badge_format;
pub mod event_lead_grouping;
pub mod event_lead_basis;
pub mod event_lead_predicate_axis;
pub mod event_interval_unit;
pub mod event_interval_kind;
pub mod event_notification_channel;
pub mod event_mail_error_kind;
pub mod event_question_kind;
pub mod event_registration_state;
pub mod event_sale_order_state;
pub mod event_sale_status;

// Re-exports
pub use booth_category::BoothCategory;
pub use booth_category::BoothCategoryBuilder;
pub use booth_category::BoothCategoryId;
pub use booth::Booth;
pub use booth::BoothBuilder;
pub use booth::BoothId;
pub use type_booth::TypeBooth;
pub use type_booth::TypeBoothBuilder;
pub use type_booth::TypeBoothId;
pub use booth_booking::BoothBooking;
pub use booth_booking::BoothBookingBuilder;
pub use booth_booking::BoothBookingId;
pub use event::Event;
pub use event::EventBuilder;
pub use event::EventId;
pub use event_type::EventType;
pub use event_type::EventTypeBuilder;
pub use event_type::EventTypeId;
pub use lead_provenance::LeadProvenance;
pub use lead_provenance::LeadProvenanceBuilder;
pub use lead_provenance::LeadProvenanceId;
pub use lead_provenance_registration::LeadProvenanceRegistration;
pub use lead_provenance_registration::LeadProvenanceRegistrationBuilder;
pub use lead_provenance_registration::LeadProvenanceRegistrationId;
pub use lead_request::LeadRequest;
pub use lead_request::LeadRequestBuilder;
pub use lead_request::LeadRequestId;
pub use lead_rule::LeadRule;
pub use lead_rule::LeadRuleBuilder;
pub use lead_rule::LeadRuleId;
pub use lead_rule_predicate::LeadRulePredicate;
pub use lead_rule_predicate::LeadRulePredicateBuilder;
pub use lead_rule_predicate::LeadRulePredicateId;
pub use mail::Mail;
pub use mail::MailBuilder;
pub use mail::MailId;
pub use mail_registration::MailRegistration;
pub use mail_registration::MailRegistrationBuilder;
pub use mail_registration::MailRegistrationId;
pub use mail_slot::MailSlot;
pub use mail_slot::MailSlotBuilder;
pub use mail_slot::MailSlotId;
pub use question::Question;
pub use question::QuestionBuilder;
pub use question::QuestionId;
pub use question_answer::QuestionAnswer;
pub use question_answer::QuestionAnswerBuilder;
pub use question_answer::QuestionAnswerId;
pub use registration_question::RegistrationQuestion;
pub use registration_question::RegistrationQuestionBuilder;
pub use registration_question::RegistrationQuestionId;
pub use registration::Registration;
pub use registration::RegistrationBuilder;
pub use registration::RegistrationId;
pub use registration_answer::RegistrationAnswer;
pub use registration_answer::RegistrationAnswerBuilder;
pub use registration_answer::RegistrationAnswerId;
pub use slot::Slot;
pub use slot::SlotBuilder;
pub use slot::SlotId;
pub use stage::Stage;
pub use stage::StageBuilder;
pub use stage::StageId;
pub use tag_category::TagCategory;
pub use tag_category::TagCategoryBuilder;
pub use tag_category::TagCategoryId;
pub use tag::Tag;
pub use tag::TagBuilder;
pub use tag::TagId;
pub use ticket::Ticket;
pub use ticket::TicketBuilder;
pub use ticket::TicketId;
pub use type_mail::TypeMail;
pub use type_mail::TypeMailBuilder;
pub use type_mail::TypeMailId;
pub use event_booth_state::EventBoothState;
pub use event_booth_booking_status::EventBoothBookingStatus;
pub use event_kanban_state::EventKanbanState;
pub use event_badge_format::EventBadgeFormat;
pub use event_lead_grouping::EventLeadGrouping;
pub use event_lead_basis::EventLeadBasis;
pub use event_lead_predicate_axis::EventLeadPredicateAxis;
pub use event_interval_unit::EventIntervalUnit;
pub use event_interval_kind::EventIntervalKind;
pub use event_notification_channel::EventNotificationChannel;
pub use event_mail_error_kind::EventMailErrorKind;
pub use event_question_kind::EventQuestionKind;
pub use event_registration_state::EventRegistrationState;
pub use event_sale_order_state::EventSaleOrderState;
pub use event_sale_status::EventSaleStatus;

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