Skip to content

Commit

Permalink
Mer informative røde dager
Browse files Browse the repository at this point in the history
  • Loading branch information
Pål Bøckmann committed Nov 3, 2024
1 parent f5c3265 commit 91119db
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,15 @@ private async Task UpdateRegisteredFlex(List<TimeEntryWithCompRateDto> entriesOn
CompensationRate = eo.Key,
Hours = eo.Sum(entry => entry.Hours)
}).OrderByDescending(e => e.CompensationRate);

var imposedOverTime = availableOvertime.Entries.Where(ot => ot.Date <= date && ot.CompensationRate >= 2.0M)
.GroupBy(eo => eo.CompensationRate)
.Select(eo => new
{
CompensationRate = eo.Key,
Hours = eo.Sum(entry => entry.Hours)
}).OrderByDescending(e => e.CompensationRate);

var overtimeGroupedByCompRate = nonImposedOverTime.Concat(imposedOverTime).ToList(); //Imposed overtime should be subtracted last

foreach (var overtimeGroup in overtimeGroupedByCompRate)
Expand Down Expand Up @@ -186,16 +186,26 @@ private async Task<List<Error>> ValidateTimeEntry(CreateTimeEntryDto timeEntry)
return usersEmploymentRateResult.Errors;
}

var anticipatedWorkHours =
IsWeekend(timeEntry.Date.Date) || allRedDays.Contains(timeEntry.Date.Date)
? 0M
: HoursInWorkday * usersEmploymentRateResult.Value;
var anticipatedWorkHours = HoursInWorkday * usersEmploymentRateResult.Value;

if (timeEntry.TaskId == _paidHolidayTask && timeEntry.Value > 0 && timeEntry.Value != anticipatedWorkHours)
{
return new List<Error> { new(ErrorCodes.InvalidAction, $"Du kan kun føre 0 eller {anticipatedWorkHours} timer med ferie på en dag") };
return new List<Error>
{
new(ErrorCodes.InvalidAction,
$"Du kan kun føre 0 eller {anticipatedWorkHours} timer med ferie på en dag")
};
}

if (IsWeekend(timeEntry.Date.Date) || allRedDays.Contains(timeEntry.Date.Date))
{
if (timeEntry.TaskId == _paidHolidayTask && timeEntry.Value > 0)
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Du trenger ikke føre ferie på helg eller røde dager") };
}
}


if (timeEntry.TaskId == _flexTask)
{
var availableHours = await GetAvailableOvertimeHoursAtDate(timeEntry.Date.Date);
Expand All @@ -209,15 +219,20 @@ private async Task<List<Error>> ValidateTimeEntry(CreateTimeEntryDto timeEntry)

if (timeEntry.Value > availableForFlex)
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Ikke nok tilgjengelige timer til å avspasere.") };
return new List<Error>
{ new(ErrorCodes.InvalidAction, "Ikke nok tilgjengelige timer til å avspasere.") };
}
}

if (PayoutWouldBeAffectedByRegistration(timeEntry, latestPayoutDate, timeEntriesOnDate.Values, anticipatedWorkHours))
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Du har registrert en utbetaling som vil bli påvirket av denne timeføringen. Slett utbetalingen eller kontakt en admin for å få endret timene dine.") };
return new List<Error>
{
new(ErrorCodes.InvalidAction,
"Du har registrert en utbetaling som vil bli påvirket av denne timeføringen. Slett utbetalingen eller kontakt en admin for å få endret timene dine.")
};
}

if (await FutureFlexWouldCauseNegativeBalance(timeEntriesOnDate.Values, currentUser.Id, anticipatedWorkHours, timeEntry))
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Fremtidig avspasering vil resultere i negativ balanse.") };
Expand All @@ -238,38 +253,52 @@ private async Task<List<Error>> ValidateTimeEntry(CreateTimeEntryDto timeEntry)
if (timeEntriesOnDate.Values.Sum(te => te.Value) > anticipatedWorkHours &&
timeEntriesOnDate.Values.Any(te => te.TaskId == _flexTask && te.Value > 0))
{
return new List<Error> { new(ErrorCodes.InvalidAction, $"Du kan ikke registrere mer enn {anticipatedWorkHours:0.00} timer når du avspaserer.") };
return new List<Error>
{
new(ErrorCodes.InvalidAction, $"Du kan ikke registrere mer enn {anticipatedWorkHours:0.00} timer når du avspaserer.")
};
}

if (PayoutWouldBeAffectedByRegistration(timeEntry, latestPayoutDate, timeEntriesOnDate.Values,
anticipatedWorkHours))
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Du har registrert en utbetaling som vil bli påvirket av denne timeføringen. Slett utbetalingen eller kontakt en admin for å få endret timene dine.") };
return new List<Error>
{
new(ErrorCodes.InvalidAction, "Du har registrert en utbetaling som vil bli påvirket av denne timeføringen. Slett utbetalingen eller kontakt en admin for å få endret timene dine.")
};
}

if (timeEntry.TaskId == _flexTask)
{
if (latestPayoutDate != null && timeEntry.Date.Date <= latestPayoutDate)
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Du har registrert en utbetaling som vil bli påvirket av denne timeføringen. Slett utbetalingen eller kontakt en admin for å få endret timene dine.") };
return new List<Error>
{
new(ErrorCodes.InvalidAction, "Du har registrert en utbetaling som vil bli påvirket av denne timeføringen. Slett utbetalingen eller kontakt en admin for å få endret timene dine.")
};
}
}

