Skip to content

Commit

Permalink
working new implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasbjoralt committed Nov 13, 2023
1 parent 82fe117 commit 98c53f3
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 26 deletions.
76 changes: 76 additions & 0 deletions backend/Api/Common/StorageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using Core.DomainModels;
using Database.DatabaseContext;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace Api.Common;

public class StorageService
{
private readonly IMemoryCache _cache;
private readonly ApplicationContext _dbContext;

public StorageService(IMemoryCache cache, ApplicationContext context)
{
_cache = cache;
_dbContext = context;
}

public List<Consultant> LoadConsultants(string orgUrlKey)
{
if (_cache.TryGetValue<List<Consultant>>("asdf", out var consultants))
if (consultants != null)
return consultants;

var loadedConsultants = LoadConsultantsFromDb(orgUrlKey);
_cache.Set("asdf", loadedConsultants);
return loadedConsultants;
}

private List<Consultant> LoadConsultantsFromDb(string orgUrlKey)
{
var consultantList = _dbContext.Consultant
.Include(consultant => consultant.Department)
.ThenInclude(department => department.Organization)
.Where(consultant => consultant.Department.Organization.UrlKey == orgUrlKey)
.OrderBy(consultant => consultant.Name)
.ToList();

var staffingPrConsultant = _dbContext.Staffing
.Include(s => s.Consultant)
.Include(staffing => staffing.Project)
.ThenInclude(project => project.Customer)
.GroupBy(staffing => staffing.Consultant.Id)
.ToDictionary(group => group.Key, grouping => grouping.ToList());

var plannedAbsencePrConsultant = _dbContext.PlannedAbsence
.Include(absence => absence.Absence)
.Include(absence => absence.Consultant)
.GroupBy(absence => absence.Consultant.Id)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToList());

var vacationsPrConsultant = _dbContext.Vacation
.Include(vacation => vacation.Consultant)
.GroupBy(vacation => vacation.Consultant.Id)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToList());

var hydratedConsultants = consultantList.Select(consultant =>
{
consultant.Staffings = staffingPrConsultant.TryGetValue(consultant.Id, out var staffing)
? staffing
: new List<Core.DomainModels.Staffing>();

consultant.PlannedAbsences = plannedAbsencePrConsultant.TryGetValue(consultant.Id, out var plannedAbsences)
? plannedAbsences
: new List<PlannedAbsence>();

consultant.Vacations = vacationsPrConsultant.TryGetValue(consultant.Id, out var vacations)
? vacations
: new List<Vacation>();

return consultant;
}).ToList();

return hydratedConsultants;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Diagnostics;
using Api.Cache;
using Api.Common;
using Core.DomainModels;
using Core.Services;
using Database.DatabaseContext;
Expand All @@ -7,7 +9,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace Api.Consultants;
namespace Api.Staffing;

[Authorize]
[Route("/v0/{orgUrlKey}/consultants")]
Expand All @@ -31,6 +33,7 @@ public ActionResult<List<ConsultantReadModel>> Get(
[FromQuery(Name = "WeekSpan")] int numberOfWeeks = 8,
[FromQuery(Name = "includeOccupied")] bool includeOccupied = true)
{
var timer = Stopwatch.StartNew();
var selectedYear = selectedYearParam ?? DateTime.Now.Year;
var selectedWeekNumber = selectedWeekParam ?? DateService.GetWeekNumber(DateTime.Now);
var selectedWeek = new Week(selectedYear, selectedWeekNumber);
Expand All @@ -42,8 +45,24 @@ public ActionResult<List<ConsultantReadModel>> Get(
|| c.IsOccupied
)
.ToList();
var elapsed = timer.ElapsedMilliseconds;
return Ok(new { Time = elapsed, Data = consultants });
}

[HttpGet("test")]
public ActionResult GetRefactored()
{
var timer = Stopwatch.StartNew();
const string orlUrlKey = "variant-norge";
var selectedYear = DateTime.Now.Year;
var selectedWeekNumber = DateService.GetWeekNumber(DateTime.Now);
var selectedWeek = new Week(selectedYear, selectedWeekNumber);
var weekSet = DateService.GetNextWeeks(selectedWeek, 8);

return Ok(consultants);
var service = new StorageService(_cache, _context);
var readModels = new ReadModelFactory(service).GetConsultantReadModelsForWeeks(orlUrlKey, weekSet);
var elapsed = timer.ElapsedMilliseconds;
return Ok(new { Time = elapsed, Data = readModels });
}

