Skip to main content

shopify_client/admin/order/
remote.rs

1use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
2
3use crate::{
4    common::{
5        http::{execute_graphql, http_client},
6        types::APIError,
7        utils::parse_response_from_text,
8        ServiceContext,
9    },
10    types::order::{
11        GetOrderResp, OrderDiscountsAndTransactionsResp, OrderQueryResp, PatchOrderRequest,
12    },
13};
14
15pub async fn patch_order(
16    ctx: &ServiceContext,
17    order_id: &String,
18    patch_request: &PatchOrderRequest,
19) -> Result<GetOrderResp, APIError> {
20    let endpoint = format!(
21        "{}/admin/api/{}/orders/{}.json",
22        ctx.shop_url.trim_end_matches('/'),
23        ctx.version,
24        order_id
25    );
26
27    let body_str = serde_json::to_string(&patch_request).unwrap_or_default();
28
29    let mut callback_headers = HeaderMap::new();
30    callback_headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
31
32    ctx.callbacks
33        .call_before(&endpoint, Some(&body_str), &callback_headers);
34
35    let response = http_client()
36        .put(&endpoint)
37        .header("X-Shopify-Access-Token", &*ctx.access_token)
38        .header("Content-Type", "application/json")
39        .json(&patch_request)
40        .send()
41        .await;
42
43    match response {
44        Ok(resp) => {
45            let response_headers = resp.headers().clone();
46            let response_text = match resp.text().await {
47                Ok(text) => text,
48                Err(e) => {
49                    let error_msg = format!("<failed to read response body: {}>", e);
50                    ctx.callbacks
51                        .call_after(&endpoint, &error_msg, &response_headers);
52                    return Err(APIError::FailedToParse);
53                }
54            };
55
56            ctx.callbacks
57                .call_after(&endpoint, &response_text, &response_headers);
58
59            parse_response_from_text::<GetOrderResp>(&response_text)
60        }
61        Err(e) => {
62            let error_msg = format!("<network error: {}>", e);
63            ctx.callbacks
64                .call_after(&endpoint, &error_msg, &HeaderMap::new());
65            Err(APIError::NetworkError)
66        }
67    }
68}
69
70pub async fn get_order_with_name(
71    ctx: &ServiceContext,
72    order_name: &String,
73) -> Result<OrderQueryResp, APIError> {
74    let endpoint = format!(
75        "{}/admin/api/{}/orders.json?query=name:%23{}&status=any",
76        ctx.shop_url.trim_end_matches('/'),
77        ctx.version,
78        order_name
79    );
80
81    let callback_headers = HeaderMap::new();
82
83    ctx.callbacks
84        .call_before(&endpoint, None, &callback_headers);
85
86    let response = http_client()
87        .get(&endpoint)
88        .header("X-Shopify-Access-Token", &*ctx.access_token)
89        .send()
90        .await;
91
92    match response {
93        Ok(resp) => {
94            let response_headers = resp.headers().clone();
95            let response_text = match resp.text().await {
96                Ok(text) => text,
97                Err(e) => {
98                    let error_msg = format!("<failed to read response body: {}>", e);
99                    ctx.callbacks
100                        .call_after(&endpoint, &error_msg, &response_headers);
101                    return Err(APIError::FailedToParse);
102                }
103            };
104
105            ctx.callbacks
106                .call_after(&endpoint, &response_text, &response_headers);
107
108            parse_response_from_text::<OrderQueryResp>(&response_text)
109        }
110        Err(e) => {
111            let error_msg = format!("<network error: {}>", e);
112            ctx.callbacks
113                .call_after(&endpoint, &error_msg, &HeaderMap::new());
114            Err(APIError::NetworkError)
115        }
116    }
117}
118
119pub async fn get_order_with_id(
120    ctx: &ServiceContext,
121    order_id: &String,
122) -> Result<GetOrderResp, APIError> {
123    let endpoint = format!(
124        "{}/admin/api/{}/orders/{}.json",
125        ctx.shop_url.trim_end_matches('/'),
126        ctx.version,
127        order_id
128    );
129
130    let callback_headers = HeaderMap::new();
131
132    ctx.callbacks
133        .call_before(&endpoint, None, &callback_headers);
134
135    let response = http_client()
136        .get(&endpoint)
137        .header("X-Shopify-Access-Token", &*ctx.access_token)
138        .send()
139        .await;
140
141    match response {
142        Ok(resp) => {
143            let response_headers = resp.headers().clone();
144            let response_text = match resp.text().await {
145                Ok(text) => text,
146                Err(e) => {
147                    let error_msg = format!("<failed to read response body: {}>", e);
148                    ctx.callbacks
149                        .call_after(&endpoint, &error_msg, &response_headers);
150                    return Err(APIError::FailedToParse);
151                }
152            };
153
154            ctx.callbacks
155                .call_after(&endpoint, &response_text, &response_headers);
156
157            parse_response_from_text::<GetOrderResp>(&response_text)
158        }
159        Err(e) => {
160            let error_msg = format!("<network error: {}>", e);
161            ctx.callbacks
162                .call_after(&endpoint, &error_msg, &HeaderMap::new());
163            Err(APIError::NetworkError)
164        }
165    }
166}
167
168pub async fn get_order_discounts_and_transactions(
169    ctx: &ServiceContext,
170    order_gid: &str,
171    lines: u32,
172) -> Result<OrderDiscountsAndTransactionsResp, APIError> {
173    let query = r#"
174        query orderDiscountsAndTransactions($id: ID!, $lines: Int!) {
175            order(id: $id) {
176                discountCodes
177                transactions {
178                    gateway
179                    kind
180                    status
181                    amountSet { shopMoney { amount currencyCode } }
182                }
183                lineItems(first: $lines) {
184                    nodes {
185                        id
186                        discountAllocations {
187                            allocatedAmountSet { shopMoney { amount currencyCode } }
188                        }
189                    }
190                    pageInfo { hasNextPage }
191                }
192                cartDiscountAmountSet { shopMoney { amount currencyCode } }
193            }
194        }
195    "#;
196
197    let variables = serde_json::json!({ "id": order_gid, "lines": lines });
198
199    execute_graphql(ctx, query, variables).await
200}