Skip to content

Commit

Permalink
Merge pull request #537 from cabinetoffice/feature/dp-516-mappings
Browse files Browse the repository at this point in the history
DP-516 - SupplierInformation mapping added
  • Loading branch information
jakzal committed Sep 2, 2024
2 parents 240f258 + bb5ea1a commit 260aa90
Show file tree
Hide file tree
Showing 14 changed files with 240 additions and 36 deletions.
8 changes: 4 additions & 4 deletions Services/CO.CDP.DataSharing.WebApi.Tests/EntityFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal static OrganisationInformation.Persistence.Forms.SharedConsent GetShare
Organisation = orgnisation,
FormId = form.Id,
Form = form,
AnswerSets = new List<FormAnswerSet> { },
AnswerSets = new List<OrganisationInformation.Persistence.Forms.FormAnswerSet> { },
SubmissionState = SubmissionState.Draft,
SubmittedAt = DateTime.UtcNow,
FormVersionId = string.Empty,
Expand Down Expand Up @@ -99,7 +99,7 @@ internal static OrganisationInformation.Persistence.Forms.SharedConsent GetShare
Organisation = orgnisation,
FormId = form.Id,
Form = form,
AnswerSets = new List<FormAnswerSet> { },
AnswerSets = new List<OrganisationInformation.Persistence.Forms.FormAnswerSet> { },
SubmissionState = SubmissionState.Draft,
SubmittedAt = DateTime.UtcNow,
FormVersionId = "V1.0",
Expand All @@ -113,7 +113,7 @@ internal static OrganisationInformation.Persistence.Forms.SharedConsent GetShare
Organisation = orgnisation,
FormId = form.Id,
Form = form,
AnswerSets = new List<FormAnswerSet> { },
AnswerSets = new List<OrganisationInformation.Persistence.Forms.FormAnswerSet> { },
SubmissionState = SubmissionState.Submitted,
SubmittedAt = DateTime.UtcNow,
FormVersionId = "V1.0",
Expand All @@ -128,7 +128,7 @@ internal static OrganisationInformation.Persistence.Forms.SharedConsent GetShare
Organisation = orgnisation,
FormId = form.Id,
Form = form,
AnswerSets = new List<FormAnswerSet> { },
AnswerSets = new List<OrganisationInformation.Persistence.Forms.FormAnswerSet> { },
SubmissionState = SubmissionState.Submitted,
SubmittedAt = DateTime.UtcNow,
FormVersionId = "V1.0",
Expand Down
151 changes: 137 additions & 14 deletions Services/CO.CDP.DataSharing.WebApi/AutoMapper/DataSharingProfile.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using AutoMapper;
using CO.CDP.DataSharing.WebApi.Model;
using CO.CDP.OrganisationInformation;
using CO.CDP.OrganisationInformation.Persistence;
using Address = CO.CDP.OrganisationInformation.Address;
using Persistence = CO.CDP.OrganisationInformation.Persistence.Forms;

