-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CRM + UI + tests for editing a person's date of birth (#880)
- Loading branch information
Showing
16 changed files
with
673 additions
and
0 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
...ngRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateContactDateOfBirthQuery.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
namespace TeachingRecordSystem.Core.Dqt.Queries; | ||
|
||
public record UpdateContactDateOfBirthQuery(Guid ContactId, DateOnly? DateOfBirth) : ICrmQuery<bool>; | ||
|
22 changes: 22 additions & 0 deletions
22
...System/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateContactDateOfBirthHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using Microsoft.PowerPlatform.Dataverse.Client; | ||
using Microsoft.Xrm.Sdk.Messages; | ||
using TeachingRecordSystem.Core.Dqt.Queries; | ||
|
||
namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; | ||
|
||
public class UpdateContactDateOfBirthHandler : ICrmQueryHandler<UpdateContactDateOfBirthQuery, bool> | ||
{ | ||
public async Task<bool> Execute(UpdateContactDateOfBirthQuery query, IOrganizationServiceAsync organizationService) | ||
{ | ||
await organizationService.ExecuteAsync(new UpdateRequest() | ||
{ | ||
Target = new Contact() | ||
{ | ||
Id = query.ContactId, | ||
BirthDate = query.DateOfBirth.FromDateOnlyWithDqtBstFix(isLocalTime: false) | ||
} | ||
}); | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
.../TeachingRecordSystem.SupportUi/Pages/Persons/PersonDetail/EditDateOfBirth/Confirm.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
@page "/persons/{personId}/edit-date-of-birth/confirm" | ||
@model TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditDateOfBirth.ConfirmModel | ||
@{ | ||
ViewBag.Title = "Confirm date of birth change"; | ||
} | ||
|
||
@section BeforeContent { | ||
<govuk-back-link href="@LinkGenerator.PersonEditDateOfBirth(Model.PersonId, Model.JourneyInstance!.InstanceId)" /> | ||
} | ||
|
||
<div class="govuk-grid-row"> | ||
<div class="govuk-grid-column-two-thirds-from-desktop"> | ||
<h1 class="govuk-heading-l">@ViewBag.Title</h1> | ||
<form action="@LinkGenerator.PersonEditDateOfBirthConfirm(Model.PersonId, Model.JourneyInstance!.InstanceId)" method="post"> | ||
<govuk-summary-list> | ||
<govuk-summary-list-row> | ||
<govuk-summary-list-row-key>Current</govuk-summary-list-row-key> | ||
<govuk-summary-list-row-value data-testid="current-value">@Model.CurrentValue</govuk-summary-list-row-value> | ||
</govuk-summary-list-row> | ||
<govuk-summary-list-row> | ||
<govuk-summary-list-row-key>Change to</govuk-summary-list-row-key> | ||
<govuk-summary-list-row-value data-testid="new-value">@Model.NewValue</govuk-summary-list-row-value> | ||
</govuk-summary-list-row> | ||
</govuk-summary-list> | ||
|
||
<govuk-button type="submit">Confirm</govuk-button> | ||
</form> | ||
</div> | ||
</div> |
67 changes: 67 additions & 0 deletions
67
...achingRecordSystem.SupportUi/Pages/Persons/PersonDetail/EditDateOfBirth/Confirm.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||
using TeachingRecordSystem.Core.Dqt.Models; | ||
using TeachingRecordSystem.Core.Dqt.Queries; | ||
|
||
namespace TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditDateOfBirth; | ||
|
||
[Journey(JourneyNames.EditDateOfBirth), RequireJourneyInstance] | ||
public class ConfirmModel : PageModel | ||
{ | ||
private readonly TrsLinkGenerator _linkGenerator; | ||
private readonly ICrmQueryDispatcher _crmQueryDispatcher; | ||
|
||
public ConfirmModel( | ||
TrsLinkGenerator linkGenerator, | ||
ICrmQueryDispatcher crmQueryDispatcher) | ||
{ | ||
_linkGenerator = linkGenerator; | ||
_crmQueryDispatcher = crmQueryDispatcher; | ||
} | ||
|
||
public JourneyInstance<EditDateOfBirthState>? JourneyInstance { get; set; } | ||
|
||
[FromRoute] | ||
public Guid PersonId { get; set; } | ||
|
||
public string? CurrentValue { get; set; } | ||
|
||
public string? NewValue { get; set; } | ||
|
||
public async Task<IActionResult> OnPost() | ||
{ | ||
await _crmQueryDispatcher.ExecuteQuery( | ||
new UpdateContactDateOfBirthQuery( | ||
PersonId, | ||
JourneyInstance!.State.DateOfBirth)); | ||
|
||
await JourneyInstance!.CompleteAsync(); | ||
|
||
TempData.SetFlashSuccess("Record has been updated"); | ||
|
||
return Redirect(_linkGenerator.PersonDetail(PersonId)); | ||
} | ||
|
||
public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) | ||
{ | ||
var state = JourneyInstance!.State; | ||
if (!state.IsComplete) | ||
{ | ||
context.Result = Redirect(_linkGenerator.PersonEditDateOfBirth(PersonId, JourneyInstance!.InstanceId)); | ||
return; | ||
} | ||
|
||
var person = await _crmQueryDispatcher.ExecuteQuery( | ||
new GetContactDetailByIdQuery( | ||
PersonId, | ||
new ColumnSet( | ||
Contact.PrimaryIdAttribute, | ||
Contact.Fields.BirthDate))); | ||
|
||
CurrentValue = person!.Contact.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false)!.Value.ToString("dd/MM/yyyy"); | ||
NewValue = state.DateOfBirth!.Value.ToString("dd/MM/yyyy"); | ||
|
||
await next(); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...RecordSystem.SupportUi/Pages/Persons/PersonDetail/EditDateOfBirth/EditDateOfBirthState.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Text.Json.Serialization; | ||
using TeachingRecordSystem.Core.Dqt.Models; | ||
using TeachingRecordSystem.Core.Dqt.Queries; | ||
|
||
namespace TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditDateOfBirth; | ||
|
||
public class EditDateOfBirthState | ||
{ | ||
public bool Initialized { get; set; } | ||
|
||
public DateOnly? DateOfBirth { get; set; } | ||
|
||
[JsonIgnore] | ||
[MemberNotNullWhen(true, nameof(DateOfBirth))] | ||
public bool IsComplete => DateOfBirth.HasValue; | ||
|
||
public async Task EnsureInitialized(ICrmQueryDispatcher crmQueryDispatcher, Guid personId) | ||
{ | ||
if (Initialized) | ||
{ | ||
return; | ||
} | ||
|
||
var person = await crmQueryDispatcher.ExecuteQuery( | ||
new GetContactDetailByIdQuery( | ||
personId, | ||
new ColumnSet( | ||
Contact.PrimaryIdAttribute, | ||
Contact.Fields.BirthDate))); | ||
DateOfBirth = person!.Contact.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false); | ||
Initialized = true; | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
...rc/TeachingRecordSystem.SupportUi/Pages/Persons/PersonDetail/EditDateOfBirth/Index.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
@page "/persons/{personId}/edit-date-of-birth" | ||
@model TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditDateOfBirth.IndexModel | ||
@{ | ||
ViewBag.Title = "Change date of birth"; | ||
} | ||
|
||
@section BeforeContent { | ||
<govuk-back-link href="@LinkGenerator.PersonDetail(Model.PersonId)">Back</govuk-back-link> | ||
} | ||
|
||
<h1 class="govuk-heading-l">@ViewBag.Title</h1> | ||
|
||
<div class="govuk-grid-row"> | ||
<div class="govuk-grid-column-two-thirds-from-desktop"> | ||
<form action="@LinkGenerator.PersonEditDateOfBirth(Model.PersonId, Model.JourneyInstance!.InstanceId)" method="post"> | ||
<govuk-date-input asp-for="DateOfBirth"> | ||
<govuk-date-input-fieldset> | ||
<govuk-date-input-fieldset-legend class="govuk-fieldset__legend--m" /> | ||
</govuk-date-input-fieldset> | ||
</govuk-date-input> | ||
|
||
<govuk-button type="submit">Continue</govuk-button> | ||
</form> | ||
</div> | ||
</div> |
59 changes: 59 additions & 0 deletions
59
...TeachingRecordSystem.SupportUi/Pages/Persons/PersonDetail/EditDateOfBirth/Index.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||
|
||
namespace TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditDateOfBirth; | ||
|
||
[Journey(JourneyNames.EditDateOfBirth), ActivatesJourney, RequireJourneyInstance] | ||
public class IndexModel : PageModel | ||
{ | ||
private readonly TrsLinkGenerator _linkGenerator; | ||
private readonly ICrmQueryDispatcher _crmQueryDispatcher; | ||
|
||
public IndexModel( | ||
TrsLinkGenerator linkGenerator, | ||
ICrmQueryDispatcher crmQueryDispatcher) | ||
{ | ||
_linkGenerator = linkGenerator; | ||
_crmQueryDispatcher = crmQueryDispatcher; | ||
} | ||
|
||
public JourneyInstance<EditDateOfBirthState>? JourneyInstance { get; set; } | ||
|
||
[FromRoute] | ||
public Guid PersonId { get; set; } | ||
|
||
[BindProperty] | ||
[Display(Name = "Date of birth")] | ||
public DateOnly? DateOfBirth { get; set; } | ||
|
||
public void OnGet() | ||
{ | ||
DateOfBirth ??= JourneyInstance!.State.DateOfBirth; | ||
} | ||
|
||
public async Task<IActionResult> OnPost() | ||
{ | ||
if (DateOfBirth is null) | ||
{ | ||
ModelState.AddModelError(nameof(DateOfBirth), "Enter a date of birth"); | ||
} | ||
|
||
if (!ModelState.IsValid) | ||
{ | ||
return this.PageWithErrors(); | ||
} | ||
|
||
await JourneyInstance!.UpdateStateAsync(s => s.DateOfBirth = DateOfBirth); | ||
|
||
return Redirect(_linkGenerator.PersonEditDateOfBirthConfirm(PersonId, JourneyInstance!.InstanceId)); | ||
} | ||
|
||
public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) | ||
{ | ||
await JourneyInstance!.State.EnsureInitialized(_crmQueryDispatcher, PersonId); | ||
|
||
await next(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...tem/tests/TeachingRecordSystem.Core.Dqt.Tests/QueryTests/UpdateContactDateOfBirthTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
namespace TeachingRecordSystem.Core.Dqt.Tests.QueryTests; | ||
|
||
public class UpdateContactDateOfBirthTests : IAsyncLifetime | ||
{ | ||
private readonly CrmClientFixture.TestDataScope _dataScope; | ||
private readonly CrmQueryDispatcher _crmQueryDispatcher; | ||
|
||
public UpdateContactDateOfBirthTests(CrmClientFixture crmClientFixture) | ||
{ | ||
_dataScope = crmClientFixture.CreateTestDataScope(); | ||
_crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); | ||
} | ||
|
||
public Task InitializeAsync() => Task.CompletedTask; | ||
|
||
public async Task DisposeAsync() => await _dataScope.DisposeAsync(); | ||
|
||
[Fact] | ||
public async Task QueryExecutesSuccessfully() | ||
{ | ||
// Arrange | ||
var person = await _dataScope.TestData.CreatePerson(); | ||
var newDateOfBirth = _dataScope.TestData.GenerateChangedDateOfBirth(person.DateOfBirth); | ||
|
||
var query = new UpdateContactDateOfBirthQuery( | ||
person.ContactId, | ||
newDateOfBirth); | ||
|
||
// Act | ||
await _crmQueryDispatcher.ExecuteQuery(query); | ||
|
||
// Assert | ||
using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); | ||
|
||
var updatedContact = ctx.ContactSet.SingleOrDefault(c => c.GetAttributeValue<Guid>(Contact.PrimaryIdAttribute) == person.ContactId); | ||
Assert.NotNull(updatedContact); | ||
Assert.Equal(newDateOfBirth, updatedContact.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.