use super::{FilingsProvider, Operation, Provider, ProviderAdapter, ProviderCore};
use crate::error::Result;
use crate::models::filings::CongressionalTrade;
pub(crate) struct CongressTradesProvider;
impl ProviderCore for CongressTradesProvider {
fn id(&self) -> Provider {
Provider::CongressTrades
}
}
#[cfg(all(feature = "housetrades", feature = "senatetrades"))]
fn merge_sources(
house: Result<Vec<CongressionalTrade>>,
senate: Result<Vec<CongressionalTrade>>,
) -> Result<Vec<CongressionalTrade>> {
let mut trades = Vec::new();
let mut last_err = None;
for result in [house, senate] {
match result {
Ok(mut rows) => trades.append(&mut rows),
Err(e) => {
tracing::warn!("congressional trades source unavailable: {e}");
last_err = Some(e);
}
}
}
if trades.is_empty()
&& let Some(e) = last_err
{
return Err(e);
}
trades.sort_by(|a, b| b.transaction_date.cmp(&a.transaction_date));
Ok(trades)
}
#[async_trait::async_trait]
impl FilingsProvider for CongressTradesProvider {
async fn fetch_filings(
&self,
_symbol: &str,
) -> Result<crate::models::filings::ProviderFilings> {
Err(self.not_supported(Operation::Filings))
}
async fn fetch_congressional_trades(&self, symbol: &str) -> Result<Vec<CongressionalTrade>> {
#[cfg(all(feature = "housetrades", feature = "senatetrades"))]
{
let (house, senate) = tokio::join!(
crate::adapters::housetrades::fetch_congressional_trades_response(symbol),
crate::adapters::senatetrades::fetch_congressional_trades_response(symbol),
);
return merge_sources(house, senate);
}
#[cfg(all(feature = "housetrades", not(feature = "senatetrades")))]
{
return crate::adapters::housetrades::fetch_congressional_trades_response(symbol).await;
}
#[cfg(all(feature = "senatetrades", not(feature = "housetrades")))]
{
return crate::adapters::senatetrades::fetch_congressional_trades_response(symbol)
.await;
}
}
}
#[async_trait::async_trait]
impl ProviderAdapter for CongressTradesProvider {
fn as_filings(&self) -> Option<&dyn FilingsProvider> {
Some(self)
}
}