finance_query_core/models/
financials.rs1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
5#[serde(rename_all = "snake_case")]
6pub enum StatementType {
7 #[serde(rename = "income")]
8 IncomeStatement,
9 #[serde(rename = "balance")]
10 BalanceSheet,
11 #[serde(rename = "cashflow")]
12 CashFlow,
13}
14
15impl StatementType {
16 #[allow(dead_code)]
17 pub fn as_str(&self) -> &'static str {
18 match self {
19 StatementType::IncomeStatement => "income",
20 StatementType::BalanceSheet => "balance",
21 StatementType::CashFlow => "cashflow",
22 }
23 }
24}
25
26#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
27#[serde(rename_all = "snake_case")]
28pub enum Frequency {
29 #[serde(rename = "annual")]
30 Annual,
31 #[serde(rename = "quarterly")]
32 Quarterly,
33}
34
35impl Frequency {
36 pub fn as_str(&self) -> &'static str {
37 match self {
38 Frequency::Annual => "annual",
39 Frequency::Quarterly => "quarterly",
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub struct FinancialStatement {
47 pub symbol: String,
48 pub statement_type: String,
49 pub frequency: String,
50 #[serde(rename = "statement")]
51 pub statement: HashMap<String, HashMap<String, serde_json::Value>>,
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use proptest::prelude::*;
58
59 proptest! {
62 #![proptest_config(ProptestConfig::with_cases(100))]
63
64 #[test]
65 fn statement_type_roundtrip(st in prop_oneof![
66 Just(StatementType::IncomeStatement),
67 Just(StatementType::BalanceSheet),
68 Just(StatementType::CashFlow),
69 ]) {
70 let json = serde_json::to_string(&st).unwrap();
71 let parsed: StatementType = serde_json::from_str(&json).unwrap();
72
73 prop_assert_eq!(st.as_str(), parsed.as_str());
74 }
75
76 #[test]
77 fn frequency_roundtrip(freq in prop_oneof![
78 Just(Frequency::Annual),
79 Just(Frequency::Quarterly),
80 ]) {
81 let json = serde_json::to_string(&freq).unwrap();
82 let parsed: Frequency = serde_json::from_str(&json).unwrap();
83
84 prop_assert_eq!(freq.as_str(), parsed.as_str());
85 }
86
87 #[test]
88 fn financial_statement_roundtrip(
89 symbol in "[A-Z]{1,5}",
90 statement_type in "income|balance|cashflow",
91 frequency in "annual|quarterly",
92 ) {
93 let statement = FinancialStatement {
94 symbol: symbol.clone(),
95 statement_type: statement_type.clone(),
96 frequency: frequency.clone(),
97 statement: HashMap::new(),
98 };
99
100 let json = serde_json::to_string(&statement).unwrap();
101 let parsed: FinancialStatement = serde_json::from_str(&json).unwrap();
102
103 prop_assert_eq!(statement.symbol, parsed.symbol);
104 prop_assert_eq!(statement.statement_type, parsed.statement_type);
105 prop_assert_eq!(statement.frequency, parsed.frequency);
106 }
107 }
108}