diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9d57ccd082..bca9bdbd71 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,6 +27,11 @@ resources: endpoint: "GitHub (SFA)" steps: +- task: UseDotNet@2 + displayName: 'Use .NET Core sdk 2.2.x' + inputs: + version: 2.2.x + - task: gittools.gitversion.gitversion-task.GitVersion@5 displayName: GitVersion inputs: diff --git a/azure/accounts.template.json b/azure/accounts.template.json index 7161457795..ed0c0f91ae 100644 --- a/azure/accounts.template.json +++ b/azure/accounts.template.json @@ -77,7 +77,7 @@ "idaTenant": { "type": "string" }, - "idaAudience": { + "accountsApiIdentifierUri": { "type": "string" }, "appServiceAllowedIPs": { @@ -307,8 +307,8 @@ "value": "[parameters('idaTenant')]" }, { - "name": "IdaAudience", - "value": "[parameters('idaAudience')]" + "name": "AccountsApiIdentifierUri", + "value": "[parameters('accountsApiIdentifierUri')]" } ] }, diff --git a/src/SFA.DAS.EAS.Account.Api.Types/AccountLegalEntityViewModel.cs b/src/SFA.DAS.EAS.Account.Api.Types/AccountLegalEntityViewModel.cs index 3430fd7bea..ef21c7c764 100644 --- a/src/SFA.DAS.EAS.Account.Api.Types/AccountLegalEntityViewModel.cs +++ b/src/SFA.DAS.EAS.Account.Api.Types/AccountLegalEntityViewModel.cs @@ -6,5 +6,6 @@ public class AccountLegalEntityViewModel public long AccountLegalEntityId { get; set; } public string AccountLegalEntityPublicHashedId { get; set; } public long LegalEntityId { get; set; } + public string Name { get; set; } } } \ No newline at end of file diff --git a/src/SFA.DAS.EmployerAccounts.Api.Types/AccountLegalEntity.cs b/src/SFA.DAS.EmployerAccounts.Api.Types/AccountLegalEntity.cs index a4eaa90b02..5c59a9ae1a 100644 --- a/src/SFA.DAS.EmployerAccounts.Api.Types/AccountLegalEntity.cs +++ b/src/SFA.DAS.EmployerAccounts.Api.Types/AccountLegalEntity.cs @@ -6,5 +6,6 @@ public class AccountLegalEntity public long AccountLegalEntityId { get; set; } public string AccountLegalEntityPublicHashedId { get; set; } public long LegalEntityId { get; set; } + public string Name { get; set; } } } \ No newline at end of file diff --git a/src/SFA.DAS.EmployerAccounts.Api.Types/Agreement.cs b/src/SFA.DAS.EmployerAccounts.Api.Types/Agreement.cs index d9958d0281..2e876897c3 100644 --- a/src/SFA.DAS.EmployerAccounts.Api.Types/Agreement.cs +++ b/src/SFA.DAS.EmployerAccounts.Api.Types/Agreement.cs @@ -8,6 +8,8 @@ public class Agreement public long Id { get; set; } public DateTime? SignedDate { get; set; } public string SignedByName { get; set; } + public long? SignedById { get; set; } + public string SignedByEmail { get; set; } public EmployerAgreementStatus Status { get; set; } public int TemplateVersionNumber { get; set; } public AgreementType AgreementType { get; set; } diff --git a/src/SFA.DAS.EmployerAccounts.Api/Startup.cs b/src/SFA.DAS.EmployerAccounts.Api/Startup.cs index 602d9ed2bf..903d535b98 100644 --- a/src/SFA.DAS.EmployerAccounts.Api/Startup.cs +++ b/src/SFA.DAS.EmployerAccounts.Api/Startup.cs @@ -11,13 +11,13 @@ public class Startup { public void Configuration(IAppBuilder app) { - app.UseWindowsAzureActiveDirectoryBearerAuthentication(new WindowsAzureActiveDirectoryBearerAuthenticationOptions + _ = app.UseWindowsAzureActiveDirectoryBearerAuthentication(new WindowsAzureActiveDirectoryBearerAuthenticationOptions { Tenant = ConfigurationManager.AppSettings["idaTenant"], TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters { RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role", - ValidAudience = ConfigurationManager.AppSettings["idaAudience"] + ValidAudiences = ConfigurationManager.AppSettings["AccountsApiIdentifierUri"].ToString().Split(',') } }); } diff --git a/src/SFA.DAS.EmployerAccounts.Messages/Events/SignedAgreementEvent.cs b/src/SFA.DAS.EmployerAccounts.Messages/Events/SignedAgreementEvent.cs index b503a9a96f..c2400a1f76 100644 --- a/src/SFA.DAS.EmployerAccounts.Messages/Events/SignedAgreementEvent.cs +++ b/src/SFA.DAS.EmployerAccounts.Messages/Events/SignedAgreementEvent.cs @@ -11,6 +11,7 @@ public class SignedAgreementEvent : Event public Guid UserRef { get; set; } public string OrganisationName { get; set; } public long AgreementId { get; set; } + public long AccountLegalEntityId { get; set; } public long LegalEntityId { get; set; } public bool CohortCreated { get; set; } public AgreementType AgreementType { get; set; } diff --git a/src/SFA.DAS.EmployerAccounts.UnitTests/Commands/SignEmployerAgreementTests/WhenISignAnEmployerAgreement.cs b/src/SFA.DAS.EmployerAccounts.UnitTests/Commands/SignEmployerAgreementTests/WhenISignAnEmployerAgreement.cs index 7c43adc0bb..0b0aeab393 100644 --- a/src/SFA.DAS.EmployerAccounts.UnitTests/Commands/SignEmployerAgreementTests/WhenISignAnEmployerAgreement.cs +++ b/src/SFA.DAS.EmployerAccounts.UnitTests/Commands/SignEmployerAgreementTests/WhenISignAnEmployerAgreement.cs @@ -49,6 +49,7 @@ public class WhenISignAnEmployerAgreement private const long LegalEntityId = 111333; private const string OrganisationName = "Foo"; private const string HashedLegalEntityId = "2635JHG"; + private const long AccountLegalEntityId = 9568456; private const AgreementType AgreementType = Common.Domain.Types.AgreementType.NonLevyExpressionOfInterest; [SetUp] @@ -80,6 +81,7 @@ public void Setup() LegalEntityName = OrganisationName, AgreementType = AgreementType, AccountId = AccountId, + AccountLegalEntityId = AccountLegalEntityId, Id = AgreementId }; @@ -230,6 +232,7 @@ public async Task ThenTheServiceShouldBeNotified() message.AccountId.Should().Be(AccountId); message.AgreementId.Should().Be(AgreementId); message.OrganisationName.Should().Be(OrganisationName); + message.AccountLegalEntityId.Should().Be(AccountLegalEntityId); message.LegalEntityId.Should().Be(LegalEntityId); message.CohortCreated.Should().BeTrue(); message.UserName.Should().Be(_owner.FullName()); @@ -255,6 +258,7 @@ public async Task ThenIfICannotGetCommitmentsForTheAccountIStillNotifyTheService message.AccountId.Should().Be(AccountId); message.AgreementId.Should().Be(AgreementId); message.OrganisationName.Should().Be(OrganisationName); + message.AccountLegalEntityId.Should().Be(AccountLegalEntityId); message.LegalEntityId.Should().Be(LegalEntityId); message.CohortCreated.Should().BeFalse(); message.UserName.Should().Be(_owner.FullName()); diff --git a/src/SFA.DAS.EmployerAccounts.UnitTests/Queries/GetLegalEntityQueryTests/GetLegalEntityQueryTests.cs b/src/SFA.DAS.EmployerAccounts.UnitTests/Queries/GetLegalEntityQueryTests/GetLegalEntityQueryTests.cs index 6106bea704..5060cbb4c2 100644 --- a/src/SFA.DAS.EmployerAccounts.UnitTests/Queries/GetLegalEntityQueryTests/GetLegalEntityQueryTests.cs +++ b/src/SFA.DAS.EmployerAccounts.UnitTests/Queries/GetLegalEntityQueryTests/GetLegalEntityQueryTests.cs @@ -10,6 +10,7 @@ using SFA.DAS.EmployerAccounts.Data; using SFA.DAS.EmployerAccounts.Mappings; using SFA.DAS.EmployerAccounts.Models.Account; +using SFA.DAS.EmployerAccounts.Models.UserProfile; using SFA.DAS.EmployerAccounts.Queries.GetLegalEntity; using SFA.DAS.EmployerAccounts.TestCommon; using FluentTestFixture = SFA.DAS.Testing.FluentTestFixture; @@ -26,13 +27,24 @@ public Task Handle_WhenGettingLegalEntity_ThenShouldReturnLegalEntity() return RunAsync(f => f.Handle(), (f, r) => r.Should().NotBeNull() .And.Match(r2 => r2.LegalEntity.LegalEntityId == f.LegalEntity.Id && - r2.LegalEntity.Agreements.Count == 2 && + r2.LegalEntity.Agreements.Count == 3 && r2.LegalEntity.Agreements.Any(a => a.TemplateVersionNumber == 1 && a.Status == Api.Types.EmployerAgreementStatus.Signed) && - r2.LegalEntity.Agreements.Any(a => a.TemplateVersionNumber == 2 && a.Status == Api.Types.EmployerAgreementStatus.Pending) && + r2.LegalEntity.Agreements.Any(a => a.TemplateVersionNumber == 2 && a.Status == Api.Types.EmployerAgreementStatus.Signed) && + r2.LegalEntity.Agreements.Any(a => a.TemplateVersionNumber == 3 && a.Status == Api.Types.EmployerAgreementStatus.Pending) && r2.LegalEntity.AgreementStatus == Api.Types.EmployerAgreementStatus.Pending && r2.LegalEntity.Agreements.Any(a => a.AgreementType == f.LegalEntity.AccountLegalEntities.First().Agreements.First().Template.AgreementType) )); } + + [Test] + public async Task Handle_WhenGettingLegalEntity_ThenShouldReturnTheCorrectEmailOfUserWhoSignedTheAgreement() + { + var f = new GetLegalEntityQueryTestsFixture(); + var result = await f.Handle(); + + result.LegalEntity.Agreements.First(a => a.TemplateVersionNumber == 1 && a.Status == Api.Types.EmployerAgreementStatus.Signed).SignedByEmail.Should().Be(f.UserB.Email); + result.LegalEntity.Agreements.First(a => a.TemplateVersionNumber == 2 && a.Status == Api.Types.EmployerAgreementStatus.Signed).SignedByEmail.Should().Be(f.UserA.Email); + } } public class GetLegalEntityQueryTestsFixture : FluentTestFixture @@ -47,6 +59,10 @@ public class GetLegalEntityQueryTestsFixture : FluentTestFixture public List LegalEntities { get; set; } public List AccountLegalEntities { get; set; } public DbSetStub AccountLegalEntitiesDbSet { get; set; } + public User UserA { get; set; } + public User UserB { get; set; } + public List Users { get; set; } + public DbSetStub UsersDbSet { get; set; } public GetLegalEntityQueryTestsFixture() { @@ -64,17 +80,24 @@ public GetLegalEntityQueryTestsFixture() AccountLegalEntities = new List(); AccountLegalEntitiesDbSet = new DbSetStub(AccountLegalEntities); + UserA = new User { Id = 1, Email = "UserA@gmail.com"}; + UserB = new User { Id = 2, Email = "UserB@gmail.com"}; + Users = new List { UserA, UserB }; + UsersDbSet = new DbSetStub(Users); + Db.Setup(d => d.LegalEntities).Returns(LegalEntitiesDbSet); Db.Setup(d => d.AccountLegalEntities).Returns(AccountLegalEntitiesDbSet); + Db.Setup(d => d.Users).Returns(UsersDbSet); Handler = new GetLegalEntityQueryHandler(new Lazy(() => Db.Object), ConfigurationProvider); SetAccount() .SetLegalEntity() .SetLegalAccountLegalEntity() - .AddLegalEntityAgreement(1, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Removed) - .AddLegalEntityAgreement(1, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Signed) - .AddLegalEntityAgreement(2, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Pending) + .AddLegalEntityAgreement(1, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Removed, UserA.Id) + .AddLegalEntityAgreement(1, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Signed, UserB.Id) + .AddLegalEntityAgreement(2, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Signed, UserA.Id) + .AddLegalEntityAgreement(3, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus.Pending) .EvaluateSignedAndPendingAgreementIdsForAllAccountLegalEntities(); } @@ -153,7 +176,7 @@ private GetLegalEntityQueryTestsFixture SetLegalAccountLegalEntity() return this; } - private GetLegalEntityQueryTestsFixture AddLegalEntityAgreement(int versionNumber, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus status) + private GetLegalEntityQueryTestsFixture AddLegalEntityAgreement(int versionNumber, EmployerAccounts.Models.EmployerAgreement.EmployerAgreementStatus status, long? signedUserId = null) { var newAgreement = new EmployerAgreement { @@ -162,7 +185,8 @@ private GetLegalEntityQueryTestsFixture AddLegalEntityAgreement(int versionNumbe VersionNumber = versionNumber, AgreementType = AgreementType.Levy }, - StatusId = status + StatusId = status, + SignedById = signedUserId }; newAgreement.AccountLegalEntity = AccountLegalEntity; diff --git a/src/SFA.DAS.EmployerAccounts/Commands/SignEmployerAgreement/SignEmployerAgreementCommandHandler.cs b/src/SFA.DAS.EmployerAccounts/Commands/SignEmployerAgreement/SignEmployerAgreementCommandHandler.cs index 2c691ec03e..dc43bd8f8d 100644 --- a/src/SFA.DAS.EmployerAccounts/Commands/SignEmployerAgreement/SignEmployerAgreementCommandHandler.cs +++ b/src/SFA.DAS.EmployerAccounts/Commands/SignEmployerAgreement/SignEmployerAgreementCommandHandler.cs @@ -97,7 +97,7 @@ private async Task PublihAgreementSignedMessage(EmployerAgreementView agreement, var commitments = await _commitmentService.GetEmployerCommitments(agreement.AccountId); var accountHasCommitments = commitments?.Any() ?? false; - await PublishAgreementSignedMessage(agreement.AccountId, agreement.LegalEntityId, agreement.LegalEntityName, + await PublishAgreementSignedMessage(agreement.AccountId, agreement.AccountLegalEntityId, agreement.LegalEntityId, agreement.LegalEntityName, agreement.Id, accountHasCommitments, owner.FullName(), owner.UserRef, agreement.AgreementType, agreement.VersionNumber, correlationId); } @@ -141,7 +141,7 @@ private async Task SignAgreement(SignEmployerAgreementCommand message, long agre } private Task PublishAgreementSignedMessage( - long accountId, long legalEntityId, string legalEntityName, long agreementId, + long accountId, long accountLegalEntityId, long legalEntityId, string legalEntityName, long agreementId, bool cohortCreated, string currentUserName, Guid currentUserRef, AgreementType agreementType, int versionNumber, string correlationId) { @@ -149,6 +149,7 @@ private Task PublishAgreementSignedMessage( { AccountId = accountId, AgreementId = agreementId, + AccountLegalEntityId = accountLegalEntityId, LegalEntityId = legalEntityId, OrganisationName = legalEntityName, CohortCreated = cohortCreated, diff --git a/src/SFA.DAS.EmployerAccounts/Mappings/AgreementMappings.cs b/src/SFA.DAS.EmployerAccounts/Mappings/AgreementMappings.cs index e460a7f1e0..89d3b4b175 100644 --- a/src/SFA.DAS.EmployerAccounts/Mappings/AgreementMappings.cs +++ b/src/SFA.DAS.EmployerAccounts/Mappings/AgreementMappings.cs @@ -52,6 +52,9 @@ public AgreementMappings() .ForMember( v => v.AgreementType, o => o.MapFrom(a => a.Template.AgreementType)) + .ForMember( + d => d.SignedByEmail, + o => o.Ignore()); ; CreateMap() diff --git a/src/SFA.DAS.EmployerAccounts/Queries/GetLegalEntity/GetLegalEntityQueryHandler.cs b/src/SFA.DAS.EmployerAccounts/Queries/GetLegalEntity/GetLegalEntityQueryHandler.cs index 06cb0d71ce..085f9519a0 100644 --- a/src/SFA.DAS.EmployerAccounts/Queries/GetLegalEntity/GetLegalEntityQueryHandler.cs +++ b/src/SFA.DAS.EmployerAccounts/Queries/GetLegalEntity/GetLegalEntityQueryHandler.cs @@ -26,9 +26,9 @@ public async Task Handle(GetLegalEntityQuery message) var legalEntity = await _db.Value.AccountLegalEntities .Where(l => l.LegalEntityId == message.LegalEntityId && - l.Account.HashedId == message.AccountHashedId && + l.Account.HashedId == message.AccountHashedId && (l.PendingAgreementId != null || l.SignedAgreementId != null) && - l.Deleted == null) + l.Deleted == null) .ProjectTo(_configurationProvider, new { accountHashedId = message.AccountHashedId @@ -40,6 +40,8 @@ public async Task Handle(GetLegalEntityQuery message) .OrderByDescending(a => a.TemplateVersionNumber) .FirstOrDefault(); + await SetEmailAddressForSignatures(legalEntity); + if (legalEntity != null && latestAgreement != null) { legalEntity.AgreementSignedByName = latestAgreement.SignedByName; @@ -52,5 +54,19 @@ public async Task Handle(GetLegalEntityQuery message) LegalEntity = legalEntity }; } + + private async Task SetEmailAddressForSignatures(LegalEntity legalEntity) + { + var userIds = legalEntity?.Agreements?.Where(a=>a.SignedById != null).Select(a => a.SignedById).ToArray(); + + if (userIds != null && userIds.Any()) + { + var users = await _db.Value.Users.Where(u => userIds.Contains(u.Id)).Select(u => new { u.Id, u.Email }).ToListAsync(); + legalEntity.Agreements.Where(a => a.SignedById != null).ToList().ForEach(a => + { + a.SignedByEmail = users.FirstOrDefault(u => u.Id == a.SignedById)?.Email; + }); + } + } } } \ No newline at end of file