use serde::{Deserialize, Serialize};
use uuid::Uuid;
use chrono::{DateTime, Utc};
#[cfg(feature = "openapi")]
#[cfg(feature = "openapi")]
use utoipa::ToSchema;
use crate::domain::entity::EmvQrConfig;
#[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct CreateEmvQrConfigDto {
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "merchant_name")]
pub merchant_name: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "merchant_city")]
pub merchant_city: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "country_code")]
pub country_code: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub mcc: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub gui: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "merchant_identifier")]
pub merchant_identifier: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub currency: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "initiation_method")]
pub initiation_method: String,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "bank_account_id")]
pub bank_account_id: Option<Uuid>,
}
#[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct UpdateEmvQrConfigDto {
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "merchant_name")]
pub merchant_name: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "merchant_city")]
pub merchant_city: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "country_code")]
pub country_code: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub mcc: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub gui: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "merchant_identifier")]
pub merchant_identifier: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub currency: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(alias = "initiation_method")]
pub initiation_method: String,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "bank_account_id")]
pub bank_account_id: Option<Uuid>,
}
#[derive(Debug, Clone, Default, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct PatchEmvQrConfigDto {
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none", alias = "merchant_name")]
pub merchant_name: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none", alias = "merchant_city")]
pub merchant_city: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none", alias = "country_code")]
pub country_code: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub mcc: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub gui: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none", alias = "merchant_identifier")]
pub merchant_identifier: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
#[serde(skip_serializing_if = "Option::is_none", alias = "initiation_method")]
pub initiation_method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", alias = "bank_account_id")]
pub bank_account_id: Option<Uuid>,
}
impl PatchEmvQrConfigDto {
pub fn has_changes(&self) -> bool {
self.merchant_name.is_some() || self.merchant_city.is_some() || self.country_code.is_some() || self.mcc.is_some() || self.gui.is_some() || self.merchant_identifier.is_some() || self.currency.is_some() || self.initiation_method.is_some() || self.bank_account_id.is_some()
}
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct EmvQrConfigResponseDto {
#[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
pub id: Uuid,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub merchant_name: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub merchant_city: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub country_code: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub mcc: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub gui: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub merchant_identifier: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub currency: String,
#[cfg_attr(feature = "openapi", schema(example = "example"))]
pub initiation_method: String,
pub bank_account_id: Option<Uuid>,
#[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
pub created_at: DateTime<Utc>,
#[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
pub updated_at: DateTime<Utc>,
pub metadata: serde_json::Value,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct EmvQrConfigListResponseDto {
pub items: Vec<EmvQrConfigResponseDto>,
pub total: u64,
pub page: u32,
pub per_page: u32,
pub total_pages: u32,
pub has_next: bool,
pub has_prev: bool,
}
impl EmvQrConfigListResponseDto {
pub fn new(items: Vec<EmvQrConfigResponseDto>, 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 EmvQrConfigSummaryDto {
pub id: Uuid,
pub merchant_name: String,
pub merchant_city: String,
pub country_code: String,
pub created_at: Option<DateTime<Utc>>,
}
impl From<EmvQrConfig> for EmvQrConfigResponseDto {
fn from(entity: EmvQrConfig) -> Self {
Self {
id: entity.id,
merchant_name: entity.merchant_name,
merchant_city: entity.merchant_city,
country_code: entity.country_code,
mcc: entity.mcc,
gui: entity.gui,
merchant_identifier: entity.merchant_identifier,
currency: entity.currency,
initiation_method: entity.initiation_method,
bank_account_id: entity.bank_account_id,
created_at: entity.created_at,
updated_at: entity.updated_at,
metadata: entity.metadata,
}
}
}
impl From<EmvQrConfig> for EmvQrConfigSummaryDto {
fn from(entity: EmvQrConfig) -> Self {
Self {
id: entity.id,
merchant_name: entity.merchant_name,
merchant_city: entity.merchant_city,
country_code: entity.country_code,
created_at: Some(entity.created_at),
}
}
}
impl From<CreateEmvQrConfigDto> for EmvQrConfig {
fn from(dto: CreateEmvQrConfigDto) -> Self {
Self {
id: Uuid::new_v4(),
merchant_name: dto.merchant_name,
merchant_city: dto.merchant_city,
country_code: dto.country_code,
mcc: dto.mcc,
gui: dto.gui,
merchant_identifier: dto.merchant_identifier,
currency: dto.currency,
initiation_method: dto.initiation_method,
bank_account_id: dto.bank_account_id,
created_at: Utc::now(),
updated_at: Utc::now(),
metadata: serde_json::json!({}),
}
}
}
impl From<&EmvQrConfig> for EmvQrConfigResponseDto {
fn from(entity: &EmvQrConfig) -> Self {
Self {
id: entity.id.clone(),
merchant_name: entity.merchant_name.clone(),
merchant_city: entity.merchant_city.clone(),
country_code: entity.country_code.clone(),
mcc: entity.mcc.clone(),
gui: entity.gui.clone(),
merchant_identifier: entity.merchant_identifier.clone(),
currency: entity.currency.clone(),
initiation_method: entity.initiation_method.clone(),
bank_account_id: entity.bank_account_id.clone(),
created_at: entity.created_at.clone(),
updated_at: entity.updated_at.clone(),
metadata: entity.metadata.clone(),
}
}
}
impl backbone_core::FromCreateDto<CreateEmvQrConfigDto> for EmvQrConfig {
fn from_create_dto(dto: CreateEmvQrConfigDto) -> backbone_core::ServiceResult<Self> {
Ok(EmvQrConfig::from(dto))
}
}
impl backbone_core::ApplyUpdateDto<UpdateEmvQrConfigDto> for EmvQrConfig {
fn apply_update(mut self, dto: UpdateEmvQrConfigDto) -> backbone_core::ServiceResult<Self> {
self.updated_at = Utc::now();
self.merchant_name = dto.merchant_name;
self.merchant_city = dto.merchant_city;
self.country_code = dto.country_code;
self.mcc = dto.mcc;
self.gui = dto.gui;
self.merchant_identifier = dto.merchant_identifier;
self.currency = dto.currency;
self.initiation_method = dto.initiation_method;
self.bank_account_id = dto.bank_account_id;
Ok(self)
}
}