Skip to content

Commit

Permalink
Working PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasbjoralt committed Nov 6, 2023
1 parent 3d75a81 commit bc7b644
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 11 deletions.
94 changes: 91 additions & 3 deletions backend/Api/Consultants/ConsultantController.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics;
using Api.Cache;
using Core.DomainModels;
using Core.Services;
Expand Down Expand Up @@ -31,6 +32,8 @@ public ActionResult<List<ConsultantReadModel>> Get(
[FromQuery(Name = "weeks")] int numberOfWeeks = 8,
[FromQuery(Name = "includeOccupied")] bool includeOccupied = true)
{
var watch = Stopwatch.StartNew();

var selectedYear = selectedYearParam ?? DateTime.Now.Year;
var selectedWeekNumber = selectedWeekParam ?? DateService.GetWeekNumber(DateTime.Now);
var selectedWeek = new Week(selectedYear, selectedWeekNumber);
Expand All @@ -41,14 +44,76 @@ public ActionResult<List<ConsultantReadModel>> Get(
)
.ToList();

return Ok(consultants);
watch.Stop();

return Ok(new { Time = watch.ElapsedMilliseconds, Data = consultants });
}

[HttpGet("perf")]
public ActionResult<List<ConsultantReadModel>> GetFast()
{
var watch = Stopwatch.StartNew();

var weekSet = DateService.GetNextWeeks(new Week(2023, 44), 8);

var minDate = new DateOnly(2023, 11, 1);
var maxDate = new DateOnly(2023, 12, 1);

var year = weekSet[0].Year;
var minWeek = weekSet.Select(w => w.WeekNumber).Min();
var maxWeek = weekSet.Select(w => w.WeekNumber).Min();


var consultants = _context.Consultant.Include(consultant => consultant.Department)
.ThenInclude(department => department.Organization).ToList();

var projects = _context.Project.Include(p => p.Customer)
.ToDictionary(project => project.Id, project => project);
var absences = _context.Absence.ToDictionary(absence => absence.Id, absence => absence);

var billableStaffings = LoadStaffingByProjectTypeForWeeks(weekSet, ProjectState.Active);
var offeredStaffings = LoadStaffingByProjectTypeForWeeks(weekSet, ProjectState.Offer);

var plannedAbsences = _context.PlannedAbsence
.Include(plannedAbsence => plannedAbsence.Consultant)
.Include(plannedAbsence => plannedAbsence.Absence)
.Where(absence => absence.Year == year && minWeek <= absence.WeekNumber && absence.WeekNumber <= maxWeek)
.GroupBy(plannedAbsence =>
new StaffingGroupKey(plannedAbsence.Consultant.Id, plannedAbsence.Absence.Id, plannedAbsence.Year,
plannedAbsence.WeekNumber))
.ToList();


var vacations = _context.Vacation
.Where(vacation => minDate <= vacation.Date && vacation.Date <= maxDate)
.Include(vacation => vacation.Consultant)
.GroupBy(vacation => vacation.Consultant.Id)
.ToList();

var a = consultants.Select(c =>
{
var billableSet = billableStaffings.Where(g =>
g.Key.ConsultantId == c.Id);
var offeredSet = offeredStaffings
.Where(g => g.Key.ConsultantId == c.Id);
var absenceSet = plannedAbsences.Where(g => g.Key.ConsultantId == c.Id);

var consultantVacations = vacations.Where(g => g.Key == c.Id).Aggregate(new List<Vacation>(),
(list, grouping) => list.Concat(grouping.Select(v => v)).ToList());

return ConsultantReadModel.FromController(c, projects, absences, billableSet, offeredSet, absenceSet,

Check failure on line 104 in backend/Api/Consultants/ConsultantController.cs

View workflow job for this annotation

GitHub Actions / dotnet_core_project_tests (7.x.x)

'ConsultantReadModel' does not contain a definition for 'FromController'
consultantVacations, weekSet);
}).ToList();
watch.Stop();

return Ok(new { Time = watch.ElapsedMilliseconds, Data = a });
}


