use super::bus::EventBus;
use stateset_core::CommerceEvent;
use std::sync::Arc;
#[derive(Clone)]
pub struct EventEmitter {
bus: Arc<EventBus>,
}
impl std::fmt::Debug for EventEmitter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventEmitter").finish_non_exhaustive()
}
}
impl EventEmitter {
pub const fn new(bus: Arc<EventBus>) -> Self {
Self { bus }
}
pub fn emit(&self, event: CommerceEvent) {
let receivers = self.bus.publish(event.clone());
tracing::debug!(event_type = event.event_type(), receivers, "Event emitted");
}
pub fn emit_all(&self, events: impl IntoIterator<Item = CommerceEvent>) {
for event in events {
self.emit(event);
}
}
pub fn subscriber_count(&self) -> usize {
self.bus.receiver_count()
}
pub fn total_events(&self) -> u64 {
self.bus.events_published()
}
pub fn total_publish_failures(&self) -> u64 {
self.bus.events_publish_failures()
}
}
impl EventEmitter {
pub fn order_created(
&self,
order_id: stateset_core::OrderId,
customer_id: stateset_core::CustomerId,
total_amount: rust_decimal::Decimal,
item_count: usize,
) {
self.emit(CommerceEvent::OrderCreated {
order_id,
customer_id,
total_amount,
item_count,
timestamp: chrono::Utc::now(),
});
}
pub fn order_status_changed(
&self,
order_id: stateset_core::OrderId,
from_status: stateset_core::OrderStatus,
to_status: stateset_core::OrderStatus,
) {
self.emit(CommerceEvent::OrderStatusChanged {
order_id,
from_status,
to_status,
timestamp: chrono::Utc::now(),
});
}
pub fn order_cancelled(&self, order_id: stateset_core::OrderId, reason: Option<String>) {
self.emit(CommerceEvent::OrderCancelled {
order_id,
reason,
timestamp: chrono::Utc::now(),
});
}
pub fn inventory_adjusted(
&self,
item_id: i64,
sku: String,
location_id: i32,
quantity_change: rust_decimal::Decimal,
new_quantity: rust_decimal::Decimal,
reason: String,
) {
self.emit(CommerceEvent::InventoryAdjusted {
item_id,
sku,
location_id,
quantity_change,
new_quantity,
reason,
timestamp: chrono::Utc::now(),
});
}
pub fn low_stock_alert(
&self,
sku: String,
location_id: i32,
current_quantity: rust_decimal::Decimal,
reorder_point: rust_decimal::Decimal,
) {
self.emit(CommerceEvent::LowStockAlert {
sku,
location_id,
current_quantity,
reorder_point,
timestamp: chrono::Utc::now(),
});
}
pub fn customer_created(&self, customer_id: stateset_core::CustomerId, email: String) {
self.emit(CommerceEvent::CustomerCreated {
customer_id,
email,
timestamp: chrono::Utc::now(),
});
}
pub fn product_created(
&self,
product_id: stateset_core::ProductId,
name: String,
slug: String,
) {
self.emit(CommerceEvent::ProductCreated {
product_id,
name,
slug,
timestamp: chrono::Utc::now(),
});
}
pub fn return_requested(
&self,
return_id: stateset_core::ReturnId,
order_id: stateset_core::OrderId,
customer_id: stateset_core::CustomerId,
reason: stateset_core::ReturnReason,
item_count: usize,
) {
self.emit(CommerceEvent::ReturnRequested {
return_id,
order_id,
customer_id,
reason,
item_count,
timestamp: chrono::Utc::now(),
});
}
pub fn return_approved(
&self,
return_id: stateset_core::ReturnId,
order_id: stateset_core::OrderId,
) {
self.emit(CommerceEvent::ReturnApproved {
return_id,
order_id,
timestamp: chrono::Utc::now(),
});
}
pub fn refund_issued(
&self,
return_id: stateset_core::ReturnId,
order_id: stateset_core::OrderId,
amount: rust_decimal::Decimal,
method: String,
) {
self.emit(CommerceEvent::RefundIssued {
return_id,
order_id,
amount,
method,
timestamp: chrono::Utc::now(),
});
}
}