namespace CO.CDP.DataSharing.WebApi.AutoMapper;
Expand All @@ -9,25 +12,144 @@ public class DataSharingProfile : Profile
public DataSharingProfile()
{
CreateMap<Persistence.SharedConsent, ShareReceipt>()
.ForMember(m => m.FormId, o => o.MapFrom(m => m.Guid))
.ForMember(m => m.FormVersionId, o => o.MapFrom(m => m.FormVersionId));
.ForMember(m => m.FormId, o => o.MapFrom(m => m.Guid))
.ForMember(m => m.FormVersionId, o => o.MapFrom(m => m.FormVersionId));

CreateMap<Persistence.SharedConsent, Model.SharedConsent>()
.ForMember(m => m.SubmittedAt, o => o.MapFrom(m => m.SubmittedAt));
CreateMap<Persistence.SharedConsent, SharedConsent>()
.ForMember(m => m.SubmittedAt, o => o.MapFrom(m => m.SubmittedAt));

CreateMap<Persistence.SharedConsentQuestionAnswer, Model.SharedConsentQuestionAnswer>()
.ForMember(m => m.QuestionId, o => o.MapFrom(m => m.QuestionId))
.ForMember(m => m.Title, o => o.MapFrom(m => m.Title))
.ForMember(m => m.Answer, o => o.MapFrom<CustomResolver>());
CreateMap<Persistence.SharedConsentQuestionAnswer, SharedConsentQuestionAnswer>()
.ForMember(m => m.QuestionId, o => o.MapFrom(m => m.QuestionId))
.ForMember(m => m.Title, o => o.MapFrom(m => m.Title))
.ForMember(m => m.Answer, o => o.MapFrom<CustomResolver>());

CreateMap<Persistence.SharedConsentDetails, Model.SharedConsentDetails>()
.ForMember(m => m.SubmittedAt, o => o.MapFrom(m => m.SubmittedAt))
.ForMember(m => m.ShareCode, o => o.MapFrom(m => m.ShareCode));
CreateMap<Persistence.SharedConsentDetails, SharedConsentDetails>()
.ForMember(m => m.SubmittedAt, o => o.MapFrom(m => m.SubmittedAt))
.ForMember(m => m.ShareCode, o => o.MapFrom(m => m.ShareCode));

CreateMap<Persistence.SharedConsent, SupplierInformation>()
.ForMember(m => m.Id, o => o.MapFrom(m => m.Organisation.Guid))
.ForMember(m => m.Name, o => o.MapFrom(m => m.Organisation.Name))
.ForMember(m => m.Identifier,
o => o.MapFrom(m => m.Organisation.Identifiers.FirstOrDefault(x => x.Primary)))
.ForMember(m => m.AdditionalIdentifiers,
o => o.MapFrom(m => m.Organisation.Identifiers.Where(x => !x.Primary).ToList()))
.ForMember(m => m.Address,
o => o.MapFrom(m =>
m.Organisation.Addresses.FirstOrDefault(x =>
x.Type == AddressType.Registered)))
.ForMember(m => m.ContactPoint, o => o.MapFrom(m => m.Organisation.ContactPoints.FirstOrDefault()))
.ForMember(m => m.Roles, o => o.MapFrom(m => m.Organisation.Roles))
.ForMember(m => m.Details, o => o.MapFrom(m => new Details()))
.ForMember(m => m.SupplierInformationData, o => o.MapFrom(m => m))
.ForMember(m => m.AssociatedPersons,
o => o.MapFrom((_, _, _, context) => context.Items["AssociatedPersons"]))
.ForMember(m => m.AdditionalEntities,
o => o.MapFrom((_, _, _, context) => context.Items["AdditionalEntities"]))
.ForMember(m => m.AdditionalParties,
o => o.MapFrom((_, _, _, context) => context.Items["AdditionalParties"]));

CreateMap<Organisation.Identifier, Identifier>()
.ForMember(m => m.Scheme, o => o.MapFrom(m => m.Scheme))
.ForMember(m => m.Id, o => o.MapFrom(m => m.IdentifierId))
.ForMember(m => m.LegalName, o => o.MapFrom(m => m.LegalName))
.ForMember(m => m.Uri, o => o.MapFrom(m => !string.IsNullOrWhiteSpace(m.Uri) ? new Uri(m.Uri) : default));

CreateMap<Organisation.OrganisationAddress, Address>()
.ForMember(m => m.StreetAddress, o => o.MapFrom(m => m.Address.StreetAddress))
.ForMember(m => m.Locality, o => o.MapFrom(m => m.Address.Locality))
.ForMember(m => m.Region, o => o.MapFrom(m => m.Address.Region))
.ForMember(m => m.PostalCode, o => o.MapFrom(m => m.Address.PostalCode))
.ForMember(m => m.CountryName, o => o.MapFrom(m => m.Address.CountryName))
.ForMember(m => m.Country, o => o.MapFrom(m => m.Address.Country))
.ForMember(m => m.Type, o => o.MapFrom(m => m.Type));

CreateMap<Organisation.ContactPoint, ContactPoint>()
.ForMember(m => m.Name, o => o.MapFrom(m => m.Name))
.ForMember(m => m.Email, o => o.MapFrom(m => m.Email))
.ForMember(m => m.Telephone, o => o.MapFrom(m => m.Telephone))
.ForMember(m => m.Url, o => o.MapFrom(m => !string.IsNullOrWhiteSpace(m.Url) ? new Uri(m.Url) : default));

CreateMap<Persistence.SharedConsent, SupplierInformationData>()
.ForMember(m => m.Form, o => o.MapFrom(m => m))
.ForMember(m => m.AnswerSets, o => o.MapFrom(m => m.AnswerSets))
.ForMember(m => m.Questions,
o => o.MapFrom(m => m.AnswerSets.SelectMany(a => a.Section.Questions).DistinctBy(q => q.Id)));

CreateMap<Persistence.SharedConsent, Form>()
.ForMember(m => m.Name, o => o.MapFrom(m => m.Form.Name))
.ForMember(m => m.SubmissionState, o => o.MapFrom(m => m.SubmissionState.ToString()))
.ForMember(m => m.SubmittedAt,
o => o.MapFrom(m => m.SubmittedAt.HasValue ? m.SubmittedAt.Value.DateTime : default))
.ForMember(m => m.OrganisationId, o => o.MapFrom(m => m.Organisation.Guid))
.ForMember(m => m.FormId, o => o.MapFrom(m => m.Guid))
.ForMember(m => m.FormVersionId, o => o.MapFrom(m => m.Form.Version))
.ForMember(m => m.IsRequired, o => o.MapFrom(m => m.Form.IsRequired))
.ForMember(m => m.ShareCode, o => o.MapFrom(m => m.ShareCode));

CreateMap<Persistence.FormAnswerSet, FormAnswerSet>()
.ForMember(m => m.Id, o => o.MapFrom(m => m.Guid))
.ForMember(m => m.Answers, o => o.MapFrom(m => m.Answers));

CreateMap<Persistence.FormAnswer, FormAnswer>()
.ForMember(m => m.QuestionName, o => o.MapFrom(m => m.Question.Guid))
.ForMember(m => m.BoolValue, o => o.MapFrom(m => m.BoolValue))
.ForMember(m => m.NumericValue, o => o.MapFrom(m => m.NumericValue))
.ForMember(m => m.StartValue, o => o.MapFrom(m => m.StartValue))
.ForMember(m => m.EndValue, o => o.MapFrom(m => m.EndValue))
.ForMember(m => m.DateValue, o => o.MapFrom(m => ToDateOnly(m.DateValue)))
.ForMember(m => m.TextValue, o => o.MapFrom(m => m.TextValue))
.ForMember(m => m.OptionValue, o => o.Ignore());

CreateMap<Persistence.FormQuestion, FormQuestion>()
.ForMember(m => m.Type, o => o.MapFrom<CustomFormQuestionTypeResolver>())
.ForMember(m => m.Title, o => o.MapFrom(m => m.Title))
.ForMember(m => m.Name, o => o.MapFrom(m => m.Guid))
.ForMember(m => m.Text, o => o.MapFrom(m => m.Description))
.ForMember(m => m.IsRequired, o => o.MapFrom(m => m.IsRequired))
.ForMember(m => m.SectionName, o => o.MapFrom(m => m.Section.Title))
.ForMember(m => m.Options, o => o.MapFrom(m => m.Options.Choices));

CreateMap<Persistence.FormQuestionChoice, FormQuestionOption>()
.ForMember(m => m.Id, o => o.MapFrom(m => m.Id))
.ForMember(m => m.Value, o => o.MapFrom(m => m.Title));
}

