-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add warning about time entries in the future
- Loading branch information
Showing
8 changed files
with
189 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package service | ||
|
||
import ( | ||
. "klog" | ||
gotime "time" | ||
) | ||
|
||
type Warning struct { | ||
Date Date | ||
Message string | ||
} | ||
|
||
type checker interface { | ||
Warn(Record) *Warning | ||
} | ||
|
||
func SanityCheck(reference gotime.Time, rs []Record) []Warning { | ||
today := NewDateFromTime(reference) | ||
sortedRs := Sort(rs, false) | ||
var ws []Warning | ||
checkers := []checker{ | ||
&unclosedOpenRangeChecker{today: today}, | ||
&futureEntriesChecker{today: today}, | ||
} | ||
for _, r := range sortedRs { | ||
for _, c := range checkers { | ||
w := c.Warn(r) | ||
if w != nil { | ||
ws = append(ws, *w) | ||
} | ||
} | ||
} | ||
return ws | ||
} | ||
|
||
type unclosedOpenRangeChecker struct { | ||
today Date | ||
encounteredRecordAtToday bool | ||
} | ||
|
||
func (c *unclosedOpenRangeChecker) Warn(r Record) *Warning { | ||
if r.Date().IsEqualTo(c.today) { | ||
// Open ranges at today’s date are always okay | ||
c.encounteredRecordAtToday = true | ||
return nil | ||
} | ||
if !c.encounteredRecordAtToday && c.today.PlusDays(-1).IsEqualTo(r.Date()) { | ||
// Open ranges at yesterday’s date are only okay if there is no entry today today | ||
return nil | ||
} | ||
if r.OpenRange() != nil { | ||
// Any other case is most likely a mistake | ||
return &Warning{ | ||
Date: r.Date(), | ||
Message: "Unclosed open range", | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
type futureEntriesChecker struct { | ||
today Date | ||
} | ||
|
||
func (c *futureEntriesChecker) Warn(r Record) *Warning { | ||
if r.Date().IsAfterOrEqual(c.today.PlusDays(1)) && len(r.Entries()) > 0 { | ||
return &Warning{ | ||
Date: r.Date(), | ||
Message: "Entry in future record", | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package service | ||
|
||
import ( | ||
"github.com/stretchr/testify/require" | ||
. "klog" | ||
"testing" | ||
gotime "time" | ||
) | ||
|
||
func TestNoWarningWhenAllGood(t *testing.T) { | ||
timestamp := gotime.Now() | ||
today := NewDateFromTime(timestamp) | ||
now := NewTimeFromTime(timestamp) | ||
rs := []Record{ | ||
func() Record { | ||
// OK: Record in the future but without entries | ||
r := NewRecord(today.PlusDays(1)) | ||
return r | ||
}(), func() Record { | ||
// OK: Open range today | ||
r := NewRecord(today) | ||
r.StartOpenRange(now, "") | ||
return r | ||
}(), func() Record { | ||
// OK: Just a regular record in the past | ||
r := NewRecord(today.PlusDays(-1)) | ||
r.AddDuration(NewDuration(1, 2), "") | ||
return r | ||
}(), | ||
} | ||
ws := SanityCheck(timestamp, rs) | ||
require.Nil(t, ws) | ||
} | ||
|
||
func TestNoOpenRangeWarningWhenYesterdayAndNoRecordToday(t *testing.T) { | ||
timestamp := gotime.Now() | ||
today := NewDateFromTime(timestamp) | ||
now := NewTimeFromTime(timestamp) | ||
rs := []Record{ | ||
func() Record { | ||
// This open range is okay, because there is no record at today’s date | ||
r := NewRecord(today.PlusDays(-1)) | ||
r.StartOpenRange(now, "") | ||
return r | ||
}(), func() Record { | ||
r := NewRecord(today.PlusDays(2)) | ||
return r | ||
}(), | ||
} | ||
ws := SanityCheck(timestamp, rs) | ||
require.Nil(t, ws) | ||
} | ||
|
||
func TestOpenRangeWarningWhenUnclosedOpenRangeBeforeTodayRegardlessOfOrder(t *testing.T) { | ||
timestamp := gotime.Now() | ||
today := NewDateFromTime(timestamp) | ||
now := NewTimeFromTime(timestamp) | ||
// The warnings must work reliably even when the records are not ordered by date initially | ||
rs := []Record{ | ||
func() Record { | ||
// NOT OK: There is a record at today’s date | ||
r := NewRecord(today.PlusDays(-1)) | ||
r.StartOpenRange(now, "") | ||
return r | ||
}(), func() Record { | ||
r := NewRecord(today) | ||
return r | ||
}(), func() Record { | ||
// NOT OK: There is a record at today’s date | ||
r := NewRecord(today.PlusDays(-2)) | ||
r.StartOpenRange(now, "") | ||
return r | ||
}(), | ||
} | ||
ws := SanityCheck(timestamp, rs) | ||
require.NotNil(t, ws) | ||
require.Len(t, ws, 2) | ||
} | ||
|
||
func TestFutureEntriesWarning(t *testing.T) { | ||
timestamp := gotime.Now() | ||
today := NewDateFromTime(timestamp) | ||
rs := []Record{ | ||
func() Record { | ||
r := NewRecord(today.PlusDays(1)) | ||
r.AddDuration(NewDuration(2, 0), "") | ||
return r | ||
}(), func() Record { | ||
r := NewRecord(today) | ||
return r | ||
}(), | ||
} | ||
ws := SanityCheck(timestamp, rs) | ||
require.NotNil(t, ws) | ||
require.Len(t, ws, 1) | ||
} |