samling/collections/
entities.rs

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