use chrono::{DateTime, FixedOffset, NaiveDate};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use url::Url;
use crate::{
auth::User,
entity_ref::{ExternalId, ExternalIdEntity, Slug, SlugEntity},
helpers::slugify,
organizations::Organization,
Color, EntityRefPathParam, I18nString, Id, ImageSource, NestedSize, NestedStyle,
PriceListSummary, Ref, RefTarget, Size, Style,
};
use samling_clorinde::{client::GenericClient, queries::collection::get_collection_id};
impl EntityRefPathParam for Collection {
fn parameter_name() -> &'static str {
"collection_ref"
}
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct Collection {
pub id: Id<Self>,
pub acronym: I18nString,
pub name: I18nString,
pub image_url: Option<Url>,
pub slug: Slug<Self>,
pub external_id: Option<ExternalId<Self>>,
pub created_by: Option<Id<User>>,
pub created_at: DateTime<FixedOffset>,
pub updated_at: DateTime<FixedOffset>,
pub sizes: Vec<NestedSize>,
pub pricing: Vec<CollectionPricing>,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct CollectionPricing {
pub list: PriceListSummary,
pub date: NaiveDate,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct CollectionSummary {
pub id: Id<Collection>,
pub acronym: I18nString,
pub name: I18nString,
pub pricing: Vec<CollectionPricing>,
pub image_url: Option<Url>,
pub slug: Slug<Collection>,
pub external_id: Option<ExternalId<Collection>>,
pub created_by: Option<Id<User>>,
pub created_at: DateTime<FixedOffset>,
pub updated_at: DateTime<FixedOffset>,
pub num_styles: u32,
pub num_colors: u32,
pub num_sizes: u32,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct CollectionWithItems {
#[serde(flatten)]
pub collection: CollectionSummary,
pub items: Vec<CollectionItem>,
}
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct CollectionItem {
pub style: NestedStyle,
pub user_comment: String, }
impl RefTarget for Collection {
async fn lookup_id(
client: &impl GenericClient,
organization_id: Id<Organization>,
entity_ref: &crate::entity_ref::Ref<Self>,
) -> crate::Result<Option<Id<Self>>> {
let (id, external_id, slug) = entity_ref.to_owned().take_all_inner();
Ok(get_collection_id()
.bind(
client,
&organization_id.into(),
&id,
&external_id.as_deref(),
&slug.as_deref(),
)
.opt()
.await?
.map(Id::new))
}
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct CreateCollection {
pub acronym: I18nString,
pub name: I18nString,
pub pricing: Vec<CollectionPricing>,
pub image: Option<ImageSource>,
pub slug: Option<Slug<Collection>>,
pub external_id: Option<ExternalId<Collection>>,
#[serde(default)]
pub sizes: Vec<Ref<Size>>,
pub new_styles: Vec<Ref<Style>>,
pub new_colors: Vec<Ref<Color>>,
}
impl SlugEntity for CreateCollection {
type RefTarget = Collection;
fn generate_slug(&self, prefix: &str) -> Option<Slug<Self::RefTarget>> {
Some(Slug::new(slugify(&[prefix, &self.name.en])))
}
fn slug(&self) -> Option<Slug<Self::RefTarget>> {
self.slug.clone()
}
fn set_slug(&mut self, value: Slug<Self::RefTarget>) {
self.slug = Some(value);
}
}
impl ExternalIdEntity for CreateCollection {
type RefTarget = Collection;
fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
self.external_id.clone()
}
fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
self.external_id = Some(value);
}
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct UpdateCollection {
pub acronym: Option<I18nString>,
pub name: Option<I18nString>,
pub pricing: Option<Vec<CollectionPricing>>,
pub image: Option<ImageSource>,
pub slug: Option<Slug<Collection>>,
pub external_id: Option<ExternalId<Collection>>,
pub sizes: Option<Vec<Ref<Size>>>,
pub new_styles: Option<Vec<Ref<Style>>>,
pub new_colors: Option<Vec<Ref<Color>>>,
}
impl From<CreateCollection> for UpdateCollection {
fn from(collection: CreateCollection) -> Self {
UpdateCollection {
acronym: Some(collection.acronym),
name: Some(collection.name),
pricing: Some(collection.pricing),
image: collection.image,
slug: collection.slug,
external_id: collection.external_id,
sizes: Some(collection.sizes),
new_styles: Some(collection.new_styles),
new_colors: Some(collection.new_colors),
}
}
}
impl SlugEntity for UpdateCollection {
type RefTarget = Collection;
fn slug(&self) -> Option<Slug<Self::RefTarget>> {
self.slug.clone()
}
fn set_slug(&mut self, value: Slug<Self::RefTarget>) {
self.slug = Some(value);
}
}
impl ExternalIdEntity for UpdateCollection {
type RefTarget = Collection;
fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
self.external_id.clone()
}
fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
self.external_id = Some(value);
}
}
impl CollectionSummary {
pub(crate) fn with_items(self, items: Vec<CollectionItem>) -> CollectionWithItems {
CollectionWithItems {
collection: self,
items,
}
}
}