use super::urls::api;
use crate::client::YahooClient;
use crate::client::{API_PARAM_MERGE, API_PARAM_PAD_TIMESERIES};
use crate::constants::{Frequency, StatementType};
use crate::error::Result;
use crate::models::financials::FinancialStatement;
use tracing::info;
pub async fn fetch(
client: &YahooClient,
symbol: &str,
statement_type: StatementType,
frequency: Frequency,
) -> Result<FinancialStatement> {
super::common::validate_symbol(symbol)?;
info!(
"Fetching {} {} financials for: {}",
frequency.as_str(),
statement_type.as_str(),
symbol
);
let fields = statement_type.get_fields();
let types: Vec<String> = fields.iter().map(|&f| frequency.prefix(f)).collect();
let types_str = types.join(",");
let url = api::financials(symbol);
let config = client.config();
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs() as i64;
let period1 = now - (10 * 365 * 24 * 60 * 60);
let params = [
("merge", API_PARAM_MERGE),
("padTimeSeries", API_PARAM_PAD_TIMESERIES),
("period1", &period1.to_string()),
("period2", &now.to_string()),
("type", types_str.as_str()),
("lang", config.lang.as_str()),
("region", config.region.as_str()),
];
let response = client.request_with_params(&url, ¶ms).await?;
let json: serde_json::Value = response.json().await?;
FinancialStatement::from_response(&json, symbol, statement_type, frequency)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::client::ClientConfig;
#[tokio::test]
#[ignore] async fn test_fetch_financials() {
let client = YahooClient::new(ClientConfig::default()).await.unwrap();
let result = fetch(&client, "AAPL", StatementType::Income, Frequency::Annual).await;
assert!(result.is_ok());
let statement = result.unwrap();
assert_eq!(statement.symbol, "AAPL");
assert!(statement.statement.contains_key("TotalRevenue"));
}
}