use chrono::{DateTime, Utc};
use uuid::Uuid;{% for import in imports %}
use {{ import }};{% endfor %}
use super::errors::{{ pascal }}Error;
#[derive(Debug, Clone)]
pub struct {{ pascal }}Props {
{% for f in fields %} pub {{ f.name }}: {{ f.rust_type }},
{% endfor %}}
#[derive(Debug, Clone)]
pub struct {{ pascal }} {
pub id: Uuid,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted: bool,
pub deleted_at: Option<DateTime<Utc>>,
{% for f in fields %} pub {{ f.name }}: {{ f.rust_type }},
{% endfor %}}
impl {{ pascal }} {
pub fn new(props: {{ pascal }}Props) -> Result<Self, {{ pascal }}Error> {
{% for f in fields | filter(attribute="required_string", value=true) %} if props.{{ f.name }}.trim().is_empty() {
return Err({{ pascal }}Error::ValidationError("{{ f.name }}_empty".into()));
}
{% endfor %} let now = chrono::Utc::now();
Ok(Self {
id: Uuid::new_v4(),
created_at: now,
updated_at: now,
deleted: false,
deleted_at: None,
{% for f in fields %} {{ f.name }}: props.{{ f.name }},
{% endfor %} })
}
pub fn from_repository(data: {{ pascal }}) -> Self {
data
}
}
{% set required = fields | filter(attribute="required_string", value=true) %}{% set string_vos = fields | filter(attribute="string_vo", value=true) %}{% set enum_vos = fields | filter(attribute="is_enum_vo", value=true) %}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_create_{{ snake }}_when_{% if fields | length == 1 and required | length == 1 and fields.0.name == "name" %}name_is_valid{% else %}fields_are_valid{% endif %}() {
let result = {{ pascal }}::new({{ pascal }}Props {
{% for f in fields %} {{ f.name }}: {{ f.props_literal }},
{% endfor %} });{% if required | length > 0 %}
assert_eq!(result.unwrap().{{ required.0.name }}, "example");{% else %}
assert!(result.is_ok());{% endif %}
}{% if required or string_vos or enum_vos %}
{% endif %}{% for sf in required %}
#[test]
fn should_reject_{{ snake }}_when_{{ sf.name }}_is_empty() {
let result = {{ pascal }}::new({{ pascal }}Props {
{% for f in fields %} {{ f.name }}: {% if f.name == sf.name %}"".into(){% else %}{{ f.props_literal }}{% endif %},
{% endfor %} });
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"{{ snake }}.validation_error.{{ sf.name }}_empty"
);
}
#[test]
fn should_reject_{{ snake }}_when_{{ sf.name }}_is_only_whitespace() {
let result = {{ pascal }}::new({{ pascal }}Props {
{% for f in fields %} {{ f.name }}: {% if f.name == sf.name %}" ".into(){% else %}{{ f.props_literal }}{% endif %},
{% endfor %} });
assert!(result.is_err());
}{% endfor %}{% for f in string_vos %}
#[test]
fn should_reject_{{ snake }}_when_{{ f.vo_snake }}_is_empty() {
let result = {{ f.vo }}::new("".to_string());
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"{% if f.is_shared_vo %}shared.value_object.{{ f.vo_snake }}.invalid{% else %}{{ snake }}.invalid_{{ f.vo_snake }}{% endif %}"
);
}{% endfor %}{% for f in enum_vos %}
#[test]
fn should_reject_{{ snake }}_when_{{ f.vo_snake }}_is_invalid() {
let result = "InvalidVariant".parse::<{{ f.vo }}>();
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"{% if f.is_shared_vo %}shared.value_object.{{ f.vo_snake }}.invalid{% else %}{{ snake }}.invalid_{{ f.vo_snake }}{% endif %}"
);
}{% endfor %}
}