private DateOnly? ToDateOnly(DateTime? dateTime) => dateTime.HasValue ? DateOnly.FromDateTime(dateTime.Value) : null;
}
public class CustomResolver : IValueResolver<Persistence.SharedConsentQuestionAnswer, Model.SharedConsentQuestionAnswer, string?>

public class CustomFormQuestionTypeResolver : IValueResolver<Persistence.FormQuestion, FormQuestion, FormQuestionType>
{
public FormQuestionType Resolve(Persistence.FormQuestion source,
FormQuestion destination, FormQuestionType destMemb, ResolutionContext context)
{
switch (source.Type)
{
case Persistence.FormQuestionType.YesOrNo:
case Persistence.FormQuestionType.CheckBox:
return FormQuestionType.Boolean;
case Persistence.FormQuestionType.Text:
case Persistence.FormQuestionType.FileUpload:
case Persistence.FormQuestionType.Address:
return FormQuestionType.Text;
case Persistence.FormQuestionType.SingleChoice:
case Persistence.FormQuestionType.MultipleChoice:
return FormQuestionType.Option;
case Persistence.FormQuestionType.Date:
return FormQuestionType.Date;
case Persistence.FormQuestionType.NoInput:
case Persistence.FormQuestionType.CheckYourAnswers:
return FormQuestionType.None;
default:
return FormQuestionType.None;
}
}
}

