Skip to content

Commit

Permalink
Merge branch 'main' into fix/sonar-issues
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertGHippo authored Jul 17, 2024
2 parents 614f757 + 72bf4b8 commit 9563d6b
Show file tree
Hide file tree
Showing 30 changed files with 856 additions and 243 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="contentful.csharp" Version="7.6.0" />
<PackageReference Include="contentful.csharp" Version="7.6.1" />
</ItemGroup>

<ItemGroup>
Expand All @@ -23,6 +23,9 @@
<None Update="csv\ey-quals-full-2024-updated.csv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="csv\reference-upload-test.csv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
127 changes: 100 additions & 27 deletions content/Dfe.EarlyYearsQualification.ContentUpload/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
using Contentful.Core.Models;
using Contentful.Core.Models.Management;
using Contentful.Core.Search;
using Dfe.EarlyYearsQualification.Content.Entities;
using Microsoft.VisualBasic.FileIO;

namespace Dfe.EarlyYearsQualification.ContentUpload;

[ExcludeFromCodeCoverage]
public static class Program
{
private const string Locale = "en-US";
private const string Locale = "en-GB";
private const string SpaceId = "";
private const string ManagementApiKey = "";

Expand Down Expand Up @@ -67,11 +66,9 @@ await client.PublishEntry(entryToPublish.SystemProperties.Id,
private static async Task SetUpContentModels(ContentfulManagementClient client)
{
// Check current version of model
var currentModels = await client.GetContentTypes();
var contentTypeModel = await client.GetContentType("Qualification");

var currentModel = currentModels.FirstOrDefault(x => x.SystemProperties.Id == "Qualification");

var version = currentModel?.SystemProperties.Version ?? 1;
var version = contentTypeModel?.SystemProperties.Version ?? 1;

var contentType = new ContentType
{
Expand Down Expand Up @@ -136,18 +133,48 @@ private static async Task SetUpContentModels(ContentfulManagementClient client)
Name = "Additional Requirements",
Id = "additionalRequirements",
Type = "Text"
},
new Field
{
Name = "Additional Requirement Questions",
Id = "additionalRequirementQuestions",
Type = "Array",
Items = new Schema
{
Type = "Link",
LinkType = "Entry",
Validations = [new LinkContentTypeValidator
{
ContentTypeIds = ["additionalRequirementQuestion"]
}]
}
},
new Field
{
Name = "Ratio Requirements",
Id = "ratioRequirements",
Type = "Array",
Items = new Schema
{
Type = "Link",
LinkType = "Entry",
Validations = [new LinkContentTypeValidator
{
ContentTypeIds = ["ratioRequirement"]
}]
}
}
]
};

var typeToActivate = await client.CreateOrUpdateContentType(contentType, version: version);
await client.ActivateContentType("Qualification", typeToActivate.SystemProperties.Version!.Value);

Thread.Sleep(2000); // Allows the API time to activate the content type
await SetHelpText(client, typeToActivate);
await SetHelpText(client);
}

