Skip to content

Commit

Permalink
Merge pull request #83 from varianter/fix/invert-availability
Browse files Browse the repository at this point in the history
fix: show booked hours instead of non-booked hours
  • Loading branch information
jonasbjoralt authored Sep 29, 2023
2 parents 8996f9c + 2ec2f8d commit 1a3dee1
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 43 deletions.
12 changes: 9 additions & 3 deletions backend/Api/Routes/ConsultantApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ private static Ok<List<ConsultantReadModel>> GetAllConsultants(ApplicationContex
var consultants = GetConsultantsWithAvailability(context, cache, numberOfWeeks)
.Where(c =>
includeOccupied
|| c.Availability.Select(a => a.AvailableHours).Sum() > 0
|| c.HasAvailability
).ToList();

return TypedResults.Ok(consultants);
Expand All @@ -41,13 +41,19 @@ private static Ok<ConsultantReadModel> GetConsultantById(ApplicationContext cont

private static ConsultantReadModel MapToReadModel(this Consultant consultant, int weeks)
{
const double tolerance = 0.1;
var bookedHours = consultant.GetBookedHoursForWeeks(weeks);

var hasAvailability = bookedHours.Any(b => b.BookedHours <= consultant.GetHoursPrWeek() - tolerance);

return new ConsultantReadModel(
consultant.Id,
consultant.Name,
consultant.Email,
consultant.Competences.Select(comp => comp.Name).ToList(),
consultant.Department.Name,
consultant.GetAvailableHoursForNWeeks(weeks));
bookedHours,
hasAvailability);
}

private static List<ConsultantReadModel> GetConsultantsWithAvailability(ApplicationContext context,
Expand Down Expand Up @@ -132,7 +138,7 @@ private static async Task<Created<Consultant>> AddBasicConsultant(ApplicationCon
}

private record ConsultantReadModel(int Id, string Name, string Email, List<string> Competences, string Department,
List<AvailabilityPerWeek> Availability);
List<BookedHoursPerWeek> Bookings, bool HasAvailability);

private record ConsultantWriteModel(string Name, string Email, string DepartmentId);
}
34 changes: 18 additions & 16 deletions backend/Core/DomainModels/Consultant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@ public class Consultant

public List<Staffing> Staffings { get; set; } = new();

public double GetAvailableHours(int year, int week)
public double GetBookedHours(int year, int week)
{
var hoursPrWorkDay = Department.Organization.HoursPerWorkday;
var holidays = Holiday.GetTotalHolidaysOfWeek(year, week);
var vacations = Vacations.Count(v => DateService.DateIsInWeek(v.Date, year, week));
var workdaysInWeek = 5 - holidays - vacations;

var workHoursInWeek = hoursPrWorkDay * workdaysInWeek;
var holidayHours = Holiday.GetTotalHolidaysOfWeek(year, week) * hoursPrWorkDay;
var vacationHours = Vacations.Count(v => DateService.DateIsInWeek(v.Date, year, week)) * hoursPrWorkDay;

var plannedAbsenceHours = PlannedAbsences
.Where(pa => pa.Year == year && pa.WeekNumber == week)
Expand All @@ -48,26 +45,31 @@ public double GetAvailableHours(int year, int week)
.Select(s => s.Hours)
.Sum();

var availableHours = workHoursInWeek - plannedAbsenceHours - staffedHours;
return Math.Max(availableHours, 0);
var bookedHours = holidayHours + vacationHours + plannedAbsenceHours + staffedHours;
return Math.Min(bookedHours, 5 * hoursPrWorkDay);
}

public List<AvailabilityPerWeek> GetAvailableHoursForNWeeks(int n)
public List<BookedHoursPerWeek> GetBookedHoursForWeeks(int weeksAhead)
{
return Enumerable.Range(0, n)
.Select(weeksAhead =>
return Enumerable.Range(0, weeksAhead)
.Select(offset =>
{
var year = DateTime.Today.AddDays(7 * weeksAhead).Year;
var week = DateService.GetWeekAhead(weeksAhead);
var year = DateTime.Today.AddDays(7 * offset).Year;
var week = DateService.GetWeekAhead(offset);

return new AvailabilityPerWeek(
return new BookedHoursPerWeek(
year,
week,
GetAvailableHours(year, week)
GetBookedHours(year, week)
);
})
.ToList();
}

public double GetHoursPrWeek()
{
return Department.Organization.HoursPerWorkday * 5;
}
}

public class Competence
Expand All @@ -85,4 +87,4 @@ public enum Degree
None
}

