shopify_sdk/rest/resources/v2025_10/
application_charge.rs1use chrono::{DateTime, Utc};
46use serde::{Deserialize, Serialize};
47
48use crate::rest::{ResourceOperation, ResourcePath, RestResource};
49use crate::HttpMethod;
50
51use super::common::{ChargeCurrency, ChargeStatus};
52
53#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
88pub struct ApplicationCharge {
89 #[serde(skip_serializing)]
92 pub id: Option<u64>,
93
94 #[serde(skip_serializing_if = "Option::is_none")]
96 pub name: Option<String>,
97
98 #[serde(skip_serializing_if = "Option::is_none")]
101 pub price: Option<String>,
102
103 #[serde(skip_serializing)]
106 pub status: Option<ChargeStatus>,
107
108 #[serde(skip_serializing_if = "Option::is_none")]
111 pub test: Option<bool>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub return_url: Option<String>,
116
117 #[serde(skip_serializing)]
120 pub confirmation_url: Option<String>,
121
122 #[serde(skip_serializing)]
125 pub currency: Option<ChargeCurrency>,
126
127 #[serde(skip_serializing)]
130 pub created_at: Option<DateTime<Utc>>,
131
132 #[serde(skip_serializing)]
135 pub updated_at: Option<DateTime<Utc>>,
136}
137
138impl ApplicationCharge {
139 #[must_use]
149 pub fn is_active(&self) -> bool {
150 self.status.as_ref().map_or(false, ChargeStatus::is_active)
151 }
152
153 #[must_use]
163 pub fn is_pending(&self) -> bool {
164 self.status.as_ref().map_or(false, ChargeStatus::is_pending)
165 }
166
167 #[must_use]
180 pub fn is_test(&self) -> bool {
181 self.test.unwrap_or(false)
182 }
183}
184
185impl RestResource for ApplicationCharge {
186 type Id = u64;
187 type FindParams = ApplicationChargeFindParams;
188 type AllParams = ApplicationChargeListParams;
189 type CountParams = ();
190
191 const NAME: &'static str = "ApplicationCharge";
192 const PLURAL: &'static str = "application_charges";
193
194 const PATHS: &'static [ResourcePath] = &[
198 ResourcePath::new(
199 HttpMethod::Get,
200 ResourceOperation::Find,
201 &["id"],
202 "application_charges/{id}",
203 ),
204 ResourcePath::new(
205 HttpMethod::Get,
206 ResourceOperation::All,
207 &[],
208 "application_charges",
209 ),
210 ResourcePath::new(
211 HttpMethod::Post,
212 ResourceOperation::Create,
213 &[],
214 "application_charges",
215 ),
216 ];
218
219 fn get_id(&self) -> Option<Self::Id> {
220 self.id
221 }
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
226pub struct ApplicationChargeFindParams {
227 #[serde(skip_serializing_if = "Option::is_none")]
229 pub fields: Option<String>,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
234pub struct ApplicationChargeListParams {
235 #[serde(skip_serializing_if = "Option::is_none")]
237 pub limit: Option<u32>,
238
239 #[serde(skip_serializing_if = "Option::is_none")]
241 pub since_id: Option<u64>,
242
243 #[serde(skip_serializing_if = "Option::is_none")]
245 pub fields: Option<String>,
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251 use crate::rest::{get_path, ResourceOperation};
252
253 #[test]
254 fn test_application_charge_serialization() {
255 let charge = ApplicationCharge {
256 id: Some(12345),
257 name: Some("Pro Widget".to_string()),
258 price: Some("19.99".to_string()),
259 status: Some(ChargeStatus::Pending),
260 test: Some(true),
261 return_url: Some("https://myapp.com/callback".to_string()),
262 confirmation_url: Some("https://shop.myshopify.com/confirm".to_string()),
263 currency: Some(ChargeCurrency::new("USD")),
264 created_at: Some(
265 DateTime::parse_from_rfc3339("2024-01-15T10:30:00Z")
266 .unwrap()
267 .with_timezone(&Utc),
268 ),
269 updated_at: Some(
270 DateTime::parse_from_rfc3339("2024-01-15T10:35:00Z")
271 .unwrap()
272 .with_timezone(&Utc),
273 ),
274 };
275
276 let json = serde_json::to_string(&charge).unwrap();
277 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
278
279 assert_eq!(parsed["name"], "Pro Widget");
281 assert_eq!(parsed["price"], "19.99");
282 assert_eq!(parsed["test"], true);
283 assert_eq!(parsed["return_url"], "https://myapp.com/callback");
284
285 assert!(parsed.get("id").is_none());
287 assert!(parsed.get("status").is_none());
288 assert!(parsed.get("confirmation_url").is_none());
289 assert!(parsed.get("currency").is_none());
290 assert!(parsed.get("created_at").is_none());
291 assert!(parsed.get("updated_at").is_none());
292 }
293
294 #[test]
295 fn test_application_charge_deserialization() {
296 let json = r#"{
297 "id": 675931192,
298 "name": "Super Duper Expensive action",
299 "price": "100.00",
300 "status": "active",
301 "test": false,
302 "return_url": "https://super-duper.shopifyapps.com/",
303 "confirmation_url": "https://jsmith.myshopify.com/admin/charges/675931192/confirm_application_charge",
304 "currency": {
305 "currency": "USD"
306 },
307 "created_at": "2024-01-15T10:30:00Z",
308 "updated_at": "2024-01-15T10:35:00Z"
309 }"#;
310
311 let charge: ApplicationCharge = serde_json::from_str(json).unwrap();
312
313 assert_eq!(charge.id, Some(675931192));
314 assert_eq!(
315 charge.name,
316 Some("Super Duper Expensive action".to_string())
317 );
318 assert_eq!(charge.price, Some("100.00".to_string()));
319 assert_eq!(charge.status, Some(ChargeStatus::Active));
320 assert_eq!(charge.test, Some(false));
321 assert_eq!(
322 charge.return_url,
323 Some("https://super-duper.shopifyapps.com/".to_string())
324 );
325 assert!(charge.confirmation_url.is_some());
326 assert_eq!(charge.currency.as_ref().unwrap().code(), Some("USD"));
327 assert!(charge.created_at.is_some());
328 assert!(charge.updated_at.is_some());
329 }
330
331 #[test]
332 fn test_application_charge_convenience_methods() {
333 let active_charge = ApplicationCharge {
335 status: Some(ChargeStatus::Active),
336 ..Default::default()
337 };
338 assert!(active_charge.is_active());
339 assert!(!active_charge.is_pending());
340
341 let pending_charge = ApplicationCharge {
343 status: Some(ChargeStatus::Pending),
344 ..Default::default()
345 };
346 assert!(pending_charge.is_pending());
347 assert!(!pending_charge.is_active());
348
349 let test_charge = ApplicationCharge {
351 test: Some(true),
352 ..Default::default()
353 };
354 assert!(test_charge.is_test());
355
356 let non_test_charge = ApplicationCharge {
357 test: Some(false),
358 ..Default::default()
359 };
360 assert!(!non_test_charge.is_test());
361
362 let default_charge = ApplicationCharge::default();
364 assert!(!default_charge.is_test());
365 assert!(!default_charge.is_active());
366 assert!(!default_charge.is_pending());
367 }
368
369 #[test]
370 fn test_application_charge_paths() {
371 let find_path = get_path(
373 ApplicationCharge::PATHS,
374 ResourceOperation::Find,
375 &["id"],
376 );
377 assert!(find_path.is_some());
378 assert_eq!(find_path.unwrap().template, "application_charges/{id}");
379
380 let all_path = get_path(ApplicationCharge::PATHS, ResourceOperation::All, &[]);
382 assert!(all_path.is_some());
383 assert_eq!(all_path.unwrap().template, "application_charges");
384
385 let create_path = get_path(ApplicationCharge::PATHS, ResourceOperation::Create, &[]);
387 assert!(create_path.is_some());
388 assert_eq!(create_path.unwrap().template, "application_charges");
389 assert_eq!(create_path.unwrap().http_method, HttpMethod::Post);
390
391 let update_path = get_path(
393 ApplicationCharge::PATHS,
394 ResourceOperation::Update,
395 &["id"],
396 );
397 assert!(update_path.is_none());
398
399 let delete_path = get_path(
401 ApplicationCharge::PATHS,
402 ResourceOperation::Delete,
403 &["id"],
404 );
405 assert!(delete_path.is_none());
406
407 let count_path = get_path(ApplicationCharge::PATHS, ResourceOperation::Count, &[]);
409 assert!(count_path.is_none());
410 }
411
412 #[test]
413 fn test_application_charge_list_params() {
414 let params = ApplicationChargeListParams {
415 limit: Some(50),
416 since_id: Some(100),
417 fields: Some("id,name,price".to_string()),
418 };
419
420 let json = serde_json::to_value(¶ms).unwrap();
421 assert_eq!(json["limit"], 50);
422 assert_eq!(json["since_id"], 100);
423 assert_eq!(json["fields"], "id,name,price");
424
425 let empty_params = ApplicationChargeListParams::default();
427 let empty_json = serde_json::to_value(&empty_params).unwrap();
428 assert_eq!(empty_json, serde_json::json!({}));
429 }
430
431 #[test]
432 fn test_application_charge_constants() {
433 assert_eq!(ApplicationCharge::NAME, "ApplicationCharge");
434 assert_eq!(ApplicationCharge::PLURAL, "application_charges");
435 }
436
437 #[test]
438 fn test_application_charge_get_id() {
439 let charge_with_id = ApplicationCharge {
440 id: Some(12345),
441 ..Default::default()
442 };
443 assert_eq!(charge_with_id.get_id(), Some(12345));
444
445 let charge_without_id = ApplicationCharge::default();
446 assert_eq!(charge_without_id.get_id(), None);
447 }
448}