1use chrono::NaiveDateTime;
2use serde::{Deserialize, Serialize};
3use serde_with::skip_serializing_none;
4
5use crate::api_client::MsEntity;
6
7pub mod assortment;
8pub mod characteristic;
9pub mod counterparty;
10pub mod country;
11pub mod currency;
12pub mod product;
13pub mod product_folder;
14pub mod region;
15pub mod uom;
16pub mod variant;
17
18#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
19#[serde(rename_all = "camelCase")]
20pub struct Meta {
21 pub href: String,
22 pub metadata_href: Option<String>,
23 #[serde(rename = "type")]
24 pub meta_type: Option<String>,
25 pub media_type: String,
26 pub uuid_href: Option<String>,
27 pub download_href: Option<String>,
28 pub size: Option<i32>,
29 pub limit: Option<i32>,
30 pub offset: Option<i32>,
31}
32
33#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub struct EntityResponse<T> {
36 pub context: Option<Context>,
37 pub meta: Meta,
38 pub rows: Vec<T>,
39}
40#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct Context {
43 pub employee: MetaWrapper,
44}
45
46#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
47#[serde(rename_all = "camelCase")]
48pub struct MetaWrapper {
49 pub meta: Meta,
50}
51#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
52#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
53pub enum TaxSystem {
54 #[default]
55 GeneralTaxSystem,
56 PatentBased,
57 PresumptiveTaxSystem,
58 SimplifiedTaxSystemIncome,
59 SimplifiedTaxSystemIncomeOutcome,
60 TaxSystemSameAsGroup,
61 UnifiedAgriculturalTax,
62}
63pub fn deserialize_date_from_str<'de, D>(deserializer: D) -> Result<NaiveDateTime, D::Error>
64where
65 D: serde::Deserializer<'de>,
66{
67 let date_str = String::deserialize(deserializer)?;
68 NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%d %H:%M:%S%.3f")
69 .map_err(serde::de::Error::custom)
70}
71pub fn deserialize_option_date_from_str<'de, D>(
72 deserializer: D,
73) -> Result<Option<NaiveDateTime>, D::Error>
74where
75 D: serde::Deserializer<'de>,
76{
77 let date_str = Option::<String>::deserialize(deserializer)?;
78 match date_str {
79 Some(str) => NaiveDateTime::parse_from_str(&str, "%Y-%m-%d %H:%M:%S%.3f")
80 .map(Some)
81 .map_err(serde::de::Error::custom),
82 None => Ok(None),
83 }
84}
85#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct ProductsCustomField {
89 pub custom_entity_meta: Option<Meta>,
90 pub meta: Meta,
91 pub id: uuid::Uuid,
92 pub name: String,
93 #[serde(rename = "type")]
94 pub attribute_type: AttributeType,
95 pub required: bool,
96 pub description: Option<String>,
97}
98impl MsEntity for ProductsCustomField {
99 fn url() -> String {
100 String::from("https://api.moysklad.ru/api/remap/1.2/entity/product/metadata/attributes")
101 }
102}
103#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
104#[serde(rename_all = "camelCase")]
105pub struct CustomEntity {
106 pub account_id: uuid::Uuid,
107 pub code: Option<String>,
108 pub description: Option<String>,
109 pub external_code: String,
110 pub id: uuid::Uuid,
111 pub meta: Meta,
112 pub name: String,
113 #[serde(deserialize_with = "deserialize_date_from_str")]
114 pub updated: NaiveDateTime,
115 pub group: MetaWrapper,
116 pub owner: MetaWrapper,
117 pub shared: Option<bool>,
118}
119#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
156#[serde(rename_all = "camelCase")]
157#[skip_serializing_none]
158pub struct Attribute {
159 pub meta: Meta,
160 pub id: uuid::Uuid,
161 pub name: String,
162 #[serde(rename = "type")]
163 pub attribute_type: AttributeType,
164 pub value: AttributeValue,
165 pub download: Option<DownloadMeta>,
166}
167impl Attribute {
168 pub fn from_field(field: &ProductsCustomField, value: AttributeValue) -> Self {
169 Self {
170 meta: field.meta.clone(),
171 id: field.id,
172 name: field.name.clone(),
173 attribute_type: field.attribute_type.clone(),
174 value,
175 download: None,
176 }
177 }
178}
179#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
253#[serde(rename_all = "camelCase")]
254pub struct DownloadMeta {
255 pub href: String,
256 pub media_type: String,
257}
258#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
259#[serde(rename_all = "camelCase")]
260pub struct CustomValue {
261 pub meta: Meta,
262 pub name: String,
263}
264impl From<CustomEntity> for CustomValue {
265 fn from(value: CustomEntity) -> Self {
266 Self {
267 meta: value.meta,
268 name: value.name,
269 }
270 }
271}
272#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
273#[serde(untagged)]
274pub enum AttributeValue {
275 Custom(CustomValue),
276 String(String),
277 #[serde(deserialize_with = "deserialize_date_from_str")]
278 Date(NaiveDateTime),
279 Bool(bool),
280 Float(f64),
281 Int(i32),
282 #[default]
283 Other,
284}
285#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
292#[serde(rename_all = "lowercase")]
293pub enum AttributeType {
294 #[default]
295 String,
296 Customentity,
297 Long,
298 Time,
299 File,
300 Double,
301 Boolean,
302 Text,
303 Link,
304}
305#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
306#[serde(rename_all = "camelCase")]
307pub struct PriceType {
308 pub meta: Meta,
309 pub id: String,
310 pub name: String,
311 pub external_code: String,
312}