rust_moysklad/models/
mod.rs

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/// Дополнительные поля
86#[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(Debug, Clone, PartialEq, Serialize, Deserialize)]
120// #[serde(untagged)]
121// pub enum Attribute {
122//     StringAttribute(StringAttribute),
123//     CustomAttribute(CustomAttribute),
124//     IntAttribute(IntAttribute),
125//     FloatAttribute(FloatAttribute),
126//     BooleanAttribute(BooleanAttribute),
127//     DateAttribute(DateAttribute),
128//     FileAttribute(FileAttribute),
129// }
130// impl Attribute {
131//     pub fn from_products_custom_field<T>(field: ProductsCustomField, value: T) -> Attribute
132//     where
133//         T: ToString,
134//     {
135//         match field.attribute_type {
136//             AttributeType::String => Attribute::StringAttribute(StringAttribute {
137//                 meta: field.meta,
138//                 id: field.id,
139//                 name: field.name,
140//                 attribute_type: field.attribute_type,
141//                 value: value.to_string(),
142//             }),
143//             AttributeType::Customentity => todo!(),
144//             AttributeType::Long => todo!(),
145//             AttributeType::Time => todo!(),
146//             AttributeType::File => todo!(),
147//             AttributeType::Double => todo!(),
148//             AttributeType::Boolean => todo!(),
149//             AttributeType::Text => todo!(),
150//             AttributeType::Link => todo!(),
151//         }
152//     }
153// }
154
155#[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)]
180// #[serde(rename_all = "camelCase")]
181// pub struct CustomAttribute {
182//     pub meta: Meta,
183//     pub id: uuid::Uuid,
184//     pub name: String,
185//     #[serde(rename = "type")]
186//     pub attribute_type: AttributeType,
187//     pub value: AttributeValue,
188// }
189
190// #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
191// #[serde(rename_all = "camelCase")]
192// pub struct StringAttribute {
193//     pub meta: Meta,
194//     pub id: uuid::Uuid,
195//     pub name: String,
196//     #[serde(rename = "type")]
197//     pub attribute_type: AttributeType,
198//     pub value: String,
199// }
200// #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
201// #[serde(rename_all = "camelCase")]
202// pub struct IntAttribute {
203//     pub meta: Meta,
204//     pub id: uuid::Uuid,
205//     pub name: String,
206//     #[serde(rename = "type")]
207//     pub attribute_type: AttributeType,
208//     pub value: i64,
209// }
210// #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
211// #[serde(rename_all = "camelCase")]
212// pub struct FloatAttribute {
213//     pub meta: Meta,
214//     pub id: uuid::Uuid,
215//     pub name: String,
216//     #[serde(rename = "type")]
217//     pub attribute_type: AttributeType,
218//     pub value: f64,
219// }
220// #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
221// #[serde(rename_all = "camelCase")]
222// pub struct BooleanAttribute {
223//     pub meta: Meta,
224//     pub id: uuid::Uuid,
225//     pub name: String,
226//     #[serde(rename = "type")]
227//     pub attribute_type: AttributeType,
228//     pub value: bool,
229// }
230// #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
231// #[serde(rename_all = "camelCase")]
232// pub struct DateAttribute {
233//     pub meta: Meta,
234//     pub id: uuid::Uuid,
235//     pub name: String,
236//     #[serde(rename = "type")]
237//     pub attribute_type: AttributeType,
238//     #[serde(deserialize_with = "deserialize_date_from_str")]
239//     pub value: NaiveDateTime,
240// }
241// #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
242// #[serde(rename_all = "camelCase")]
243// pub struct FileAttribute {
244//     pub meta: Meta,
245//     pub id: uuid::Uuid,
246//     pub name: String,
247//     #[serde(rename = "type")]
248//     pub attribute_type: AttributeType,
249//     pub value: String,
250//     pub download: DownloadMeta,
251// }
252#[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)]
286// #[serde(rename_all = "camelCase")]
287// pub struct AttributeValue {
288//     pub meta: Meta,
289//     pub name: String,
290// }
291#[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}