public class CustomResolver : IValueResolver<Persistence.SharedConsentQuestionAnswer, SharedConsentQuestionAnswer, string?>
{
public string? Resolve(Persistence.SharedConsentQuestionAnswer source, Model.SharedConsentQuestionAnswer destination, string? destMemb, ResolutionContext context)
public string? Resolve(Persistence.SharedConsentQuestionAnswer source,
SharedConsentQuestionAnswer destination, string? destMemb, ResolutionContext context)
{
switch (source.QuestionType)
{
Expand All @@ -47,6 +169,7 @@ public class CustomResolver : IValueResolver<Persistence.SharedConsentQuestionAn

private string ToHtmlString(Persistence.FormAddress source)
{
return $"{source.StreetAddress}<br/>{source.Locality}<br/>{source.PostalCode}<br/>{source.Region}<br/>{source.CountryName}";
return
$"{source.StreetAddress}<br/>{source.Locality}<br/>{source.PostalCode}<br/>{source.Region}<br/>{source.CountryName}";
}
}
3 changes: 2 additions & 1 deletion Services/CO.CDP.DataSharing.WebApi/Model/AssociatedPerson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public record AssociatedPerson
[Required] public required string Name { get; init; }
/// <example>"Company Director"</example>
[Required] public required string Relationship { get; init; }

/// <example>"https://cdp.cabinetoffice.gov.uk/persons/c16f9f7b-3f10-42db-86f8-93607b034a4c"</example>
[Required] public required Uri Uri { get; init; }
public Uri? Uri { get; init; }
[Required] public required List<PartyRole> Roles { get; init; }
}
7 changes: 5 additions & 2 deletions Services/CO.CDP.DataSharing.WebApi/Model/FormAnswer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ public record FormAnswer
/// <example>"2024-04-22:00:00.000Z"</example>
public DateTime? EndValue { get; init; }

/// <example>"2024-04-22"</example>
public DateOnly? DateValue { get; init; }

/// <example>"Compliance confirmed through third-party audit."</example>
public string? TextValue { get; init; }

/// <example>2</example>
public int? OptionValue { get; init; }
/// <example>["option-id-1"]</example>
public List<string> OptionValue { get; init; } = [];
}
9 changes: 9 additions & 0 deletions Services/CO.CDP.DataSharing.WebApi/Model/FormAnswerSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace CO.CDP.DataSharing.WebApi.Model;

public record FormAnswerSet
{
/// <example>"3b3a269a-c1fa-4bfa-8892-7c6a9aef03bb"</example>
public required Guid Id { get; set; }

public required ICollection<FormAnswer> Answers { get; set; } = [];
}
3 changes: 3 additions & 0 deletions Services/CO.CDP.DataSharing.WebApi/Model/FormQuestion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ public record FormQuestion
/// <example>"_Steel01"</example>
public required string Name { get; init; }

/// <example>"Upload your accounts"</example>
public required string Title { get; init; }

/// <example><![CDATA["<span style=\"font-weight: bold;\">Central Government Only - UK</span><span style=\"font-size:16.000000000000004px\"><br /></span><p><span style=\"font-size:13.333299999999998px\">For contracts which relate to projects/programmes (i) with a value of £10 million or more; or (ii) a value of less than £10 million where it is anticipated that the project will require in excess of 500 tonnes of steel; please describe the steel specific supply chain management systems, policies, standards and procedures you have in place to ensure robust supply chain management and compliance with relevant legislation.</span><span style=\"font-size:16.000000000000004px\"></span></p><span style=\"font-size:13.333299999999998px\">Please provide details of previous similar projects where you have demonstrated a high level of competency and effectiveness in managing all supply chain members involved in steel supply or production to ensure a sustainable and resilient supply of steel.</span>"]]></example>
public required string Text { get; init; }

