Skip to content

Commit

Permalink
232 trekkspill m backend stotte (#248)
Browse files Browse the repository at this point in the history
Co-authored-by: Sigrid Elnan <sge@variant.no>
  • Loading branch information
jonasbjoralt and sigridge authored Nov 6, 2023
1 parent 4d062eb commit 3d75a81
Show file tree
Hide file tree
Showing 10 changed files with 407 additions and 188 deletions.
100 changes: 78 additions & 22 deletions backend/Api/Consultants/ConsultantExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public static ConsultantReadModel MapConsultantToReadModel(this Consultant consu
currentYear - (consultant.GraduationYear is null or 0 ? currentYear : consultant.GraduationYear) ?? 0;

var bookedHours = GetBookedHoursForWeeks(consultant, firstWeek, weeks);
var detailedBooking = GetDetailedBooking(consultant, firstWeek, weeks);

var isOccupied = bookedHours.All(b => b.BookingModel.TotalSellableTime <= 0 + tolerance);

Expand All @@ -26,10 +27,76 @@ public static ConsultantReadModel MapConsultantToReadModel(this Consultant consu
yearsOfExperience,
consultant.Degree ?? Degree.None,
bookedHours,
detailedBooking,
isOccupied
);
}

private static List<DetailedBooking> GetDetailedBooking(Consultant consultant, Week firstWeek, int weeks)
{
var org = consultant.Department.Organization;

var hoursPrWorkDay = org.HoursPerWorkday;

var weeksInSet = DateService.GetNextWeeks(firstWeek, weeks);

var projects = consultant.Staffings
.Where(s => weeksInSet.Contains(new Week(s.Year, s.Week)))
.Where(s=> s.Project.State == ProjectState.Active || s.Project.State == ProjectState.Offer)
.GroupBy(s => s.Project.Customer.Name)
.Select(grouping => new DetailedBooking(
new BookingDetails(grouping.Key, grouping.First().Project.State==ProjectState.Active ? BookingType.Booking : BookingType.Offer),
weeksInSet.Select(w => new WeeklyHours(
int.Parse($"{w.Year}{w.WeekNumber}"),
grouping
.Where(staffing => w.Equals(new Week(staffing.Year, staffing.Week)))
.Select(staffing => staffing.Hours)
.Sum()
)).ToList()
))
.ToList();

var plannedAbsences = consultant.PlannedAbsences
.Where(pa => weeksInSet.Contains(new Week(pa.Year, pa.WeekNumber)))
.GroupBy(pa=> pa.Absence.Name)
.Select(grouping => new DetailedBooking(
new BookingDetails(grouping.Key, BookingType.PlannedAbsence),
weeksInSet.Select(w => new WeeklyHours(
int.Parse($"{w.Year}{w.WeekNumber}"),
grouping
.Where(plannedAbsence => w.Equals(new Week(plannedAbsence.Year, plannedAbsence.WeekNumber)))
.Select(plannedAbsence => plannedAbsence.Hours)
.Sum()
)).ToList()
))
.ToList();

var detailedBookings = projects.Concat(plannedAbsences);

var firstDay = DateService.GetDatesInWorkWeek(firstWeek.Year, firstWeek.WeekNumber).First();
var lastDay = DateService.GetDatesInWorkWeek(weeksInSet.Last().Year, weeksInSet.Last().WeekNumber).Last();

if (consultant.Vacations.Exists(v => v.Date >= firstDay && v.Date <= lastDay))
{
var vacationList = weeksInSet
.Aggregate(new List<WeeklyHours>(), (list, week) =>
list.Append(new WeeklyHours(
int.Parse($"{week.Year}{week.WeekNumber}"),
consultant.Vacations.Count(v =>
DateService.DateIsInWeek(v.Date, week.Year, week.WeekNumber))
* hoursPrWorkDay)).ToList());

var vacations = new DetailedBooking(
new BookingDetails("Ferie", BookingType.Vacation),
new List<WeeklyHours>(vacationList));

detailedBookings = detailedBookings.Append(vacations).ToList();

}

return detailedBookings.ToList();
}

public static WeeklyBookingReadModel GetBookingModelForWeek(this Consultant consultant, int year, int week)
{
var org = consultant.Department.Organization;
Expand All @@ -45,28 +112,14 @@ public static WeeklyBookingReadModel GetBookingModelForWeek(this Consultant cons
.Select(pa => pa.Hours)
.Sum();

var staffings = consultant.Staffings
var billableHours = consultant.Staffings
.Where(s => s.Year == year && s.Week == week && s.Project.State.Equals(ProjectState.Active))
.Select(s => new BookingReadModel(s.Project.Customer.Name, s.Hours, BookingType.Booking)).ToList();
.Select(s => s.Hours).Sum();

var offers = consultant.Staffings
var offeredHours = consultant.Staffings
.Where(s => s.Year == year && s.Week == week && s.Project.State.Equals(ProjectState.Offer))
.Select(s => new BookingReadModel(s.Project.Customer.Name, s.Hours, BookingType.Offer)).ToList();

var plannedAbsences = consultant.PlannedAbsences
.Where(s => s.Year == year && s.WeekNumber == week)
.Select(s => new BookingReadModel(s.Absence.Name, s.Hours, BookingType.PlannedAbsence)).ToList();

var bookingList = staffings.Concat(offers).Concat(plannedAbsences).ToList();

if (vacationHours > 0)
{
var vacation = new BookingReadModel("Ferie", vacationHours, BookingType.Vacation);
bookingList = bookingList.Append(vacation).ToList();
}

var billableHours = staffings.Select(s => s.Hours).Sum();
var offeredHours = offers.Select(s => s.Hours).Sum();
.Select(s => s.Hours).Sum();


var bookedTime = billableHours + plannedAbsenceHours + vacationHours + holidayHours;

Expand All @@ -78,8 +131,9 @@ public static WeeklyBookingReadModel GetBookingModelForWeek(this Consultant cons
Math.Max(bookedTime - hoursPrWorkDay * 5, 0);


return new WeeklyBookingReadModel(billableHours, offeredHours, plannedAbsenceHours, totalFreeTime, holidayHours, vacationHours,
totalOverbooked, bookingList);
return new WeeklyBookingReadModel(billableHours, offeredHours, plannedAbsenceHours, totalFreeTime, holidayHours,
vacationHours,
totalOverbooked);
}

private static List<BookedHoursPerWeek> GetBookedHoursForWeeks(this Consultant consultant, Week firstWeek,
Expand All @@ -91,6 +145,7 @@ private static List<BookedHoursPerWeek> GetBookedHoursForWeeks(this Consultant c
.Select(week => new BookedHoursPerWeek(
week.Year,
week.WeekNumber,
int.Parse($"{week.Year}{week.WeekNumber}"),
GetDatesForWeek(week),
GetBookingModelForWeek(consultant, week.Year, week.WeekNumber)))
.ToList();
Expand All @@ -99,7 +154,8 @@ private static List<BookedHoursPerWeek> GetBookedHoursForWeeks(this Consultant c
private static string GetDatesForWeek(Week week)
{
return DateService.GetDatesInWorkWeek(week.Year, week.WeekNumber)[0].ToString("dd.MM") +
"-" + DateService
" - " + DateService
.GetDatesInWorkWeek(week.Year, week.WeekNumber)[^1].ToString("dd.MM");
}

}
13 changes: 10 additions & 3 deletions backend/Api/Consultants/ConsultantReadModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@ namespace Api.Consultants;

public record ConsultantReadModel(int Id, string Name, string Email, List<string> Competences, string Department,
int YearsOfExperience, Degree Degree,
List<BookedHoursPerWeek> Bookings, bool IsOccupied);
List<BookedHoursPerWeek> Bookings, List<DetailedBooking> DetailedBooking, bool IsOccupied);

public record BookedHoursPerWeek(int Year, int WeekNumber, int SortableWeek, string DateString,
WeeklyBookingReadModel BookingModel);

public record BookedHoursPerWeek(int Year, int WeekNumber, string DateString, WeeklyBookingReadModel BookingModel);
public record DetailedBooking(BookingDetails BookingDetails, List<WeeklyHours> Hours);

public record WeeklyBookingReadModel(double TotalBillable, double TotalOffered, double TotalPlannedAbstences, double TotalSellableTime, double TotalHolidayHours, double TotalVacationHours, double TotalOverbooking, List<BookingReadModel> Bookings);
public record WeeklyBookingReadModel(double TotalBillable, double TotalOffered, double TotalPlannedAbstences,
double TotalSellableTime, double TotalHolidayHours, double TotalVacationHours, double TotalOverbooking);

public record BookingReadModel(string Name, double Hours, BookingType Type);

public record BookingDetails(string Name, BookingType Type);

public record WeeklyHours(int Week, double Hours);

public enum BookingType
{
Offer,
Expand Down
37 changes: 36 additions & 1 deletion backend/Core/DomainModels/Week.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
namespace Core.DomainModels;

public record Week(int Year, int WeekNumber);
public class Week : IComparable<Week>, IEquatable<Week>

{
public Week(int year, int weekNumber)
{
Year = year;
WeekNumber = weekNumber;
}

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

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


public int CompareTo(Week? other)
{
// 1 if this is first
// 0 if equal
if (other is null)
return 1;

if (Year == other.Year) return WeekNumber - other.WeekNumber;

return Year - other.Year;
}

public bool Equals(Week? other)
{
if (other is null) return false;
return Year == other.Year && WeekNumber == other.WeekNumber;
}
}
12 changes: 0 additions & 12 deletions backend/Tests/AbsenceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,6 @@ public void AvailabilityCalculation(int vacationDays, double plannedAbsenceHours
Assert.That(bookingModel.TotalHolidayHours, Is.EqualTo(numberOfHolidays * 7.5));
Assert.That(bookingModel.TotalSellableTime, Is.EqualTo(expectedSellableHours));
});

if (staffedHours > 0)
{
var staffing = bookingModel.Bookings.Single(b => b.Name == "TestCustomer");
Assert.That(staffing.Hours, Is.EqualTo(staffedHours));
}

if (vacationDays > 0)
{
var vacation = bookingModel.Bookings.Single(b => b.Name == "Ferie");
Assert.That(vacation.Hours, Is.EqualTo(vacationDays * 7.5));
}
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion frontend/mockdata/mockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const MockWeeklyBookingReadModel: WeeklyBookingReadModel = {
totalPlannedAbstences: 0,
totalSellableTime: 0,
totalHolidayHours: 0,
bookings: [],
totalOverbooking: 0,
totalVacationHours: 0,
};
Expand All @@ -32,6 +31,7 @@ export const MockConsultants: Consultant[] = [
},
],
yearsOfExperience: 23,
detailedBooking: [],
isOccupied: true,
},
];
Expand Down
Loading

0 comments on commit 3d75a81

Please sign in to comment.