Skip to content

Commit

Permalink
Add --year flag
Browse files Browse the repository at this point in the history
  • Loading branch information
mawkler committed Nov 13, 2024
1 parent eaceb15 commit 3995d83
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 39 deletions.
19 changes: 19 additions & 0 deletions src/cli/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ pub enum Line {
/// Week number
#[arg(long, short)]
week: Option<u8>,

/// Year
#[arg(long, short, requires = "week")]
year: Option<i32>,

},
}

Expand All @@ -41,6 +46,11 @@ pub enum Command {
/// Week number
#[arg(long, short)]
week: Option<u8>,

/// Year
#[arg(long, short, requires = "week")]
year: Option<i32>,

/// Output format
#[arg(long, short, default_value = "table")]
format: Format,
Expand All @@ -56,6 +66,10 @@ pub enum Command {
#[arg(long, short)]
week: Option<u8>,

/// Year
#[arg(long, short, requires = "week")]
year: Option<i32>,

/// Name of the job
#[arg(long, short)]
job: String,
Expand Down Expand Up @@ -100,6 +114,11 @@ pub enum Command {
/// Week number
#[arg(long, short)]
week: Option<u8>,

/// Year
#[arg(long, short, requires = "week")]
year: Option<i32>,

},

/// Submit time sheet for week
Expand Down
32 changes: 20 additions & 12 deletions src/cli/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ impl<'a> CommandClient<'a> {
Ok(())
}

pub(crate) async fn get(&self, week: Option<u8>, format: Format) {
let week = week.map(WeekNumber::from);
pub(crate) async fn get(&self, week: Option<u8>, year: Option<i32>, format: Format) {
let week = create_week_with_fallback(week, year);

match format {
Format::Json => self.get_json(week.as_ref()).await.context("JSON"),
Format::Table => self.get_table(week.as_ref()).await.context("table"),
Expand All @@ -73,6 +74,7 @@ impl<'a> CommandClient<'a> {
hours: f32,
days: Option<Days>,
week: Option<u8>,
year: Option<i32>,
job: &str,
task: &str,
) {
Expand All @@ -81,7 +83,7 @@ impl<'a> CommandClient<'a> {
}

let day = get_days(days);
let week = week.map(WeekNumber::from);
let week = create_week_with_fallback(week, year);

self.time_sheet_service
.lock()
Expand All @@ -103,12 +105,13 @@ impl<'a> CommandClient<'a> {
task: &str,
days: Option<Days>,
week: Option<u8>,
year: Option<i32>,
) {
if days.as_ref().is_some_and(|days| days.is_empty()) {
exit_with_error!("`--day` is set but no day was provided");
}

let week = week.map(WeekNumber::from);
let week = create_week_with_fallback(week, year);
self.time_sheet_service
.lock()
.await
Expand All @@ -129,8 +132,13 @@ impl<'a> CommandClient<'a> {
});
}

pub(crate) async fn delete(&mut self, line_number: &LineNumber, week: Option<u8>) {
let week = week.map(WeekNumber::from);
pub(crate) async fn delete(
&mut self,
line_number: &LineNumber,
week: Option<u8>,
year: Option<i32>,
) {
let week = create_week_with_fallback(week, year);

self.repository
.lock()
Expand Down Expand Up @@ -163,10 +171,10 @@ fn get_days(days: Option<Days>) -> Days {
})
}

impl From<Option<u8>> for WeekNumber {
fn from(week: Option<u8>) -> Self {
// Fall back to today's week
week.unwrap_or_else(|| Local::now().date_naive().iso_week().week() as u8)
.into()
}
fn create_week_with_fallback(week: Option<u8>, year: Option<i32>) -> Option<WeekNumber> {
week.map(|week| {
// Fall back to today's year
let year = year.unwrap_or_else(|| year.unwrap_or_else(|| chrono::Utc::now().year()));
WeekNumber::new(week, year).unwrap_or_else(|err| exit_with_error!("{err}"))
})
}
32 changes: 19 additions & 13 deletions src/domain/models/week.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
use std::fmt::Display;

use anyhow::anyhow;
use chrono::{NaiveDate, Weekday};
use std::fmt::Display;

// TODO: switch from `u8` to `IsoWeek`
#[derive(Debug, Clone)]
pub(crate) struct WeekNumber(u8);
pub(crate) struct WeekNumber {
number: u8,
year: i32,
}

impl WeekNumber {
pub(crate) fn first_day(&self, year: i32) -> Option<NaiveDate> {
NaiveDate::from_isoywd_opt(year, self.0.into(), Weekday::Mon)
pub(crate) fn new(week: u8, year: i32) -> anyhow::Result<Self> {
first_day_of_week(week, year).ok_or(anyhow!("Invalid week '{week}'"))?;

Ok(Self { number: week, year })
}
}

impl From<u8> for WeekNumber {
fn from(week: u8) -> Self {
Self(week)
pub(crate) fn first_day(&self) -> Option<NaiveDate> {
first_day_of_week(self.number, self.year)
}
}

impl Display for WeekNumber {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
write!(f, "Week {}, year {}", self.number, self.year)
}
}

fn first_day_of_week(week: u8, year: i32) -> Option<NaiveDate> {
NaiveDate::from_isoywd_opt(year, week.into(), Weekday::Mon)
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -37,8 +43,8 @@ mod tests {
];

for (year, week, expected_date) in dates {
let week_number = WeekNumber(week);
let date = week_number.first_day(year).unwrap();
let week_number = WeekNumber { number: week, year };
let date = week_number.first_day().unwrap();

assert_eq!(
date,
Expand Down
15 changes: 7 additions & 8 deletions src/infrastructure/repositories/time_sheet_repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::{
},
};
use anyhow::{anyhow, Context, Result};
use chrono::{Datelike, Local};
use log::{debug, info};
use std::collections::HashSet;

Expand Down Expand Up @@ -122,11 +121,12 @@ impl TimeSheetRepository<'_> {
info!("Found no line for job '{job}', task '{task}'. Creating new line for it");
let time_sheet = self.add_line(job, task).await?;

time_sheet
.find_line_nr(job, task)
.with_context(|| format!(
"format not find job '{job}' and task '{task}', even after creating a new line for it"
))?
time_sheet.find_line_nr(job, task).with_context(|| {
format!(
"format not find job '{job}' and task '{task}', even after creating a new \
line for it"
)
})?
}
};

Expand Down Expand Up @@ -272,9 +272,8 @@ impl TimeSheetRepository<'_> {
.await
.context("Failed to get container instance")?;

let year = Local::now().date_naive().year();
let date = week
.first_day(year)
.first_day()
.with_context(|| format!("Failed to get first day of week {week}"))?;

let (time_registration, concurrency_control) = self
Expand Down
22 changes: 16 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,35 @@ async fn main() -> anyhow::Result<()> {
);

match parse_arguments() {
Command::Get { week, format } => command_client.get(week, format).await,
Command::Get { week, year, format } => command_client.get(week, year, format).await,
Command::Set {
hours,
week,
day,
week,
year,
job,
task,
} => command_client.set(hours, day, week, &job, &task).await,
} => {
command_client
.set(hours, day, week, year, &job, &task)
.await
}
Command::Clear {
day,
week,
year,
job,
task,
day,
} => command_client.clear(&job, &task, day, week).await,
} => command_client.clear(&job, &task, day, week, year).await,
// TODO: haven't actually tested this yet (can only be tested once a week)
Command::Submit => command_client.submit().await,
Command::Logout => command_client.logout().await,
Command::Line(line) => match line {
Line::Delete { line_number, week } => command_client.delete(&line_number, week).await,
Line::Delete {
line_number,
week,
year,
} => command_client.delete(&line_number, week, year).await,
},
};

Expand Down

0 comments on commit 3995d83

Please sign in to comment.