pub struct Si { /* private fields */ }Expand description
SiServer client. Authentication is two-stage: LDAP login yields a
token, the token is exchanged for a PORTALSESSID cookie, and the
cookie rides on every API call.
Implementations§
Source§impl Si
impl Si
Sourcepub fn new(config: &SiConfig) -> Self
pub fn new(config: &SiConfig) -> Self
Builds a client from the config; no network activity yet.
use kasl::api::si::{Si, SiConfig};
let config = SiConfig {
login: "username".to_string(),
auth_url: "https://auth.company.com".to_string(),
api_url: "https://api.company.com".to_string(),
};
let si = Si::new(&config);Sourcepub async fn send(&mut self, data: &str, date: &NaiveDate) -> Result<StatusCode>
pub async fn send(&mut self, data: &str, date: &NaiveDate) -> Result<StatusCode>
Submits the daily report (tasks as JSON) for the date. On a 401 the
cached session is dropped and the call retried up to the limit; a
network error maps to BAD_REQUEST so a scheduled send fails soft.
let mut si = Si::new(&config);
let report_data = r#"{"hours": 8, "tasks": 5}"#.to_string();
let today = Local::now().date_naive();
let status = si.send(&report_data, &today).await?;
if status.is_success() {
println!("Report submitted successfully");
}Sourcepub async fn send_monthly(&mut self, date: &NaiveDate) -> Result<StatusCode>
pub async fn send_monthly(&mut self, date: &NaiveDate) -> Result<StatusCode>
Submits the monthly report for the month containing date, with
the same 401-retry and network-error behavior as Si::send.
let mut si = Si::new(&config);
let today = Local::now().date_naive();
if si.is_last_working_day_of_month(&today)? {
let status = si.send_monthly(&today).await?;
if status.is_success() {
println!("Monthly report submitted");
}
}Sourcepub async fn rest_dates(
&mut self,
year: NaiveDate,
) -> Result<HashSet<NaiveDate>>
pub async fn rest_dates( &mut self, year: NaiveDate, ) -> Result<HashSet<NaiveDate>>
Fetches the company rest-date calendar for the year of date.
Every failure path - session, network, parsing - logs and returns an empty set: the calendar makes reports nicer, and its absence must not break them.
let mut si = Si::new(&config);
let this_year = Local::now().date_naive();
let rest_dates = si.rest_dates(this_year).await?;
println!("Found {} rest dates this year", rest_dates.len());
let today = Local::now().date_naive();
if rest_dates.contains(&today) {
println!("Today is a company rest day");
}Sourcepub fn is_last_working_day_of_month(&self, date: &NaiveDate) -> Result<bool>
pub fn is_last_working_day_of_month(&self, date: &NaiveDate) -> Result<bool>
True when date is the month’s last working day (weekends walked
back; company holidays are not consulted).
let si = Si::new(&config);
let date = NaiveDate::from_ymd_opt(2024, 1, 31).unwrap(); // January 31st
if si.is_last_working_day_of_month(&date)? {
println!("Time to submit monthly report!");
}Trait Implementations§
Source§impl Session for Si
impl Session for Si
Source§async fn login(&self) -> Result<String>
async fn login(&self) -> Result<String>
Runs the two-stage login and returns the session id extracted from
the Set-Cookie header.
Source§fn set_credentials(&mut self, password: &str) -> Result<()>
fn set_credentials(&mut self, password: &str) -> Result<()>
Stores the credentials, double-base64-encoding the password as SiServer requires.
Source§fn session_id_file(&self) -> &str
fn session_id_file(&self) -> &str
Source§fn reset_retry(&mut self)
fn reset_retry(&mut self)
Source§async fn get_session_id(&mut self) -> Result<String>
async fn get_session_id(&mut self) -> Result<String>
MAX_RETRY_COUNT] password attempts (a retry always
re-prompts rather than reusing a password that just failed).