private List<ConsultantReadModel> GetConsultantsWithAvailability(string orgUrlKey, Week initialWeekNumber,
int numberOfWeeks)
{
if (numberOfWeeks == 8)
if (numberOfWeeks == 8 && false)
{
_cache.TryGetValue(
$"{orgUrlKey}/{initialWeekNumber}/{CacheKeys.ConsultantAvailability8Weeks}",
Expand All @@ -63,6 +128,25 @@ private List<ConsultantReadModel> GetConsultantsWithAvailability(string orgUrlKe
return consultants;
}

private List<IGrouping<StaffingGroupKey, Staffing>> LoadStaffingByProjectTypeForWeeks(List<Week> weeks,
ProjectState state)
{
var year = weeks[0].Year;
var minWeek = weeks.Select(w => w.WeekNumber).Min();
var maxWeek = weeks.Select(w => w.WeekNumber).Min();


return _context.Staffing
.Where(staffing => staffing.Year == year && minWeek <= staffing.Week && staffing.Week <= maxWeek)
.Where(staffing =>
staffing.Project.State == state)
.Include(s => s.Consultant)
.Include(staffing => staffing.Project)
.GroupBy(s => new StaffingGroupKey(s.Consultant.Id, s.Project.Id, s.Year, s.Week))
.ToList();
}


private List<Consultant> LoadConsultantAvailability(string orgUrlKey, Week selectedWeek, int numberOfWeeks)
{
var applicableWeeks = DateService.GetNextWeeks(selectedWeek, numberOfWeeks);
Expand Down Expand Up @@ -109,4 +193,8 @@ private List<Consultant> LoadConsultantAvailability(string orgUrlKey, Week selec
.OrderBy(c => c.Name)
.ToList();
}
}
}

public record StaffingGroupKey(int ConsultantId, int WorkTypeId, int Year, int Week);

public record WeeklyBooking(int YearWeek, double TotalBillable, double TotalOffered);
17 changes: 11 additions & 6 deletions backend/Core/DomainModels/Week.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ public Week(int year, int weekNumber)

public int Year { get; set; }
public int WeekNumber { get; set; }

public override string ToString()
{
return ($"{Year}{WeekNumber}");
}



public int CompareTo(Week? other)
{
Expand All @@ -35,4 +30,14 @@ public bool Equals(Week? other)
if (other is null) return false;
return Year == other.Year && WeekNumber == other.WeekNumber;
}

public override string ToString()
{
return $"{Year}{WeekNumber}";
}

public int ToSortableInt()
{
return int.Parse($"{Year}{WeekNumber}");
}
}
10 changes: 8 additions & 2 deletions backend/Core/Services/DateService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,20 @@ public static int GetWeekNumber(DateTime time)
DayOfWeek.Monday);
}

public static Week GetWeek(DateOnly date)
{
var weekNum = GetWeekNumber(date.ToDateTime(TimeOnly.MinValue));
return new Week(date.Year, weekNum);
}

public static int GetWeekAhead(int offset)
{
return GetWeekNumber(DateTime.Today.AddDays(7 * offset));
}

public static bool DateIsInWeek(DateOnly day, int year, int week)
public static bool DateIsInWeek(DateOnly day, Week week)
{
return day.Year == year && GetWeekNumber(day.ToDateTime(TimeOnly.MinValue)) == week;
return day.Year == week.Year && GetWeekNumber(day.ToDateTime(TimeOnly.MinValue)) == week.WeekNumber;
}

public static List<Week> GetNextWeeks(Week firstWeek, int weeksAhead)
Expand Down
2 changes: 2 additions & 0 deletions backend/Database/DatabaseContext/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public ApplicationContext(DbContextOptions options) : base(options)
public DbSet<Competence> Competence { get; set; } = null!;
public DbSet<Department> Department { get; set; } = null!;
public DbSet<Organization> Organization { get; set; } = null!;
public DbSet<Absence> Absence { get; set; } = null!;

public DbSet<PlannedAbsence> PlannedAbsence { get; set; } = null!;
public DbSet<Vacation> Vacation { get; set; } = null!;
public DbSet<Customer> Customer { get; set; } = null!;
Expand Down

0 comments on commit bc7b644

Please sign in to comment.