use crate::{
request::WebHandle,
enums::*,
model::*,
error::VueError,
};
use std::{
borrow::Cow,
fmt,
fmt::Write,
};
use quick_xml::de;
use serde::Deserialize;
static ENDPOINT: &str = "/Service/PXPCommunication.asmx/ProcessWebServiceRequest";
#[derive(Debug, Clone, PartialEq)]
pub struct Client<'c> {
pub uri: Cow<'c, str>,
pub user: &'c str,
pub pwd: &'c str,
}
#[derive(Debug, Clone)]
pub struct ParamBuilder {
pub param_str: String,
}
impl<'c> Client<'c> {
pub fn create(district_url: &'c str, username: &'c str, password: &'c str) -> Self {
Client {
uri: [district_url, ENDPOINT].concat().into(),
user: username,
pwd: password,
}
}
pub async fn call_service(
&self,
web_service_handle: WebServiceHandle,
method_name: Method,
param_str: ParamBuilder,
) -> Result<String, VueError> {
let body = [
("userID", self.user),
("password", self.pwd),
("skipLoginLog", "true"),
("parent", "false"),
("webServiceHandleName", web_service_handle.into()),
("methodName", method_name.into()),
("paramStr", ¶m_str.build_string())
];
Ok(
WebHandle::send(&self.uri, body)
.await?
)
}
#[inline]
pub async fn get_grades(&self, report_period: Option<u64>) -> Result<grade::GbData, VueError> {
let parms = if report_period.is_none() {
ParamBuilder::create()
} else {
ParamBuilder::create()
.add_elements(&[ParamType::ReportPeriod(report_period.unwrap())])?
};
let xml_data = self.call_service(WebServiceHandle::PXPWebServices, Method::GradeBook, parms)
.await?;
Ok(de::from_str(xml_data.as_str())?)
}
#[inline]
pub async fn get_attendance(&self) -> Result<attendance::AttData, VueError> {
let xml_data = self.call_service(WebServiceHandle::PXPWebServices, Method::Attendance, ParamBuilder::create())
.await?;
Ok(de::from_str(xml_data.as_str())?)
}
#[inline]
pub async fn get_student_info(&self) -> Result<student::Student, VueError> {
let xml_data = self.call_service(WebServiceHandle::PXPWebServices, Method::StudentInfo, ParamBuilder::create())
.await?;
Ok(de::from_str(xml_data.as_str())?)
}
#[inline]
pub async fn get_schedule(&self) -> Result<schedule::StudentClassSchedule, VueError> {
let xml_data = self.call_service(WebServiceHandle::PXPWebServices, Method::StudentClassList, ParamBuilder::create())
.await?;
Ok(de::from_str(xml_data.as_str())?)
}
#[inline]
pub async fn get_school_info(&self) -> Result<school::StudentSchoolInfoListing, VueError> {
let xml_data = self.call_service(WebServiceHandle::PXPWebServices, Method::StudentSchoolInfo, ParamBuilder::create())
.await?;
Ok(de::from_str(xml_data.as_str())?)
}
}
impl ParamBuilder {
pub fn create() -> Self {
ParamBuilder {
param_str: String::new()
}
}
#[inline]
pub fn add_elements(&mut self, params: &[ParamType]) -> Result<Self, std::fmt::Error> {
for p in params.iter() {
write!(&mut self.param_str, "{}\n", p.to_string())?;
}
Ok(self.clone())
}
#[inline]
pub fn build_string(&self) -> String {
["<Parms>\n", self.param_str.as_ref(), "</Parms>"].concat()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xml_building() {
let mut params = ParamBuilder::create()
.add_elements(&[ParamType::AssignmentID("e2qekn"),
ParamType::ChildIntID(1),
ParamType::LanguageCode(0),
ParamType::RequestDate("1/23/19"),
ParamType::HealthImmunizations(true)
]).unwrap();
let res = "<Parms>\n<AssignmentID>e2qekn</AssignmentID>\n<ChildIntID>1</ChildIntID>\n<LanguageCode>0</LanguageCode>\n<RequestDate>1/23/19</RequestDate>\n<HealthImmunizations>true</HealthImmunizations>\n</Parms>";
assert_eq!(¶ms.build_string(), res);
}
}