private List<ConsultantReadModel> GetConsultantReadModels(string orgUrlKey, List<Week> weeks)
Expand All @@ -66,9 +85,11 @@ private Dictionary<StaffingGroupKey, double> LoadStaffingByProjectTypeForWeeks(L
{
var firstWeek = weeks.First().ToSortableInt();
var lastWeek = weeks.Last().ToSortableInt();

return _context.Staffing
.Where(staffing => firstWeek <= (staffing.Year * 100 + staffing.Week) && (staffing.Year * 100 + staffing.Week) <= lastWeek) //Compare weeks by using the format yyyyww, for example 202352 and 202401
.Where(staffing => firstWeek <= staffing.Year * 100 + staffing.Week &&
staffing.Year * 100 + staffing.Week <=
lastWeek) //Compare weeks by using the format yyyyww, for example 202352 and 202401
.Where(staffing =>
staffing.Project.State == state)
.Include(s => s.Consultant)
Expand All @@ -83,7 +104,7 @@ private List<ConsultantReadModel> LoadReadModelFromDb(string orgUrlKey, List<Wee
weekSet.Sort();
var firstWeek = weekSet.First().ToSortableInt();
var lastWeek = weekSet.Last().ToSortableInt();

var firstDayInScope = DateService.FirstDayOfWorkWeek(weekSet.First());
var firstWorkDayOutOfScope = DateService.LastWorkDayOfWeek(weekSet.Last()).AddDays(1);

Expand All @@ -105,7 +126,9 @@ private List<ConsultantReadModel> LoadReadModelFromDb(string orgUrlKey, List<Wee
var plannedAbsences = _context.PlannedAbsence
.Include(plannedAbsence => plannedAbsence.Consultant)
.Include(plannedAbsence => plannedAbsence.Absence)
.Where(absence => firstWeek <= (absence.Year * 100 + absence.WeekNumber) && (absence.Year * 100 + absence.WeekNumber) <= lastWeek) //Compare weeks by using the format yyyyww, for example 202352 and 202401
.Where(absence => firstWeek <= absence.Year * 100 + absence.WeekNumber &&
absence.Year * 100 + absence.WeekNumber <=
lastWeek) //Compare weeks by using the format yyyyww, for example 202352 and 202401
.GroupBy(plannedAbsence =>
new StaffingGroupKey(plannedAbsence.Consultant.Id, plannedAbsence.Absence.Id, plannedAbsence.Year,
plannedAbsence.WeekNumber))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Core.DomainModels;
using Core.Services;

namespace Api.Consultants;
namespace Api.Staffing;

public static class ConsultantExtensions
{
Expand Down Expand Up @@ -37,33 +37,23 @@ public static ConsultantReadModel MapToReadModelList(
isOccupied);
}

public static WeeklyBookingReadModel GetBookingModelForWeek(this Consultant consultant, int year, int week)
public static WeeklyBookingReadModel GetBookingModelForWeek(this Consultant consultant, int year, int weekNumber)
{
var org = consultant.Department.Organization;

var hoursPrWorkDay = org.HoursPerWorkday;

var holidayHours = org.GetTotalHolidaysOfWeek(new Week(year, week)) * hoursPrWorkDay;
var vacationHours = consultant.Vacations.Count(v => DateService.DateIsInWeek(v.Date, new Week(year, week))) *
hoursPrWorkDay;
var week = new Week(year, weekNumber);

var plannedAbsenceHours = consultant.PlannedAbsences
.Where(pa => pa.Year == year && pa.WeekNumber == week)
.Select(pa => pa.Hours)
.Sum();

var billableHours = consultant.Staffings
.Where(s => s.Year == year && s.Week == week && s.Project.State.Equals(ProjectState.Active))
.Select(s => s.Hours).Sum();

var offeredHours = consultant.Staffings
.Where(s => s.Year == year && s.Week == week && s.Project.State.Equals(ProjectState.Offer))
.Select(s => s.Hours).Sum();
var holidayHours = org.GetTotalHolidayHoursOfWeek(week);

var vacationHours = consultant.GetVacationHoursForWeek(week);
var plannedAbsenceHours = consultant.GetAbsenceHoursForWeek(week);
var billableHours = consultant.GetBillableHoursForWeek(week);
var offeredHours = consultant.GetOfferedHoursForWeek(week);

var bookedTime = billableHours + plannedAbsenceHours + vacationHours + holidayHours;


var totalFreeTime =
Math.Max(hoursPrWorkDay * 5 - bookedTime, 0);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Core.DomainModels;

namespace Api.Consultants;
namespace Api.Staffing;

public record ConsultantReadModel(int Id, string Name, string Email, List<string> Competences, string Department,
int YearsOfExperience, Degree Degree,
Expand Down
Loading

0 comments on commit 98c53f3

Please sign in to comment.