sure_client_rs/client/valuations.rs
1use crate::error::ApiResult;
2use crate::models::valuation::{
3 CreateValuationData, CreateValuationRequest, UpdateValuationData, UpdateValuationRequest,
4 Valuation,
5};
6use crate::types::{AccountId, ValuationId};
7use bon::bon;
8use chrono::NaiveDate;
9use reqwest::Method;
10use rust_decimal::Decimal;
11
12use super::SureClient;
13
14#[bon]
15impl SureClient {
16 /// Create a new valuation entry for an account.
17 ///
18 /// Valuations are most commonly used to record point-in-time balances for
19 /// asset accounts whose value drifts over time, such as properties, vehicles,
20 /// or investment portfolios that are not synced from a brokerage. Each
21 /// valuation appears as a `reconciliation` entry on the account's timeline.
22 ///
23 /// # Arguments
24 /// * `account_id` - The account the valuation applies to (required).
25 /// * `amount` - The valuation amount (required).
26 /// * `date` - The valuation date (required).
27 /// * `notes` - Optional notes attached to the entry.
28 ///
29 /// # Returns
30 /// The created valuation entry.
31 ///
32 /// # Errors
33 /// Returns `ApiError::ValidationError` if required fields are missing or invalid.
34 /// Returns `ApiError::Unauthorized` if the credentials are missing/invalid.
35 /// Returns `ApiError::Network` if the request fails due to network issues.
36 ///
37 /// # Example
38 /// ```no_run
39 /// use sure_client_rs::{SureClient, AccountId};
40 /// use chrono::NaiveDate;
41 /// use rust_decimal::Decimal;
42 /// use uuid::Uuid;
43 ///
44 /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
45 /// let account_id = AccountId::new(Uuid::new_v4());
46 /// let valuation = client.create_valuation()
47 /// .account_id(account_id)
48 /// .amount(Decimal::new(77000000, 2)) // $770,000.00
49 /// .date(NaiveDate::from_ymd_opt(2025, 12, 12).unwrap())
50 /// .call()
51 /// .await?;
52 /// println!("Created valuation: {} on {}", valuation.amount, valuation.date);
53 /// # Ok(())
54 /// # }
55 /// ```
56 #[builder]
57 pub async fn create_valuation(
58 &self,
59 account_id: AccountId,
60 amount: Decimal,
61 date: NaiveDate,
62 notes: Option<String>,
63 ) -> ApiResult<Valuation> {
64 let request = CreateValuationRequest {
65 valuation: CreateValuationData {
66 account_id,
67 amount,
68 date,
69 notes,
70 },
71 };
72
73 self.execute_request(
74 Method::POST,
75 "/api/v1/valuations",
76 None,
77 Some(serde_json::to_string(&request)?),
78 )
79 .await
80 }
81
82 /// Get a specific valuation by ID.
83 ///
84 /// # Arguments
85 /// * `id` - The valuation ID to retrieve.
86 pub async fn get_valuation(&self, id: &ValuationId) -> ApiResult<Valuation> {
87 self.execute_request(
88 Method::GET,
89 &format!("/api/v1/valuations/{}", id),
90 None,
91 None,
92 )
93 .await
94 }
95
96 /// Update an existing valuation entry.
97 ///
98 /// The Sure API requires both `amount` and `date` to be supplied together
99 /// when changing the underlying reconciliation; `notes` may be updated
100 /// independently.
101 ///
102 /// # Arguments
103 /// * `id` - The valuation ID to update.
104 /// * `amount` - New amount (must accompany `date` if either is set).
105 /// * `date` - New date (must accompany `amount` if either is set).
106 /// * `notes` - New notes.
107 #[builder]
108 pub async fn update_valuation(
109 &self,
110 id: &ValuationId,
111 amount: Option<Decimal>,
112 date: Option<NaiveDate>,
113 notes: Option<String>,
114 ) -> ApiResult<Valuation> {
115 let request = UpdateValuationRequest {
116 valuation: UpdateValuationData {
117 amount,
118 date,
119 notes,
120 },
121 };
122
123 self.execute_request(
124 Method::PATCH,
125 &format!("/api/v1/valuations/{}", id),
126 None,
127 Some(serde_json::to_string(&request)?),
128 )
129 .await
130 }
131}