Change logic for due dates. Previosuly they were 15 days after the first days of the quarters last month. Now, due dates are 15 days after the last day of the quarters last month.

Этот коммит содержится в:
Conor Macpherson
2023-01-05 15:31:58 -05:00
родитель bdd7cb4638
Коммит 8d604f715a
4 изменённых файлов: 210 добавлений и 145 удалений

Просмотреть файл

@@ -16,7 +16,6 @@ import (
"os"
"path/filepath"
"strconv"
"time"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
@@ -35,11 +34,6 @@ hwIDAQAB
var LicenseValidator LicenseValidatorIface
const trueUpReviewDueDay = 15
const businessQuarterStep = 3
const day = time.Hour * 24
const week = day * 7
func init() {
if LicenseValidator == nil {
LicenseValidator = &LicenseValidatorImpl{}
@@ -230,30 +224,3 @@ func GetSanitizedClientLicense(l map[string]string) map[string]string {
return sanitizedLicense
}
func GetNextTrueUpReviewDueDate(now time.Time) time.Time {
quaterEndMonths := []time.Month{time.March, time.June, time.September, time.December}
var nextQuarterEndMonth time.Month = time.March
for _, month := range quaterEndMonths {
if now.Month() <= month && now.Day() <= trueUpReviewDueDay {
nextQuarterEndMonth = month
break
} else if now.Month() <= month && now.Day() > trueUpReviewDueDay {
nextQuarterEndMonth = month + businessQuarterStep
break
}
}
return time.Date(now.Year(), nextQuarterEndMonth, trueUpReviewDueDay, 0, 0, 0, 0, now.Location())
}
func IsTrueUpReviewDueDateWithinTheNextTwoWeeks(now time.Time, dueDate time.Time) bool {
dueDateWindow := dueDate.Add(-(week * 2))
if now.Before(dueDateWindow) || now.After(dueDate) {
return false
}
return true
}

Просмотреть файл

@@ -8,7 +8,6 @@ import (
"encoding/base64"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -92,114 +91,3 @@ func TestGetLicenseFileFromDisk(t *testing.T) {
assert.False(t, success, "should have been an invalid file")
})
}
func TestGetNextTrueUpReviewDueDate(t *testing.T) {
t.Run("Due date always falls on the 15th", func(t *testing.T) {
// Before the 15th
now := time.Date(2022, 12, 14, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, due.Day(), trueUpReviewDueDay)
// On the 15th
now = time.Date(2022, 12, 15, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, due.Day(), trueUpReviewDueDay)
// After the 15th
now = time.Date(2022, 12, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, due.Day(), trueUpReviewDueDay)
})
t.Run("Due date will always be in next quarter if the current date is past the 15th", func(t *testing.T) {
now := time.Date(2022, time.March, 16, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.June, due.Month())
now = time.Date(2022, time.June, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.September, due.Month())
now = time.Date(2022, time.September, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.December, due.Month())
now = time.Date(2022, time.December, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.March, due.Month())
})
t.Run("Due date will always be in the current quarter if the current date is before or on the 15th", func(t *testing.T) {
now := time.Date(2022, time.March, 15, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.March, due.Month())
now = time.Date(2022, time.June, 15, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.June, due.Month())
now = time.Date(2022, time.September, 14, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.September, due.Month())
now = time.Date(2022, time.December, 14, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.December, due.Month())
})
t.Run("Due date will be in the next year if the next quarter is not within the current year", func(t *testing.T) {
now := time.Date(2022, time.December, 18, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.March, due.Month())
assert.Equal(t, 2023, due.Year())
})
}
func TestIsTrueUpReviewDueDateWithinTheNextTwoWeeks(t *testing.T) {
t.Run("Ensure a date within two weeks before the due date returns true", func(t *testing.T) {
// 1 Day before the due date
now := time.Date(2022, time.December, 14, 0, 0, 0, 0, time.Local)
// Due date is December 15th, 2022
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNextTwoWeeks(now, due)
assert.True(t, res)
})
t.Run("Ensure a date that is more than two weeks before the due date returns false", func(t *testing.T) {
// 15 Days before the due date
now := time.Date(2022, time.November, 30, 0, 0, 0, 0, time.Local)
// Due date is December 15th, 2022
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNextTwoWeeks(now, due)
assert.False(t, res)
})
t.Run("Ensure a date that past the due date returns false", func(t *testing.T) {
now := time.Date(2022, time.December, 16, 0, 0, 0, 0, time.Local)
// Due date is December 15th, 2022
dueNow := time.Date(2022, time.December, 15, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(dueNow)
res := IsTrueUpReviewDueDateWithinTheNextTwoWeeks(now, due)
assert.False(t, res)
})
t.Run("Ensure a date that is on the due date returns true", func(t *testing.T) {
now := time.Date(2022, time.December, 15, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNextTwoWeeks(now, due)
assert.True(t, res)
})
t.Run("Ensure a date that is on the first day of the due date window returns true", func(t *testing.T) {
now := time.Date(2022, time.December, 1, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNextTwoWeeks(now, due)
assert.True(t, res)
})
}

85
utils/true_up.go Обычный файл
Просмотреть файл

@@ -0,0 +1,85 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package utils
import (
"fmt"
"time"
)
const trueUpReviewDueDay = 15
const day = time.Hour * 24
const week = day * 7
type DueDateWindow struct {
Start time.Time
End time.Time
}
func GetNextTrueUpReviewDueDate(now time.Time) time.Time {
nowYear := now.Year()
nowMonth := now.Month()
nowDay := now.Day()
finalQuarterYear := nowYear
if nowMonth >= time.October && nowMonth <= time.December {
finalQuarterYear = nowYear + 1
}
trueUpSubmissionWindows := []DueDateWindow{
{
Start: time.Date(now.Year(), time.January, 16, 0, 0, 0, 0, now.Location()),
End: time.Date(now.Year(), time.April, 15, 0, 0, 0, 0, now.Location()),
},
{
Start: time.Date(now.Year(), time.April, 16, 0, 0, 0, 0, now.Location()),
End: time.Date(now.Year(), time.July, 15, 0, 0, 0, 0, now.Location()),
},
{
Start: time.Date(now.Year(), time.July, 16, 0, 0, 0, 0, now.Location()),
End: time.Date(now.Year(), time.October, 15, 0, 0, 0, 0, now.Location()),
},
{
Start: time.Date(now.Year(), time.October, 16, 0, 0, 0, 0, now.Location()),
End: time.Date(finalQuarterYear, time.January, 15, 0, 0, 0, 0, now.Location()),
},
}
for _, window := range trueUpSubmissionWindows {
withinWindow := false
// Our due dates "wrap" around, so we'll need to check the months different. Since January = 1 and December = 12, the checks
// for the current month being greater or equal to the start month and less than or equal to the end month will not work.
if window.End.Month() == time.January {
withinWindow = (nowMonth != time.January && nowMonth >= window.Start.Month()) || nowMonth == window.End.Month()
} else {
withinWindow = nowMonth >= window.Start.Month() && nowMonth <= window.End.Month()
fmt.Printf("now month: %s, window start month: %s, window end month: %s\n", now.Format("Jan"), window.Start.Format("Jan"), window.End.Format("Jan"))
}
// Only check the days if the current month is equal to the start or end months.
// The dates of the middle month(s) don't matter so much.
isFirstMonth := nowMonth == window.Start.Month()
if isFirstMonth {
withinWindow = withinWindow && nowDay >= window.Start.Day()
}
isFinalMonth := nowMonth == window.End.Month()
if isFinalMonth {
withinWindow = withinWindow && nowDay <= window.End.Day()
}
if withinWindow {
return window.End
}
}
return trueUpSubmissionWindows[0].End
}
func IsTrueUpReviewDueDateWithinTheNext30Days(now time.Time, dueDate time.Time) bool {
dueDateWindow := dueDate.Add(-day * 30)
if now.Before(dueDateWindow) || now.After(dueDate) {
return false
}
return true
}

125
utils/true_up_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,125 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package utils
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestGetNextTrueUpReviewDueDate(t *testing.T) {
t.Run("Due date always falls on the 15th", func(t *testing.T) {
// Before the 15th
now := time.Date(2022, 12, 14, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, due.Day(), trueUpReviewDueDay)
// On the 15th
now = time.Date(2022, 12, 15, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, due.Day(), trueUpReviewDueDay)
// After the 15th
now = time.Date(2022, 12, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, due.Day(), trueUpReviewDueDay)
})
t.Run("Due date will always be in next quarter if the current date is past the 15th", func(t *testing.T) {
now := time.Date(2022, time.March, 16, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.April, due.Month())
now = time.Date(2022, time.June, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.July, due.Month())
now = time.Date(2022, time.September, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.October, due.Month())
now = time.Date(2022, time.December, 16, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.January, due.Month())
})
t.Run("Due date will always be in the current quarter if the current date is before or on the 15th", func(t *testing.T) {
now := time.Date(2022, time.April, 15, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.April, due.Month())
now = time.Date(2022, time.July, 15, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.July, due.Month())
now = time.Date(2022, time.October, 14, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.October, due.Month())
now = time.Date(2022, time.January, 14, 0, 0, 0, 0, time.Local)
due = GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.January, due.Month())
})
t.Run("Due date will be in the next year if the next quarter is not within the current year", func(t *testing.T) {
now := time.Date(2022, time.October, 21, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
assert.Equal(t, time.January, due.Month())
assert.Equal(t, 2023, due.Year())
})
}
func TestIsTrueUpReviewDueDateWithinTheNext15Days(t *testing.T) {
t.Run("Ensure a date within 30 days before the due date returns true", func(t *testing.T) {
// 1 Day before the due date
now := time.Date(2022, time.March, 16, 0, 0, 0, 0, time.Local)
// Due date is December 15th, 2022
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNext30Days(now, due)
assert.True(t, res)
})
t.Run("Ensure a date that is more than two weeks before the due date returns false", func(t *testing.T) {
// 15 Days before the due date
now := time.Date(2022, time.October, 16, 0, 0, 0, 0, time.Local)
// Due date is December 15th, 2022
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNext30Days(now, due)
assert.False(t, res)
})
t.Run("Ensure a date that is past the due date returns false", func(t *testing.T) {
now := time.Date(2022, time.April, 15, 0, 0, 0, 0, time.Local)
// Due date is April 16th, 2022
dueNow := time.Date(2022, time.April, 16, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(dueNow)
res := IsTrueUpReviewDueDateWithinTheNext30Days(now, due)
assert.False(t, res)
})
t.Run("Ensure a date that is on the due date returns true", func(t *testing.T) {
now := time.Date(2022, time.January, 15, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
fmt.Printf("\n\ndue date: %s\n\n", due.Format("2006-Jan-02"))
fmt.Printf("\n\nnow: %s\n\n", now.Format("2006-Jan-02"))
res := IsTrueUpReviewDueDateWithinTheNext30Days(now, due)
assert.True(t, res)
})
t.Run("Ensure a date that is on the first day of the due date window returns true", func(t *testing.T) {
now := time.Date(2022, time.December, 16, 0, 0, 0, 0, time.Local)
due := GetNextTrueUpReviewDueDate(now)
res := IsTrueUpReviewDueDateWithinTheNext30Days(now, due)
assert.True(t, res)
})
}