var taskGivesOvertime = await _taskUtils.TaskGivesOvertime(timeEntry.TaskId);
if (timeEntry.Value > anticipatedWorkHours && !taskGivesOvertime)
{
return new List<Error> { new(ErrorCodes.InvalidAction, $"Du kan ikke registrere mer enn {anticipatedWorkHours:0.00} timer på den oppgaven.") };
return new List<Error>
{
new(ErrorCodes.InvalidAction, $"Du kan ikke registrere mer enn {anticipatedWorkHours:0.00} timer på den oppgaven.")
};
}

if (!taskGivesOvertime &&
timeEntry.Date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday)
{
return new List<Error> { new(ErrorCodes.InvalidAction, "Du kan ikke registrere den oppgaven på en helgedag.") };
}

return new List<Error>();
}

private async Task<bool> FutureFlexWouldCauseNegativeBalance(IEnumerable<TimeEntryResponseDto> timeEntriesOnDate,
private async Task<bool> FutureFlexWouldCauseNegativeBalance(
IEnumerable<TimeEntryResponseDto> timeEntriesOnDate,
int currentUserId, decimal anticipatedWorkHours, CreateTimeEntryDto createTimeEntryDto)
{
var date = createTimeEntryDto.Date.Date;
Expand Down Expand Up @@ -311,14 +340,17 @@ private async Task<bool> FutureFlexWouldCauseNegativeBalance(IEnumerable<TimeEnt
UserId = currentUserId,
FromDateInclusive = date,
})).ToList();

if (newTotalOnDay < oldTotalOnDay && futureFlex.Any())
{
foreach (var flexEntry in futureFlex)
{
var availableOtOnDay = await GetAvailableOvertimeHoursAtDate(flexEntry.Date);
var diffInOvertime = newTotalOnDay < anticipatedWorkHours ? oldTotalOnDay - anticipatedWorkHours : oldTotalOnDay - newTotalOnDay;
var newAvailableOvertimeAfterChange = availableOtOnDay.AvailableHoursBeforeCompensation - diffInOvertime;
var diffInOvertime = newTotalOnDay < anticipatedWorkHours
? oldTotalOnDay - anticipatedWorkHours
: oldTotalOnDay - newTotalOnDay;
var newAvailableOvertimeAfterChange =
availableOtOnDay.AvailableHoursBeforeCompensation - diffInOvertime;

if (newAvailableOvertimeAfterChange < flexEntry.Hours)
{
Expand Down Expand Up @@ -455,8 +487,7 @@ public async Task<AvailableOvertimeDto> GetAvailableOvertimeHoursAtDate(DateTime
};
}

private async Task<List<TimeEntry>> CompensateForFlexedHours(List<TimeEntry> timeEntries, DateTime toDateInclusive,
User currentUser = null)
private async Task<List<TimeEntry>> CompensateForFlexedHours(List<TimeEntry> timeEntries, DateTime toDateInclusive, User currentUser = null)
{
if (currentUser is null)
{
Expand All @@ -482,7 +513,8 @@ private async Task<List<TimeEntry>> CompensateForFlexedHours(List<TimeEntry> tim
return compensatedFlexHours;
}

private async Task<List<TimeEntry>> CompensateForPayouts(List<TimeEntry> overtimeEntries, DateTime toDateInclusive,
private async Task<List<TimeEntry>> CompensateForPayouts(List<TimeEntry> overtimeEntries,
DateTime toDateInclusive,
User currentUser = null)
{
if (currentUser is null)
Expand Down Expand Up @@ -536,8 +568,11 @@ private async Task StoreNewOvertime(List<TimeEntryWithCompRateDto> timeEntriesOn
{
return;
}

var anticipatedWorkHours =
IsWeekend(timeEntryDate) || allRedDays.Contains(timeEntryDate) ? 0M : HoursInWorkday * usersEmploymentRateResult.Value;
IsWeekend(timeEntryDate) || allRedDays.Contains(timeEntryDate)
? 0M
: HoursInWorkday * usersEmploymentRateResult.Value;

var normalWorkHoursLeft = anticipatedWorkHours;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ await _payoutService.RegisterPayout(new GenericPayoutHourEntry
}

[Fact]
public async System.Threading.Tasks.Task UpsertTimeEntry_RecordedVacationOnChristmas_CannotRegisterVactionOnRedDay()
public async System.Threading.Tasks.Task UpsertTimeEntry_RecordedVacationOnChristmas_CannotRegisterVacationOnRedDay()
{
var vacationEntry =
CreateTimeEntryForExistingTask(new DateTime(2021, 12, 24), 7.5M, 13);
Expand All @@ -119,6 +119,7 @@ public async System.Threading.Tasks.Task UpsertTimeEntry_RecordedVacationOnChris

Assert.False(timeEntryResult.IsSuccess);
Assert.True(timeEntryResult.Errors.Any());
Assert.True(timeEntryResult.Errors.First().Description.Equals("Du trenger ikke føre ferie på helg eller røde dager"));
}

[Fact]
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/src/services/holidays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ function createNorwegianHolidaysForYear(yearNumber: number) {
},
{ date: easter.clone().add(49, "days"), description: "Første pinsedag" },
{ date: easter.clone().add(50, "days"), description: "Andre pinsedag" },
{ date: moment(yearString + "-12-24"), description: "Juleaften" },
{ date: moment(yearString + "-12-25"), description: "Første juledag" },
{ date: moment(yearString + "-12-26"), description: "Andre juledag" },
{ date: moment(yearString + "-12-31"), description: "Nyttårsaften" },
];

return norwegianHolidays;
Expand Down

0 comments on commit 91119db

Please sign in to comment.