private static async Task SetHelpText(ContentfulManagementClient client, ContentType typeToActivate)
private static async Task SetHelpText(ContentfulManagementClient client)
{
var editorInterface = await client.GetEditorInterface("Qualification");
SetHelpTextForField(editorInterface, "qualificationId",
Expand All @@ -163,9 +190,10 @@ private static async Task SetHelpText(ContentfulManagementClient client, Content
SetHelpTextForField(editorInterface, "qualificationNumber", "The number of the qualification");
SetHelpTextForField(editorInterface, "additionalRequirements",
"The additional requirements for the qualification", SystemWidgetIds.MultipleLine);

await client.UpdateEditorInterface(editorInterface, "Qualification",
typeToActivate.SystemProperties.Version!.Value);
SetHelpTextForField(editorInterface, "additionalRequirementQuestions", "The optional additional requirements questions", SystemWidgetIds.EntryMultipleLinksEditor);
SetHelpTextForField(editorInterface, "ratioRequirements", "The optional ratio requirements", SystemWidgetIds.EntryMultipleLinksEditor);

await client.UpdateEditorInterface(editorInterface, "Qualification", editorInterface.SystemProperties.Version!.Value);
}

private static void SetHelpTextForField(EditorInterface editorInterface, string fieldId, string helpText,
Expand All @@ -176,8 +204,27 @@ private static void SetHelpTextForField(EditorInterface editorInterface, string
editorInterface.Controls.First(x => x.FieldId == fieldId).WidgetId = widgetId;
}

private static Entry<dynamic> BuildEntryFromQualification(Qualification qualification)
private static Entry<dynamic> BuildEntryFromQualification(QualificationUpload qualification)
{
var addtionalRequirementQuestions = new List<Reference>();
if (qualification.AdditionalRequirementQuestions is not null)
{
foreach (var questionId in qualification.AdditionalRequirementQuestions)
{
addtionalRequirementQuestions.Add(new Reference(SystemLinkTypes.Entry, questionId));
}
}

var ratioRequirements = new List<Reference>();
if (qualification.RatioRequirements is not null)
{
foreach (var ratioId in qualification.RatioRequirements)
{
ratioRequirements.Add(new Reference(SystemLinkTypes.Entry, ratioId));
}
}


var entry = new Entry<dynamic>
{
SystemProperties = new SystemProperties
Expand Down Expand Up @@ -226,18 +273,28 @@ private static Entry<dynamic> BuildEntryFromQualification(Qualification qualific
additionalRequirements = new Dictionary<string, string>
{
{ Locale, qualification.AdditionalRequirements ?? "" }
}
},

additionalRequirementQuestions = new Dictionary<string, List<Reference>>()
{
{ Locale, addtionalRequirementQuestions }
},

ratioRequirements = new Dictionary<string, List<Reference>>()
{
{ Locale, ratioRequirements }
}
}
};

return entry;
}

private static List<Qualification> GetQualificationsToAddOrUpdate()
private static List<QualificationUpload> GetQualificationsToAddOrUpdate()
{
var lines = ReadCsvFile("./csv/ey-quals-full-2024-updated.csv");
var lines = ReadCsvFile("./csv/reference-upload-test.csv");

var listObjResult = new List<Qualification>();
var listObjResult = new List<QualificationUpload>();

foreach (var t in lines)
{
Expand All @@ -249,17 +306,33 @@ private static List<Qualification> GetQualificationsToAddOrUpdate()
var toWhichYear = t[3];
var qualificationNumber = t[6];
var additionalRequirements = t[7];
var additionalRequirementQuestionString = t[8];
var ratioRequirementsString = t[9];

string[] additionalRequirementQuestionsArray = [];
if (!string.IsNullOrEmpty(additionalRequirementQuestionString))
{
additionalRequirementQuestionsArray = additionalRequirementQuestionString.Split(':');
}

string[] ratioRequirementsArray = [];
if (!string.IsNullOrEmpty(ratioRequirementsString))
{
ratioRequirementsArray = ratioRequirementsString.Split(':');
}

listObjResult.Add(new Qualification(
qualificationId,
qualificationName,
awardingOrganisationTitle,
qualificationLevel,
fromWhichYear,
toWhichYear,
qualificationNumber,
additionalRequirements
));
listObjResult.Add(new QualificationUpload(
qualificationId,
qualificationName,
awardingOrganisationTitle,
qualificationLevel,
fromWhichYear,
toWhichYear,
qualificationNumber,
additionalRequirements,
additionalRequirementQuestionsArray,
ratioRequirementsArray
));
}

return listObjResult;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace Dfe.EarlyYearsQualification.ContentUpload;

public class QualificationUpload(
string qualificationId,
string qualificationName,
string awardingOrganisationTitle,
int qualificationLevel,
string? fromWhichYear,
string? toWhichYear,
string? qualificationNumber,
string? additionalRequirements,
string[]? additionalRequirementQuestions,
string[]? ratioRequirements)
{
// Required Fields
public string QualificationId { get; } = qualificationId;
public string QualificationName { get; } = qualificationName;
public string AwardingOrganisationTitle { get; } = awardingOrganisationTitle;
public int QualificationLevel { get; } = qualificationLevel;

// Optional Fields
public string? FromWhichYear { get; } = fromWhichYear;
public string? ToWhichYear { get; } = toWhichYear;
public string? QualificationNumber { get; } = qualificationNumber;
public string? AdditionalRequirements { get; } = additionalRequirements;

public string[]? AdditionalRequirementQuestions { get; } = additionalRequirementQuestions;

public string[]? RatioRequirements { get; } = ratioRequirements;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Qualification Ref,Qualification Level,From which date,To which date,Qualification Name,Awarding Organisation Title,Qualification Number,Notes/Additional Requirements,AdditionalRequirementQuestions,RatioRequirements
EYQ-600-SAM,5,Sep-24,,NCFE CACHE Level 5 Diploma for the Early Years Senior Practitioner (HTQ),NCFE,610/4163/4,"This qualification will replace the predecessor version NCFE CACHE Level 5 Diploma for the Early Years Senior Practitioner 603/3907/X, listed on the post-Sept 2014 tab, which will be withdrawn on 31st August 2024 and this new version launched on 1 September 2024. ","4Mx3V72twImd3VY5uNHiTG:7ymGLoQg58CBfQt91G3ez5","5flybYVibSWDwCdo9LB90b"
EYQ-601-SAM,5,Sep-24,,NCFE CACHE Level 5 Diploma for the Early Years Senior Practitioner (HTQ),NCFE,610/4163/4,"This qualification will replace the predecessor version NCFE CACHE Level 5 Diploma for the Early Years Senior Practitioner 603/3907/X, listed on the post-Sept 2014 tab, which will be withdrawn on 31st August 2024 and this new version launched on 1 September 2024. ","4Mx3V72twImd3VY5uNHiTG",
EYQ-602-SAM,5,Sep-24,,NCFE CACHE Level 5 Diploma for the Early Years Senior Practitioner (HTQ),NCFE,610/4163/4,"This qualification will replace the predecessor version NCFE CACHE Level 5 Diploma for the Early Years Senior Practitioner 603/3907/X, listed on the post-Sept 2014 tab, which will be withdrawn on 31st August 2024 and this new version launched on 1 September 2024. ",,
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="contentful.csharp" Version="7.6.0" />
<PackageReference Include="contentful.csharp" Version="7.6.1" />
<PackageReference Include="FuzzySharp" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ public class QualificationListPage
public string SearchCriteriaHeading { get; init; } = string.Empty;

public Document? PostSearchCriteriaContent { get; init; }

public string AnyLevelHeading { get; init; } = string.Empty;

public string AnyAwardingOrganisationHeading { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ public Task<List<Qualification>> GetQualifications()
SingleQualificationFoundText = "qualification found",
PreSearchBoxContent = ContentfulContentHelper.Text("Pre search box content"),
PostQualificationListContent = ContentfulContentHelper.Text("Post qualification list content"),
PostSearchCriteriaContent = ContentfulContentHelper.Text("Post search criteria content")
PostSearchCriteriaContent = ContentfulContentHelper.Text("Post search criteria content"),
AnyLevelHeading = "Any level",
AnyAwardingOrganisationHeading = "Various awarding organisations"
});
}

Expand Down
18 changes: 14 additions & 4 deletions src/Dfe.EarlyYearsQualification.Web/Controllers/ErrorController.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
using System.Diagnostics;
using Dfe.EarlyYearsQualification.Web.Models;
using Microsoft.AspNetCore.Mvc;

namespace Dfe.EarlyYearsQualification.Web.Controllers;

[Route("/error")]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorController : Controller
{
[HttpGet]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Index()
{
return View("Error", new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
return View("ProblemWithTheService");
}

[Route("{statusCode:int}")]
public IActionResult HttpStatusCodeHandler(int statusCode)
{
HttpContext.Response.StatusCode = statusCode;

return statusCode switch
{
404 => View("NotFound"),
_ => View("ProblemWithTheService")
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private async Task<QualificationListModel> MapList(QualificationListPage content
{
var basicQualificationsModels = GetBasicQualificationsModels(qualifications);

var filterModel = GetFilterModel();
var filterModel = GetFilterModel(content);

return new QualificationListModel
{
Expand All @@ -114,11 +114,13 @@ private async Task<QualificationListModel> MapList(QualificationListPage content
};
}

private FilterModel GetFilterModel()
private FilterModel GetFilterModel(QualificationListPage content)
{
var filterModel = new FilterModel
{
Country = userJourneyCookieService.GetWhereWasQualificationAwarded()!
Country = userJourneyCookieService.GetWhereWasQualificationAwarded()!,
Level = content.AnyLevelHeading,
AwardingOrganisation = content.AnyAwardingOrganisationHeading
};

var (startDateMonth, startDateYear) = userJourneyCookieService.GetWhenWasQualificationAwarded();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Dfe.EarlyYearsQualification.Web.Constants;
using Dfe.EarlyYearsQualification.Web.Controllers.Base;
using Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels;
using Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels.Validators;
using Dfe.EarlyYearsQualification.Web.Services.UserJourneyCookieService;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
Expand All @@ -17,7 +18,8 @@ public class QuestionsController(
IContentService contentService,
IHtmlRenderer renderer,
IUserJourneyCookieService userJourneyCookieService,
IContentFilterService contentFilterService)
IContentFilterService contentFilterService,
IDateQuestionModelValidator questionModelValidator)
: ServiceController
{
private const string Questions = "Questions";
Expand Down Expand Up @@ -77,7 +79,7 @@ public async Task<IActionResult> WhenWasTheQualificationStarted()
[HttpPost("when-was-the-qualification-started")]
public async Task<IActionResult> WhenWasTheQualificationStarted(DateQuestionModel model)
{
if (!ModelState.IsValid || !model.IsModelValid())
if (!ModelState.IsValid || !questionModelValidator.IsValid(model))
{
var questionPage = await contentService.GetDateQuestionPage(QuestionPages.WhenWasTheQualificationStarted);
if (questionPage is not null)
Expand Down Expand Up @@ -119,7 +121,7 @@ public async Task<IActionResult> WhatLevelIsTheQualification(RadioQuestionModel

userJourneyCookieService.SetLevelOfQualification(model.Option!);

if (model.Option == "2" && WithinDateRange())
if (model.Option == "2" && WasAwardedBetweenSeptember2014AndAugust2019())
{
return RedirectToAction("QualificationsStartedBetweenSept2014AndAug2019", "Advice");
}
Expand Down Expand Up @@ -171,7 +173,7 @@ public async Task<IActionResult> WhatIsTheAwardingOrganisation(DropdownQuestionM
return RedirectToAction("Get", "QualificationDetails");
}

private bool WithinDateRange()
private bool WasAwardedBetweenSeptember2014AndAugust2019()
{
var (startDateMonth, startDateYear) = userJourneyCookieService.GetWhenWasQualificationAwarded();
if (startDateMonth is not null && startDateYear is not null)
Expand Down
Loading

0 comments on commit 9563d6b

Please sign in to comment.