use distributed::{sourced, Entity, Snapshottable};
use serde::{Deserialize, Serialize};
#[derive(Default, Debug, Clone)]
pub struct Ledger {
pub entity: Entity,
pub balance: i64,
pub applied: u64,
pub last_note: String,
}
#[sourced(entity, aggregate_type = "replay_property.ledger")]
impl Ledger {
#[event("opened", when = self.entity.id().is_empty())]
pub fn open(&mut self, id: String) {
self.entity.set_id(&id);
}
#[event("deposited", when = amount > 0)]
pub fn deposit(&mut self, amount: i64) {
self.balance += amount;
self.applied += 1;
}
#[event("withdrawn", when = amount > 0 && self.balance >= amount)]
pub fn withdraw(&mut self, amount: i64) {
self.balance -= amount;
self.applied += 1;
}
#[event("annotated", when = !note.is_empty())]
pub fn annotate(&mut self, note: String) {
self.last_note = note;
self.applied += 1;
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LedgerSnapshot {
pub id: String,
pub balance: i64,
pub applied: u64,
pub last_note: String,
}
impl Snapshottable for Ledger {
type Snapshot = LedgerSnapshot;
fn create_snapshot(&self) -> LedgerSnapshot {
LedgerSnapshot {
id: self.entity.id().to_string(),
balance: self.balance,
applied: self.applied,
last_note: self.last_note.clone(),
}
}
fn restore_from_snapshot(&mut self, snapshot: LedgerSnapshot) {
self.entity.set_id(&snapshot.id);
self.balance = snapshot.balance;
self.applied = snapshot.applied;
self.last_note = snapshot.last_note;
}
}
#[derive(Clone, Debug)]
pub enum Command {
Deposit(i64),
Withdraw(i64),
Annotate(String),
}
impl Command {
pub fn apply(&self, ledger: &mut Ledger) {
match self {
Command::Deposit(amount) => {
let _ = ledger.deposit(*amount);
}
Command::Withdraw(amount) => {
let _ = ledger.withdraw(*amount);
}
Command::Annotate(note) => {
let _ = ledger.annotate(note.clone());
}
}
}
}