op_api_sdk/apis/accounts.rs
1//! Client and structures for OP
2//! [AccountsV3](https://op-developer.fi/docs/api/3Oo5zCujXGw2SGEi00skug/OP%20Accounts%20V3.0%20API)
3//! API
4
5use crate::options::Options;
6use crate::requests::Requests;
7use chrono::{DateTime, Utc};
8use log::debug;
9use serde::{Deserialize, Serialize};
10use std::error::Error;
11
12/// Link inside the results of Accounts API.
13#[derive(Deserialize, Debug)]
14pub struct Link {
15 pub href: String,
16}
17
18/// Describes a single Account in response.
19#[derive(Deserialize, Debug)]
20pub struct Account {
21 /// A surrogate identifier for the bank account.
22 #[serde(rename = "accountId")]
23 pub account_id: String,
24 /// Account name. This is a name assigned by the servicer and bears no significance to the
25 /// user.
26 pub name: String,
27 /// Nickname of the account, if assigned by the owner of the account.
28 pub nickname: Option<String>,
29 /// Current balance of the account. Note: This field will only be returned after the end user
30 /// has provided consent to the consuming application.
31 pub balance: Option<f64>,
32 /// Code of the currency of the account. All currency codes are ISO 4217-compliant strings.
33 pub currency: String,
34 /// "IBAN".
35 #[serde(rename = "identifierScheme")]
36 pub identifier_scheme: String,
37 /// Account identifier. Follows the scheme described by the field identifierScheme.
38 pub identifier: String,
39 /// Identifier of the scheme used for identifying the servicer.
40 #[serde(rename = "servicerScheme")]
41 pub servicer_scheme: String,
42 /// Identifier of the servicing bank. Follows the scheme described by the servicerScheme
43 /// parameter.
44 #[serde(rename = "servicerIdentifier")]
45 pub servicer_identifier: String,
46}
47
48/// Describes a list of Accounts in accounts response.
49#[derive(Deserialize, Debug)]
50pub struct AccountList {
51 pub accounts: Vec<Account>,
52}
53
54/// Optional parameters to fetch transactions.
55#[derive(Serialize, Debug, Default)]
56pub struct TransactionParams {
57 /// ISO 8601-compatible date-time string representing the earliest date-time from which
58 /// transactions will be queried. Timezone must not be set. Set time to to 00:00:00 for
59 /// Date-only queries.
60 #[serde(rename = "fromBookingDateTime")]
61 pub from_booking_datetime: Option<DateTime<Utc>>,
62 /// ISO 8601-compatible date-time string representing the latest date-time up to which
63 /// transactions will be queried. Timezone must not be set. Set time to 00:00:00 for Date-only
64 /// queries.
65 #[serde(rename = "toBookingDateTime")]
66 pub to_booking_datetime: Option<DateTime<Utc>>,
67 /// Number of transactions to be returned per each page.
68 #[serde(rename = "pageSize")]
69 pub page_size: Option<u32>,
70 /// Paging token used to retrieve the next page of data. Tokens are available in the links
71 /// located in the _links object.
72 #[serde(rename = "forwardPagingToken")]
73 pub forward_paging_token: Option<String>,
74}
75
76/// Implementation of the TransactionParams.
77impl TransactionParams {
78 /// Sets fromBookingDateTime parameter.
79 pub fn with_from_booking_datetime(mut self, datetime: DateTime<Utc>) -> Self {
80 self.from_booking_datetime = Some(datetime);
81 self
82 }
83
84 /// Sets toBookingDateTime parameter.
85 pub fn with_to_booking_datetime(mut self, datetime: DateTime<Utc>) -> Self {
86 self.to_booking_datetime = Some(datetime);
87 self
88 }
89
90 /// Sets pageSize parameter.
91 pub fn with_page_size(mut self, page_size: u32) -> Self {
92 self.page_size = Some(page_size);
93 self
94 }
95
96 /// Sets forwardPagingToken parameter.
97 pub fn with_forward_paging_token(mut self, token: String) -> Self {
98 self.forward_paging_token = Some(token);
99 self
100 }
101}
102
103/// Describes a single party in Transaction.
104#[derive(Deserialize, Debug)]
105pub struct TransactionParty {
106 /// Account identifier schema.
107 #[serde(rename = "accountIdentifierType")]
108 pub account_identifier_type: String,
109 /// Name of the account.
110 #[serde(rename = "accountName")]
111 pub account_name: String,
112 /// Identifier of the party's bank account.
113 #[serde(rename = "accountIdentifier")]
114 pub account_identifier: String,
115 /// A code identifying the party's servicer.
116 #[serde(rename = "servicerIdentifier")]
117 pub servicer_identifier: String,
118 /// Type of the servicerIdentifier, i.e. the scheme of the servicer ID.
119 #[serde(rename = "servicerIdentifierType")]
120 pub servicer_identifier_type: String,
121}
122
123/// Describes a single Transaction for Account in transactions response.
124#[derive(Deserialize, Debug)]
125pub struct Transaction {
126 /// Surrogate identifier for the transaction.
127 #[serde(rename = "transactionId")]
128 pub transaction_id: String,
129 /// Surrogate identifier for the account.
130 #[serde(rename = "accountId")]
131 pub account_id: String,
132 /// Archive ID of the transaction.
133 #[serde(rename = "archiveId")]
134 pub archive_id: Option<String>,
135 /// Reference number used in the transaction.
136 pub reference: Option<String>,
137 /// A message sent with the transaction. Created by the payer and comprises free-form text.
138 pub message: Option<String>,
139 /// Amount transferred in the transaction. The value is a string decimal. Debit transactions
140 /// are marked with a minus sign.
141 pub amount: String,
142 /// Currency of the transaction.
143 pub currency: String,
144 /// Enum(debit, credit)
145 /// Describes whether the transaction is a debit of credit transaction.
146 #[serde(rename = "creditDebitIndicator")]
147 pub credit_debit_indicator: String,
148 /// Balance of the account after the transaction.
149 #[serde(rename = "accountBalance")]
150 pub account_balance: String,
151 /// Account information of the creditor. The response body will only contain this field if the
152 /// transaction is of type debit, i.e. the counterparty in the transaction is the creditor.
153 pub creditor: Option<TransactionParty>,
154 /// Account information of the debtor. The response body will only contain this field if the
155 /// transaction is of type credit, i.e. the counterparty in the transaction is the debtor.
156 pub debtor: Option<TransactionParty>,
157 /// Date and time the transaction was entered into book-keeping. ISO 8601-formatted date-time string.
158 #[serde(rename = "bookingDateTime")]
159 pub booking_datetime: DateTime<Utc>,
160 /// The date and time when amount of the transaction was counted towards the balance of the
161 /// account. ISO 8601-formatted date-time string.
162 #[serde(rename = "valueDateTime")]
163 pub value_datetaime: DateTime<Utc>,
164 /// Enum(Authorised, AwaitingAuthorisation, Rejected, Revoked)
165 /// Current status of the transaction.
166 pub status: Option<String>,
167 /// ISO 20022-compliant transaction code for the transaction.
168 #[serde(rename = "isoTransactionCode")]
169 pub iso_transaction_code: Option<String>,
170 /// OP-specific transaction code for the transaction.
171 #[serde(rename = "opTransactionCode")]
172 pub op_transaction_code: Option<String>,
173}
174
175/// Describes links in the Transactions object in transactions response.
176#[derive(Deserialize, Debug)]
177pub struct TransactionListLinks {
178 pub next: Option<Link>,
179}
180
181/// Describes a list of Transactions in transactions response.
182#[derive(Deserialize, Debug)]
183pub struct TransactionList {
184 pub transactions: Vec<Transaction>,
185 #[serde(rename = "_links")]
186 pub links: TransactionListLinks,
187}
188
189/// Accounts client.
190///
191/// This client is used to access the OP AccountsV3 API.
192pub struct Accounts {
193 options: Options,
194}
195
196impl Accounts {
197 /// Creates new Accounts client.
198 ///
199 /// Bear in mind that this API is implemented to follow v3 so you must
200 /// specify v3 as version for the Options.
201 pub fn new(options: Options) -> Accounts {
202 Accounts { options }
203 }
204
205 /// Gets all accounts from the API and returns list of them.
206 pub async fn accounts(&self) -> Result<AccountList, Box<dyn Error>> {
207 let url = format!("/accounts/{}/accounts", self.options.version());
208 let response = Requests::get(&self.options, &url, None::<()>).await?;
209 debug!("Accounts response: {:#?}", response);
210 let accounts: AccountList = response.json().await?;
211 Ok(accounts)
212 }
213
214 /// Gets single account from the API based on accountId.
215 pub async fn account(&self, account_id: String) -> Result<Account, Box<dyn Error>> {
216 let url = format!(
217 "/accounts/{}/accounts/{}",
218 self.options.version(),
219 account_id
220 );
221 let response = Requests::get(&self.options, &url, None::<()>).await?;
222 debug!("Account response: {:#?}", response);
223 let account: Account = response.json().await?;
224 Ok(account)
225 }
226
227 /// Gets all transactions for a single account with account id
228 /// with optional parameters for filtering the results.
229 pub async fn transactions(
230 &self,
231 account_id: String,
232 params: Option<TransactionParams>,
233 ) -> Result<TransactionList, Box<dyn Error>> {
234 let url = format!(
235 "/accounts/{}/accounts/{}/transactions",
236 self.options.version(),
237 account_id
238 );
239 let response = Requests::get(&self.options, &url, params).await?;
240 debug!("Transactions response: {:#?}", response);
241 let list: TransactionList = response.json().await?;
242 Ok(list)
243 }
244}