Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace DigitalLearningSolutions.Data.Tests.DataServices
{
using System;
using System.Linq;
using DigitalLearningSolutions.Data.DataServices;
using DigitalLearningSolutions.Data.Tests.TestHelpers;
using FluentAssertions;
using NUnit.Framework;

public class ActivityDataServiceTests
{
private IActivityDataService service = null!;

[SetUp]
public void Setup()
{
var connection = ServiceTestHelper.GetDatabaseConnection();
service = new ActivityDataService(connection);
}

[Test]
public void GetActivityForMonthsInYear_gets_activity_by_month_for_date_range()
{
// when
var start = DateTime.Parse("2014-01-01 00:00:00.000");
var end = DateTime.Parse("2014-04-30 23:59:59.999");
var result = service.GetActivityInRangeByMonth(101, start, end).ToList();

// then
result.Count().Should().Be(4);

var first = result.First();
first.Year.Should().Be(2014);
first.Month.Should().Be(1);
first.Completions.Should().Be(1);
first.Evaluations.Should().Be(0);
first.Registrations.Should().Be(12);

var last = result.Last();
last.Year.Should().Be(2014);
last.Month.Should().Be(4);
last.Completions.Should().Be(0);
last.Evaluations.Should().Be(1);
last.Registrations.Should().Be(7);
}
}
}
72 changes: 72 additions & 0 deletions DigitalLearningSolutions.Data.Tests/Helpers/DateHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace DigitalLearningSolutions.Data.Tests.Helpers
{
using System;
using System.Linq;
using DigitalLearningSolutions.Web.Helpers;
using FluentAssertions;
using NUnit.Framework;

public class DateHelperTests
{
[Test]
public void GetMonthsAndYearsBetweenDates_returns_single_entry_for_dates_in_same_month()
{
// when
var startDate = DateTime.Parse("2014-01-01 00:00:00.000");
var endDate = DateTime.Parse("2014-01-31 23:59:59.999");
var result = DateHelper.GetMonthsAndYearsBetweenDates(startDate, endDate).ToList();

// then
result.Count.Should().Be(1);
result[0].Year.Should().Be(2014);
result[0].Month.Should().Be(1);
}

[Test]
public void GetMonthsAndYearsBetweenDates_returns_loops_over_months_and_increments_years()
{
// when
var startDate = DateTime.Parse("2013-12-31 23:59:59.999");
var endDate = DateTime.Parse("2014-01-01 00:00:00.000");
var result = DateHelper.GetMonthsAndYearsBetweenDates(startDate, endDate).ToList();

// then
result.Count.Should().Be(2);
result[0].Year.Should().Be(2013);
result[0].Month.Should().Be(12);
result[1].Year.Should().Be(2014);
result[1].Month.Should().Be(1);
}

[Test]
public void GetMonthsAndYearsBetweenDates_increments_months_within_year()
{
// when
var startDate = DateTime.Parse("2014-01-31 23:59:59.999");
var endDate = DateTime.Parse("2014-02-01 00:00:00.000");
var result = DateHelper.GetMonthsAndYearsBetweenDates(startDate, endDate).ToList();

// then
result.Count.Should().Be(2);
result[0].Year.Should().Be(2014);
result[0].Month.Should().Be(1);
result[1].Year.Should().Be(2014);
result[1].Month.Should().Be(2);
}

[Test]
public void GetMonthsAndYearsBetweenDates_returns_13_months_across_two_years_for_one_year_difference()
{
// when
var startDate = DateTime.Parse("2014-01-01 00:00:00.000");
var endDate = DateTime.Parse("2015-01-01 00:00:00.000");
var result = DateHelper.GetMonthsAndYearsBetweenDates(startDate, endDate).ToList();

// then
result.Count.Should().Be(13);
result.Select(m => m.Month).Should().BeEquivalentTo(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1 });
result.Take(12).Select(m => m.Year).Should().AllBeEquivalentTo(2014);
result[12].Year.Should().Be(2015);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
namespace DigitalLearningSolutions.Data.Tests.Services
{
using System;
using System.Collections.Generic;
using System.Linq;
using DigitalLearningSolutions.Data.DataServices;
using DigitalLearningSolutions.Data.Models.TrackingSystem;
using DigitalLearningSolutions.Data.Services;
using FakeItEasy;
using FluentAssertions;
using NUnit.Framework;

public class ActivityServiceTests
{
private IActivityDataService activityDataService = null!;
private IClockService clockService = null!;
private IActivityService activityService = null!;

[SetUp]
public void SetUp()
{
activityDataService = A.Fake<IActivityDataService>();
clockService = A.Fake<IClockService>();
activityService = new ActivityService(activityDataService, clockService);
}

[Test]
public void GetRecentActivity_gets_recent_activity()
{
// given
var expectedActivityResult = new List<MonthOfActivity>{new MonthOfActivity()};
A.CallTo(() => activityDataService.GetActivityInRangeByMonth(A<int>._, A<DateTime>._, A<DateTime>._))
.Returns(expectedActivityResult);
GivenCurrentTimeIs(DateTime.Parse("2015-12-22 06:52:09.080"));

// when
var result = activityService.GetRecentActivity(101).ToList();

// then
A.CallTo(() => activityDataService.GetActivityInRangeByMonth(A<int>._, A<DateTime>._, A<DateTime>._))
.MustHaveHappened(1, Times.Exactly);
result.Last().Should().BeEquivalentTo(new MonthOfActivity
{
Year = 2014,
Month = 12,
Completions = 0,
Registrations = 0,
Evaluations = 0
});
result.First().Should().BeEquivalentTo(new MonthOfActivity
{
Year = 2015,
Month = 12,
Completions = 0,
Registrations = 0,
Evaluations = 0
});
result.Count().Should().Be(13);
result.All(m => m.Completions == 0 && m.Evaluations == 0 && m.Registrations == 0).Should().BeTrue();
}

private void GivenCurrentTimeIs(DateTime time)
{
A.CallTo(() => clockService.UtcNow).Returns(time);
}
}
}
40 changes: 40 additions & 0 deletions DigitalLearningSolutions.Data/DataServices/ActivityDataService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace DigitalLearningSolutions.Data.DataServices
{
using System;
using System.Collections.Generic;
using System.Data;
using Dapper;
using DigitalLearningSolutions.Data.Models.TrackingSystem;

public interface IActivityDataService
{
IEnumerable<MonthOfActivity> GetActivityInRangeByMonth(int centreId, DateTime start, DateTime end);
}

public class ActivityDataService : IActivityDataService
{
private readonly IDbConnection connection;

public ActivityDataService(IDbConnection connection)
{
this.connection = connection;
}

public IEnumerable<MonthOfActivity> GetActivityInRangeByMonth(int centreId, DateTime start, DateTime end)
{
return connection.Query<MonthOfActivity>(
@"SELECT
LogYear AS Year,
LogMonth AS Month,
SUM(CONVERT(INT, Completed)) AS Completions,
SUM(CONVERT(INT, Evaluated)) AS Evaluations,
SUM(CONVERT(INT, Registered)) AS Registrations
FROM tActivityLog
WHERE (LogDate > @start AND LogDate < @end AND CentreID = @centreId)
GROUP BY LogYear, LogMonth
ORDER BY LogYear, LogMonth",
new { centreId, start, end }
);
}
}
}
24 changes: 24 additions & 0 deletions DigitalLearningSolutions.Data/Helpers/DateHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace DigitalLearningSolutions.Web.Helpers
{
using System;
using System.Collections.Generic;
using System.Linq;

public static class DateHelper
{
public static IEnumerable<(int Month, int Year)> GetMonthsAndYearsBetweenDates(DateTime startDate, DateTime endDate)
{
var diffInMonths = (endDate.Year - startDate.Year) * 12 + (endDate.Month - startDate.Month);
var monthEnumerable = Enumerable.Range(startDate.Month, diffInMonths + 1);

return monthEnumerable.Select(
m =>
{
var month = (m - 1) % 12 + 1;
var yearsToAdd = (m - 1) / 12;
return (month, startDate.Year + yearsToAdd);
}
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace DigitalLearningSolutions.Data.Models.TrackingSystem
{
public class MonthOfActivity
{
public MonthOfActivity()
{
Year = 0;
Month = 0;
Completions = 0;
Evaluations = 0;
Registrations = 0;
}

public MonthOfActivity((int Month, int Year) slot, MonthOfActivity? data)
{
Year = slot.Year;
Month = slot.Month;
Completions = data?.Completions ?? 0;
Evaluations = data?.Evaluations ?? 0;
Registrations = data?.Registrations ?? 0;
}

public int Year { get; set; }
public int Month { get; set; }
public int Completions { get; set; }
public int Evaluations { get; set; }
public int Registrations { get; set; }
}
}
46 changes: 46 additions & 0 deletions DigitalLearningSolutions.Data/Services/ActivityService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace DigitalLearningSolutions.Data.Services
{
using System;
using System.Collections.Generic;
using System.Linq;
using DigitalLearningSolutions.Data.DataServices;
using DigitalLearningSolutions.Data.Models.TrackingSystem;
using DigitalLearningSolutions.Web.Helpers;

public interface IActivityService
{
public IEnumerable<MonthOfActivity> GetRecentActivity(int centreId);
}

public class ActivityService : IActivityService
{
private readonly IActivityDataService activityDataService;
private readonly IClockService clockService;

public ActivityService(IActivityDataService activityDataService, IClockService clockService)
{
this.activityDataService = activityDataService;
this.clockService = clockService;
}

public IEnumerable<MonthOfActivity> GetRecentActivity(int centreId)
{
var endTime = clockService.UtcNow;
var startTime = endTime.AddYears(-1);

var activityData = activityDataService.GetActivityInRangeByMonth(centreId, startTime, endTime).ToList();

var monthSlots = DateHelper.GetMonthsAndYearsBetweenDates(startTime, endTime).ToList();
monthSlots.Reverse();

return monthSlots.Select(
slot =>
{
var monthData =
activityData.SingleOrDefault(data => data.Year == slot.Year && data.Month == slot.Month);
return new MonthOfActivity(slot, monthData);
}
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre.Reports
{
using DigitalLearningSolutions.Data.Services;
using DigitalLearningSolutions.Web.Helpers;
using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Reports;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -9,9 +10,18 @@
[Route("/TrackingSystem/Centre/Reports")]
public class ReportsController : Controller
{
private readonly IActivityService activityService;

public ReportsController(IActivityService activityService)
{
this.activityService = activityService;
}

public IActionResult Index()
{
var model = new ReportsViewModel();
var centreId = User.GetCentreId();
var monthsOfActivity = activityService.GetRecentActivity(centreId);
var model = new ReportsViewModel(monthsOfActivity);
return View(model);
}
}
Expand Down
3 changes: 3 additions & 0 deletions DigitalLearningSolutions.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ public void ConfigureServices(IServiceCollection services)
services.AddScoped<ISupportTicketDataService, SupportTicketDataService>();
services.AddScoped<IRoleProfileService, RoleProfileService>();
services.AddHttpClient<IMapsApiHelper, MapsApiHelper>();
services.AddScoped<IActivityDataService, ActivityDataService>();
services.AddScoped<IActivityService, ActivityService>();

RegisterWebServiceFilters(services);
}

Expand Down
Loading