use serde::{Deserialize, Serialize};
use crate::constants::{CommandId, IdentifierTypes};
use crate::environment::ApiEnvironment;
use crate::{Mpesa, MpesaError, MpesaResult};
#[derive(Debug, Serialize)]
struct AccountBalancePayload<'mpesa> {
#[serde(rename(serialize = "Initiator"))]
initiator: &'mpesa str,
#[serde(rename(serialize = "SecurityCredential"))]
security_credential: &'mpesa str,
#[serde(rename(serialize = "CommandID"))]
command_id: CommandId,
#[serde(rename(serialize = "PartyA"))]
party_a: &'mpesa str,
#[serde(rename(serialize = "IdentifierType"))]
identifier_type: &'mpesa str,
#[serde(rename(serialize = "Remarks"))]
remarks: &'mpesa str,
#[serde(rename(serialize = "QueueTimeOutURL"))]
queue_time_out_url: &'mpesa str,
#[serde(rename(serialize = "ResultURL"))]
result_url: &'mpesa str,
}
#[derive(Debug, Deserialize, Clone)]
pub struct AccountBalanceResponse {
#[serde(rename(deserialize = "ConversationID"))]
pub conversation_id: String,
#[serde(rename(deserialize = "OriginatorConversationID"))]
pub originator_conversation_id: String,
#[serde(rename(deserialize = "ResponseCode"))]
pub response_code: String,
#[serde(rename(deserialize = "ResponseDescription"))]
pub response_description: String,
}
#[derive(Debug)]
pub struct AccountBalanceBuilder<'mpesa, Env: ApiEnvironment> {
initiator_name: &'mpesa str,
client: &'mpesa Mpesa<Env>,
command_id: Option<CommandId>,
party_a: Option<&'mpesa str>,
identifier_type: Option<IdentifierTypes>,
remarks: Option<&'mpesa str>,
queue_timeout_url: Option<&'mpesa str>,
result_url: Option<&'mpesa str>,
}
impl<'mpesa, Env: ApiEnvironment> AccountBalanceBuilder<'mpesa, Env> {
pub fn new(
client: &'mpesa Mpesa<Env>,
initiator_name: &'mpesa str,
) -> AccountBalanceBuilder<'mpesa, Env> {
AccountBalanceBuilder {
initiator_name,
client,
command_id: None,
party_a: None,
identifier_type: None,
remarks: None,
queue_timeout_url: None,
result_url: None,
}
}
pub fn command_id(mut self, command_id: CommandId) -> AccountBalanceBuilder<'mpesa, Env> {
self.command_id = Some(command_id);
self
}
pub fn party_a(mut self, party_a: &'mpesa str) -> AccountBalanceBuilder<'mpesa, Env> {
self.party_a = Some(party_a);
self
}
pub fn identifier_type(
mut self,
identifier_type: IdentifierTypes,
) -> AccountBalanceBuilder<'mpesa, Env> {
self.identifier_type = Some(identifier_type);
self
}
pub fn remarks(mut self, remarks: &'mpesa str) -> AccountBalanceBuilder<'mpesa, Env> {
self.remarks = Some(remarks);
self
}
pub fn timeout_url(mut self, timeout_url: &'mpesa str) -> AccountBalanceBuilder<'mpesa, Env> {
self.queue_timeout_url = Some(timeout_url);
self
}
pub fn result_url(mut self, result_url: &'mpesa str) -> AccountBalanceBuilder<'mpesa, Env> {
self.result_url = Some(result_url);
self
}
#[deprecated]
pub fn urls(
mut self,
timeout_url: &'mpesa str,
result_url: &'mpesa str,
) -> AccountBalanceBuilder<'mpesa, Env> {
self.queue_timeout_url = Some(timeout_url);
self.result_url = Some(result_url);
self
}
#[allow(clippy::unnecessary_lazy_evaluations)]
pub async fn send(self) -> MpesaResult<AccountBalanceResponse> {
let url = format!(
"{}/mpesa/accountbalance/v1/query",
self.client.environment.base_url()
);
let credentials = self.client.gen_security_credentials()?;
let payload = AccountBalancePayload {
command_id: self.command_id.unwrap_or_else(|| CommandId::AccountBalance),
party_a: self
.party_a
.ok_or(MpesaError::Message("party_a is required"))?,
identifier_type: &self
.identifier_type
.unwrap_or_else(|| IdentifierTypes::ShortCode)
.to_string(),
remarks: self.remarks.unwrap_or_else(|| stringify!(None)),
initiator: self.initiator_name,
queue_time_out_url: self
.queue_timeout_url
.ok_or(MpesaError::Message("queue_timeout_url is required"))?,
result_url: self
.result_url
.ok_or(MpesaError::Message("result_url is required"))?,
security_credential: &credentials,
};
let response = self
.client
.http_client
.post(&url)
.bearer_auth(self.client.auth().await?)
.json(&payload)
.send()
.await?;
if response.status().is_success() {
let value = response.json::<_>().await?;
return Ok(value);
}
let value = response.json().await?;
Err(MpesaError::AccountBalanceError(value))
}
}