Skip to main content

backbone_integrations/presentation/dto/
integration_account_dto.rs

1//! IntegrationAccount DTOs (Data Transfer Objects)
2//!
3//! Generated by metaphor-schema. Do not edit manually.
4//!
5//! DTOs provide a clean separation between domain entities and API
6//! representations, with validation and OpenAPI documentation support.
7
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10use chrono::{DateTime, Utc};
11
12#[cfg(feature = "openapi")]
13#[cfg(feature = "openapi")]
14use utoipa::ToSchema;
15
16#[cfg(feature = "validation")]
17use validator::Validate;
18
19use crate::domain::entity::IntegrationAccount;
20use crate::domain::entity::AuditMetadata;
21use crate::domain::entity::IntegrationAccountStatus;
22use crate::domain::entity::OAuthProvider;
23
24// =============================================================================
25// Create DTO
26// =============================================================================
27
28/// Request DTO for creating a new IntegrationAccount
29///
30/// Used in POST requests to create new entities.
31/// Excludes auto-generated fields (id, created_at, updated_at, deleted_at).
32#[derive(Debug, Clone, Deserialize)]
33#[cfg_attr(feature = "openapi", derive(ToSchema))]
34#[cfg_attr(feature = "validation", derive(Validate))]
35#[serde(rename_all = "camelCase")]
36pub struct CreateIntegrationAccountDto {
37    pub provider: OAuthProvider,
38    #[cfg_attr(feature = "openapi", schema(example = "example"))]
39    #[serde(alias = "account_ref")]
40    pub account_ref: String,
41    pub status: IntegrationAccountStatus,
42    #[cfg_attr(feature = "openapi", schema(example = "example"))]
43    pub scopes: String,
44    #[serde(default, skip_serializing_if = "Option::is_none", alias = "pkce_verifier")]
45    pub pkce_verifier: Option<String>,
46    #[serde(default, skip_serializing_if = "Option::is_none", alias = "expires_at")]
47    pub expires_at: Option<DateTime<Utc>>,
48    #[serde(default, skip_serializing_if = "Option::is_none", alias = "last_refreshed_at")]
49    pub last_refreshed_at: Option<DateTime<Utc>>,
50}
51
52// =============================================================================
53// Update DTO
54// =============================================================================
55
56/// Request DTO for full update of a IntegrationAccount
57///
58/// Used in PUT requests for full entity replacement.
59/// All fields are required (except auto-generated ones).
60#[derive(Debug, Clone, Deserialize)]
61#[cfg_attr(feature = "openapi", derive(ToSchema))]
62#[cfg_attr(feature = "validation", derive(Validate))]
63#[serde(rename_all = "camelCase")]
64pub struct UpdateIntegrationAccountDto {
65    pub provider: OAuthProvider,
66    #[cfg_attr(feature = "openapi", schema(example = "example"))]
67    #[serde(alias = "account_ref")]
68    pub account_ref: String,
69    pub status: IntegrationAccountStatus,
70    #[cfg_attr(feature = "openapi", schema(example = "example"))]
71    pub scopes: String,
72    #[serde(default, skip_serializing_if = "Option::is_none", alias = "pkce_verifier")]
73    pub pkce_verifier: Option<String>,
74    #[serde(default, skip_serializing_if = "Option::is_none", alias = "expires_at")]
75    pub expires_at: Option<DateTime<Utc>>,
76    #[serde(default, skip_serializing_if = "Option::is_none", alias = "last_refreshed_at")]
77    pub last_refreshed_at: Option<DateTime<Utc>>,
78}
79
80// =============================================================================
81// Patch DTO
82// =============================================================================
83
84/// Request DTO for partial update of a IntegrationAccount
85///
86/// Used in PATCH requests for partial updates.
87/// All fields are optional - only provided fields will be updated.
88#[derive(Debug, Clone, Default, Deserialize)]
89#[cfg_attr(feature = "openapi", derive(ToSchema))]
90#[cfg_attr(feature = "validation", derive(Validate))]
91#[serde(rename_all = "camelCase")]
92pub struct PatchIntegrationAccountDto {
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub provider: Option<OAuthProvider>,
95    #[cfg_attr(feature = "openapi", schema(example = "example"))]
96    #[serde(skip_serializing_if = "Option::is_none", alias = "account_ref")]
97    pub account_ref: Option<String>,
98    #[serde(skip_serializing_if = "Option::is_none")]
99    pub status: Option<IntegrationAccountStatus>,
100    #[cfg_attr(feature = "openapi", schema(example = "example"))]
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub scopes: Option<String>,
103    #[serde(skip_serializing_if = "Option::is_none", alias = "pkce_verifier")]
104    pub pkce_verifier: Option<String>,
105    #[serde(skip_serializing_if = "Option::is_none", alias = "expires_at")]
106    pub expires_at: Option<DateTime<Utc>>,
107    #[serde(skip_serializing_if = "Option::is_none", alias = "last_refreshed_at")]
108    pub last_refreshed_at: Option<DateTime<Utc>>,
109}
110
111impl PatchIntegrationAccountDto {
112    /// Check if any field is set
113    pub fn has_changes(&self) -> bool {
114        self.provider.is_some() || self.account_ref.is_some() || self.status.is_some() || self.scopes.is_some() || self.pkce_verifier.is_some() || self.expires_at.is_some() || self.last_refreshed_at.is_some()
115    }
116}
117
118// =============================================================================
119// Response DTO
120// =============================================================================
121
122/// Response DTO for IntegrationAccount entity
123///
124/// Used in API responses for single entity.
125/// Includes all fields including metadata.
126#[derive(Debug, Clone, Serialize)]
127#[cfg_attr(feature = "openapi", derive(ToSchema))]
128#[serde(rename_all = "camelCase")]
129pub struct IntegrationAccountResponseDto {
130    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
131    pub id: Uuid,
132    pub provider: OAuthProvider,
133    #[cfg_attr(feature = "openapi", schema(example = "example"))]
134    pub account_ref: String,
135    pub status: IntegrationAccountStatus,
136    #[cfg_attr(feature = "openapi", schema(example = "example"))]
137    pub scopes: String,
138    pub pkce_verifier: Option<String>,
139    pub expires_at: Option<DateTime<Utc>>,
140    pub last_refreshed_at: Option<DateTime<Utc>>,
141    pub metadata: AuditMetadata,
142}
143
144// =============================================================================
145// List Response DTO
146// =============================================================================
147
148/// Paginated list response for IntegrationAccount entities
149///
150/// Used in API responses for list endpoints.
151/// Includes pagination metadata.
152#[derive(Debug, Clone, Serialize)]
153#[cfg_attr(feature = "openapi", derive(ToSchema))]
154#[serde(rename_all = "camelCase")]
155pub struct IntegrationAccountListResponseDto {
156    /// List of items
157    pub items: Vec<IntegrationAccountResponseDto>,
158    /// Total number of items (across all pages)
159    pub total: u64,
160    /// Current page number (1-indexed)
161    pub page: u32,
162    /// Number of items per page
163    pub per_page: u32,
164    /// Total number of pages
165    pub total_pages: u32,
166    /// Whether there is a next page
167    pub has_next: bool,
168    /// Whether there is a previous page
169    pub has_prev: bool,
170}
171
172impl IntegrationAccountListResponseDto {
173    /// Create a new list response from items and pagination info
174    pub fn new(items: Vec<IntegrationAccountResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
175        let total_pages = if per_page > 0 {
176            ((total as f64) / (per_page as f64)).ceil() as u32
177        } else {
178            0
179        };
180        Self {
181            items,
182            total,
183            page,
184            per_page,
185            total_pages,
186            has_next: page < total_pages,
187            has_prev: page > 1,
188        }
189    }
190}
191
192/// Summary DTO for list views (compact version)
193#[derive(Debug, Clone, Serialize)]
194#[cfg_attr(feature = "openapi", derive(ToSchema))]
195#[serde(rename_all = "camelCase")]
196pub struct IntegrationAccountSummaryDto {
197    pub id: Uuid,
198    pub provider: OAuthProvider,
199    pub account_ref: String,
200    pub status: IntegrationAccountStatus,
201    pub created_at: Option<DateTime<Utc>>,
202}
203
204// =============================================================================
205// Conversions
206// =============================================================================
207
208impl From<IntegrationAccount> for IntegrationAccountResponseDto {
209    fn from(entity: IntegrationAccount) -> Self {
210        Self {
211            id: entity.id,
212            provider: entity.provider,
213            account_ref: entity.account_ref,
214            status: entity.status,
215            scopes: entity.scopes,
216            pkce_verifier: entity.pkce_verifier,
217            expires_at: entity.expires_at,
218            last_refreshed_at: entity.last_refreshed_at,
219            metadata: entity.metadata,
220        }
221    }
222}
223
224impl From<IntegrationAccount> for IntegrationAccountSummaryDto {
225    fn from(entity: IntegrationAccount) -> Self {
226        let created_at = backbone_core::PersistentEntity::created_at(&entity);
227        Self {
228            id: entity.id,
229            provider: entity.provider,
230            account_ref: entity.account_ref,
231            status: entity.status,
232            created_at,
233        }
234    }
235}
236
237impl From<CreateIntegrationAccountDto> for IntegrationAccount {
238    fn from(dto: CreateIntegrationAccountDto) -> Self {
239        Self {
240            id: Uuid::new_v4(),
241            provider: dto.provider,
242            account_ref: dto.account_ref,
243            status: dto.status,
244            scopes: dto.scopes,
245            pkce_verifier: dto.pkce_verifier,
246            expires_at: dto.expires_at,
247            last_refreshed_at: dto.last_refreshed_at,
248            metadata: AuditMetadata::default(),
249        }
250    }
251}
252
253impl From<&IntegrationAccount> for IntegrationAccountResponseDto {
254    fn from(entity: &IntegrationAccount) -> Self {
255        Self {
256            id: entity.id.clone(),
257            provider: entity.provider.clone(),
258            account_ref: entity.account_ref.clone(),
259            status: entity.status.clone(),
260            scopes: entity.scopes.clone(),
261            pkce_verifier: entity.pkce_verifier.clone(),
262            expires_at: entity.expires_at.clone(),
263            last_refreshed_at: entity.last_refreshed_at.clone(),
264            metadata: entity.metadata.clone(),
265        }
266    }
267}
268
269impl backbone_core::FromCreateDto<CreateIntegrationAccountDto> for IntegrationAccount {
270    fn from_create_dto(dto: CreateIntegrationAccountDto) -> backbone_core::ServiceResult<Self> {
271        Ok(IntegrationAccount::from(dto))
272    }
273}
274
275impl backbone_core::ApplyUpdateDto<UpdateIntegrationAccountDto> for IntegrationAccount {
276    fn apply_update(mut self, dto: UpdateIntegrationAccountDto) -> backbone_core::ServiceResult<Self> {
277        self.provider = dto.provider;
278        self.account_ref = dto.account_ref;
279        self.status = dto.status;
280        self.scopes = dto.scopes;
281        self.pkce_verifier = dto.pkce_verifier;
282        self.expires_at = dto.expires_at;
283        self.last_refreshed_at = dto.last_refreshed_at;
284        Ok(self)
285    }
286}
287
288// =============================================================================
289// Custom DTOs
290// =============================================================================
291
292// <<< CUSTOM DTOs
293// Add custom DTOs specific to IntegrationAccount here.
294// This section will be preserved during regeneration.
295// >>> END CUSTOM DTOs