Skip to main content

thunkmetrc_wrapper/services/
items_service.rs

1use thunkmetrc_client::MetrcClient;
2use serde_json::Value;
3use std::error::Error;
4use std::sync::Arc;
5#[allow(unused_imports)]
6use futures::Stream;
7use crate::ratelimiter::MetrcRateLimiter;
8#[allow(unused_imports)]
9use crate::utils::iterate_pages;
10#[allow(unused_imports)]
11use crate::models::*;
12
13pub struct ItemsService {
14    client: MetrcClient,
15    rate_limiter: Arc<MetrcRateLimiter>,
16}
17
18impl ItemsService {
19    pub fn new(client: MetrcClient, rate_limiter: Arc<MetrcRateLimiter>) -> Self {
20        Self {
21            client,
22            rate_limiter,
23        }
24    }
25
26    /// POST CreateBrand
27    /// Creates one or more new item brands for the specified Facility identified by the License Number.
28    /// Permissions Required:
29    /// - Manage Items
30    /// Parameters:
31    /// - body (Option<&Value>): Request body
32    /// - license_number (Option<String>): Filter by licenseNumber
33    pub async fn create_items_brand(&self, license_number: Option<String>, body: Option<Vec<CreateBrandRequestItem>>) -> std::result::Result<Option<WriteResponse>, Box<dyn Error + Send + Sync>> {
34        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
35        let client = self.client.clone();
36        
37        let body_val = body_val.clone();
38
39        let resp_val = self.rate_limiter.execute(None,false,
40            move || {
41                let client = client.clone();
42                let license_number = license_number.clone();
43                let body_val = body_val.clone();
44
45                async move {
46                    client.items().create_items_brand(license_number, body_val.as_ref()
47                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
48                }
49            }
50        ).await?;
51
52        if let Some(v) = resp_val {
53            let typed: WriteResponse = serde_json::from_value(v)?;
54            Ok(Some(typed))
55        } else {
56            Ok(None)
57        }
58    }
59
60    /// POST CreateFile
61    /// Uploads one or more image or PDF files for products, labels, packaging, or documents at the specified Facility.
62    /// Permissions Required:
63    /// - Manage Items
64    /// Parameters:
65    /// - body (Option<&Value>): Request body
66    /// - license_number (Option<String>): Filter by licenseNumber
67    pub async fn create_items_file(&self, license_number: Option<String>, body: Option<Vec<CreateFileRequestItem>>) -> std::result::Result<Option<WriteResponse>, Box<dyn Error + Send + Sync>> {
68        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
69        let client = self.client.clone();
70        
71        let body_val = body_val.clone();
72
73        let resp_val = self.rate_limiter.execute(None,false,
74            move || {
75                let client = client.clone();
76                let license_number = license_number.clone();
77                let body_val = body_val.clone();
78
79                async move {
80                    client.items().create_items_file(license_number, body_val.as_ref()
81                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
82                }
83            }
84        ).await?;
85
86        if let Some(v) = resp_val {
87            let typed: WriteResponse = serde_json::from_value(v)?;
88            Ok(Some(typed))
89        } else {
90            Ok(None)
91        }
92    }
93
94    /// POST CreateItems
95    /// Permissions Required:
96    /// - Manage Items
97    /// Parameters:
98    /// - body (Option<&Value>): Request body
99    /// - license_number (Option<String>): Filter by licenseNumber
100    pub async fn create_items(&self, license_number: Option<String>, body: Option<Vec<CreateItemsRequestItem>>) -> std::result::Result<Option<WriteResponse>, Box<dyn Error + Send + Sync>> {
101        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
102        let client = self.client.clone();
103        
104        let body_val = body_val.clone();
105
106        let resp_val = self.rate_limiter.execute(None,false,
107            move || {
108                let client = client.clone();
109                let license_number = license_number.clone();
110                let body_val = body_val.clone();
111
112                async move {
113                    client.items().create_items(license_number, body_val.as_ref()
114                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
115                }
116            }
117        ).await?;
118
119        if let Some(v) = resp_val {
120            let typed: WriteResponse = serde_json::from_value(v)?;
121            Ok(Some(typed))
122        } else {
123            Ok(None)
124        }
125    }
126
127    /// POST CreatePhoto
128    /// This endpoint allows only BMP, GIF, JPG, and PNG files and uploaded files can be no more than 5 MB in size.
129    /// Permissions Required:
130    /// - Manage Items
131    /// Parameters:
132    /// - body (Option<&Value>): Request body
133    /// - license_number (Option<String>): Filter by licenseNumber
134    pub async fn create_items_photo(&self, license_number: Option<String>, body: Option<Vec<CreatePhotoRequestItem>>) -> std::result::Result<Option<WriteResponse>, Box<dyn Error + Send + Sync>> {
135        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
136        let client = self.client.clone();
137        
138        let body_val = body_val.clone();
139
140        let resp_val = self.rate_limiter.execute(None,false,
141            move || {
142                let client = client.clone();
143                let license_number = license_number.clone();
144                let body_val = body_val.clone();
145
146                async move {
147                    client.items().create_items_photo(license_number, body_val.as_ref()
148                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
149                }
150            }
151        ).await?;
152
153        if let Some(v) = resp_val {
154            let typed: WriteResponse = serde_json::from_value(v)?;
155            Ok(Some(typed))
156        } else {
157            Ok(None)
158        }
159    }
160
161    /// DELETE DeleteBrandById
162    /// Archives the specified Item Brand by Id for the given Facility License Number.
163    /// Permissions Required:
164    /// - Manage Items
165    /// Parameters:
166    /// - id (str): Path parameter id
167    /// - license_number (Option<String>): Filter by licenseNumber
168    pub async fn delete_items_brand_by_id(&self, id: &str, license_number: Option<String>, body: Option<&Value>) -> std::result::Result<Option<serde_json::Value>, Box<dyn Error + Send + Sync>> {
169        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
170        let id = id.to_string();
171        let client = self.client.clone();
172        
173        let body_val = body_val.clone();
174
175        let resp_val = self.rate_limiter.execute(None,false,
176            move || {
177                let client = client.clone();
178                let id = id.clone();
179                let license_number = license_number.clone();
180                let body_val = body_val.clone();
181
182                async move {
183                    client.items().delete_items_brand_by_id(&id, license_number, body_val.as_ref()
184                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
185                }
186            }
187        ).await?;
188
189        if let Some(v) = resp_val {
190            let typed: serde_json::Value = serde_json::from_value(v)?;
191            Ok(Some(typed))
192        } else {
193            Ok(None)
194        }
195    }
196
197    /// DELETE DeleteItemsById
198    /// Archives the specified Product by Id for the given Facility License Number.
199    /// Permissions Required:
200    /// - Manage Items
201    /// Parameters:
202    /// - id (str): Path parameter id
203    /// - license_number (Option<String>): Filter by licenseNumber
204    pub async fn delete_items_by_id(&self, id: &str, license_number: Option<String>, body: Option<&Value>) -> std::result::Result<Option<serde_json::Value>, Box<dyn Error + Send + Sync>> {
205        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
206        let id = id.to_string();
207        let client = self.client.clone();
208        
209        let body_val = body_val.clone();
210
211        let resp_val = self.rate_limiter.execute(None,false,
212            move || {
213                let client = client.clone();
214                let id = id.clone();
215                let license_number = license_number.clone();
216                let body_val = body_val.clone();
217
218                async move {
219                    client.items().delete_items_by_id(&id, license_number, body_val.as_ref()
220                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
221                }
222            }
223        ).await?;
224
225        if let Some(v) = resp_val {
226            let typed: serde_json::Value = serde_json::from_value(v)?;
227            Ok(Some(typed))
228        } else {
229            Ok(None)
230        }
231    }
232
233    /// GET GetActiveItems
234    /// Returns a list of active items for the specified Facility.
235    /// Permissions Required:
236    /// - Manage Items
237    /// Parameters:
238    /// - last_modified_end (Option<String>): Filter by lastModifiedEnd
239    /// - last_modified_start (Option<String>): Filter by lastModifiedStart
240    /// - license_number (Option<String>): Filter by licenseNumber
241    /// - page_number (Option<String>): Filter by pageNumber
242    /// - page_size (Option<String>): Filter by pageSize
243    pub async fn get_active_items(&self, last_modified_end: Option<String>, last_modified_start: Option<String>, license_number: Option<String>, page_number: Option<String>, page_size: Option<String>, body: Option<&Value>) -> std::result::Result<Option<PaginatedResponse<Item>>, Box<dyn Error + Send + Sync>> {
244        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
245        let client = self.client.clone();
246        
247        let body_val = body_val.clone();
248
249        let resp_val = self.rate_limiter.execute(None,true,
250            move || {
251                let client = client.clone();
252                let last_modified_end = last_modified_end.clone();
253                let last_modified_start = last_modified_start.clone();
254                let license_number = license_number.clone();
255                let page_number = page_number.clone();
256                let page_size = page_size.clone();
257                let body_val = body_val.clone();
258
259                async move {
260                    client.items().get_active_items(last_modified_end, last_modified_start, license_number, page_number, page_size, body_val.as_ref()
261                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
262                }
263            }
264        ).await?;
265
266        if let Some(v) = resp_val {
267            let typed: PaginatedResponse<Item> = serde_json::from_value(v)?;
268            Ok(Some(typed))
269        } else {
270            Ok(None)
271        }
272    }
273
274    /// GET GetBrands
275    /// Retrieves a list of active item brands for the specified Facility.
276    /// Permissions Required:
277    /// - Manage Items
278    /// Parameters:
279    /// - license_number (Option<String>): Filter by licenseNumber
280    /// - page_number (Option<String>): Filter by pageNumber
281    /// - page_size (Option<String>): Filter by pageSize
282    pub async fn get_items_brands(&self, license_number: Option<String>, page_number: Option<String>, page_size: Option<String>, body: Option<&Value>) -> std::result::Result<Option<PaginatedResponse<Brand>>, Box<dyn Error + Send + Sync>> {
283        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
284        let client = self.client.clone();
285        
286        let body_val = body_val.clone();
287
288        let resp_val = self.rate_limiter.execute(None,true,
289            move || {
290                let client = client.clone();
291                let license_number = license_number.clone();
292                let page_number = page_number.clone();
293                let page_size = page_size.clone();
294                let body_val = body_val.clone();
295
296                async move {
297                    client.items().get_items_brands(license_number, page_number, page_size, body_val.as_ref()
298                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
299                }
300            }
301        ).await?;
302
303        if let Some(v) = resp_val {
304            let typed: PaginatedResponse<Brand> = serde_json::from_value(v)?;
305            Ok(Some(typed))
306        } else {
307            Ok(None)
308        }
309    }
310
311    /// GET GetCategories
312    /// Retrieves a list of item categories.
313    /// Parameters:
314    /// - license_number (Option<String>): Filter by licenseNumber
315    /// - page_number (Option<String>): Filter by pageNumber
316    /// - page_size (Option<String>): Filter by pageSize
317    pub async fn get_items_categories(&self, license_number: Option<String>, page_number: Option<String>, page_size: Option<String>, body: Option<&Value>) -> std::result::Result<Option<PaginatedResponse<Category>>, Box<dyn Error + Send + Sync>> {
318        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
319        let client = self.client.clone();
320        
321        let body_val = body_val.clone();
322
323        let resp_val = self.rate_limiter.execute(None,true,
324            move || {
325                let client = client.clone();
326                let license_number = license_number.clone();
327                let page_number = page_number.clone();
328                let page_size = page_size.clone();
329                let body_val = body_val.clone();
330
331                async move {
332                    client.items().get_items_categories(license_number, page_number, page_size, body_val.as_ref()
333                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
334                }
335            }
336        ).await?;
337
338        if let Some(v) = resp_val {
339            let typed: PaginatedResponse<Category> = serde_json::from_value(v)?;
340            Ok(Some(typed))
341        } else {
342            Ok(None)
343        }
344    }
345
346    /// GET GetFileById
347    /// Retrieves a file by its Id for the specified Facility.
348    /// Permissions Required:
349    /// - Manage Items
350    /// Parameters:
351    /// - id (str): Path parameter id
352    /// - license_number (Option<String>): Filter by licenseNumber
353    pub async fn get_items_file_by_id(&self, id: &str, license_number: Option<String>, body: Option<&Value>) -> std::result::Result<Option<File>, Box<dyn Error + Send + Sync>> {
354        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
355        let id = id.to_string();
356        let client = self.client.clone();
357        
358        let body_val = body_val.clone();
359
360        let resp_val = self.rate_limiter.execute(None,true,
361            move || {
362                let client = client.clone();
363                let id = id.clone();
364                let license_number = license_number.clone();
365                let body_val = body_val.clone();
366
367                async move {
368                    client.items().get_items_file_by_id(&id, license_number, body_val.as_ref()
369                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
370                }
371            }
372        ).await?;
373
374        if let Some(v) = resp_val {
375            let typed: File = serde_json::from_value(v)?;
376            Ok(Some(typed))
377        } else {
378            Ok(None)
379        }
380    }
381
382    /// GET GetInactiveItems
383    /// Retrieves a list of inactive items for the specified Facility.
384    /// Permissions Required:
385    /// - Manage Items
386    /// Parameters:
387    /// - license_number (Option<String>): Filter by licenseNumber
388    /// - page_number (Option<String>): Filter by pageNumber
389    /// - page_size (Option<String>): Filter by pageSize
390    pub async fn get_inactive_items(&self, license_number: Option<String>, page_number: Option<String>, page_size: Option<String>, body: Option<&Value>) -> std::result::Result<Option<PaginatedResponse<Item>>, Box<dyn Error + Send + Sync>> {
391        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
392        let client = self.client.clone();
393        
394        let body_val = body_val.clone();
395
396        let resp_val = self.rate_limiter.execute(None,true,
397            move || {
398                let client = client.clone();
399                let license_number = license_number.clone();
400                let page_number = page_number.clone();
401                let page_size = page_size.clone();
402                let body_val = body_val.clone();
403
404                async move {
405                    client.items().get_inactive_items(license_number, page_number, page_size, body_val.as_ref()
406                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
407                }
408            }
409        ).await?;
410
411        if let Some(v) = resp_val {
412            let typed: PaginatedResponse<Item> = serde_json::from_value(v)?;
413            Ok(Some(typed))
414        } else {
415            Ok(None)
416        }
417    }
418
419    /// GET GetItemsById
420    /// Retrieves detailed information about a specific Item by Id.
421    /// Permissions Required:
422    /// - Manage Items
423    /// Parameters:
424    /// - id (str): Path parameter id
425    /// - license_number (Option<String>): Filter by licenseNumber
426    pub async fn get_items_by_id(&self, id: &str, license_number: Option<String>, body: Option<&Value>) -> std::result::Result<Option<Item>, Box<dyn Error + Send + Sync>> {
427        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
428        let id = id.to_string();
429        let client = self.client.clone();
430        
431        let body_val = body_val.clone();
432
433        let resp_val = self.rate_limiter.execute(None,true,
434            move || {
435                let client = client.clone();
436                let id = id.clone();
437                let license_number = license_number.clone();
438                let body_val = body_val.clone();
439
440                async move {
441                    client.items().get_items_by_id(&id, license_number, body_val.as_ref()
442                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
443                }
444            }
445        ).await?;
446
447        if let Some(v) = resp_val {
448            let typed: Item = serde_json::from_value(v)?;
449            Ok(Some(typed))
450        } else {
451            Ok(None)
452        }
453    }
454
455    /// GET GetPhotoById
456    /// Retrieves an image by its Id for the specified Facility.
457    /// Permissions Required:
458    /// - Manage Items
459    /// Parameters:
460    /// - id (str): Path parameter id
461    /// - license_number (Option<String>): Filter by licenseNumber
462    pub async fn get_items_photo_by_id(&self, id: &str, license_number: Option<String>, body: Option<&Value>) -> std::result::Result<Option<Photo>, Box<dyn Error + Send + Sync>> {
463        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
464        let id = id.to_string();
465        let client = self.client.clone();
466        
467        let body_val = body_val.clone();
468
469        let resp_val = self.rate_limiter.execute(None,true,
470            move || {
471                let client = client.clone();
472                let id = id.clone();
473                let license_number = license_number.clone();
474                let body_val = body_val.clone();
475
476                async move {
477                    client.items().get_items_photo_by_id(&id, license_number, body_val.as_ref()
478                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
479                }
480            }
481        ).await?;
482
483        if let Some(v) = resp_val {
484            let typed: Photo = serde_json::from_value(v)?;
485            Ok(Some(typed))
486        } else {
487            Ok(None)
488        }
489    }
490
491    /// PUT UpdateBrand
492    /// Updates one or more existing item brands for the specified Facility.
493    /// Permissions Required:
494    /// - Manage Items
495    /// Parameters:
496    /// - body (Option<&Value>): Request body
497    /// - license_number (Option<String>): Filter by licenseNumber
498    pub async fn update_items_brand(&self, license_number: Option<String>, body: Option<Vec<UpdateBrandRequestItem>>) -> std::result::Result<Option<WriteResponse>, Box<dyn Error + Send + Sync>> {
499        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
500        let client = self.client.clone();
501        
502        let body_val = body_val.clone();
503
504        let resp_val = self.rate_limiter.execute(None,false,
505            move || {
506                let client = client.clone();
507                let license_number = license_number.clone();
508                let body_val = body_val.clone();
509
510                async move {
511                    client.items().update_items_brand(license_number, body_val.as_ref()
512                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
513                }
514            }
515        ).await?;
516
517        if let Some(v) = resp_val {
518            let typed: WriteResponse = serde_json::from_value(v)?;
519            Ok(Some(typed))
520        } else {
521            Ok(None)
522        }
523    }
524
525    /// PUT UpdateItems
526    /// Updates one or more existing products for the specified Facility.
527    /// Permissions Required:
528    /// - Manage Items
529    /// Parameters:
530    /// - body (Option<&Value>): Request body
531    /// - license_number (Option<String>): Filter by licenseNumber
532    pub async fn update_items(&self, license_number: Option<String>, body: Option<Vec<UpdateItemsRequestItem>>) -> std::result::Result<Option<WriteResponse>, Box<dyn Error + Send + Sync>> {
533        let body_val = if let Some(b) = body { Some(serde_json::to_value(b)?) } else { None };
534        let client = self.client.clone();
535        
536        let body_val = body_val.clone();
537
538        let resp_val = self.rate_limiter.execute(None,false,
539            move || {
540                let client = client.clone();
541                let license_number = license_number.clone();
542                let body_val = body_val.clone();
543
544                async move {
545                    client.items().update_items(license_number, body_val.as_ref()
546                    ).await.map_err(|e| e as Box<dyn Error + Send + Sync>)
547                }
548            }
549        ).await?;
550
551        if let Some(v) = resp_val {
552            let typed: WriteResponse = serde_json::from_value(v)?;
553            Ok(Some(typed))
554        } else {
555            Ok(None)
556        }
557    }
558}
559