public void MapForProjectUtilizationViewModel_WithValidParams_ShouldReturnValidModel() { // ARRANGE var project = new Project { Id = Guid.Parse("bfb77fc0-12a9-4250-a5fb-e52ddc48ff86"), Title = "TimesheetEntity App", ClientName = "Microsoft", BillableHours = 200, NonBillableHours = 200, StartDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 2), EndDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 28), CreatedBy = Guid.Parse("08310120-ff64-45a4-b67a-6f2f19fba937"), CreatedOn = DateTime.Now, }; var members = new List <Member> { new Member { Id = Guid.Parse("d3d964ae-2979-4dac-b1e0-6c1b936c2640"), ProjectId = Guid.Parse("bfb77fc0-12a9-4250-a5fb-e52ddc48ff86"), UserId = Guid.Parse("3fd7af65-67df-43cb-baa0-30917e133d94"), IsBillable = true, IsRemoved = false, }, new Member { Id = Guid.Parse("d3d764ae-2979-4dac-b1e0-6c1b936c2640"), ProjectId = Guid.Parse("bfb77fc0-12a9-4250-a5fb-e52ddc48ff86"), UserId = Guid.Parse("3fd8af65-67df-43cb-baa0-30917e133d94"), IsBillable = true, IsRemoved = false, }, }; var expectedProjectUtilization = new ProjectUtilizationDTO { Id = project.Id, Title = project.Title, BillableUtilizedHours = 10, NonBillableUtilizedHours = 0, BillableUnderutilizedHours = project.BillableHours - 10, NonBillableUnderutilizedHours = project.NonBillableHours - 0, TotalHours = project.BillableHours + project.NonBillableHours, }; // ACT var resultUtilizationModel = this.projectMapper.MapForProjectUtilizationViewModel(project, TestData.TestData.ApprovedTimesheets, members); // ASSERT Assert.AreEqual(expectedProjectUtilization.BillableUtilizedHours, resultUtilizationModel.BillableUtilizedHours); Assert.AreEqual(expectedProjectUtilization.NonBillableUtilizedHours, resultUtilizationModel.NonBillableUtilizedHours); Assert.AreEqual(expectedProjectUtilization.BillableUnderutilizedHours, resultUtilizationModel.BillableUnderutilizedHours); Assert.AreEqual(expectedProjectUtilization.NonBillableUnderutilizedHours, resultUtilizationModel.NonBillableUnderutilizedHours); Assert.AreEqual(expectedProjectUtilization.TotalHours, resultUtilizationModel.TotalHours); }
/// <summary> /// Gets project utilization view model to be sent as API response. /// </summary> /// <param name="project">The project entity model.</param> /// <param name="timesheets">Collection of timesheet entity model.</param> /// <returns>Returns a project utilization view entity model.</returns> public ProjectUtilizationDTO MapForProjectUtilizationViewModel(Project project, IEnumerable <TimesheetEntity> timesheets) { project = project ?? throw new ArgumentNullException(nameof(project)); var totalHours = project.BillableHours + project.NonBillableHours; var projectUtilization = new ProjectUtilizationDTO { Id = project.Id, Title = project.Title, BillableHours = project.BillableHours, NonBillableHours = project.NonBillableHours, NotUtilizedHours = totalHours - timesheets.Sum(timesheet => timesheet.Hours), }; return(projectUtilization); }
/// <summary> /// Gets project utilization view model to be sent as API response. /// </summary> /// <param name="project">The project entity model.</param> /// <param name="timesheets">List of timesheet entity model.</param> /// <param name="members">List of project members.</param> /// <returns>Returns a project utilization view entity model.</returns> public ProjectUtilizationDTO MapForProjectUtilizationViewModel(Project project, IEnumerable <TimesheetEntity> timesheets, IEnumerable <Member> members) { project = project ?? throw new ArgumentNullException(nameof(project)); timesheets = timesheets ?? throw new ArgumentNullException(nameof(timesheets)); members = members ?? throw new ArgumentNullException(nameof(members)); var billableUtilizedHours = 0; var nonBillableUtilizedHours = 0; var membersDictionary = members.ToDictionary(member => member.UserId); foreach (var timesheet in timesheets) { if (membersDictionary.TryGetValue(timesheet.UserId, out var member)) { if (member.IsBillable) { billableUtilizedHours += timesheet.Hours; } else { nonBillableUtilizedHours += timesheet.Hours; } } else { this.logger.LogError($"Member {timesheet.UserId} is not part of project {project.Id}"); return(null); } } var projectUtilization = new ProjectUtilizationDTO { Id = project.Id, Title = project.Title, ProjectStartDate = project.StartDate, ProjectEndDate = project.EndDate, BillableUtilizedHours = billableUtilizedHours, NonBillableUtilizedHours = nonBillableUtilizedHours, BillableUnderutilizedHours = project.BillableHours - billableUtilizedHours, NonBillableUnderutilizedHours = project.NonBillableHours - nonBillableUtilizedHours, TotalHours = project.BillableHours + project.NonBillableHours, }; return(projectUtilization); }
public async Task GetProjectUtilization_WhenProjectNotFound_ShouldReturnNotFoundStatus() { // ARRANGE ProjectUtilizationDTO project = null; this.projectHelper .Setup(helper => helper.GetProjectUtilizationAsync(It.IsAny <Guid>(), It.IsAny <string>(), It.IsAny <DateTime>(), It.IsAny <DateTime>())) .Returns(Task.FromResult(project)); var projectId = Guid.NewGuid(); var startDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 5); var endDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, startDate.Day + 1); // ACT var result = (ObjectResult)await this.projectController.GetProjectUtilizationAsync(projectId, startDate, endDate); // ASSERT Assert.AreEqual(StatusCodes.Status404NotFound, result.StatusCode); }
/// <summary> /// Gets project utilization view model to be sent as API response. /// </summary> /// <param name="project">The project entity model.</param> /// <param name="timesheets">List of timesheet entity model.</param> /// <param name="members">List of members.</param> /// <returns>Returns a project utilization view entity model.</returns> public ProjectUtilizationDTO MapForProjectUtilizationViewModel(Project project, List <TimesheetEntity> timesheets, List <Member> members) { project = project ?? throw new ArgumentNullException(nameof(project)); var billableUtilizedHours = 0; var nonBillableUtilizedHours = 0; #pragma warning disable CA1062 // Validate arguments of public methods foreach (var timesheet in timesheets) #pragma warning restore CA1062 // Validate arguments of public methods { #pragma warning disable CA1062 // Validate arguments of public methods foreach (var member in members) #pragma warning restore CA1062 // Validate arguments of public methods { if (timesheet.UserId == member.UserId) { if (member.IsBillable) { billableUtilizedHours += timesheet.Hours; } else { nonBillableUtilizedHours += timesheet.Hours; } } } } var projectUtilization = new ProjectUtilizationDTO { Id = project.Id, Title = project.Title, BillableUtilizedHours = billableUtilizedHours, NonBillableUtilizedHours = nonBillableUtilizedHours, UnderutilizedBillableHours = project.BillableHours - billableUtilizedHours, UnderutilizedNonBillableHours = project.NonBillableHours - nonBillableUtilizedHours, TotalHours = project.BillableHours + project.NonBillableHours, }; return(projectUtilization); }