samling/colors/
entities.rs

1use chrono::{DateTime, FixedOffset};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    auth::User,
7    entity_ref::{ExternalId, ExternalIdEntity, Id, Ref, RefTarget, Slug, SlugEntity},
8    helpers::slugify,
9    organizations::Organization,
10    EntityRefPathParam, I18nString, ImageSummary, NestedSize, NestedSizeSummary, Style,
11    StyleSummary,
12};
13use samling_clorinde::{client::GenericClient, queries::color::get_color_id};
14
15/// Color
16#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
17pub struct Color {
18    pub id: Id<Self>,
19    pub style: StyleSummary,
20    pub number: String,
21    pub name: I18nString,
22    pub slug: Slug<Self>,
23    pub images: Vec<ImageSummary>,
24    pub external_id: Option<ExternalId<Self>>,
25    pub created_by: Option<Id<User>>,
26    pub created_at: DateTime<FixedOffset>,
27    pub updated_at: DateTime<FixedOffset>,
28}
29
30impl EntityRefPathParam for Color {
31    fn parameter_name() -> &'static str {
32        "color_ref"
33    }
34}
35
36/// Color with sizes included
37#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
38pub struct NestedColor {
39    pub id: Id<Color>,
40    pub number: String,
41    pub name: I18nString,
42    pub slug: Slug<Color>,
43    pub external_id: Option<ExternalId<Color>>,
44    pub images: Vec<ImageSummary>,
45    pub sizes: Vec<NestedSize>,
46    pub is_new: Option<bool>,
47}
48
49/// Color with sizes included
50#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
51pub struct NestedColorSummary {
52    pub id: Id<Color>,
53    pub number: String,
54    pub name: I18nString,
55    pub primary_image: Option<ImageSummary>,
56    pub sizes: Vec<NestedSizeSummary>,
57}
58impl NestedColor {
59    pub(crate) fn into_summary(self) -> NestedColorSummary {
60        NestedColorSummary {
61            id: self.id,
62            number: self.number,
63            name: self.name,
64            primary_image: self.images.into_iter().next(),
65            sizes: self.sizes.into_iter().map(|c| c.into_summary()).collect(),
66        }
67    }
68
69    pub(crate) fn service_item(&self) -> bool {
70        self.sizes
71            .iter()
72            .any(|size| size.service_item == Some(true))
73    }
74
75    pub(crate) fn primary_image(&self) -> Option<&ImageSummary> {
76        self.images.first()
77    }
78}
79
80/// Color summary
81#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
82pub struct ColorSummary {
83    pub id: Id<Color>,
84    pub style: StyleSummary,
85    pub number: String,
86    pub name: I18nString,
87    pub slug: Slug<Color>,
88    pub external_id: Option<ExternalId<Color>>,
89}
90
91impl RefTarget for Color {
92    async fn lookup_id(
93        client: &impl GenericClient,
94        organization_id: Id<Organization>,
95        entity_ref: &crate::entity_ref::Ref<Self>,
96    ) -> crate::Result<Option<Id<Self>>> {
97        let (id, external_id, slug) = entity_ref.to_owned().take_all_inner();
98        Ok(get_color_id()
99            .bind(
100                client,
101                &organization_id.into(),
102                &id,
103                &external_id.as_deref(),
104                &slug.as_deref(),
105            )
106            .opt()
107            .await?
108            .map(Id::new))
109    }
110}
111
112/// Color, for creation
113#[derive(Debug, Deserialize)]
114pub struct CreateColor {
115    pub style: Ref<Style>,
116    pub number: String,
117    pub name: I18nString,
118    pub slug: Option<Slug<Color>>,
119    pub external_id: Option<ExternalId<Color>>,
120}
121
122impl SlugEntity for CreateColor {
123    type RefTarget = Color;
124    fn generate_slug(&self, prefix: &str) -> Option<Slug<Self::RefTarget>> {
125        Some(Slug::new(slugify(&[prefix, &self.number, &self.name.en])))
126    }
127
128    fn slug(&self) -> Option<Slug<Self::RefTarget>> {
129        self.slug.clone()
130    }
131
132    fn set_slug(&mut self, value: Slug<Self::RefTarget>) {
133        self.slug = Some(value);
134    }
135}
136
137impl ExternalIdEntity for CreateColor {
138    type RefTarget = Color;
139
140    fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
141        self.external_id.clone()
142    }
143
144    fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
145        self.external_id = Some(value);
146    }
147}
148
149/// Color, for update
150#[derive(Debug, Deserialize)]
151pub struct UpdateColor {
152    pub style: Option<Ref<Style>>,
153    pub number: Option<String>,
154    pub name: Option<I18nString>,
155    pub slug: Option<Slug<Color>>,
156    pub external_id: Option<ExternalId<Color>>,
157}
158
159impl From<CreateColor> for UpdateColor {
160    fn from(color: CreateColor) -> Self {
161        Self {
162            style: Some(color.style),
163            number: Some(color.number),
164            name: Some(color.name),
165            slug: color.slug,
166            external_id: color.external_id,
167        }
168    }
169}
170
171impl SlugEntity for UpdateColor {
172    type RefTarget = Color;
173
174    fn slug(&self) -> Option<Slug<Self::RefTarget>> {
175        self.slug.clone()
176    }
177
178    fn set_slug(&mut self, value: Slug<Self::RefTarget>) {
179        self.slug = Some(value);
180    }
181}
182
183impl ExternalIdEntity for UpdateColor {
184    type RefTarget = Color;
185
186    fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
187        self.external_id.clone()
188    }
189
190    fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
191        self.external_id = Some(value);
192    }
193}