use crate::aux::Owned;
use super::prelude::*;
#[derive(Owned!)]
pub struct Deliver {
who: Dir,
price: Money,
split: Option<Split>,
}
#[apply(cmd_args!)]
pub struct DeliverArgs {
#[pos]
what: Object,
#[named]
who: Dir,
#[named(opt)]
price: Option<Money>,
#[named(opt)]
split: Option<Split>,
}
impl Command for Deliver {
type Args = DeliverArgs;
}
impl Resolve<Deliver, error::Construction> for DeliverArgs {
fn resolve(self, _ctx: &State) -> Result<Deliver, error::Construction> {
let Self {
what,
who,
price,
split,
} = self;
#[expect(clippy::unnecessary_lazy_evaluations)] let price = price
.or_else(|| {
what.parent()
.and_then(|concept| concept.default_price().cloned())
})
.ok_or_else(|| error::PriceUnspecified { object: what })?;
Ok(Deliver { who, price, split })
}
}
impl Run for Deliver {
fn run(self: Box<Self>, ctx: &mut State) -> Output {
let Self { who, price, split } = *self;
let receiver_amount = match split {
Some(split) => split.apply(price).1,
None => price,
};
let implied_payment = super::Pay {
amount: receiver_amount,
who,
};
Box::new(implied_payment).run(ctx)
}
}
#[cfg(test)]
mod tests {
use insta::{assert_snapshot, with_settings};
use crate::{eval, one};
#[test]
fn basic() {
let setup = "
create entity A
create entity B
create object Something
deliver from=A to=B price=1€ Something
";
let mut rt = eval(setup).unwrap();
with_settings!({ description => setup }, {
assert_snapshot!(
one(&mut rt, "balance from=A to=B"),
@"entity A is owed 1.00 € by entity B",
);
})
}
}