gime-lib/model_timeentry.go

224 lines
6.1 KiB
Go
Raw Normal View History

2017-07-28 11:44:08 +00:00
package gime
import (
"errors"
2018-01-18 15:54:12 +00:00
"sort"
2017-07-28 11:44:08 +00:00
"strconv"
"time"
"github.com/br0xen/boltease"
)
2018-01-18 15:54:12 +00:00
// GetLastTimeEntry pulls the time entry with the most recent stop time
func (gdb *GimeDB) GetLatestTimeEntry() (*TimeEntry, error) {
var ret *TimeEntry
var err error
tc := gdb.LoadTimeEntryCollection(TypeRecent)
for i := 0; i < tc.Length(); i++ {
te := tc.Get(i)
if ret == nil {
ret = te
} else {
if te.GetEnd().After(ret.GetEnd()) {
ret = te
}
}
}
if ret == nil {
err = errors.New("Could not find latest time entry")
}
return ret, err
}
2017-08-01 20:39:24 +00:00
// FindTimeEntryByUUID searches all entries
// for the time entry with the given uuid, return the TimeEntry, the type, and/or and error
// Types are searched TypeCurrent -> TypeRecent -> TypeArchive
2018-01-11 16:52:44 +00:00
func (gdb *GimeDB) FindTimeEntryByUUID(uuid string) (*TimeEntry, int, error) {
2017-08-01 20:39:24 +00:00
for i := range gdb.AllTypes {
timeCollection := gdb.LoadTimeEntryCollection(gdb.AllTypes[i])
for j := 0; j < timeCollection.Length(); j++ {
if timeCollection.Get(j).GetUUID() == uuid {
return timeCollection.Get(j), gdb.AllTypes[i], nil
2017-07-31 12:00:16 +00:00
}
}
}
2018-01-11 16:52:44 +00:00
return nil, TypeAll, errors.New("Unable to find time entry with uuid " + uuid)
2017-07-31 12:00:16 +00:00
}
2017-07-28 11:44:08 +00:00
// SaveTimeEntry creates a time entry in the database
// If TimeEntry.end is zero, then it puts it in TypeCurrent
func (gdb *GimeDB) SaveTimeEntry(te *TimeEntry) error {
var err error
var useDb *boltease.DB
tp := TypeRecent
if te.end.IsZero() {
// Currently running
tp = TypeCurrent
} else {
// We have an end time. Does this entry go in 'recent' or 'archive'
2017-08-02 19:14:53 +00:00
// We shove times that happened 90 days ago (~1/4 year) into 'archive'
if time.Since(te.end) > (time.Hour * 24 * 90) {
2017-07-28 11:44:08 +00:00
tp = TypeArchive
}
}
2017-08-01 20:39:24 +00:00
useDb, err = gdb.openDBType(tp)
if err != nil {
return err
}
2018-01-11 16:52:44 +00:00
tePath := []string{TypeToString(tp), te.start.Format(time.RFC3339)}
2017-07-31 12:00:16 +00:00
if err = useDb.SetValue(tePath, "uuid", te.uuid); err != nil {
return err
}
2017-07-28 11:44:08 +00:00
if err = useDb.SetTimestamp(tePath, "start", te.start); err != nil {
return err
}
if err = useDb.SetTimestamp(tePath, "end", te.end); err != nil {
return err
}
2017-07-31 12:00:16 +00:00
for i := 0; i < te.tags.Length(); i++ {
err = useDb.SetValue(append(tePath, "tags"), strconv.Itoa(i), te.tags.Get(i))
2017-07-28 11:44:08 +00:00
}
return nil
}
2017-07-31 12:00:16 +00:00
// UpdateTimeEntry updates the time entry in the database
// It first finds the current entry in the database by the uuid
func (gdb *GimeDB) UpdateTimeEntry(te *TimeEntry) error {
var err error
if te.uuid == "" {
return errors.New("Given time entry has no uuid")
}
2017-08-01 20:39:24 +00:00
if err = gdb.RemoveTimeEntry(te.uuid); err != nil {
2017-07-31 12:00:16 +00:00
return err
}
2017-08-01 20:39:24 +00:00
return gdb.SaveTimeEntry(te)
2017-07-31 12:00:16 +00:00
}
2017-08-01 20:39:24 +00:00
// RemoveTimeEntry removes a time entry with the given uuid from the database
func (gdb *GimeDB) RemoveTimeEntry(uuid string) error {
fndEntry, tp, err := gdb.FindTimeEntryByUUID(uuid)
if err != nil {
return errors.New("Unable to find time entry with uuid " + uuid)
2017-07-31 12:00:16 +00:00
}
var useDb *boltease.DB
if useDb, err = gdb.openDBType(tp); err != nil {
2017-08-01 20:39:24 +00:00
return err
2017-07-31 12:00:16 +00:00
}
defer gdb.closeDBType(tp)
2017-08-01 20:39:24 +00:00
if err != nil {
return err
}
2018-01-11 16:52:44 +00:00
return useDb.DeleteBucket([]string{TypeToString(tp)}, fndEntry.start.Format(time.RFC3339))
2017-07-31 12:00:16 +00:00
}
2017-08-02 19:14:53 +00:00
// GetTimeEntriesInRange takes two times and returns all time entries that occur
// on or between those dates
func (gdb *GimeDB) GetTimeEntriesInRange(st time.Time, end time.Time) *TimeEntryCollection {
var err error
ret := new(TimeEntryCollection)
if time.Since(st) > ArchiveDays {
if err = gdb.openArchiveDatabase(); err != nil {
return ret
}
defer gdb.closeArchiveDatabase()
var sttimes []string
2018-01-11 16:52:44 +00:00
if sttimes, err = gdb.db.GetBucketList([]string{TypeToString(TypeArchive)}); err != nil {
2017-08-02 19:14:53 +00:00
return ret
}
for i := len(sttimes) - 1; i > 0; i-- {
}
}
return ret
}
2017-07-28 11:44:08 +00:00
// dbGetAllTimeEntries gets all time entries of a specific type
// tp can be:
// TypeCurrent = "current"
// TypeRecent = "recent"
// TypeArchive = "archive"
2018-01-11 16:52:44 +00:00
// TypeAll = "unknown" - Returns _ALL_ entries
2017-07-28 11:44:08 +00:00
// Getting all archived time entries has the potential to be a lot of data
2018-01-11 16:52:44 +00:00
func (gdb *GimeDB) dbGetAllTimeEntries(tp int) []TimeEntry {
2017-07-28 11:44:08 +00:00
var ret []TimeEntry
2018-01-11 16:52:44 +00:00
if tp == TypeAll {
2017-08-01 20:39:24 +00:00
for _, v := range gdb.AllTypes {
ret = append(ret, gdb.dbGetAllTimeEntries(v)...)
2017-07-31 12:00:16 +00:00
}
return ret
2018-01-11 16:52:44 +00:00
} else if tp == TypeNoArchive {
ret = append(ret, gdb.dbGetAllTimeEntries(TypeCurrent)...)
ret = append(ret, gdb.dbGetAllTimeEntries(TypeRecent)...)
return ret
2017-07-31 12:00:16 +00:00
}
2018-01-11 16:52:44 +00:00
2017-07-28 11:44:08 +00:00
var useDb *boltease.DB
var err error
if useDb, err = gdb.openDBType(tp); err != nil {
return ret
}
defer gdb.closeDBType(tp)
2017-07-31 12:00:16 +00:00
var sttimes []string
2018-01-11 16:52:44 +00:00
if sttimes, err = useDb.GetBucketList([]string{TypeToString(tp)}); err != nil {
2017-07-28 11:44:08 +00:00
return ret
}
2018-01-18 15:54:12 +00:00
sort.Slice(sttimes, func(i, j int) bool {
return sttimes[j] < sttimes[i]
})
2017-07-31 12:00:16 +00:00
for _, v := range sttimes {
2017-07-28 11:44:08 +00:00
if te, _ := gdb.dbGetTimeEntry(tp, v); te != nil {
ret = append(ret, *te)
}
}
return ret
}
2017-08-02 19:14:53 +00:00
// dbGetTimeEntry pulls a time entry of type tp with the given start time
2017-07-28 11:44:08 +00:00
// from the db and returns it.
2018-01-11 16:52:44 +00:00
func (gdb *GimeDB) dbGetTimeEntry(tp int, sttm string) (*TimeEntry, error) {
2017-07-28 11:44:08 +00:00
var ret *TimeEntry
var err error
2018-01-11 16:52:44 +00:00
if tp == TypeAll {
2017-07-31 12:00:16 +00:00
// Loop through the types and return the first entry found that matches
2017-08-01 20:39:24 +00:00
for _, v := range gdb.AllTypes {
2017-07-31 12:00:16 +00:00
ret, _ = gdb.dbGetTimeEntry(v, sttm)
if ret != nil {
return ret, nil
}
}
2017-08-01 20:39:24 +00:00
return nil, errors.New("Couldn't find time entry")
2017-07-31 12:00:16 +00:00
}
2017-07-28 11:44:08 +00:00
var useDb *boltease.DB
if useDb, err = gdb.openDBType(tp); err != nil {
return ret, err
}
defer gdb.closeDBType(tp)
2018-01-11 16:52:44 +00:00
entryPath := []string{TypeToString(tp), sttm}
2017-07-28 11:44:08 +00:00
ret = new(TimeEntry)
2017-07-31 12:00:16 +00:00
if ret.uuid, err = useDb.GetValue(entryPath, "uuid"); err != nil {
return nil, errors.New("Unable to read entry uuid")
}
2017-07-28 11:44:08 +00:00
if ret.start, err = useDb.GetTimestamp(entryPath, "start"); err != nil {
return nil, errors.New("Unable to read entry start time")
}
if ret.end, err = useDb.GetTimestamp(entryPath, "end"); err != nil {
return nil, errors.New("Unable to read entry end time")
}
var keys []string
entryTagsPath := append(entryPath, "tags")
if keys, err = useDb.GetKeyList(entryTagsPath); err != nil {
keys = []string{}
}
2017-07-31 12:00:16 +00:00
ret.tags = new(TagCollection)
2017-07-28 11:44:08 +00:00
for i := range keys {
var val string
2017-07-31 12:00:16 +00:00
if val, err = useDb.GetValue(entryTagsPath, keys[i]); err == nil {
ret.tags.Push(val)
2017-07-28 11:44:08 +00:00
}
}
return ret, nil
}