diff --git a/HerPublicWebsite.BusinessLogic/IDataAccessProvider.cs b/HerPublicWebsite.BusinessLogic/IDataAccessProvider.cs index 3c8f03e1..e704fbdc 100644 --- a/HerPublicWebsite.BusinessLogic/IDataAccessProvider.cs +++ b/HerPublicWebsite.BusinessLogic/IDataAccessProvider.cs @@ -7,6 +7,7 @@ public interface IDataAccessProvider Task PersistNewReferralRequestAsync(ReferralRequest referralRequest); Task PersistNotificationConsentAsync(string referralId, NotificationDetails notificationDetails); Task> GetUnsubmittedReferralRequestsAsync(); + Task> GetReferralRequestsWithNoFollowUpBeforeDate(DateTime date); Task> GetReferralRequestsByCustodianAndRequestDateAsync(string custodianCode, int month, int year); Task PersistAnonymisedReportAsync(AnonymisedReport report); Task PersistPerReferralReportAsync(PerReferralReport report); diff --git a/HerPublicWebsite.BusinessLogic/Models/ReferralRequest.cs b/HerPublicWebsite.BusinessLogic/Models/ReferralRequest.cs index a7fc20ad..73951315 100644 --- a/HerPublicWebsite.BusinessLogic/Models/ReferralRequest.cs +++ b/HerPublicWebsite.BusinessLogic/Models/ReferralRequest.cs @@ -30,7 +30,9 @@ public class ReferralRequest public DateTime RequestDate { get; set; } - public bool ReferralWrittenToCsv { get; set; } = false; + public bool ReferralWrittenToCsv { get; set; } + + public bool FollowUpEmailSent { get; set; } public string ReferralCode { get; set; } diff --git a/HerPublicWebsite.BusinessLogic/Services/RegularJobs/ReferralFollowUpService.cs b/HerPublicWebsite.BusinessLogic/Services/RegularJobs/ReferralFollowUpService.cs new file mode 100644 index 00000000..971d73c8 --- /dev/null +++ b/HerPublicWebsite.BusinessLogic/Services/RegularJobs/ReferralFollowUpService.cs @@ -0,0 +1,32 @@ +using HerPublicWebsite.BusinessLogic.Models; + +namespace HerPublicWebsite.BusinessLogic.Services.RegularJobs; + +public interface IReferralFollowUpService +{ + public Task> GetReferralsPastTenWorkingDayThresholdWithNoFollowUp(); +} + +public class ReferralFollowUpService : IReferralFollowUpService +{ + private readonly IDataAccessProvider dataProvider; + private readonly CsvFileCreator.CsvFileCreator csvFileCreator; + private readonly IWorkingDayHelperService workingDayHelperService; + + public ReferralFollowUpService( + IDataAccessProvider dataProvider, + CsvFileCreator.CsvFileCreator csvFileCreator, + IWorkingDayHelperService workingDayHelperService) + { + this.dataProvider = dataProvider; + this.csvFileCreator = csvFileCreator; + this.workingDayHelperService = workingDayHelperService; + } + + public async Task> GetReferralsPastTenWorkingDayThresholdWithNoFollowUp() + { + var endDate = await workingDayHelperService.AddWorkingDaysToDateTime(DateTime.Today, -10); + return await dataProvider.GetReferralRequestsWithNoFollowUpBeforeDate(endDate); + } +} + diff --git a/HerPublicWebsite.BusinessLogic/Services/RegularJobs/RegularJobsService.cs b/HerPublicWebsite.BusinessLogic/Services/RegularJobs/UnsubmittedReferralRequestService.cs similarity index 79% rename from HerPublicWebsite.BusinessLogic/Services/RegularJobs/RegularJobsService.cs rename to HerPublicWebsite.BusinessLogic/Services/RegularJobs/UnsubmittedReferralRequestService.cs index 885816d7..6af5e0f1 100644 --- a/HerPublicWebsite.BusinessLogic/Services/RegularJobs/RegularJobsService.cs +++ b/HerPublicWebsite.BusinessLogic/Services/RegularJobs/UnsubmittedReferralRequestService.cs @@ -1,19 +1,19 @@ -using HerPublicWebsite.BusinessLogic.ExternalServices.S3FileWriter; +using HerPublicWebsite.BusinessLogic.ExternalServices.S3FileWriter; namespace HerPublicWebsite.BusinessLogic.Services.RegularJobs; -public interface IRegularJobsService +public interface IUnsubmittedReferralRequestsService { - public Task RunNightlyTasksAsync(); + public Task WriteUnsubmittedReferralRequestsToCsv(); } -public class RegularJobsService : IRegularJobsService +public class UnsubmittedReferralRequestsService : IUnsubmittedReferralRequestsService { private readonly IDataAccessProvider dataProvider; private readonly IS3FileWriter s3FileWriter; private readonly CsvFileCreator.CsvFileCreator csvFileCreator; - public RegularJobsService( + public UnsubmittedReferralRequestsService( IDataAccessProvider dataProvider, IS3FileWriter s3FileWriter, CsvFileCreator.CsvFileCreator csvFileCreator) @@ -22,8 +22,8 @@ public RegularJobsService( this.s3FileWriter = s3FileWriter; this.csvFileCreator = csvFileCreator; } - - public async Task RunNightlyTasksAsync() + + public async Task WriteUnsubmittedReferralRequestsToCsv() { var newReferrals = await dataProvider.GetUnsubmittedReferralRequestsAsync(); @@ -46,3 +46,4 @@ public async Task RunNightlyTasksAsync() } } } + diff --git a/HerPublicWebsite.BusinessLogic/Services/RegularJobs/WorkingDayHelperService.cs b/HerPublicWebsite.BusinessLogic/Services/RegularJobs/WorkingDayHelperService.cs new file mode 100644 index 00000000..d1867534 --- /dev/null +++ b/HerPublicWebsite.BusinessLogic/Services/RegularJobs/WorkingDayHelperService.cs @@ -0,0 +1,47 @@ +using HerPublicWebsite.BusinessLogic.ExternalServices.Common; + +namespace HerPublicWebsite.BusinessLogic.Services.RegularJobs; + +public interface IWorkingDayHelperService +{ + public Task AddWorkingDaysToDateTime(DateTime initialDateTime, int workingDaysToAdd); +} + +public class WorkingDayHelperService : IWorkingDayHelperService +{ + public async Task AddWorkingDaysToDateTime(DateTime initialDateTime, int workingDaysToAdd) + { + var direction = workingDaysToAdd < 0 ? -1 : 1; + var holidays = await getHolidays(); + var newDateTime = initialDateTime; + while (workingDaysToAdd != 0) + { + newDateTime = newDateTime.AddDays(direction); + if (newDateTime.DayOfWeek != DayOfWeek.Saturday && + newDateTime.DayOfWeek != DayOfWeek.Sunday && + !holidays.Contains(newDateTime.Date)) + { + workingDaysToAdd -= direction; + } + } + return newDateTime; + } + + private async Task> getHolidays() { + var parameters = new RequestParameters + { + BaseAddress = "https://www.gov.uk/bank-holidays.json", + }; + var holidayDataJson = await HttpRequestHelper.SendGetRequestAsync>(parameters); + var englandAndWalesHolidays = holidayDataJson["england-and-wales"]; + return englandAndWalesHolidays.events.Select(x => x.date).ToList(); + } + + private class Holidays { + public List events { get; set;} + } + private class Event { + public DateTime date { get; set; } + + } +} diff --git a/HerPublicWebsite.Data/DataAccessProvider.cs b/HerPublicWebsite.Data/DataAccessProvider.cs index 4d1fc7aa..80894502 100644 --- a/HerPublicWebsite.Data/DataAccessProvider.cs +++ b/HerPublicWebsite.Data/DataAccessProvider.cs @@ -63,6 +63,13 @@ public async Task> GetUnsubmittedReferralRequestsAsync() .ToListAsync(); } + public async Task> GetReferralRequestsWithNoFollowUpBeforeDate(DateTime cutoffDate) + { + return await context.ReferralRequests + .Where(rr => rr.RequestDate <= cutoffDate && !rr.FollowUpEmailSent) + .ToListAsync(); + } + public async Task> GetReferralRequestsByCustodianAndRequestDateAsync(string custodianCode, int month, int year) { return await context.ReferralRequests diff --git a/HerPublicWebsite.Data/Migrations/20240108162849_AddFollowUpEmailSentToReferralRequests.Designer.cs b/HerPublicWebsite.Data/Migrations/20240108162849_AddFollowUpEmailSentToReferralRequests.Designer.cs new file mode 100644 index 00000000..791afda9 --- /dev/null +++ b/HerPublicWebsite.Data/Migrations/20240108162849_AddFollowUpEmailSentToReferralRequests.Designer.cs @@ -0,0 +1,251 @@ +// +using System; +using HerPublicWebsite.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace HerPublicWebsite.Data.Migrations +{ + [DbContext(typeof(HerDbContext))] + [Migration("20240108162849_AddFollowUpEmailSentToReferralRequests")] + partial class AddFollowUpEmailSentToReferralRequests + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.16") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("HerPublicWebsite.BusinessLogic.Models.AnonymisedReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("EpcLodgementDate") + .HasColumnType("timestamp without time zone"); + + b.Property("EpcRating") + .HasColumnType("integer"); + + b.Property("HasGasBoiler") + .HasColumnType("integer"); + + b.Property("IncomeBand") + .HasColumnType("integer"); + + b.Property("IsEligible") + .HasColumnType("boolean"); + + b.Property("IsLsoaProperty") + .HasColumnType("boolean"); + + b.Property("OwnershipStatus") + .HasColumnType("integer"); + + b.Property("PostcodeFirstHalf") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("Id"); + + b.ToTable("AnonymisedReports"); + }); + + modelBuilder.Entity("HerPublicWebsite.BusinessLogic.Models.NotificationDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FutureSchemeNotificationConsent") + .HasColumnType("boolean"); + + b.Property("FutureSchemeNotificationEmail") + .HasColumnType("text"); + + b.Property("ReferralRequestId") + .HasColumnType("integer"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("Id"); + + b.HasIndex("ReferralRequestId"); + + b.ToTable("NotificationDetails"); + }); + + modelBuilder.Entity("HerPublicWebsite.BusinessLogic.Models.PerReferralReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddressCounty") + .HasColumnType("text"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressPostcode") + .HasColumnType("text"); + + b.Property("AddressTown") + .HasColumnType("text"); + + b.Property("ApplicationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferralCode") + .HasColumnType("text"); + + b.Property("Uprn") + .HasColumnType("text"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("Id"); + + b.ToTable("PerReferralReports"); + }); + + modelBuilder.Entity("HerPublicWebsite.BusinessLogic.Models.ReferralRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddressCounty") + .HasColumnType("text"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressPostcode") + .HasColumnType("text"); + + b.Property("AddressTown") + .HasColumnType("text"); + + b.Property("ContactEmailAddress") + .HasColumnType("text"); + + b.Property("ContactTelephone") + .HasColumnType("text"); + + b.Property("CustodianCode") + .HasColumnType("text"); + + b.Property("EpcConfirmation") + .HasColumnType("integer"); + + b.Property("EpcLodgementDate") + .HasColumnType("timestamp without time zone"); + + b.Property("EpcRating") + .HasColumnType("integer"); + + b.Property("FollowUpEmailSent") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("HasGasBoiler") + .HasColumnType("integer"); + + b.Property("IncomeBand") + .HasColumnType("integer"); + + b.Property("IsLsoaProperty") + .HasColumnType("boolean"); + + b.Property("ReferralCode") + .HasColumnType("text"); + + b.Property("ReferralWrittenToCsv") + .HasColumnType("boolean"); + + b.Property("RequestDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Uprn") + .HasColumnType("text"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("Id"); + + b.ToTable("ReferralRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("text"); + + b.Property("Xml") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("HerPublicWebsite.BusinessLogic.Models.NotificationDetails", b => + { + b.HasOne("HerPublicWebsite.BusinessLogic.Models.ReferralRequest", "ReferralRequest") + .WithMany() + .HasForeignKey("ReferralRequestId"); + + b.Navigation("ReferralRequest"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/HerPublicWebsite.Data/Migrations/20240108162849_AddFollowUpEmailSentToReferralRequests.cs b/HerPublicWebsite.Data/Migrations/20240108162849_AddFollowUpEmailSentToReferralRequests.cs new file mode 100644 index 00000000..6053ed4d --- /dev/null +++ b/HerPublicWebsite.Data/Migrations/20240108162849_AddFollowUpEmailSentToReferralRequests.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace HerPublicWebsite.Data.Migrations +{ + public partial class AddFollowUpEmailSentToReferralRequests : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "FollowUpEmailSent", + table: "ReferralRequests", + type: "boolean", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "FollowUpEmailSent", + table: "ReferralRequests"); + } + } +} diff --git a/HerPublicWebsite.Data/Migrations/HerDbContextModelSnapshot.cs b/HerPublicWebsite.Data/Migrations/HerDbContextModelSnapshot.cs index 90553c2d..f6ae9b4a 100644 --- a/HerPublicWebsite.Data/Migrations/HerDbContextModelSnapshot.cs +++ b/HerPublicWebsite.Data/Migrations/HerDbContextModelSnapshot.cs @@ -179,6 +179,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EpcRating") .HasColumnType("integer"); + b.Property("FollowUpEmailSent") + .HasColumnType("boolean"); + b.Property("FullName") .HasColumnType("text"); diff --git a/HerPublicWebsite.UnitTests/Builders/ReferralRequestBuilder.cs b/HerPublicWebsite.UnitTests/Builders/ReferralRequestBuilder.cs index 61798bda..a30dd502 100644 --- a/HerPublicWebsite.UnitTests/Builders/ReferralRequestBuilder.cs +++ b/HerPublicWebsite.UnitTests/Builders/ReferralRequestBuilder.cs @@ -27,6 +27,7 @@ public ReferralRequestBuilder(int id) IncomeBand = IncomeBand.UnderOrEqualTo31000, Uprn = $"100 111 222 {id:D3}", ReferralWrittenToCsv = false, + FollowUpEmailSent = false, RequestDate = new DateTime(2023, 01, 01, 13, 00, id), IsLsoaProperty = false, ContactEmailAddress = $"contact{id}@example.com", diff --git a/HerPublicWebsite.UnitTests/BusinessLogic/Services/RegularJobsServiceTests.cs b/HerPublicWebsite.UnitTests/BusinessLogic/Services/UnsubmittedReferralRequestServiceTests.cs similarity index 80% rename from HerPublicWebsite.UnitTests/BusinessLogic/Services/RegularJobsServiceTests.cs rename to HerPublicWebsite.UnitTests/BusinessLogic/Services/UnsubmittedReferralRequestServiceTests.cs index 53600b62..de0110c6 100644 --- a/HerPublicWebsite.UnitTests/BusinessLogic/Services/RegularJobsServiceTests.cs +++ b/HerPublicWebsite.UnitTests/BusinessLogic/Services/UnsubmittedReferralRequestServiceTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -11,26 +11,31 @@ using HerPublicWebsite.BusinessLogic.Services.RegularJobs; using Moq; using Tests.Builders; +using RichardSzalay.MockHttp; +using HerPublicWebsite.BusinessLogic.ExternalServices.Common; namespace Tests.BusinessLogic.Services; [TestFixture] -public class RegularJobsServiceTests +public class UnsubmittedReferralRequestsServiceTests { - private IRegularJobsService regularJobsService; + private IUnsubmittedReferralRequestsService unsubmittedReferralRequestsService; private Mock mockDataAccessProvider; private Mock mockS3FileWriter; + private MockHttpMessageHandler mockHttpHandler; [SetUp] public void Setup() { mockDataAccessProvider = new Mock(); mockS3FileWriter = new Mock(); - regularJobsService = new RegularJobsService(mockDataAccessProvider.Object, mockS3FileWriter.Object, new CsvFileCreator()); + unsubmittedReferralRequestsService = new UnsubmittedReferralRequestsService(mockDataAccessProvider.Object, mockS3FileWriter.Object, new CsvFileCreator()); + mockHttpHandler = new MockHttpMessageHandler(); + HttpRequestHelper.handler = mockHttpHandler; } [Test] - public async Task RunNightlyTasksAsync_WhenCalledWithNewReferral_UpdatesReferralCreated() + public async Task WriteUnsubmittedReferralRequestsToCsv_WhenCalledWithNewReferral_UpdatesReferralCreated() { // Arrange var newReferralList = new List @@ -42,7 +47,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithNewReferral_UpdatesReferral .Returns(newReferralList); // Act - await regularJobsService.RunNightlyTasksAsync(); + await unsubmittedReferralRequestsService.WriteUnsubmittedReferralRequestsToCsv(); // Assert newReferralList.Should().AllSatisfy(rr => rr.ReferralWrittenToCsv.Should().BeTrue()); @@ -50,7 +55,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithNewReferral_UpdatesReferral } [Test] - public async Task RunNightlyTasksAsync_WhenCalledWithNewReferral_CreatesFile() + public async Task WriteUnsubmittedReferralRequestsToCsv_WhenCalledWithNewReferral_CreatesFile() { // Arrange var newReferralList = new List @@ -62,7 +67,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithNewReferral_CreatesFile() .Returns(newReferralList); // Act - await regularJobsService.RunNightlyTasksAsync(); + await unsubmittedReferralRequestsService.WriteUnsubmittedReferralRequestsToCsv(); // Assert mockS3FileWriter.Verify(fw => @@ -70,7 +75,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithNewReferral_CreatesFile() } [Test] - public async Task RunNightlyTasksAsync_WhenCalledWithNewReferralForSameMonthAsOldReferrals_UpdatesReferralCreated() + public async Task WriteUnsubmittedReferralRequestsToCsv_WhenCalledWithNewReferralForSameMonthAsOldReferrals_UpdatesReferralCreated() { // Arrange var oldReferral = new ReferralRequestBuilder(1) @@ -95,7 +100,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithNewReferralForSameMonthAsOl .Returns(allReferralList); // Act - await regularJobsService.RunNightlyTasksAsync(); + await unsubmittedReferralRequestsService.WriteUnsubmittedReferralRequestsToCsv(); // Assert allReferralList.Should().AllSatisfy(rr => rr.ReferralWrittenToCsv.Should().BeTrue()); @@ -103,7 +108,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithNewReferralForSameMonthAsOl } [Test] - public async Task RunNightlyTasksAsync_WhenCalledWithMultipleNewReferralsForDifferentCustodianCodes_CreatesMultipleFiles() + public async Task WriteUnsubmittedReferralRequestsToCsv_WhenCalledWithMultipleNewReferralsForDifferentCustodianCodes_CreatesMultipleFiles() { // Arrange var newReferral1 = new ReferralRequestBuilder(1) @@ -127,7 +132,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWithMultipleNewReferralsForDiff .Returns(allReferralListForCustodianCode6); // Act - await regularJobsService.RunNightlyTasksAsync(); + await unsubmittedReferralRequestsService.WriteUnsubmittedReferralRequestsToCsv(); // Assert mockS3FileWriter.Verify(fw => @@ -136,8 +141,9 @@ public async Task RunNightlyTasksAsync_WhenCalledWithMultipleNewReferralsForDiff fw.WriteFileAsync("6", 3, 2023, It.IsAny())); } + [Test] - public async Task RunNightlyTasksAsync_WhenCalledWritingTheSecondFileFails_UpdatesTheReferralsInTheFirstFileButNotTheSecond() + public async Task WriteUnsubmittedReferralRequestsToCsv_WhenCalledWritingTheSecondFileFails_UpdatesTheReferralsInTheFirstFileButNotTheSecond() { // Arrange var newReferral1 = new ReferralRequestBuilder(1) @@ -165,7 +171,7 @@ public async Task RunNightlyTasksAsync_WhenCalledWritingTheSecondFileFails_Updat // Act try { - await regularJobsService.RunNightlyTasksAsync(); + await unsubmittedReferralRequestsService.WriteUnsubmittedReferralRequestsToCsv(); } catch (InvalidOperationException e) when (e.Message == "Test exception") { diff --git a/HerPublicWebsite.UnitTests/BusinessLogic/Services/WorkingDayHelperServiceTests.cs b/HerPublicWebsite.UnitTests/BusinessLogic/Services/WorkingDayHelperServiceTests.cs new file mode 100644 index 00000000..76153626 --- /dev/null +++ b/HerPublicWebsite.UnitTests/BusinessLogic/Services/WorkingDayHelperServiceTests.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using FluentAssertions; +using NUnit.Framework; +using RichardSzalay.MockHttp; +using HerPublicWebsite.BusinessLogic.ExternalServices.Common; +using HerPublicWebsite.BusinessLogic.Services.RegularJobs; + +namespace Tests.BusinessLogic.Services; + +[TestFixture] +public class WorkingDayHelperServiceTests +{ + private IWorkingDayHelperService workingDayHelperService; + private MockHttpMessageHandler mockHttpHandler; + + [SetUp] + public void Setup() + { + workingDayHelperService = new WorkingDayHelperService(); + mockHttpHandler = new MockHttpMessageHandler(); + HttpRequestHelper.handler = mockHttpHandler; + } + + [TestCase("2024-01-24", 0, "2024-01-24")] // Zero days change + [TestCase("2024-01-24", +2, "2024-01-26")] // Adding days + [TestCase("2024-01-24", -2, "2024-01-22")] // Subtracting days + [TestCase("2024-01-24", +10, "2024-02-07")] // Over weekends + [TestCase("2024-05-8", -5, "2024-04-30")] // Over bank holiday + [TestCase("2024-05-30", -20, "2024-04-30")] // Over multiple bank holidays + [TestCase("2024-05-12", -3, "2024-05-08")] // Starting during weekend + [TestCase("2024-05-06", -3, "2024-05-01")] // Starting during bank holiday + [TestCase("2024-05-15", -3, "2024-05-10")] // Ending during weekend + [TestCase("2024-05-09", -3, "2024-05-03")] // Ending during bank holiday + [TestCase("2024-05-24 00:05:00", -5, "2024-05-17")] // Starting after midnight + + public async Task AddWorkingDaysToDateTime_WhenCalledOnADayFollowingABankHoliday_CorrectlyCalculatesANewDate(DateTime initialDateTime, int workingDaysToAdd, DateTime expectedResult) + { + // Arrange + var bankHolidayResponse = await File.ReadAllTextAsync("MockHttpResponses/bank-holidays.json"); + mockHttpHandler.Expect("https://www.gov.uk/bank-holidays.json") + .Respond("application/json", bankHolidayResponse + ); + // Act + var newDateTime = await workingDayHelperService.AddWorkingDaysToDateTime(initialDateTime, workingDaysToAdd); + + // Assert + newDateTime.Should().BeSameDateAs(expectedResult); + } +} diff --git a/HerPublicWebsite.UnitTests/HerPublicWebsite.UnitTests.csproj b/HerPublicWebsite.UnitTests/HerPublicWebsite.UnitTests.csproj index ec859e7c..965cc96c 100644 --- a/HerPublicWebsite.UnitTests/HerPublicWebsite.UnitTests.csproj +++ b/HerPublicWebsite.UnitTests/HerPublicWebsite.UnitTests.csproj @@ -20,5 +20,9 @@ + + + + diff --git a/HerPublicWebsite.UnitTests/MockHttpResponses/bank-holidays.json b/HerPublicWebsite.UnitTests/MockHttpResponses/bank-holidays.json new file mode 100644 index 00000000..cd08d8bb --- /dev/null +++ b/HerPublicWebsite.UnitTests/MockHttpResponses/bank-holidays.json @@ -0,0 +1,1529 @@ +{ + "england-and-wales": { + "division": "england-and-wales", + "events": [ + { + "title": "New Year’s Day", + "date": "2018-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2018-03-30", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2018-04-02", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2018-05-07", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2018-05-28", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2018-08-27", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2018-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2018-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2019-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2019-04-19", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2019-04-22", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2019-05-06", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2019-05-27", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2019-08-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2019-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2019-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2020-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2020-04-10", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2020-04-13", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday (VE day)", + "date": "2020-05-08", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2020-05-25", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2020-08-31", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2020-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2020-12-28", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2021-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2021-04-02", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2021-04-05", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2021-05-03", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2021-05-31", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2021-08-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2021-12-27", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2021-12-28", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2022-01-03", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2022-04-15", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2022-04-18", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2022-05-02", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2022-06-02", + "notes": "", + "bunting": true + }, + { + "title": "Platinum Jubilee bank holiday", + "date": "2022-06-03", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2022-08-29", + "notes": "", + "bunting": true + }, + { + "title": "Bank Holiday for the State Funeral of Queen Elizabeth II", + "date": "2022-09-19", + "notes": "", + "bunting": false + }, + { + "title": "Boxing Day", + "date": "2022-12-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2022-12-27", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2023-01-02", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2023-04-07", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2023-04-10", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2023-05-01", + "notes": "", + "bunting": true + }, + { + "title": "Bank holiday for the coronation of King Charles III", + "date": "2023-05-08", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2023-05-29", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2023-08-28", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2023-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2023-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2024-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2024-03-29", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2024-04-01", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2024-05-06", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2024-05-27", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2024-08-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2024-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2024-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2025-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2025-04-18", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2025-04-21", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2025-05-05", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2025-05-26", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2025-08-25", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2025-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2025-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2026-01-01", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2026-04-03", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2026-04-06", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2026-05-04", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2026-05-25", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2026-08-31", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2026-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2026-12-28", + "notes": "Substitute day", + "bunting": true + } + ] + }, + "scotland": { + "division": "scotland", + "events": [ + { + "title": "New Year’s Day", + "date": "2018-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2018-01-02", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2018-03-30", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2018-05-07", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2018-05-28", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2018-08-06", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2018-11-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2018-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2018-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2019-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2019-01-02", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2019-04-19", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2019-05-06", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2019-05-27", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2019-08-05", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2019-12-02", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2019-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2019-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2020-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2020-01-02", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2020-04-10", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday (VE day)", + "date": "2020-05-08", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2020-05-25", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2020-08-03", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2020-11-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2020-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2020-12-28", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2021-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2021-01-04", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2021-04-02", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2021-05-03", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2021-05-31", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2021-08-02", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2021-11-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2021-12-27", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2021-12-28", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2022-01-03", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "2nd January", + "date": "2022-01-04", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2022-04-15", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2022-05-02", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2022-06-02", + "notes": "", + "bunting": true + }, + { + "title": "Platinum Jubilee bank holiday", + "date": "2022-06-03", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2022-08-01", + "notes": "", + "bunting": true + }, + { + "title": "Bank Holiday for the State Funeral of Queen Elizabeth II", + "date": "2022-09-19", + "notes": "", + "bunting": false + }, + { + "title": "St Andrew’s Day", + "date": "2022-11-30", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2022-12-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2022-12-27", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2023-01-02", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "2nd January", + "date": "2023-01-03", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2023-04-07", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2023-05-01", + "notes": "", + "bunting": true + }, + { + "title": "Bank holiday for the coronation of King Charles III", + "date": "2023-05-08", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2023-05-29", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2023-08-07", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2023-11-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2023-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2023-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2024-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2024-01-02", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2024-03-29", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2024-05-06", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2024-05-27", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2024-08-05", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2024-12-02", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2024-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2024-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2025-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2025-01-02", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2025-04-18", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2025-05-05", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2025-05-26", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2025-08-04", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2025-12-01", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2025-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2025-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2026-01-01", + "notes": "", + "bunting": true + }, + { + "title": "2nd January", + "date": "2026-01-02", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2026-04-03", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday", + "date": "2026-05-04", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2026-05-25", + "notes": "", + "bunting": true + }, + { + "title": "Summer bank holiday", + "date": "2026-08-03", + "notes": "", + "bunting": true + }, + { + "title": "St Andrew’s Day", + "date": "2026-11-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2026-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2026-12-28", + "notes": "Substitute day", + "bunting": true + } + ] + }, + "northern-ireland": { + "division": "northern-ireland", + "events": [ + { + "title": "New Year’s Day", + "date": "2018-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2018-03-19", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2018-03-30", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2018-04-02", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2018-05-07", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2018-05-28", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2018-07-12", + "notes": "", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2018-08-27", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2018-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2018-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2019-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2019-03-18", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2019-04-19", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2019-04-22", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2019-05-06", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2019-05-27", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2019-07-12", + "notes": "", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2019-08-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2019-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2019-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2020-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2020-03-17", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2020-04-10", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2020-04-13", + "notes": "", + "bunting": false + }, + { + "title": "Early May bank holiday (VE day)", + "date": "2020-05-08", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2020-05-25", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2020-07-13", + "notes": "Substitute day", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2020-08-31", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2020-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2020-12-28", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2021-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2021-03-17", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2021-04-02", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2021-04-05", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2021-05-03", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2021-05-31", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2021-07-12", + "notes": "", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2021-08-30", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2021-12-27", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2021-12-28", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2022-01-03", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2022-03-17", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2022-04-15", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2022-04-18", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2022-05-02", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2022-06-02", + "notes": "", + "bunting": true + }, + { + "title": "Platinum Jubilee bank holiday", + "date": "2022-06-03", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2022-07-12", + "notes": "", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2022-08-29", + "notes": "", + "bunting": true + }, + { + "title": "Bank Holiday for the State Funeral of Queen Elizabeth II", + "date": "2022-09-19", + "notes": "", + "bunting": false + }, + { + "title": "Boxing Day", + "date": "2022-12-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2022-12-27", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2023-01-02", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2023-03-17", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2023-04-07", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2023-04-10", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2023-05-01", + "notes": "", + "bunting": true + }, + { + "title": "Bank holiday for the coronation of King Charles III", + "date": "2023-05-08", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2023-05-29", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2023-07-12", + "notes": "", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2023-08-28", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2023-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2023-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2024-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2024-03-18", + "notes": "Substitute day", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2024-03-29", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2024-04-01", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2024-05-06", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2024-05-27", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2024-07-12", + "notes": "", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2024-08-26", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2024-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2024-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2025-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2025-03-17", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2025-04-18", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2025-04-21", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2025-05-05", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2025-05-26", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2025-07-14", + "notes": "Substitute day", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2025-08-25", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2025-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2025-12-26", + "notes": "", + "bunting": true + }, + { + "title": "New Year’s Day", + "date": "2026-01-01", + "notes": "", + "bunting": true + }, + { + "title": "St Patrick’s Day", + "date": "2026-03-17", + "notes": "", + "bunting": true + }, + { + "title": "Good Friday", + "date": "2026-04-03", + "notes": "", + "bunting": false + }, + { + "title": "Easter Monday", + "date": "2026-04-06", + "notes": "", + "bunting": true + }, + { + "title": "Early May bank holiday", + "date": "2026-05-04", + "notes": "", + "bunting": true + }, + { + "title": "Spring bank holiday", + "date": "2026-05-25", + "notes": "", + "bunting": true + }, + { + "title": "Battle of the Boyne (Orangemen’s Day)", + "date": "2026-07-13", + "notes": "Substitute day", + "bunting": false + }, + { + "title": "Summer bank holiday", + "date": "2026-08-31", + "notes": "", + "bunting": true + }, + { + "title": "Christmas Day", + "date": "2026-12-25", + "notes": "", + "bunting": true + }, + { + "title": "Boxing Day", + "date": "2026-12-28", + "notes": "Substitute day", + "bunting": true + } + ] + } +} diff --git a/HerPublicWebsite/Controllers/QuestionnaireController.cs b/HerPublicWebsite/Controllers/QuestionnaireController.cs index 011dbc35..072434bc 100644 --- a/HerPublicWebsite/Controllers/QuestionnaireController.cs +++ b/HerPublicWebsite/Controllers/QuestionnaireController.cs @@ -473,6 +473,7 @@ public IActionResult Pending_Get(QuestionFlowStep? entryPoint, bool emailPrefere var viewModel = new PendingViewModel() { LocalAuthorityName = questionnaire.LocalAuthorityName, + LocalAuthorityMessagePartialViewPath = GetLocalAuthorityPendingMessagePartialViewPath(questionnaire), Submitted = emailPreferenceSubmitted, EmailAddress = questionnaire.NotificationEmailAddress, CanContactByEmailAboutFutureSchemes = questionnaire.NotificationConsent.ToNullableYesOrNo(), @@ -621,6 +622,7 @@ public IActionResult Confirmation_Get(bool emailPreferenceSubmitted) { ReferenceCode = questionnaire.ReferralCode, LocalAuthorityName = questionnaire.LocalAuthorityName, + LocalAuthorityMessagePartialViewPath = GetLocalAuthorityConfirmationMessagePartialViewPath(questionnaire), LocalAuthorityWebsite = questionnaire.LocalAuthorityWebsite, LocalAuthorityIsLiveWithHug2 = questionnaire.LocalAuthorityHug2Status is LocalAuthorityData.Hug2Status.Live, ConfirmationSentToEmailAddress = questionnaire.LaContactEmailAddress ?? questionnaire.ConfirmationEmailAddress, @@ -810,4 +812,23 @@ public PathByActionArguments(string action, string controller, RouteValueDiction Values = values; } } + + private static string GetLocalAuthorityPendingMessagePartialViewPath(Questionnaire questionnaire) + { + var partialViewName = questionnaire.CustodianCode switch + { + "2610" => "Broadland", + _ => "Default" + }; + return $"~/Views/Partials/LocalAuthorityMessages/Pending/{partialViewName}.cshtml"; + } + + private static string GetLocalAuthorityConfirmationMessagePartialViewPath(Questionnaire questionnaire) + { + var partialViewName = questionnaire.CustodianCode switch + { + _ => "Default" + }; + return $"~/Views/Partials/LocalAuthorityMessages/Confirmation/{partialViewName}.cshtml"; + } } diff --git a/HerPublicWebsite/Models/Questionnaire/ConfirmationViewModel.cs b/HerPublicWebsite/Models/Questionnaire/ConfirmationViewModel.cs index 92f77de9..530c2df9 100644 --- a/HerPublicWebsite/Models/Questionnaire/ConfirmationViewModel.cs +++ b/HerPublicWebsite/Models/Questionnaire/ConfirmationViewModel.cs @@ -8,6 +8,7 @@ public class ConfirmationViewModel : QuestionFlowViewModel { public string ReferenceCode { get; set; } public string LocalAuthorityName { get; set; } + public string LocalAuthorityMessagePartialViewPath { get; set; } public string LocalAuthorityWebsite { get; set; } public bool LocalAuthorityIsLiveWithHug2 { get; set; } public bool RequestEmailAddress { get; set; } diff --git a/HerPublicWebsite/Models/Questionnaire/PendingViewModel.cs b/HerPublicWebsite/Models/Questionnaire/PendingViewModel.cs index f67e832a..9fc20248 100644 --- a/HerPublicWebsite/Models/Questionnaire/PendingViewModel.cs +++ b/HerPublicWebsite/Models/Questionnaire/PendingViewModel.cs @@ -7,6 +7,8 @@ namespace HerPublicWebsite.Models.Questionnaire; public class PendingViewModel : QuestionFlowViewModel { public string LocalAuthorityName { get; set; } + + public string LocalAuthorityMessagePartialViewPath { get; set; } [EmailAddress(ErrorMessage = "Enter an email address in the correct format, like name@example.com")] [GovUkValidateRequiredIf(ErrorMessageIfMissing = "Enter your email address", IsRequiredPropertyName = nameof(IsEmailAddressRequired))] diff --git a/HerPublicWebsite/Program.cs b/HerPublicWebsite/Program.cs index 38a99da1..7c388c95 100644 --- a/HerPublicWebsite/Program.cs +++ b/HerPublicWebsite/Program.cs @@ -29,15 +29,29 @@ public static void Main(string[] args) var dbContext = scope.ServiceProvider.GetRequiredService(); dbContext.Database.Migrate(); + // Remove deprecated nightly tasks service + app + .Services + .GetService() + .RemoveIfExists("Nightly tasks"); + // Run nightly tasks at 00:30 UTC daily app .Services .GetService() - .AddOrUpdate( - "Nightly tasks", - rjs => rjs.RunNightlyTasksAsync(), + .AddOrUpdate( + "Get referrals passed ten day working threshold with no follow up", + rjs => rjs.GetReferralsPastTenWorkingDayThresholdWithNoFollowUp(), "30 0 * * *"); + app + .Services + .GetService() + .AddOrUpdate( + "Write unsubmitted referral requests to csv", + rjs => rjs.WriteUnsubmittedReferralRequestsToCsv(), + "45 0 * * *"); + app.Run(); } } diff --git a/HerPublicWebsite/Startup.cs b/HerPublicWebsite/Startup.cs index 682ed9fe..c8b96275 100644 --- a/HerPublicWebsite/Startup.cs +++ b/HerPublicWebsite/Startup.cs @@ -65,7 +65,9 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddMemoryCache(); services.AddSingleton(); diff --git a/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Confirmation/Default.cshtml b/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Confirmation/Default.cshtml new file mode 100644 index 00000000..74c1afac --- /dev/null +++ b/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Confirmation/Default.cshtml @@ -0,0 +1,6 @@ +@model HerPublicWebsite.Models.Questionnaire.ConfirmationViewModel + +

+ @Model.LocalAuthorityName or their official contractor will process + your details and contact you if they need any more information on the contact details you provided. +

diff --git a/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Pending/Broadland.cshtml b/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Pending/Broadland.cshtml new file mode 100644 index 00000000..fd2a53bf --- /dev/null +++ b/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Pending/Broadland.cshtml @@ -0,0 +1,19 @@ +@model HerPublicWebsite.Models.Questionnaire.PendingViewModel + +

+ Based on the information you provided, it looks like your local authority, + @Model.LocalAuthorityName, + is not signed up to use this service. + This means you will need to contact them directly. + To apply, please see the details below. +

+ +
+

Norfolk Warm Homes

+

01603 430103

+

+ + warmhomesfund@southnorfolkandbroadland.gov.uk + +

+
\ No newline at end of file diff --git a/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Pending/Default.cshtml b/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Pending/Default.cshtml new file mode 100644 index 00000000..60f7200b --- /dev/null +++ b/HerPublicWebsite/Views/Partials/LocalAuthorityMessages/Pending/Default.cshtml @@ -0,0 +1,8 @@ +@model HerPublicWebsite.Models.Questionnaire.PendingViewModel + +

+ Based on the information you provided, it looks like your local authority, + @Model.LocalAuthorityName, + is not signed up to use this service yet. + This means you are unable to create an application at this time. +

diff --git a/HerPublicWebsite/Views/Questionnaire/Confirmation.cshtml b/HerPublicWebsite/Views/Questionnaire/Confirmation.cshtml index 94b865de..1585c701 100644 --- a/HerPublicWebsite/Views/Questionnaire/Confirmation.cshtml +++ b/HerPublicWebsite/Views/Questionnaire/Confirmation.cshtml @@ -31,8 +31,7 @@

You will receive an email confirmation at @Model.ConfirmationSentToEmailAddress

} -

