use serde::Deserialize;
use crate::api::ApiClient;
use crate::deserialize::{from_none_str, from_str};
use crate::error::{detect_common_helper_error, Error, Result};
#[derive(Debug, Deserialize, Clone, Default)]
pub struct Annual {
#[serde(rename = "fiscalDateEnding")]
fiscal_date_ending: String,
#[serde(rename = "reportedEPS", deserialize_with = "from_str")]
reported_eps: f64,
}
impl Annual {
#[must_use]
pub fn fiscal_date_ending(&self) -> &str {
&self.fiscal_date_ending
}
#[must_use]
pub fn reported_eps(&self) -> f64 {
self.reported_eps
}
}
#[derive(Debug, Deserialize, Clone, Default)]
pub struct Quarterly {
#[serde(rename = "fiscalDateEnding")]
fiscal_date_ending: String,
#[serde(rename = "reportedDate")]
reported_date: String,
#[serde(rename = "reportedEPS", deserialize_with = "from_none_str")]
reported_eps: Option<f64>,
#[serde(rename = "estimatedEPS", deserialize_with = "from_str")]
estimated_eps: f64,
#[serde(rename = "surprise", deserialize_with = "from_none_str")]
surprise: Option<f64>,
#[serde(rename = "surprisePercentage", deserialize_with = "from_none_str")]
surprise_percentage: Option<f64>,
}
impl Quarterly {
#[must_use]
pub fn fiscal_date_ending(&self) -> &str {
&self.fiscal_date_ending
}
#[must_use]
pub fn reported_date(&self) -> &str {
&self.reported_date
}
#[must_use]
pub fn reported_eps(&self) -> Option<f64> {
self.reported_eps
}
#[must_use]
pub fn estimated_eps(&self) -> f64 {
self.estimated_eps
}
#[must_use]
pub fn surprise(&self) -> Option<f64> {
self.surprise
}
#[must_use]
pub fn surprise_percentage(&self) -> Option<f64> {
self.surprise_percentage
}
}
#[derive(Debug, Default)]
pub struct Earning {
symbol: String,
annual_earning: Vec<Annual>,
quarterly_earning: Vec<Quarterly>,
}
impl Earning {
#[must_use]
pub fn symbol(&self) -> &str {
&self.symbol
}
#[must_use]
pub fn annual_earning(&self) -> &Vec<Annual> {
&self.annual_earning
}
#[must_use]
pub fn quarterly_earning(&self) -> &Vec<Quarterly> {
&self.quarterly_earning
}
}
#[derive(Debug, Deserialize)]
pub(crate) struct EarningHelper {
#[serde(rename = "Information")]
information: Option<String>,
#[serde(rename = "Error Message")]
error_message: Option<String>,
#[serde(rename = "Note")]
note: Option<String>,
#[serde(rename = "symbol")]
symbol: Option<String>,
#[serde(rename = "annualEarnings")]
annual_earning: Option<Vec<Annual>>,
#[serde(rename = "quarterlyEarnings")]
quarterly_earning: Option<Vec<Quarterly>>,
}
impl EarningHelper {
pub(crate) fn convert(self) -> Result<Earning> {
let mut earning = Earning::default();
detect_common_helper_error(self.information, self.error_message, self.note)?;
if self.symbol.is_none()
|| self.annual_earning.is_none()
|| self.quarterly_earning.is_none()
{
return Err(Error::EmptyResponse);
}
earning.symbol = self.symbol.unwrap();
earning.annual_earning = self.annual_earning.unwrap();
earning.quarterly_earning = self.quarterly_earning.unwrap();
Ok(earning)
}
}
pub struct EarningBuilder<'a> {
api_client: &'a ApiClient,
symbol: &'a str,
}
impl<'a> EarningBuilder<'a> {
#[must_use]
pub fn new(api_client: &'a ApiClient, symbol: &'a str) -> Self {
Self { api_client, symbol }
}
fn create_url(&self) -> String {
format!("query?function=EARNINGS&symbol={}", self.symbol)
}
pub async fn json(&self) -> Result<Earning> {
let url = self.create_url();
let earning_helper: EarningHelper = self.api_client.get_json(&url).await?;
earning_helper.convert()
}
}