use crate::models::format::{Both, Format};
use finance_query_derive::FormatConvert;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, FormatConvert)]
#[serde(rename_all = "camelCase", bound = "")]
pub struct FinancialData<F: Format = Both> {
#[serde(skip_serializing_if = "Option::is_none")]
pub current_price: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_ratio: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub debt_to_equity: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub earnings_growth: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ebitda: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ebitda_margins: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub financial_currency: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub free_cashflow: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gross_margins: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gross_profits: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_age: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub number_of_analyst_opinions: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operating_cashflow: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operating_margins: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub profit_margins: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quick_ratio: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recommendation_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recommendation_mean: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub return_on_assets: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub return_on_equity: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub revenue_growth: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub revenue_per_share: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_high_price: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_low_price: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_mean_price: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_median_price: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_cash: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_cash_per_share: Option<F::Value<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_debt: Option<F::Value<i64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_revenue: Option<F::Value<i64>>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_financial_data() {
let json = r#"{
"currentPrice": {
"fmt": "276.97",
"raw": 276.97
},
"ebitda": {
"fmt": "144.75B",
"longFmt": "144,748,003,328",
"raw": 144748003328
},
"financialCurrency": "USD",
"recommendationKey": "buy"
}"#;
let data: FinancialData = serde_json::from_str(json).unwrap();
assert_eq!(
data.current_price.as_ref().map(|v| v.raw),
Some(Some(276.97))
);
assert_eq!(
data.ebitda.as_ref().map(|v| v.raw),
Some(Some(144748003328))
);
assert_eq!(data.financial_currency.as_deref(), Some("USD"));
assert_eq!(data.recommendation_key.as_deref(), Some("buy"));
}
#[test]
fn test_into_raw() {
let json = r#"{
"currentPrice": {"fmt": "276.97", "raw": 276.97},
"financialCurrency": "USD",
"recommendationKey": "buy"
}"#;
let data: FinancialData = serde_json::from_str(json).unwrap();
let raw = data.into_raw();
assert_eq!(raw.current_price, Some(276.97));
assert_eq!(raw.financial_currency.as_deref(), Some("USD"));
assert_eq!(raw.recommendation_key.as_deref(), Some("buy"));
}
#[test]
fn test_into_pretty() {
let json = r#"{
"currentPrice": {"fmt": "276.97", "raw": 276.97},
"ebitda": {"fmt": "144.75B", "longFmt": "144,748,003,328", "raw": 144748003328}
}"#;
let data: FinancialData = serde_json::from_str(json).unwrap();
let pretty = data.into_pretty();
assert_eq!(pretty.current_price.as_deref(), Some("276.97"));
assert_eq!(pretty.ebitda.as_deref(), Some("144.75B"));
}
}