Skip to content

Commit

Permalink
Added v3 put QTLS endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
MrKevJoy committed Apr 22, 2024
1 parent dae38e1 commit 4f5ba9b
Show file tree
Hide file tree
Showing 24 changed files with 1,612 additions and 8 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,7 @@
<data name="Errors.10029.Title" xml:space="preserve">
<value>Request has already been submitted</value>
</data>
<data name="Errors.10030.Title" xml:space="preserve">
<value>Unable to set QTLSDate</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Microsoft.Xrm.Sdk.Query;
using TeachingRecordSystem.Api.V3.Core.SharedModels;
using TeachingRecordSystem.Core.Dqt;
using TeachingRecordSystem.Core.Dqt.Models;
using TeachingRecordSystem.Core.Dqt.Queries;

namespace TeachingRecordSystem.Api.V3.Core.Operations;

public record GetQTLSCommand(string Trn);

public class GetQTLSHandler(ICrmQueryDispatcher _crmQueryDispatcher)
{
public async Task<QTLSInfo?> Handle(GetQTLSCommand command)
{
var contact = (await _crmQueryDispatcher.ExecuteQuery(
new GetActiveContactByTrnQuery(
command.Trn,
new ColumnSet(
Contact.Fields.dfeta_TRN,
Contact.Fields.dfeta_qtlsdate
)
)
))!;

if (contact is null)
{
return null;
}

return new QTLSInfo()
{
Trn = command.Trn,
QTSDate = contact.dfeta_qtlsdate.ToDateOnlyWithDqtBstFix(isLocalTime: true),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Microsoft.Xrm.Sdk.Query;
using TeachingRecordSystem.Api.V3.Core.SharedModels;
using TeachingRecordSystem.Api.Validation;
using TeachingRecordSystem.Core.Dqt;
using TeachingRecordSystem.Core.Dqt.Models;
using TeachingRecordSystem.Core.Dqt.Queries;

namespace TeachingRecordSystem.Api.V3.Core.Operations;


public record SetQTLSCommand(string Trn, DateOnly? QTSDate);

public class SetQTLSHandler(ICrmQueryDispatcher _crmQueryDispatcher)
{
public async Task<QTLSInfo?> Handle(SetQTLSCommand command)
{
var contact = (await _crmQueryDispatcher.ExecuteQuery(
new GetActiveContactByTrnQuery(
command.Trn,
new ColumnSet(
Contact.Fields.dfeta_TRN,
Contact.Fields.dfeta_InductionStatus,
Contact.Fields.dfeta_qtlsdate
)
)
))!;

if (contact == null)
{
return null;
}

if (!CanSetQTLSDate(contact.dfeta_InductionStatus, contact.dfeta_qtlsdate, command.QTSDate))
{
var _ = await _crmQueryDispatcher.ExecuteQuery(
new CreateReviewTaskQuery()
{
TeacherId = contact.Id,
Category = "Unable to set QTLSDate",
Description = $"Unable to set QTLSDate {command.QTSDate}",
Subject = "Notification for SET QTLS data collections team"
}
);

throw new ErrorException(ErrorRegistry.UnableToUpdateQTLSDate());
}

await _crmQueryDispatcher.ExecuteQuery(
new SetQTLSDateQuery(contact.Id, command.QTSDate))!;

contact = (await _crmQueryDispatcher.ExecuteQuery(
new GetActiveContactByTrnQuery(
command.Trn,
new ColumnSet(
Contact.Fields.dfeta_TRN,
Contact.Fields.dfeta_qtlsdate
)
)
))!;

return new QTLSInfo()
{
Trn = command.Trn,
QTSDate = contact.dfeta_qtlsdate.ToDateOnlyWithDqtBstFix(isLocalTime: true)
};
}

private bool CanSetQTLSDate(dfeta_InductionStatus? inductionStatus, DateTime? existingQtlsdate, DateOnly? incomingQtlsDate) =>
inductionStatus switch
{
dfeta_InductionStatus.InProgress when !existingQtlsdate.HasValue && incomingQtlsDate.HasValue => false,
dfeta_InductionStatus.InductionExtended when !existingQtlsdate.HasValue && incomingQtlsDate.HasValue => false,
dfeta_InductionStatus.Fail => false,
dfeta_InductionStatus.FailedinWales when !existingQtlsdate.HasValue && incomingQtlsDate.HasValue => false,
dfeta_InductionStatus.FailedinWales when existingQtlsdate.HasValue && incomingQtlsDate.HasValue => false,
dfeta_InductionStatus.Exempt when existingQtlsdate.HasValue => false,
_ when existingQtlsdate.HasValue && incomingQtlsDate.HasValue && incomingQtlsDate.Value != existingQtlsdate.ToDateOnlyWithDqtBstFix(isLocalTime: false) => false,
_ => true
};
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TeachingRecordSystem.Api.V3.Core.SharedModels;

public record QTLSInfo
{
public required DateOnly? QTSDate { get; init; }
public required string Trn { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using Mapster;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using TeachingRecordSystem.Api.V3.Core.Operations;
using TeachingRecordSystem.Api.V3.Core.SharedModels;
using TeachingRecordSystem.Api.V3.VNext.Requests;

namespace TeachingRecordSystem.Api.V3.V20240307.Controllers;

[ApiController]
[Route("persons")]
[Authorize(Roles = ApiRoles.UpdatePerson)]
public class PersonsController : ControllerBase
{
private readonly IMediator _mediator;

public PersonsController(IMediator mediator)
{
_mediator = mediator;
}


[HttpPut("{trn}/qtls")]
[SwaggerOperation(
OperationId = "PutQTLS",
Summary = "Sets QTLS status for a teacher",
Description = "Sets QTLS status for a teacher.")]
[ProducesResponseType(typeof(QTLSInfo), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
[MapError(10030, statusCode: StatusCodes.Status202Accepted)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Put(
[FromBody] SetQTLSRequest request,
[FromServices] SetQTLSHandler handler)
{
var command = new SetQTLSCommand(request.Trn!, request.QTSDate);
var result = await handler.Handle(command);

if (result is null)
{
return NotFound();
}

var response = result.Adapt<QTLSInfo>();
return Ok(response);
}

[HttpGet("{trn}/qtls")]
[SwaggerOperation(
OperationId = "GetQTLS",
Summary = "Gets QTLS status for a teacher",
Description = "Gets QTLS status for a teacher.")]
[ProducesResponseType(typeof(QTLSInfo), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Get(
[FromRoute] string trn,
[FromServices] GetQTLSHandler handler)
{
var command = new GetQTLSCommand(trn);
var result = await handler.Handle(command);

if (result is null)
{
return NotFound();
}

var response = result.Adapt<QTLSInfo>();
return Ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;

namespace TeachingRecordSystem.Api.V3.VNext.Requests;

public record SetQTLSRequest
{
public required DateOnly? QTSDate { get; init; }

[FromRoute]
public string? Trn { get; set; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using FluentValidation;
using TeachingRecordSystem.Api.V3.VNext.Requests;

namespace TeachingRecordSystem.Api.V3.VNext.Validators;

public class SetQTLSSRequestValidator : AbstractValidator<SetQTLSRequest>
{
public SetQTLSSRequestValidator(IClock clock)
{
RuleFor(x => x.Trn)
.Matches(@"^\d{7}$")
.WithMessage(Properties.StringResources.ErrorMessages_TRNMustBe7Digits);

RuleFor(x => x.QTSDate)
.LessThanOrEqualTo(clock.Today)
.WithMessage($"QTLS Date cannot be in the future.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static class ErrorRegistry
ErrorDescriptor.Create(10027), // Unable to change Failed Result.
ErrorDescriptor.Create(10028), // The specified URL does not exist
ErrorDescriptor.Create(10029), // Request has already been submitted
ErrorDescriptor.Create(10030), // Unable to update QTLSDate
}.ToDictionary(d => d.ErrorCode, d => d);

public static Error TeacherWithSpecifiedTrnNotFound() => CreateError(10001);
Expand Down Expand Up @@ -90,6 +91,8 @@ public static class ErrorRegistry

public static Error CannotResubmitRequest() => CreateError(10029);

public static Error UnableToUpdateQTLSDate() => CreateError(10030);

private static Error CreateError(int errorCode)
{
var descriptor = _all[errorCode];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2231,6 +2231,7 @@ public static class Fields
public const string dfeta_loginfailedcounter = "dfeta_loginfailedcounter";
public const string dfeta_NINumber = "dfeta_ninumber";
public const string dfeta_PreviousLastName = "dfeta_previouslastname";
public const string dfeta_qtlsdate = "dfeta_qtlsdate";
public const string dfeta_QTSDate = "dfeta_qtsdate";
public const string dfeta_SlugId = "dfeta_slugid";
public const string dfeta_StatedFirstName = "dfeta_statedfirstname";
Expand Down Expand Up @@ -2737,6 +2738,26 @@ public string dfeta_PreviousLastName
}
}

/// <summary>
///
/// </summary>
[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_qtlsdate")]
public System.Nullable<System.DateTime> dfeta_qtlsdate
{
[System.Diagnostics.DebuggerNonUserCode()]
get
{
return this.GetAttributeValue<System.Nullable<System.DateTime>>("dfeta_qtlsdate");
}
[System.Diagnostics.DebuggerNonUserCode()]
set
{
this.OnPropertyChanging("dfeta_qtlsdate");
this.SetAttributeValue("dfeta_qtlsdate", value);
this.OnPropertyChanged("dfeta_qtlsdate");
}
}

/// <summary>
///
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,14 @@ public enum Audit_Action
[OptionSetMetadataAttribute("Add To Queue", 46)]
AddToQueue = 52,

[System.Runtime.Serialization.EnumMemberAttribute()]
[OptionSetMetadataAttribute("ApplicationBasedAccessAllowed", 82)]
ApplicationBasedAccessAllowed = 122,

[System.Runtime.Serialization.EnumMemberAttribute()]
[OptionSetMetadataAttribute("ApplicationBasedAccessDenied", 81)]
ApplicationBasedAccessDenied = 121,

[System.Runtime.Serialization.EnumMemberAttribute()]
[OptionSetMetadataAttribute("Approve", 22)]
Approve = 28,
Expand Down Expand Up @@ -2824,6 +2832,19 @@ public enum IncidentResolution_StatusCode
Open = 1,
}

[System.Runtime.Serialization.DataContractAttribute()]
public enum IsInherited
{

[System.Runtime.Serialization.EnumMemberAttribute()]
[OptionSetMetadataAttribute("Direct User (Basic) access level and Team privileges", 1)]
DirectUser_BasicaccesslevelandTeamprivileges = 1,

[System.Runtime.Serialization.EnumMemberAttribute()]
[OptionSetMetadataAttribute("Team privileges only", 0)]
Teamprivilegesonly = 0,
}

[System.Runtime.Serialization.DataContractAttribute()]
public enum msft_DataState
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TeachingRecordSystem.Core.Dqt.Queries;
public record CreateReviewTaskQuery : ICrmQuery<Guid>
{
public required Guid TeacherId { get; set; }
public required string Category { get; set; }
public required string Subject { get; set; }
public required string Description { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace TeachingRecordSystem.Core.Dqt.Queries;

public record SetQTLSDateQuery(Guid contactId, DateOnly? qtlsDate) : ICrmQuery<bool>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.PowerPlatform.Dataverse.Client;
using TeachingRecordSystem.Core.Dqt;
using TeachingRecordSystem.Core.Dqt.Queries;

public class CreateReviewTaskHandler : ICrmQueryHandler<CreateReviewTaskQuery, Guid>
{
public async Task<Guid> Execute(CreateReviewTaskQuery query, IOrganizationServiceAsync organizationService)
{
var crmTaskId = await organizationService.CreateAsync(new CrmTask()
{
Id = Guid.NewGuid(),
RegardingObjectId = query.TeacherId.ToEntityReference(Contact.EntityLogicalName),
Category = query.Category,
Subject = query.Subject,
Description = query.Description
});

return crmTaskId;
}
}
Loading

0 comments on commit 4f5ba9b

Please sign in to comment.