use crate::{
DEFAULT_ENDPOINT_FILTER,
client::OpenFIGIClient,
error::Result,
impl_filter_builder,
model::{
enums::{
Currency, ExchCode, MarketSecDesc, MicCode, OptionType, SecurityType, SecurityType2,
StateCode,
},
request::{FilterRequestBuilder, RequestFilters},
response::FilterData,
},
};
use chrono::NaiveDate;
use reqwest::Method;
pub struct SingleFilterRequestBuilder {
client: OpenFIGIClient,
request_builder: FilterRequestBuilder,
}
impl SingleFilterRequestBuilder {
#[must_use]
pub fn query(mut self, query: &str) -> Self {
self.request_builder = self.request_builder.query(query);
self
}
#[must_use]
pub fn start(mut self, start: &str) -> Self {
self.request_builder = self.request_builder.start(start);
self
}
pub fn filters_mut(&mut self) -> &mut RequestFilters {
self.request_builder.filters_mut()
}
impl_filter_builder!();
pub async fn send_raw(self) -> Result<reqwest::Response> {
let request = self.request_builder.build()?;
self.client
.request(DEFAULT_ENDPOINT_FILTER, Method::POST)
.body(&request)
.send()
.await
}
pub async fn send(self) -> Result<FilterData> {
let client = self.client.clone();
let raw_response = self.send_raw().await?;
client.parse_single_response(raw_response).await
}
}
impl OpenFIGIClient {
#[must_use]
pub fn filter(&self) -> SingleFilterRequestBuilder {
SingleFilterRequestBuilder {
client: self.clone(),
request_builder: FilterRequestBuilder::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::client::OpenFIGIClient;
fn create_test_client() -> OpenFIGIClient {
OpenFIGIClient::new()
}
#[test]
fn test_single_filter_request_builder_creation() {
let client = create_test_client();
let builder = client.filter().query("ibm");
assert_eq!(builder.client.base_url(), client.base_url());
assert_eq!(builder.client.has_api_key(), client.has_api_key());
let request_result = builder.request_builder.build();
assert!(
request_result.is_ok(),
"Builder should create a valid filter request"
);
let request = request_result.unwrap();
assert_eq!(request.query, Some("ibm".to_string()));
}
#[test]
fn test_single_filter_request_builder_chaining() {
let client = create_test_client();
let builder = client
.filter()
.query("ibm")
.exch_code(ExchCode::US)
.currency(Currency::USD)
.market_sec_des(MarketSecDesc::Equity)
.security_type(SecurityType::CommonStock)
.include_unlisted_equities(true);
let request = builder
.request_builder
.build()
.expect("Should build valid filter request");
assert_eq!(request.query, Some("ibm".to_string()));
assert_eq!(request.filters.exch_code, Some(ExchCode::US));
assert_eq!(request.filters.currency, Some(Currency::USD));
assert_eq!(request.filters.market_sec_des, Some(MarketSecDesc::Equity));
assert_eq!(
request.filters.security_type,
Some(SecurityType::CommonStock)
);
assert_eq!(request.filters.include_unlisted_equities, Some(true));
assert_eq!(builder.client.base_url(), client.base_url());
}
#[test]
fn test_single_filter_request_builder_option_fields() {
let client = create_test_client();
let builder = client
.filter()
.query("AAPL")
.option_type(OptionType::Call)
.strike([Some(150.0), Some(200.0)])
.contract_size([Some(100.0), None])
.coupon([None, Some(5.0)]);
let request = builder
.request_builder
.build()
.expect("Should build valid filter request");
assert_eq!(request.query, Some("AAPL".to_string()));
assert_eq!(request.filters.option_type, Some(OptionType::Call));
assert_eq!(request.filters.strike, Some([Some(150.0), Some(200.0)]));
assert_eq!(request.filters.contract_size, Some([Some(100.0), None]));
assert_eq!(request.filters.coupon, Some([None, Some(5.0)]));
assert_eq!(builder.client.base_url(), client.base_url());
}
#[test]
fn test_single_filter_request_builder_date_fields() {
let client = create_test_client();
let expiration_start = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
let expiration_end = NaiveDate::from_ymd_opt(2024, 12, 31).unwrap();
let maturity_start = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
let builder = client
.filter()
.query("ibm")
.expiration([Some(expiration_start), Some(expiration_end)])
.maturity([Some(maturity_start), None])
.state_code(StateCode::CA);
let request = builder
.request_builder
.build()
.expect("Should build valid filter request");
assert_eq!(request.query, Some("ibm".to_string()));
assert_eq!(
request.filters.expiration,
Some([Some(expiration_start), Some(expiration_end)])
);
assert_eq!(request.filters.maturity, Some([Some(maturity_start), None]));
assert_eq!(request.filters.state_code, Some(StateCode::CA));
assert_eq!(builder.client.base_url(), client.base_url());
}
}