Skip to content

Commit

Permalink
Allow flag in --week previous
Browse files Browse the repository at this point in the history
Also, fix a bug where a previous `--week` argument is remembered when
running with no `--week` argument. It seems that Maconomy remembers the
selected week for like a minute. Now I just always specify the week,
which sadly adds an extra (sometimes redundant) request. Perhaps there's
a simpler way to specify the week without an extra request? I
haven't found one yet.
  • Loading branch information
mawkler committed Nov 20, 2024
1 parent 7670315 commit 8921f9a
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 80 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ cargo run

# To pass arguments to maconomy-cli you can use `--`:
cargo run -- set --job '<job name>' --task '<task name>' 8

# To get the full debug log printed to stderr
RUST_LOG=debug cargo run -- ...
```

To run tests:
Expand Down
10 changes: 5 additions & 5 deletions src/cli/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub enum Line {

/// Week number (defaults to current week if omitted)
#[arg(long, short)]
week: Option<u8>,
week: Option<String>,

/// Year (defaults to current year if omitted)
#[arg(long, short, requires = "week")]
Expand All @@ -44,7 +44,7 @@ pub enum Command {
Get {
/// Week number (defaults to current week if omitted)
#[arg(long, short)]
week: Option<u8>,
week: Option<String>,

/// Year (defaults to current year if omitted)
#[arg(long, short, requires = "week")]
Expand Down Expand Up @@ -82,7 +82,7 @@ pub enum Command {

/// Week number (defaults to current week if omitted)
#[arg(long, short)]
week: Option<u8>,
week: Option<String>,

/// Year (defaults to current year if omitted)
#[arg(long, short, requires = "week")]
Expand Down Expand Up @@ -112,7 +112,7 @@ pub enum Command {

/// Week number (defaults to current week if omitted)
#[arg(long, short)]
week: Option<u8>,
week: Option<String>,

/// Year (defaults to current year if omitted)
#[arg(long, short, requires = "week")]
Expand All @@ -123,7 +123,7 @@ pub enum Command {
Submit {
/// Week number (defaults to current week if omitted)
#[arg(long, short)]
week: Option<u8>,
week: Option<String>,

/// Year (defaults to current year if omitted)
#[arg(long, short, requires = "week")]
Expand Down
78 changes: 56 additions & 22 deletions src/cli/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
};
use anyhow::Context;
use chrono::{Datelike, Local};
use log::info;
use std::collections::HashSet;
use std::rc::Rc;
use tokio::sync::Mutex;
Expand Down Expand Up @@ -42,14 +43,14 @@ impl<'a> CommandClient<'a> {
}
}

pub(crate) async fn get_table(&self, week: Option<&WeekNumber>) -> anyhow::Result<()> {
pub(crate) async fn get_table(&self, week: &WeekNumber) -> anyhow::Result<()> {
let time_sheet = self.repository.lock().await.get_time_sheet(week).await?;

println!("{time_sheet}");
Ok(())
}

async fn get_json(&self, week: Option<&WeekNumber>) -> anyhow::Result<()> {
async fn get_json(&self, week: &WeekNumber) -> anyhow::Result<()> {
let time_sheet = self.repository.lock().await.get_time_sheet(week).await?;
let json =
serde_json::to_string(&time_sheet).context("Failed to deserialize time sheet")?;
Expand All @@ -58,12 +59,13 @@ impl<'a> CommandClient<'a> {
Ok(())
}

pub(crate) async fn get(&self, week: Option<u8>, year: Option<i32>, format: Format) {
let week = to_week_with_fallback(week, year);
pub(crate) async fn get(&self, week: Option<String>, year: Option<i32>, format: Format) {
let week =
get_week_with_fallback(week, year).unwrap_or_else(|err| exit_with_error!("{err}"));

match format {
Format::Json => self.get_json(week.as_ref()).await.context("JSON"),
Format::Table => self.get_table(week.as_ref()).await.context("table"),
Format::Json => self.get_json(&week).await.context("JSON"),
Format::Table => self.get_table(&week).await.context("table"),
}
.unwrap_or_else(|err| {
exit_with_error!("Failed to get time sheet as {}", error_stack_fmt(&err));
Expand All @@ -74,7 +76,7 @@ impl<'a> CommandClient<'a> {
&mut self,
hours: f32,
days: Option<Days>,
week: Option<u8>,
week: Option<String>,
year: Option<i32>,
job: &str,
task: &str,
Expand All @@ -84,12 +86,13 @@ impl<'a> CommandClient<'a> {
}

let day = get_days(days);
let week = to_week_with_fallback(week, year);
let week =
get_week_with_fallback(week, year).unwrap_or_else(|err| exit_with_error!("{err}"));

self.time_sheet_service
.lock()
.await
.set_time(hours, &day, week.as_ref(), job, task)
.set_time(hours, &day, &week, job, task)
.await
.unwrap_or_else(|err| {
if let SetTimeError::Unknown(err) = err {
Expand All @@ -105,18 +108,19 @@ impl<'a> CommandClient<'a> {
job: &str,
task: &str,
days: Option<Days>,
week: Option<u8>,
week: Option<String>,
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 = to_week_with_fallback(week, year);
let week =
get_week_with_fallback(week, year).unwrap_or_else(|err| exit_with_error!("{err}"));
self.time_sheet_service
.lock()
.await
.clear(job, task, &get_days(days), week.as_ref())
.clear(job, task, &get_days(days), &week)
.await
.unwrap_or_else(|err| {
if let SetTimeError::Unknown(err) = err {
Expand All @@ -136,28 +140,31 @@ impl<'a> CommandClient<'a> {
pub(crate) async fn delete(
&mut self,
line_number: &LineNumber,
week: Option<u8>,
week: Option<String>,
year: Option<i32>,
) {
let week = to_week_with_fallback(week, year);
let week =
get_week_with_fallback(week, year).unwrap_or_else(|err| exit_with_error!("{err}"));

self.repository
.lock()
.await
.delete_line(line_number, week.as_ref())
.delete_line(line_number, &week)
.await
.unwrap_or_else(|err| {
let source = error_stack_fmt(&err);
exit_with_error!("Failed to delete line {line_number:?}: {source}");
});
}

pub(crate) async fn submit(&mut self, week: Option<u8>, year: Option<i32>) {
let week = to_week_with_fallback(week, year);
pub(crate) async fn submit(&mut self, week: Option<String>, year: Option<i32>) {
let week =
get_week_with_fallback(week, year).unwrap_or_else(|err| exit_with_error!("{err}"));

self.repository
.lock()
.await
.submit(week.as_ref())
.submit(&week)
.await
.unwrap_or_else(|err| {
exit_with_error!("Failed to submit: {}", error_stack_fmt(&err));
Expand All @@ -173,8 +180,35 @@ fn get_days(days: Option<Days>) -> Days {
})
}

fn to_week_with_fallback(week: Option<u8>, year: Option<i32>) -> Option<WeekNumber> {
week.map(|week| {
WeekNumber::new_with_fallback(week, year).unwrap_or_else(|err| exit_with_error!("{err}"))
})
// TODO: refactor this so that it lives on WeekNumber and parse_week calls this instead of
// vice-versa
fn get_week_with_fallback(week: Option<String>, year: Option<i32>) -> anyhow::Result<WeekNumber> {
if let Some(week) = week {
let week = parse_week(week)?;

let week = WeekNumber::new_with_fallback(week, year)?;
Ok(week)
} else {
let week = Local::now().date_naive().iso_week().week().try_into();
let week = week.expect("Week numbers are always less than 255");

WeekNumber::new_with_fallback(week, year)
}
}

fn parse_week(week: String) -> anyhow::Result<u8> {
let week = match week.trim().to_lowercase().as_str() {
"previous" => {
let week = Local::now().date_naive().iso_week().week() - 1;
info!("Using previous week number: {week}");
Ok(week)
}
number => number
.parse()
.with_context(|| format!("Invalid week number '{week}'")),
}?
.try_into()
.expect("Week numbers are always less than 255");

Ok(week)
}
3 changes: 2 additions & 1 deletion src/cli/rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::domain::models::time_sheet::{Line, TimeSheet};
use owo_colors::OwoColorize;
use std::fmt::Display;
use tabled::settings::{
object::Rows, style::BorderColor, themes::Colorization, Color, Style, Theme,
object::Rows, style::BorderColor, themes::Colorization, Color, Panel, Style, Theme,
};

#[derive(tabled::Tabled, Default)]
Expand Down Expand Up @@ -89,6 +89,7 @@ impl Display for TimeSheet {
[tabled::settings::Color::BOLD],
Rows::first(),
))
.with(Panel::footer(format!("Week {}", self.week_number)))
.with(gray_borders());

write!(f, "{table}")
Expand Down
7 changes: 4 additions & 3 deletions src/domain/models/time_sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ impl Line {
}
}

#[derive(Default, Debug, serde::Serialize)]
#[derive(Debug, serde::Serialize)]
pub(crate) struct TimeSheet {
pub(crate) lines: Vec<Line>,
pub(crate) week_number: u8,
}

impl TimeSheet {
pub(crate) fn new(lines: Vec<Line>) -> Self {
Self { lines }
pub(crate) fn new(lines: Vec<Line>, week_number: u8) -> Self {
Self { lines, week_number }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/domain/models/week.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::anyhow;
use chrono::{Datelike, NaiveDate, Weekday};
use std::fmt::Display;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default, serde::Serialize)]
pub(crate) struct WeekNumber {
number: u8,
year: i32,
Expand Down
4 changes: 2 additions & 2 deletions src/domain/time_sheet_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl TimeSheetService<'_> {
job: &str,
task: &str,
days: &Days,
week: Option<&WeekNumber>,
week: &WeekNumber,
) -> Result<(), SetTimeError> {
self.set_time(0.0, days, week, job, task).await
}
Expand All @@ -47,7 +47,7 @@ impl TimeSheetService<'_> {
&mut self,
hours: f32,
days: &Days,
week: Option<&WeekNumber>,
week: &WeekNumber,
job: &str,
task: &str,
) -> Result<(), SetTimeError> {
Expand Down
1 change: 1 addition & 0 deletions src/infrastructure/repositories/maconomy_http_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ impl MaconomyHttpClient<'_> {
Ok((time_registration, concurrency_control.into()))
}

// Setting the week also returns its time registration
pub(crate) async fn set_week(
&self,
date: NaiveDate,
Expand Down
Loading

0 comments on commit 8921f9a

Please sign in to comment.