Implement time off management (Issue #3)
Add full time-off lifecycle: create/edit/delete with shift conflict detection, auto-removal from conflicting shifts with admin notification, shift restoration on admin delete, and hard block on assigning volunteers with approved time off to shifts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -200,7 +200,7 @@ func do(t *testing.T, router http.Handler, method, path, body, token string) *ht
|
||||
func TestListTemplates_ReturnsEmpty(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -219,7 +219,7 @@ func TestListTemplates_ReturnsEmpty(t *testing.T) {
|
||||
func TestCreateTemplate_AdminOnly(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 2, "volunteer")
|
||||
@@ -235,7 +235,7 @@ func TestCreateTemplate_AdminOnly(t *testing.T) {
|
||||
func TestCreateTemplate_Success(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -256,7 +256,7 @@ func TestCreateTemplate_Success(t *testing.T) {
|
||||
func TestCreateTemplate_MissingFields(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -271,7 +271,7 @@ func TestCreateTemplate_MissingFields(t *testing.T) {
|
||||
func TestDeleteTemplate_AdminOnly(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 2, "volunteer")
|
||||
@@ -285,7 +285,7 @@ func TestDeleteTemplate_AdminOnly(t *testing.T) {
|
||||
func TestDeleteTemplate_Success(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -303,7 +303,7 @@ func TestDeleteTemplate_Success(t *testing.T) {
|
||||
func TestGenerateInstances_AdminOnly(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 2, "volunteer")
|
||||
@@ -318,7 +318,7 @@ func TestGenerateInstances_AdminOnly(t *testing.T) {
|
||||
func TestGenerateInstances_AlreadyExists(t *testing.T) {
|
||||
store := &fakeStore{genErr: schedule.ErrAlreadyExists}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -337,7 +337,7 @@ func TestGenerateInstances_Success(t *testing.T) {
|
||||
},
|
||||
}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -362,7 +362,7 @@ func TestPublishMonth_SendsNotifications(t *testing.T) {
|
||||
},
|
||||
}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -380,7 +380,7 @@ func TestPublishMonth_SendsNotifications(t *testing.T) {
|
||||
func TestUnpublishMonth_SendsNotifications(t *testing.T) {
|
||||
store := &fakeStore{unpubResult: []int64{10, 20}}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -398,7 +398,7 @@ func TestUnpublishMonth_SendsNotifications(t *testing.T) {
|
||||
func TestUpdateInstance_AdminOnly(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 2, "volunteer")
|
||||
@@ -424,7 +424,7 @@ func TestUpdateInstance_PublishedResetsAndNotifies(t *testing.T) {
|
||||
addedVols: []int64{6}, // Bob is newly added
|
||||
}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 1, "admin")
|
||||
@@ -446,7 +446,7 @@ func TestUpdateInstance_PublishedResetsAndNotifies(t *testing.T) {
|
||||
func TestConfirmShift_NotAssigned(t *testing.T) {
|
||||
store := &fakeStore{confirmErr: schedule.ErrNotFound}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 5, "volunteer")
|
||||
@@ -460,7 +460,7 @@ func TestConfirmShift_NotAssigned(t *testing.T) {
|
||||
func TestConfirmShift_Success(t *testing.T) {
|
||||
store := &fakeStore{}
|
||||
notifier := &fakeNotifier{}
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier)
|
||||
h := schedule.NewHandlerFromInterfaces(store, notifier, nil)
|
||||
router := newRouter(h)
|
||||
|
||||
token := jwtForRole(t, 5, "volunteer")
|
||||
|
||||
Reference in New Issue
Block a user