Expand Down
4 changes: 3 additions & 1 deletion Services/CO.CDP.DataSharing.WebApi/Model/FormQuestionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ namespace CO.CDP.DataSharing.WebApi.Model;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FormQuestionType
{
None,
Boolean,
Numeric,
Text,
Option,
DateTimeRange
DateTimeRange,
Date
}
11 changes: 6 additions & 5 deletions Services/CO.CDP.DataSharing.WebApi/Model/SupplierInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ public record SupplierInformation
[Required] public required Guid Id { get; init; }
/// <example>"Acme Corporation"</example>
[Required(AllowEmptyStrings = true)] public required string Name { get; init; }
[Required] public required List<AssociatedPerson> AssociatedPersons { get; init; }
[Required] public required List<OrganisationReference> AdditionalParties { get; init; }
[Required] public required List<OrganisationReference> AdditionalEntities { get; init; }
[Required] public required List<AssociatedPerson> AssociatedPersons { get; init; } = [];
[Required] public required List<OrganisationReference> AdditionalParties { get; init; } = [];
[Required] public required List<OrganisationReference> AdditionalEntities { get; init; } = [];
[Required] public required Identifier Identifier { get; init; }
[Required] public required List<Identifier> AdditionalIdentifiers { get; init; }
[Required] public required List<Identifier> AdditionalIdentifiers { get; init; } = [];
[Required] public required Address Address { get; init; }
[Required] public required ContactPoint ContactPoint { get; init; }

/// <example>["supplier"]</example>
[Required] public required List<PartyRole> Roles { get; init; }
[Required] public required List<PartyRole> Roles { get; init; } = [];
[Required] public required Details Details { get; init; }
[Required] public required SupplierInformationData SupplierInformationData { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ namespace CO.CDP.DataSharing.WebApi.Model;
public record SupplierInformationData
{
public required Form Form { get; init; }
public required List<FormAnswer> Answers { get; init; } = new();
public required List<FormQuestion> Questions { get; init; } = new();
public required ICollection<FormAnswerSet> AnswerSets { get; init; } = [];
public required ICollection<FormQuestion> Questions { get; set; } = [];
}
42 changes: 37 additions & 5 deletions Services/CO.CDP.DataSharing.WebApi/UseCase/GetSharedDataUseCase.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,54 @@
using AutoMapper;
using CO.CDP.DataSharing.WebApi.Model;
using CO.CDP.OrganisationInformation;
using CO.CDP.OrganisationInformation.Persistence;
using SharedConsent = CO.CDP.OrganisationInformation.Persistence.Forms.SharedConsent;

namespace CO.CDP.DataSharing.WebApi.UseCase;

public class GetSharedDataUseCase(
IShareCodeRepository shareCodeRepository,
IOrganisationRepository organisationRepository,
IMapper mapper)
: IUseCase<string, SupplierInformation?>
{
public async Task<SupplierInformation?> Execute(string sharecode)
{
var organisation = await shareCodeRepository.GetByShareCode(sharecode);
if (organisation == null)
var sharedConsent = await shareCodeRepository.GetByShareCode(sharecode)
?? throw new SharedConsentNotFoundException("Shared Consent not found.");

var associatedPersons = await AssociatedPersons(sharedConsent);
var additionalEntities = await AdditionalEntities(sharedConsent);
return mapper.Map<SupplierInformation>(sharedConsent, opts =>
{
opts.Items["AssociatedPersons"] = associatedPersons;
opts.Items["AdditionalParties"] = new List<OrganisationReference>();
opts.Items["AdditionalEntities"] = additionalEntities;
});
}

private async Task<ICollection<AssociatedPerson>> AssociatedPersons(SharedConsent sharedConsent)
{
var associatedPersons = await organisationRepository.GetConnectedIndividualTrusts(sharedConsent.OrganisationId);
return associatedPersons.Select(x => new AssociatedPerson
{
throw new SharedConsentNotFoundException("Shared Consent not found.");
}
Id = x.Guid,
Name = string.Format($"{x.IndividualOrTrust?.FirstName} {x.IndividualOrTrust?.LastName}"),
Relationship = x.IndividualOrTrust?.Category.ToString() ?? string.Empty,
Uri = null,
Roles = []
}).ToList();
}

return mapper.Map<SupplierInformation>(organisation);
private async Task<ICollection<OrganisationReference>> AdditionalEntities(SharedConsent sharedConsent)
{
var additionalEntities = await organisationRepository.GetConnectedOrganisations(sharedConsent.OrganisationId);
return additionalEntities.Select(x => new OrganisationReference
{
Id = x.Guid,
Name = x.Organisation?.Name ?? string.Empty,
Roles = [],
Uri = null
}).ToList();
}
}
Loading

0 comments on commit 260aa90

Please sign in to comment.