use crate::prelude::*;
#[derive(Clone, Debug, Display, Serialize, PartialEq, Eq, Hash, Deserialize)]
#[serde(untagged)]
pub enum PaymentTerms {
Net(NetDays),
}
impl FromStr for PaymentTerms {
type Err = crate::prelude::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let net_days = NetDays::from_str(s)?;
Ok(PaymentTerms::Net(net_days))
}
}
impl Default for PaymentTerms {
fn default() -> Self {
Self::net30()
}
}
impl PaymentTerms {
pub fn net30() -> Self {
PaymentTerms::Net(NetDays::net30())
}
}
impl HasSample for PaymentTerms {
fn sample() -> Self {
Self::default()
}
fn sample_other() -> Self {
Self::Net(
NetDays::builder()
.due_in(Day::try_from(15).unwrap())
.build(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use insta::assert_ron_snapshot;
type Sut = PaymentTerms;
#[test]
fn equality() {
assert_eq!(Sut::sample(), Sut::sample());
assert_eq!(Sut::sample_other(), Sut::sample_other());
}
#[test]
fn inequality() {
assert_ne!(Sut::sample(), Sut::sample_other());
}
#[test]
fn test_payment_terms_net_days() {
let net_days: NetDays = "Net 30".parse().unwrap();
assert_eq!(net_days.due_in(), &Day::try_from(30).unwrap());
assert_ron_snapshot!(net_days);
}
#[test]
fn test_payment_terms_default() {
let payment_terms = Sut::default();
assert!(matches!(payment_terms, Sut::Net(_)));
assert_ron_snapshot!(payment_terms);
}
#[test]
fn from_str_invalid_all_reasons() {
let invalid_strings = [
"Net", "Net 0", "Net -30", "Net 32", "Net abc", "Net 30 extra", ];
for invalid in invalid_strings {
let result: Result<NetDays, _> = invalid.parse();
assert!(result.is_err(), "Expected error for '{}'", invalid);
}
}
#[test]
fn test_payment_terms_from_str() {
let payment_terms: PaymentTerms = "Net 30".parse().unwrap();
assert!(matches!(payment_terms, PaymentTerms::Net(_)));
}
}