Skip to main content

concur_api/api/
purchase_request.rs

1//! SAP Concur Purchase Request API v4.
2//!
3//! Endpoints: `purchaserequest/v4/...`
4
5use crate::client::ConcurClient;
6use crate::error::Result;
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9
10/// Purchase Request API.
11pub struct PurchaseRequestApi<'a> {
12    client: &'a ConcurClient,
13}
14
15impl<'a> PurchaseRequestApi<'a> {
16    pub fn new(client: &'a ConcurClient) -> Self {
17        Self { client }
18    }
19
20    /// Create a purchase request.
21    pub async fn create(&self, request: &CreatePurchaseRequest) -> Result<CreatePurchaseResponse> {
22        let req = self
23            .client
24            .request(Method::POST, "/purchaserequest/v4/purchaserequests")
25            .await?;
26        let req = ConcurClient::with_json(req, request)?;
27        self.client.execute(req).await
28    }
29
30    /// Get purchase request details.
31    pub async fn get(&self, purchase_request_id: &str) -> Result<PurchaseRequest> {
32        self.client
33            .request(
34                Method::GET,
35                &format!(
36                    "/purchaserequest/v4/purchaserequests/{}",
37                    purchase_request_id
38                ),
39            )
40            .await?
41            .send()
42            .await?
43            .json()
44            .await
45            .map_err(Into::into)
46    }
47}
48
49#[derive(Debug, Clone, Default, Serialize, Deserialize)]
50pub struct CreatePurchaseRequest {
51    #[serde(rename = "userId")]
52    pub user_id: Option<String>,
53    #[serde(rename = "userEmail")]
54    pub user_email: Option<String>,
55    #[serde(rename = "userLoginId")]
56    pub user_login_id: Option<String>,
57    pub description: Option<String>,
58    #[serde(rename = "policyId")]
59    pub policy_id: Option<String>,
60    pub currency: Option<String>,
61    #[serde(rename = "notesToSupplier")]
62    pub notes_to_supplier: Option<String>,
63    pub comments: Option<String>,
64    #[serde(rename = "custom1", skip_serializing_if = "Option::is_none")]
65    pub custom1: Option<String>,
66    #[serde(rename = "custom2", skip_serializing_if = "Option::is_none")]
67    pub custom2: Option<String>,
68    #[serde(rename = "custom3", skip_serializing_if = "Option::is_none")]
69    pub custom3: Option<String>,
70    #[serde(rename = "custom4", skip_serializing_if = "Option::is_none")]
71    pub custom4: Option<String>,
72    #[serde(rename = "custom5", skip_serializing_if = "Option::is_none")]
73    pub custom5: Option<String>,
74    #[serde(rename = "custom6", skip_serializing_if = "Option::is_none")]
75    pub custom6: Option<String>,
76    #[serde(rename = "custom7", skip_serializing_if = "Option::is_none")]
77    pub custom7: Option<String>,
78    #[serde(rename = "custom8", skip_serializing_if = "Option::is_none")]
79    pub custom8: Option<String>,
80    #[serde(rename = "custom9", skip_serializing_if = "Option::is_none")]
81    pub custom9: Option<String>,
82    #[serde(rename = "custom10", skip_serializing_if = "Option::is_none")]
83    pub custom10: Option<String>,
84    #[serde(rename = "custom11", skip_serializing_if = "Option::is_none")]
85    pub custom11: Option<String>,
86    #[serde(rename = "custom12", skip_serializing_if = "Option::is_none")]
87    pub custom12: Option<String>,
88    #[serde(rename = "custom13", skip_serializing_if = "Option::is_none")]
89    pub custom13: Option<String>,
90    #[serde(rename = "custom14", skip_serializing_if = "Option::is_none")]
91    pub custom14: Option<String>,
92    #[serde(rename = "custom15", skip_serializing_if = "Option::is_none")]
93    pub custom15: Option<String>,
94    #[serde(rename = "custom16", skip_serializing_if = "Option::is_none")]
95    pub custom16: Option<String>,
96    #[serde(rename = "custom17", skip_serializing_if = "Option::is_none")]
97    pub custom17: Option<String>,
98    #[serde(rename = "custom18", skip_serializing_if = "Option::is_none")]
99    pub custom18: Option<String>,
100    #[serde(rename = "custom19", skip_serializing_if = "Option::is_none")]
101    pub custom19: Option<String>,
102    #[serde(rename = "custom20", skip_serializing_if = "Option::is_none")]
103    pub custom20: Option<String>,
104    #[serde(rename = "lineItems")]
105    pub line_items: Vec<PurchaseRequestLineItem>,
106}
107
108#[derive(Debug, Clone, Default, Serialize, Deserialize)]
109pub struct PurchaseRequestLineItem {
110    #[serde(rename = "expenseTypeId")]
111    pub expense_type_id: Option<String>,
112    pub description: Option<String>,
113    pub quantity: Option<f64>,
114    #[serde(rename = "unitPrice")]
115    pub unit_price: Option<f64>,
116    pub currency: Option<String>,
117    #[serde(rename = "vendorCode")]
118    pub vendor_code: Option<String>,
119    #[serde(rename = "vendorAddressCode")]
120    pub vendor_address_code: Option<String>,
121    #[serde(rename = "shipToAddressCode")]
122    pub ship_to_address_code: Option<String>,
123}
124
125#[derive(Debug, Clone, Deserialize)]
126pub struct CreatePurchaseResponse {
127    pub id: String,
128    pub uri: String,
129}
130
131#[derive(Debug, Clone, Deserialize)]
132pub struct PurchaseRequest {
133    pub id: String,
134    #[serde(rename = "purchaseRequestNumber")]
135    pub purchase_request_number: Option<String>,
136    #[serde(rename = "purchaseOrderNumber")]
137    pub purchase_order_number: Option<String>,
138    #[serde(rename = "workflowStatus")]
139    pub workflow_status: Option<String>,
140    pub exceptions: Option<Vec<serde_json::Value>>,
141}