use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
#[cfg_attr(feature = "js", napi_derive::napi(object))]
pub struct CapitalChangesResponse {
#[serde(rename = "type")]
pub data_type: String,
pub exchange: String,
pub market: String,
pub data: Vec<CapitalChange>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
#[cfg_attr(feature = "js", napi_derive::napi(object))]
pub struct CapitalChange {
pub symbol: String,
pub name: Option<String>,
pub date: String,
#[serde(rename = "previousCapital")]
pub previous_capital: Option<f64>,
#[serde(rename = "currentCapital")]
pub current_capital: Option<f64>,
#[serde(rename = "changeType")]
pub change_type: Option<String>,
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
#[cfg_attr(feature = "js", napi_derive::napi(object))]
pub struct DividendsResponse {
#[serde(rename = "type")]
pub data_type: String,
pub exchange: String,
pub market: String,
pub data: Vec<Dividend>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
#[cfg_attr(feature = "js", napi_derive::napi(object))]
pub struct Dividend {
pub symbol: String,
pub name: Option<String>,
#[serde(rename = "exDividendDate")]
pub ex_dividend_date: Option<String>,
#[serde(rename = "paymentDate")]
pub payment_date: Option<String>,
#[serde(rename = "cashDividend")]
pub cash_dividend: Option<f64>,
#[serde(rename = "stockDividend")]
pub stock_dividend: Option<f64>,
#[serde(rename = "dividendYear")]
pub dividend_year: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
#[cfg_attr(feature = "js", napi_derive::napi(object))]
pub struct ListingApplicantsResponse {
#[serde(rename = "type")]
pub data_type: String,
pub exchange: String,
pub market: String,
pub data: Vec<ListingApplicant>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
#[cfg_attr(feature = "js", napi_derive::napi(object))]
pub struct ListingApplicant {
pub symbol: String,
pub name: Option<String>,
#[serde(rename = "applicationDate")]
pub application_date: Option<String>,
#[serde(rename = "listingDate")]
pub listing_date: Option<String>,
pub status: Option<String>,
pub industry: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_capital_changes_response_deserialization() {
let json = r#"{
"type": "CAPITAL_CHANGES",
"exchange": "TWSE",
"market": "TSE",
"data": [
{
"symbol": "2330",
"name": "TSMC",
"date": "2024-01-15",
"previousCapital": 259303804580.0,
"currentCapital": 259303804580.0,
"changeType": "increase",
"reason": "Cash capital increase"
}
]
}"#;
let response: CapitalChangesResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data_type, "CAPITAL_CHANGES");
assert_eq!(response.exchange, "TWSE");
assert_eq!(response.market, "TSE");
assert_eq!(response.data.len(), 1);
assert_eq!(response.data[0].symbol, "2330");
assert_eq!(response.data[0].name.as_deref(), Some("TSMC"));
assert_eq!(response.data[0].date, "2024-01-15");
assert_eq!(response.data[0].change_type.as_deref(), Some("increase"));
}
#[test]
fn test_dividends_response_deserialization() {
let json = r#"{
"type": "DIVIDENDS",
"exchange": "TWSE",
"market": "TSE",
"data": [
{
"symbol": "2330",
"name": "TSMC",
"exDividendDate": "2024-06-15",
"paymentDate": "2024-07-15",
"cashDividend": 3.0,
"stockDividend": 0.0,
"dividendYear": "2023"
}
]
}"#;
let response: DividendsResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data_type, "DIVIDENDS");
assert_eq!(response.exchange, "TWSE");
assert_eq!(response.data.len(), 1);
assert_eq!(response.data[0].symbol, "2330");
assert_eq!(response.data[0].cash_dividend, Some(3.0));
assert_eq!(response.data[0].stock_dividend, Some(0.0));
assert_eq!(response.data[0].ex_dividend_date.as_deref(), Some("2024-06-15"));
}
#[test]
fn test_listing_applicants_response_deserialization() {
let json = r#"{
"type": "LISTING_APPLICANTS",
"exchange": "TWSE",
"market": "TSE",
"data": [
{
"symbol": "6XXX",
"name": "New Tech Corp",
"applicationDate": "2024-01-01",
"listingDate": "2024-03-15",
"status": "approved",
"industry": "Technology"
}
]
}"#;
let response: ListingApplicantsResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data_type, "LISTING_APPLICANTS");
assert_eq!(response.exchange, "TWSE");
assert_eq!(response.data.len(), 1);
assert_eq!(response.data[0].symbol, "6XXX");
assert_eq!(response.data[0].name.as_deref(), Some("New Tech Corp"));
assert_eq!(response.data[0].status.as_deref(), Some("approved"));
assert_eq!(response.data[0].industry.as_deref(), Some("Technology"));
}
#[test]
fn test_capital_changes_minimal() {
let json = r#"{
"type": "CAPITAL_CHANGES",
"exchange": "TWSE",
"market": "TSE",
"data": [{"symbol": "2330", "date": "2024-01-15"}]
}"#;
let response: CapitalChangesResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data[0].symbol, "2330");
assert!(response.data[0].name.is_none());
assert!(response.data[0].previous_capital.is_none());
}
#[test]
fn test_dividends_minimal() {
let json = r#"{
"type": "DIVIDENDS",
"exchange": "TWSE",
"market": "TSE",
"data": [{"symbol": "2330"}]
}"#;
let response: DividendsResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data[0].symbol, "2330");
assert!(response.data[0].cash_dividend.is_none());
assert!(response.data[0].ex_dividend_date.is_none());
}
#[test]
fn test_listing_applicants_minimal() {
let json = r#"{
"type": "LISTING_APPLICANTS",
"exchange": "TWSE",
"market": "TSE",
"data": [{"symbol": "6XXX"}]
}"#;
let response: ListingApplicantsResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data[0].symbol, "6XXX");
assert!(response.data[0].name.is_none());
assert!(response.data[0].status.is_none());
}
}