@Model.LocalAuthorityName or their official contractor will process - your details and contact you if they need any more information on the contact details you provided.

+ @await Html.PartialAsync(Model.LocalAuthorityMessagePartialViewPath) @if (Model.LocalAuthorityIsLiveWithHug2) { diff --git a/HerPublicWebsite/Views/Questionnaire/Pending.cshtml b/HerPublicWebsite/Views/Questionnaire/Pending.cshtml index 32edf1bf..db250965 100644 --- a/HerPublicWebsite/Views/Questionnaire/Pending.cshtml +++ b/HerPublicWebsite/Views/Questionnaire/Pending.cshtml @@ -1,6 +1,5 @@ @using GovUkDesignSystem @using GovUkDesignSystem.GovUkDesignSystemComponents -@using HerPublicWebsite.BusinessLogic.Models.Enums @using Microsoft.AspNetCore.Mvc.TagHelpers @using HerPublicWebsite.Controllers @using HerPublicWebsite.Models.Enums @@ -27,10 +26,8 @@

Your Local Authority is not ready to process applications yet

What to do next

- -

- Based on the information you provided, it looks like your local authority, @Model.LocalAuthorityName, is not signed up to use this service yet. This means you are unable to create an application at this time. -

+ + @await Html.PartialAsync(Model.LocalAuthorityMessagePartialViewPath)

If your local authority does not seem right, find your correct local authority and contact them directly.