public record AvailabilityPerWeek(int Year, int WeekNumber, double AvailableHours);
public record BookedHoursPerWeek(int Year, int WeekNumber, double BookedHours);
34 changes: 17 additions & 17 deletions backend/Tests/AbsenceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ namespace Tests;

public class Tests
{
[TestCase(2, 15, 0, 0, 7.5)]
[TestCase(0, 7.5, 0, 0, 30)]
[TestCase(5, 37.5, 0, 0, 0)]
[TestCase(0, 0, 0, 0, 37.5)]
[TestCase(5, 30, 0, 0, 0)]
[TestCase(5, 0, 0, 0, 0)]
[TestCase(5, 37.5, 0, 0, 0)]
[TestCase(0, 0, 1, 0, 30.0)]
[TestCase(0, 0, 2, 0, 22.5)]
[TestCase(0, 0, 5, 0, 0)]
[TestCase(0, 0, 0, 37.5, 0)]
[TestCase(0, 0, 0, 30, 7.5)]
[TestCase(0, 7.5, 0, 22.5, 7.5)]
[TestCase(2, 15, 0, 0, 30)]
[TestCase(0, 7.5, 0, 0, 7.5)]
[TestCase(5, 37.5, 0, 0, 37.5)]
[TestCase(0, 0, 0, 0, 0)]
[TestCase(5, 30, 0, 0, 37.5)]
[TestCase(5, 0, 0, 0, 37.5)]
[TestCase(5, 37.5, 0, 0, 37.5)]
[TestCase(0, 0, 1, 0, 7.5)]
[TestCase(0, 0, 2, 0, 15)]
[TestCase(0, 0, 5, 0, 37.5)]
[TestCase(0, 0, 0, 37.5, 37.5)]
[TestCase(0, 0, 0, 30, 30)]
[TestCase(0, 7.5, 0, 22.5, 30)]
public void AvailabilityCalculation(int vacationDays, double plannedAbsenceHours, int numberOfHolidays,
double staffedHours,
double expectedAvailability)
double expectedBookedHours)
{
var department = Substitute.For<Department>();
var organization = Substitute.For<Organization>();
Expand Down Expand Up @@ -75,8 +75,8 @@ public void AvailabilityCalculation(int vacationDays, double plannedAbsenceHours
Hours = staffedHours
});

var availability = consultant.GetAvailableHours(year, week);
Assert.That(availability, Is.EqualTo(expectedAvailability));
var availability = consultant.GetBookedHours(year, week);
Assert.That(availability, Is.EqualTo(expectedBookedHours));
}

[Test]
Expand Down Expand Up @@ -110,7 +110,7 @@ public void MultiplePlannedAbsences()
Hours = 15
});

var availability = consultant.GetAvailableHours(year, week);
var availability = consultant.GetBookedHours(year, week);
Assert.That(availability, Is.EqualTo(7.5));
}
}
10 changes: 5 additions & 5 deletions frontend/src/app/variant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export function VariantList() {
<th>Email</th>
<th>Department</th>
<th>Competences</th>
{data[0].availability.map((availabilityWeek) => (
<th key={availabilityWeek.weekNumber}>
W# {availabilityWeek.weekNumber}
{data[0].bookings.map((weeklyBooking) => (
<th key={weeklyBooking.weekNumber}>
W# {weeklyBooking.weekNumber}
</th>
))}
</tr>
Expand All @@ -52,9 +52,9 @@ export function VariantList() {
<td>{variant.email}</td>
<td>{variant.department}</td>
<td>{variant.competences.join(", ")}</td>
{variant.availability.map((a) => (
{variant.bookings.map((a) => (
<td key={`${variant.id}/${a.weekNumber}`}>
{a.availableHours}
{a.bookedHours}
</td>
))}
</tr>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ export type Variant = {
email: string;
competences: string[];
department: string;
availability: [
bookings: [
{
year: number;
weekNumber: number;
availableHours: number;
bookedHours: number;
},
];
};
Expand Down

0 comments on commit 1a3dee1

Please sign in to comment.