Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

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
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace ServiceLayer.Mesh.Migrations
{
/// <inheritdoc />
public partial class ValidationErrors : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "ValidationErrors",
table: "MeshFiles",
type: "nvarchar(max)",
nullable: true);
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ValidationErrors",
table: "MeshFiles");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");

b.Property<string>("ValidationErrors")
.HasColumnType("nvarchar(max)");

b.HasKey("FileId");

b.ToTable("MeshFiles");
Expand Down
2 changes: 2 additions & 0 deletions src/ServiceLayer.Common/Data/Models/MeshFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ public class MeshFile
public string? BlobPath { get; set; }
public DateTime FirstSeenUtc { get; set; }
public DateTime LastUpdatedUtc { get; set; }
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
public string? ValidationErrors { get; set; }
}
1 change: 0 additions & 1 deletion src/ServiceLayer.Mesh/Configuration/AppConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ namespace ServiceLayer.Mesh.Configuration;

public class AppConfiguration :
IFileDiscoveryFunctionConfiguration,
IFileExtractFunctionConfiguration,
IFileExtractQueueClientConfiguration,
IFileTransformQueueClientConfiguration,
IFileTransformFunctionConfiguration,
Expand Down

This file was deleted.

11 changes: 11 additions & 0 deletions src/ServiceLayer.Mesh/Extensions/ApiErrorResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using NHS.MESH.Client.Models;

namespace ServiceLayer.Mesh.Extensions;

public static class ApiErrorResponseExtensions
{
public static string ToFormattedString(this APIErrorResponse? error)
{
return error == null ? "Unknown error" : $"ErrorEvent: {error.ErrorEvent ?? "N/A"}, ErrorCode: {error.ErrorCode ?? "N/A"}, ErrorDescription: {error.ErrorDescription}";
}
}
10 changes: 10 additions & 0 deletions src/ServiceLayer.Mesh/FileTransformerBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using ServiceLayer.Data.Models;

namespace ServiceLayer.Mesh;

public abstract class FileTransformerBase : IFileTransformer
{
protected abstract MeshFileType HandlesFileType { get; }
public virtual bool CanHandle(MeshFileType fileType) => fileType == HandlesFileType;
public abstract Task<IList<ValidationError>> TransformFileAsync(Stream stream, MeshFile metaData);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,23 @@

namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents;

// TODO - NBSS appointment file specific implementation of IFileTransformer. To orchestrate parsing, validation and staging of data (delegated to separate classes)
public class FileTransformer : IFileTransformer
public class FileTransformer(
IFileParser fileParser,
IValidationRunner validationRunner,
IStagingPersister stagingPersister)
: FileTransformerBase
{
private readonly IFileParser _fileParser;
private readonly IValidationRunner _validationRunner;
private readonly IStagingPersister _stagingPersister;
protected override MeshFileType HandlesFileType => MeshFileType.NbssAppointmentEvents;

public FileTransformer(IFileParser fileParser, IValidationRunner validationRunner, IStagingPersister stagingPersister)
{
_fileParser = fileParser;
_validationRunner = validationRunner;
_stagingPersister = stagingPersister;
}

public MeshFileType HandlesFileType => MeshFileType.NbssAppointmentEvents;

public async Task<IList<ValidationError>> TransformFileAsync(Stream stream, MeshFile metaData)
public override async Task<IList<ValidationError>> TransformFileAsync(Stream stream, MeshFile metaData)
{
// TODO - wrap this parsing in a try-catch and return a List<ValidationError> in case of any unforeseen parsing issues (file is totally unlike anything we expect)
var parsed = _fileParser.Parse(stream);
var parsed = fileParser.Parse(stream);

var validationErrors = _validationRunner.Validate(parsed);
var validationErrors = validationRunner.Validate(parsed);
if (!validationErrors.Any())
{
await _stagingPersister.WriteStagedData(parsed, metaData);
await stagingPersister.WriteStagedData(parsed, metaData);
}

return validationErrors;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.Extensions.DependencyInjection;
using ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Validation;


namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents;

public static class ServiceCollectionExtensions
{
public static IServiceCollection ConfigureNbssAppointmentEvents(this IServiceCollection services)
{
services.AddTransient<IFileTransformer, FileTransformer>();
services.AddTransient<IFileParser, FileParser>();
services.AddTransient<IStagingPersister, StagingPersister>();

services.AddSingleton<IValidationRunner, ValidationRunner>();
services.RegisterValidators();

return services;
}

private static IServiceCollection RegisterValidators(this IServiceCollection services)
{
foreach (var recordValidator in ValidatorRegistry.GetAllRecordValidators())
{
services.AddSingleton<IRecordValidator>(_ => recordValidator);
}

foreach (var fileValidator in ValidatorRegistry.GetAllFileValidators())
{
services.AddSingleton<IFileValidator>(_ => fileValidator);
}

return services;
}
}
Loading
Loading