use serde::{Deserialize, Serialize};
use uuid::Uuid;
use chrono::{DateTime, Utc};
#[cfg(feature = "openapi")]
#[cfg(feature = "openapi")]
use utoipa::ToSchema;
#[cfg(feature = "validation")]
use validator::Validate;
use crate::domain::entity::Mail;
use crate::domain::entity::AuditMetadata;
use crate::domain::entity::EventIntervalKind;
use crate::domain::entity::EventIntervalUnit;
use crate::domain::entity::EventMailErrorKind;
use crate::domain::entity::EventNotificationChannel;
#[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "validation", derive(Validate))]
#[serde(rename_all = "camelCase")]
pub struct CreateMailDto {
#[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
#[serde(alias = "event_id")]
pub event_id: Uuid,
#[cfg_attr(feature = "openapi", schema(example = 42))]
#[serde(alias = "interval_nbr")]
pub interval_nbr: i32,
#[serde(alias = "interval_unit")]
pub interval_unit: EventIntervalUnit,
#[serde(alias = "interval_kind")]
pub interval_kind: EventIntervalKind,
#[serde(alias = "notification_channel")]
pub notification_channel: EventNotificationChannel,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "scheduled_date")]
pub scheduled_date: Option<DateTime<Utc>>,
#[cfg_attr(feature = "openapi", schema(example = true))]
#[serde(alias = "mail_done")]
pub mail_done: bool,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "last_registration_id")]
pub last_registration_id: Option<Uuid>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "template_ref")]
pub template_ref: Option<Uuid>,
#[cfg_attr(feature = "validation", validate(length(max = 40)))]
#[serde(default, skip_serializing_if = "Option::is_none", alias = "template_kind")]
pub template_kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "error_datetime")]
pub error_datetime: Option<DateTime<Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "error_kind")]
pub error_kind: Option<EventMailErrorKind>,
}
#[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "validation", derive(Validate))]
#[serde(rename_all = "camelCase")]
pub struct UpdateMailDto {
#[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
#[serde(alias = "event_id")]
pub event_id: Uuid,
#[cfg_attr(feature = "openapi", schema(example = 42))]
#[serde(alias = "interval_nbr")]
pub interval_nbr: i32,
#[serde(alias = "interval_unit")]
pub interval_unit: EventIntervalUnit,
#[serde(alias = "interval_kind")]
pub interval_kind: EventIntervalKind,
#[serde(alias = "notification_channel")]
pub notification_channel: EventNotificationChannel,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "scheduled_date")]
pub scheduled_date: Option<DateTime<Utc>>,
#[cfg_attr(feature = "openapi", schema(example = true))]
#[serde(alias = "mail_done")]
pub mail_done: bool,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "last_registration_id")]
pub last_registration_id: Option<Uuid>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "template_ref")]
pub template_ref: Option<Uuid>,
#[cfg_attr(feature = "validation", validate(length(max = 40)))]
#[serde(default, skip_serializing_if = "Option::is_none", alias = "template_kind")]
pub template_kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "error_datetime")]
pub error_datetime: Option<DateTime<Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "error_kind")]
pub error_kind: Option<EventMailErrorKind>,
}
#[derive(Debug, Clone, Default, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "validation", derive(Validate))]
#[serde(rename_all = "camelCase")]
pub struct PatchMailDto {
#[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
#[serde(skip_serializing_if = "Option::is_none", alias = "event_id")]
pub event_id: Option<Uuid>,
#[cfg_attr(feature = "openapi", schema(example = 42))]
#[serde(skip_serializing_if = "Option::is_none", alias = "interval_nbr")]
pub interval_nbr: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none", alias = "interval_unit")]
pub interval_unit: Option<EventIntervalUnit>,
#[serde(skip_serializing_if = "Option::is_none", alias = "interval_kind")]
pub interval_kind: Option<EventIntervalKind>,
#[serde(skip_serializing_if = "Option::is_none", alias = "notification_channel")]
pub notification_channel: Option<EventNotificationChannel>,
#[serde(skip_serializing_if = "Option::is_none", alias = "scheduled_date")]
pub scheduled_date: Option<DateTime<Utc>>,
#[cfg_attr(feature = "openapi", schema(example = true))]
#[serde(skip_serializing_if = "Option::is_none", alias = "mail_done")]
pub mail_done: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none", alias = "last_registration_id")]
pub last_registration_id: Option<Uuid>,
#[serde(skip_serializing_if = "Option::is_none", alias = "template_ref")]
pub template_ref: Option<Uuid>,
#[cfg_attr(feature = "validation", validate(length(max = 40)))]
#[serde(skip_serializing_if = "Option::is_none", alias = "template_kind")]
pub template_kind: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", alias = "error_datetime")]
pub error_datetime: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none", alias = "error_kind")]
pub error_kind: Option<EventMailErrorKind>,
}
impl PatchMailDto {
pub fn has_changes(&self) -> bool {
self.event_id.is_some() || self.interval_nbr.is_some() || self.interval_unit.is_some() || self.interval_kind.is_some() || self.notification_channel.is_some() || self.scheduled_date.is_some() || self.mail_done.is_some() || self.last_registration_id.is_some() || self.template_ref.is_some() || self.template_kind.is_some() || self.error_datetime.is_some() || self.error_kind.is_some()
}
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct MailResponseDto {
#[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
pub id: Uuid,
#[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
pub event_id: Uuid,
#[cfg_attr(feature = "openapi", schema(example = 42))]
pub interval_nbr: i32,
pub interval_unit: EventIntervalUnit,
pub interval_kind: EventIntervalKind,
pub notification_channel: EventNotificationChannel,
pub scheduled_date: Option<DateTime<Utc>>,
#[cfg_attr(feature = "openapi", schema(example = true))]
pub mail_done: bool,
pub last_registration_id: Option<Uuid>,
pub template_ref: Option<Uuid>,
pub template_kind: Option<String>,
pub error_datetime: Option<DateTime<Utc>>,
pub error_kind: Option<EventMailErrorKind>,
pub metadata: AuditMetadata,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct MailListResponseDto {
pub items: Vec<MailResponseDto>,
pub total: u64,
pub page: u32,
pub per_page: u32,
pub total_pages: u32,
pub has_next: bool,
pub has_prev: bool,
}
impl MailListResponseDto {
pub fn new(items: Vec<MailResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
let total_pages = if per_page > 0 {
((total as f64) / (per_page as f64)).ceil() as u32
} else {
0
};
Self {
items,
total,
page,
per_page,
total_pages,
has_next: page < total_pages,
has_prev: page > 1,
}
}
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct MailSummaryDto {
pub id: Uuid,
pub event_id: Uuid,
pub interval_nbr: i32,
pub interval_unit: EventIntervalUnit,
pub created_at: Option<DateTime<Utc>>,
}
impl From<Mail> for MailResponseDto {
fn from(entity: Mail) -> Self {
Self {
id: entity.id,
event_id: entity.event_id,
interval_nbr: entity.interval_nbr,
interval_unit: entity.interval_unit,
interval_kind: entity.interval_kind,
notification_channel: entity.notification_channel,
scheduled_date: entity.scheduled_date,
mail_done: entity.mail_done,
last_registration_id: entity.last_registration_id,
template_ref: entity.template_ref,
template_kind: entity.template_kind,
error_datetime: entity.error_datetime,
error_kind: entity.error_kind,
metadata: entity.metadata,
}
}
}
impl From<Mail> for MailSummaryDto {
fn from(entity: Mail) -> Self {
let created_at = backbone_core::PersistentEntity::created_at(&entity);
Self {
id: entity.id,
event_id: entity.event_id,
interval_nbr: entity.interval_nbr,
interval_unit: entity.interval_unit,
created_at,
}
}
}
impl From<CreateMailDto> for Mail {
fn from(dto: CreateMailDto) -> Self {
Self {
id: Uuid::new_v4(),
event_id: dto.event_id,
interval_nbr: dto.interval_nbr,
interval_unit: dto.interval_unit,
interval_kind: dto.interval_kind,
notification_channel: dto.notification_channel,
scheduled_date: dto.scheduled_date,
mail_done: dto.mail_done,
last_registration_id: dto.last_registration_id,
template_ref: dto.template_ref,
template_kind: dto.template_kind,
error_datetime: dto.error_datetime,
error_kind: dto.error_kind,
metadata: AuditMetadata::default(),
}
}
}
impl From<&Mail> for MailResponseDto {
fn from(entity: &Mail) -> Self {
Self {
id: entity.id.clone(),
event_id: entity.event_id.clone(),
interval_nbr: entity.interval_nbr.clone(),
interval_unit: entity.interval_unit.clone(),
interval_kind: entity.interval_kind.clone(),
notification_channel: entity.notification_channel.clone(),
scheduled_date: entity.scheduled_date.clone(),
mail_done: entity.mail_done.clone(),
last_registration_id: entity.last_registration_id.clone(),
template_ref: entity.template_ref.clone(),
template_kind: entity.template_kind.clone(),
error_datetime: entity.error_datetime.clone(),
error_kind: entity.error_kind.clone(),
metadata: entity.metadata.clone(),
}
}
}
impl backbone_core::FromCreateDto<CreateMailDto> for Mail {
fn from_create_dto(dto: CreateMailDto) -> backbone_core::ServiceResult<Self> {
Ok(Mail::from(dto))
}
}
impl backbone_core::ApplyUpdateDto<UpdateMailDto> for Mail {
fn apply_update(mut self, dto: UpdateMailDto) -> backbone_core::ServiceResult<Self> {
self.event_id = dto.event_id;
self.interval_nbr = dto.interval_nbr;
self.interval_unit = dto.interval_unit;
self.interval_kind = dto.interval_kind;
self.notification_channel = dto.notification_channel;
self.scheduled_date = dto.scheduled_date;
self.mail_done = dto.mail_done;
self.last_registration_id = dto.last_registration_id;
self.template_ref = dto.template_ref;
self.template_kind = dto.template_kind;
self.error_datetime = dto.error_datetime;
self.error_kind = dto.error_kind;
Ok(self)
}
}