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#[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#[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#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
64pub struct CollectionWithItems {
65 #[serde(flatten)]
66 pub collection: CollectionSummary,
67 pub items: Vec<CollectionItem>,
68}
69
70#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
72pub struct CollectionItem {
73 pub style: NestedStyle,
74 pub user_comment: String, }
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#[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#[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}