thunkmetrc_wrapper/services/
items_service.rs1use 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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