backbone_integrations/presentation/dto/
integration_connector_dto.rs1use 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::IntegrationConnector;
20use crate::domain::entity::AuditMetadata;
21use crate::domain::entity::ConnectorDirection;
22use crate::domain::entity::ConnectorKind;
23use crate::domain::entity::ConnectorStatus;
24
25#[derive(Debug, Clone, Deserialize)]
34#[cfg_attr(feature = "openapi", derive(ToSchema))]
35#[cfg_attr(feature = "validation", derive(Validate))]
36#[serde(rename_all = "camelCase")]
37pub struct CreateIntegrationConnectorDto {
38 #[cfg_attr(feature = "openapi", schema(example = "example"))]
39 pub provider: String,
40 pub kind: ConnectorKind,
41 pub direction: ConnectorDirection,
42 pub status: ConnectorStatus,
43}
44
45#[derive(Debug, Clone, Deserialize)]
54#[cfg_attr(feature = "openapi", derive(ToSchema))]
55#[cfg_attr(feature = "validation", derive(Validate))]
56#[serde(rename_all = "camelCase")]
57pub struct UpdateIntegrationConnectorDto {
58 #[cfg_attr(feature = "openapi", schema(example = "example"))]
59 pub provider: String,
60 pub kind: ConnectorKind,
61 pub direction: ConnectorDirection,
62 pub status: ConnectorStatus,
63}
64
65#[derive(Debug, Clone, Default, Deserialize)]
74#[cfg_attr(feature = "openapi", derive(ToSchema))]
75#[cfg_attr(feature = "validation", derive(Validate))]
76#[serde(rename_all = "camelCase")]
77pub struct PatchIntegrationConnectorDto {
78 #[cfg_attr(feature = "openapi", schema(example = "example"))]
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub provider: Option<String>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub kind: Option<ConnectorKind>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub direction: Option<ConnectorDirection>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub status: Option<ConnectorStatus>,
87}
88
89impl PatchIntegrationConnectorDto {
90 pub fn has_changes(&self) -> bool {
92 self.provider.is_some() || self.kind.is_some() || self.direction.is_some() || self.status.is_some()
93 }
94}
95
96#[derive(Debug, Clone, Serialize)]
105#[cfg_attr(feature = "openapi", derive(ToSchema))]
106#[serde(rename_all = "camelCase")]
107pub struct IntegrationConnectorResponseDto {
108 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
109 pub id: Uuid,
110 #[cfg_attr(feature = "openapi", schema(example = "example"))]
111 pub provider: String,
112 pub kind: ConnectorKind,
113 pub direction: ConnectorDirection,
114 pub status: ConnectorStatus,
115 pub metadata: AuditMetadata,
116}
117
118#[derive(Debug, Clone, Serialize)]
127#[cfg_attr(feature = "openapi", derive(ToSchema))]
128#[serde(rename_all = "camelCase")]
129pub struct IntegrationConnectorListResponseDto {
130 pub items: Vec<IntegrationConnectorResponseDto>,
132 pub total: u64,
134 pub page: u32,
136 pub per_page: u32,
138 pub total_pages: u32,
140 pub has_next: bool,
142 pub has_prev: bool,
144}
145
146impl IntegrationConnectorListResponseDto {
147 pub fn new(items: Vec<IntegrationConnectorResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
149 let total_pages = if per_page > 0 {
150 ((total as f64) / (per_page as f64)).ceil() as u32
151 } else {
152 0
153 };
154 Self {
155 items,
156 total,
157 page,
158 per_page,
159 total_pages,
160 has_next: page < total_pages,
161 has_prev: page > 1,
162 }
163 }
164}
165
166#[derive(Debug, Clone, Serialize)]
168#[cfg_attr(feature = "openapi", derive(ToSchema))]
169#[serde(rename_all = "camelCase")]
170pub struct IntegrationConnectorSummaryDto {
171 pub id: Uuid,
172 pub provider: String,
173 pub kind: ConnectorKind,
174 pub direction: ConnectorDirection,
175 pub created_at: Option<DateTime<Utc>>,
176}
177
178impl From<IntegrationConnector> for IntegrationConnectorResponseDto {
183 fn from(entity: IntegrationConnector) -> Self {
184 Self {
185 id: entity.id,
186 provider: entity.provider,
187 kind: entity.kind,
188 direction: entity.direction,
189 status: entity.status,
190 metadata: entity.metadata,
191 }
192 }
193}
194
195impl From<IntegrationConnector> for IntegrationConnectorSummaryDto {
196 fn from(entity: IntegrationConnector) -> Self {
197 let created_at = backbone_core::PersistentEntity::created_at(&entity);
198 Self {
199 id: entity.id,
200 provider: entity.provider,
201 kind: entity.kind,
202 direction: entity.direction,
203 created_at,
204 }
205 }
206}
207
208impl From<CreateIntegrationConnectorDto> for IntegrationConnector {
209 fn from(dto: CreateIntegrationConnectorDto) -> Self {
210 Self {
211 id: Uuid::new_v4(),
212 provider: dto.provider,
213 kind: dto.kind,
214 direction: dto.direction,
215 status: dto.status,
216 metadata: AuditMetadata::default(),
217 }
218 }
219}
220
221impl From<&IntegrationConnector> for IntegrationConnectorResponseDto {
222 fn from(entity: &IntegrationConnector) -> Self {
223 Self {
224 id: entity.id.clone(),
225 provider: entity.provider.clone(),
226 kind: entity.kind.clone(),
227 direction: entity.direction.clone(),
228 status: entity.status.clone(),
229 metadata: entity.metadata.clone(),
230 }
231 }
232}
233
234impl backbone_core::FromCreateDto<CreateIntegrationConnectorDto> for IntegrationConnector {
235 fn from_create_dto(dto: CreateIntegrationConnectorDto) -> backbone_core::ServiceResult<Self> {
236 Ok(IntegrationConnector::from(dto))
237 }
238}
239
240impl backbone_core::ApplyUpdateDto<UpdateIntegrationConnectorDto> for IntegrationConnector {
241 fn apply_update(mut self, dto: UpdateIntegrationConnectorDto) -> backbone_core::ServiceResult<Self> {
242 self.provider = dto.provider;
243 self.kind = dto.kind;
244 self.direction = dto.direction;
245 self.status = dto.status;
246 Ok(self)
247 }
248}
249
250