concur_api/api/
receipts.rs1use crate::client::ConcurClient;
6use crate::error::Result;
7use reqwest::Method;
8use serde::Deserialize;
9
10pub struct ReceiptsApi<'a> {
12 client: &'a ConcurClient,
13}
14
15impl<'a> ReceiptsApi<'a> {
16 pub fn new(client: &'a ConcurClient) -> Self {
17 Self { client }
18 }
19
20 pub async fn index(&self) -> Result<ReceiptIndex> {
22 self.client
23 .request(Method::GET, "/receipts/")
24 .await?
25 .send()
26 .await?
27 .json()
28 .await
29 .map_err(Into::into)
30 }
31
32 pub async fn schemas(&self, schema_id: Option<&str>) -> Result<serde_json::Value> {
34 let path = match schema_id {
35 Some(id) => format!("/receipts/schemas/{}", id),
36 None => "/receipts/schemas".to_string(),
37 };
38 self.client
39 .request(Method::GET, &path)
40 .await?
41 .send()
42 .await?
43 .json()
44 .await
45 .map_err(Into::into)
46 }
47
48 pub async fn status(&self, receipt_id: &str) -> Result<ReceiptStatus> {
50 self.client
51 .request(Method::GET, &format!("/receipts/v4/status/{}", receipt_id))
52 .await?
53 .send()
54 .await?
55 .json()
56 .await
57 .map_err(Into::into)
58 }
59
60 pub async fn post_receipt(
62 &self,
63 user_id: &str,
64 receipt: &serde_json::Value,
65 schema_url: &str,
66 ) -> Result<PostReceiptResponse> {
67 let req = self
68 .client
69 .request(Method::POST, &format!("/receipts/v4/users/{}", user_id))
70 .await?;
71 let req = req
72 .header("Content-Type", "application/json")
73 .header("link", format!("<{}>;rel=describedBy", schema_url))
74 .json(receipt);
75 let response = self.client.execute_with_raw(req).await?;
76 let location = response
77 .headers()
78 .get("location")
79 .and_then(|v| v.to_str().ok())
80 .map(String::from);
81 let link = response
82 .headers()
83 .get("link")
84 .and_then(|v| v.to_str().ok())
85 .map(String::from);
86 Ok(PostReceiptResponse { location, link })
87 }
88
89 pub async fn get_user_receipts(&self, user_id: &str) -> Result<Vec<serde_json::Value>> {
91 self.client
92 .request(Method::GET, &format!("/receipts/v4/users/{}", user_id))
93 .await?
94 .send()
95 .await?
96 .json()
97 .await
98 .map_err(Into::into)
99 }
100
101 pub async fn get_receipt(&self, receipt_id: &str) -> Result<serde_json::Value> {
103 self.client
104 .request(Method::GET, &format!("/receipts/v4/{}", receipt_id))
105 .await?
106 .send()
107 .await?
108 .json()
109 .await
110 .map_err(Into::into)
111 }
112
113 pub async fn get_receipt_image(&self, receipt_id: &str) -> Result<Vec<u8>> {
115 self.client
116 .request(Method::GET, &format!("/receipts/v4/{}/image", receipt_id))
117 .await?
118 .send()
119 .await?
120 .bytes()
121 .await
122 .map(|b| b.to_vec())
123 .map_err(Into::into)
124 }
125}
126
127#[derive(Debug, Clone, Deserialize)]
128pub struct ReceiptIndex {
129 pub links: Vec<ReceiptLink>,
130}
131
132#[derive(Debug, Clone, Deserialize)]
133pub struct ReceiptLink {
134 pub rel: String,
135 pub href: String,
136 pub method: Option<String>,
137}
138
139#[derive(Debug, Clone, Deserialize)]
140pub struct ReceiptStatus {
141 pub status: String,
142 pub logs: Vec<ReceiptLog>,
143}
144
145#[derive(Debug, Clone, Deserialize)]
146pub struct ReceiptLog {
147 #[serde(rename = "logLevel")]
148 pub log_level: String,
149 pub message: String,
150 pub timestamp: String,
151}
152
153#[derive(Debug, Clone, Default)]
154pub struct PostReceiptResponse {
155 pub location: Option<String>,
156 pub link: Option<String>,
157}