openleadr_client/
event.rs

1use std::sync::Arc;
2
3use crate::{
4    error::{Error, Result},
5    ClientRef, ReportClient,
6};
7use openleadr_wire::{event::EventContent, report::ReportContent, Event, Report};
8
9/// Client to manage the data of a specific event and the reports contained in that event
10///
11/// Can be created by a [`ProgramClient`](crate::ProgramClient)
12/// ```no_run
13/// # use openleadr_client::{Client, Filter};
14/// # use openleadr_wire::event::Priority;
15/// let client = Client::with_url("https://your-vtn.com".try_into().unwrap(), None);
16/// # tokio_test::block_on(async {
17/// let program = client.get_program_by_id(&"program-1".parse().unwrap()).await.unwrap();
18///
19/// // retrieve all events in that specific program
20/// let mut events = program.get_event_list(Filter::none()).await.unwrap();
21/// let mut event = events.remove(0);
22///
23/// // Set event priority to maximum
24/// event.content_mut().priority = Priority::MAX;
25/// event.update().await.unwrap()
26/// # })
27/// ```
28#[derive(Debug, Clone)]
29pub struct EventClient {
30    client: Arc<ClientRef>,
31    data: Event,
32}
33
34impl EventClient {
35    pub(super) fn from_event(client: Arc<ClientRef>, event: Event) -> Self {
36        Self {
37            client,
38            data: event,
39        }
40    }
41
42    /// Get the id of the event
43    pub fn id(&self) -> &openleadr_wire::event::EventId {
44        &self.data.id
45    }
46
47    /// Get the time the event was created on the VTN
48    pub fn created_date_time(&self) -> chrono::DateTime<chrono::Utc> {
49        self.data.created_date_time
50    }
51
52    /// Get the time the event was last modified on the VTN
53    pub fn modification_date_time(&self) -> chrono::DateTime<chrono::Utc> {
54        self.data.modification_date_time
55    }
56
57    /// Read the data of the event
58    pub fn content(&self) -> &EventContent {
59        &self.data.content
60    }
61
62    /// Modify the data of the event.
63    /// Make sure to call [`update`](Self::update)
64    /// after your modifications to store them on the VTN
65    pub fn content_mut(&mut self) -> &mut EventContent {
66        &mut self.data.content
67    }
68
69    /// Stores any modifications made to the event content at the server
70    /// and refreshes the locally stored data with the returned VTN data
71    pub async fn update(&mut self) -> Result<()> {
72        self.data = self
73            .client
74            .put(&format!("events/{}", self.id()), &self.data.content)
75            .await?;
76        Ok(())
77    }
78
79    /// Delete the event from the VTN
80    pub async fn delete(self) -> Result<Event> {
81        self.client.delete(&format!("events/{}", self.id())).await
82    }
83
84    /// Create a new report object
85    pub fn new_report(&self, client_name: String) -> ReportContent {
86        ReportContent {
87            program_id: self.content().program_id.clone(),
88            event_id: self.id().clone(),
89            client_name,
90            report_name: None,
91            payload_descriptors: None,
92            resources: vec![],
93        }
94    }
95
96    /// Create a new report on the VTN.
97    /// The content should be created with [`EventClient::new_report`]
98    /// to automatically insert the correct program ID and event ID
99    pub async fn create_report(&self, report_data: ReportContent) -> Result<ReportClient> {
100        if report_data.program_id != self.content().program_id {
101            return Err(Error::InvalidParentObject);
102        }
103
104        if &report_data.event_id != self.id() {
105            return Err(Error::InvalidParentObject);
106        }
107
108        let report = self.client.post("reports", &report_data).await?;
109        Ok(ReportClient::from_report(self.client.clone(), report))
110    }
111
112    async fn get_reports_req(
113        &self,
114        client_name: Option<&str>,
115        skip: usize,
116        limit: usize,
117    ) -> Result<Vec<ReportClient>> {
118        let skip_str = skip.to_string();
119        let limit_str = limit.to_string();
120
121        let mut query = vec![
122            ("programID", self.content().program_id.as_str()),
123            ("eventID", self.id().as_str()),
124            ("skip", &skip_str),
125            ("limit", &limit_str),
126        ];
127
128        if let Some(client_name) = client_name {
129            query.push(("clientName", client_name));
130        }
131
132        let reports: Vec<Report> = self.client.get("reports", &query).await?;
133        Ok(reports
134            .into_iter()
135            .map(|report| ReportClient::from_report(self.client.clone(), report))
136            .collect())
137    }
138
139    /// Get all reports from the VTN, possibly filtered by `client_name`, trying to paginate whenever possible
140    pub async fn get_report_list(&self, client_name: Option<&str>) -> Result<Vec<ReportClient>> {
141        self.client
142            .iterate_pages(|skip, limit| self.get_reports_req(client_name, skip, limit))
143            .await
144    }
145}