From 82848a201bf82ef775828f5d01dd6cc7a938199e Mon Sep 17 00:00:00 2001 From: Yossi Tamari Date: Wed, 15 May 2024 16:56:29 -0700 Subject: [PATCH 1/5] EMBCESSMOD-5208: added primary registrant check on self serve calls; fixed task mapping when querynig supports --- .../Managers/Events/EventsManager.Supports.cs | 37 +++++---- .../Evacuations/EvacuationRepository.cs | 79 +++++++++++-------- .../Resources/Supports/SupportRepository.cs | 33 ++++---- .../DynamicsTestData.cs | 17 +++- .../Engines/Supporting/SelfServeTests.cs | 11 +-- .../Managers/Events/SupportTests.cs | 10 +-- .../Controllers/SupportsController.cs | 69 ++++++++++++++-- .../Events/SelfServeSupports.cs | 15 ++-- 8 files changed, 176 insertions(+), 95 deletions(-) diff --git a/ess/src/API/EMBC.ESS/Managers/Events/EventsManager.Supports.cs b/ess/src/API/EMBC.ESS/Managers/Events/EventsManager.Supports.cs index 6d8686ecb..25de74633 100644 --- a/ess/src/API/EMBC.ESS/Managers/Events/EventsManager.Supports.cs +++ b/ess/src/API/EMBC.ESS/Managers/Events/EventsManager.Supports.cs @@ -80,9 +80,10 @@ public async System.Threading.Tasks.Task Handle(ProcessPaperSupportsCommand cmd) public async System.Threading.Tasks.Task Handle(ProcessSelfServeSupportsCommand cmd) { - var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = cmd.EvacuationFileId })).Items.SingleOrDefault(); - if (file == null) throw new NotFoundException("file not found", cmd.EvacuationFileId); - if (file.NeedsAssessment.EligibilityCheck == null || !file.NeedsAssessment.EligibilityCheck.Eligible) throw new BusinessLogicException($"File {cmd.EvacuationFileId} latest needs assessment doesn't have a valid eligibility check"); + var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = cmd.EvacuationFileNumber })).Items.SingleOrDefault(); + if (file == null) throw new NotFoundException("file not found", cmd.EvacuationFileNumber); + if (file.PrimaryRegistrantUserId != cmd.RegistrantUserId) throw new InvalidOperationException($"Registrant {cmd.RegistrantUserId} does not match file {cmd.EvacuationFileNumber} primary registrant which is {file.PrimaryRegistrantUserId}"); + if (file.NeedsAssessment.EligibilityCheck == null || !file.NeedsAssessment.EligibilityCheck.Eligible) throw new BusinessLogicException($"File {cmd.EvacuationFileNumber} latest needs assessment doesn't have a valid eligibility check"); var response = (GenerateSelfServeSupportsResponse)await supportingEngine.Generate(new CalculateSelfServeSupports(cmd.Supports, file.NeedsAssessment.HouseholdMembers.Select(hm => new SelfServeHouseholdMember(hm.Id, hm.IsMinor)))); @@ -90,14 +91,14 @@ public async System.Threading.Tasks.Task Handle(ProcessSelfServeSupportsCommand new GenerateSelfServeETransferSupports(file.Id, file.PrimaryRegistrantId, response.Supports, cmd.ETransferDetails, file.NeedsAssessment.EligibilityCheck.From.Value, file.NeedsAssessment.EligibilityCheck.To.Value))).Supports; var validationResponse = (DigitalSupportsValidationResponse)await supportingEngine.Validate(new DigitalSupportsValidationRequest { - FileId = cmd.EvacuationFileId, + FileId = cmd.EvacuationFileNumber, Supports = supports }); if (!validationResponse.IsValid) throw new BusinessValidationException(string.Join(',', validationResponse.Errors)); await supportingEngine.Process(new ProcessDigitalSupportsRequest { - FileId = cmd.EvacuationFileId, + FileId = cmd.EvacuationFileNumber, Supports = supports, RequestingUserId = null, IncludeSummaryInReferralsPrintout = false, @@ -334,14 +335,19 @@ public async System.Threading.Tasks.Task Handle(ProcessApprovedSupportsCommand _ public async System.Threading.Tasks.Task Handle(OptOutSelfServeCommand cmd) { - await evacuationRepository.Manage(new Resources.Evacuations.OptoutSelfServe { EvacuationFileNumber = cmd.EvacuationFileId }); + var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = cmd.EvacuationFileNumber })).Items.SingleOrDefault(); + if (file == null) throw new NotFoundException("file not found", cmd.EvacuationFileNumber); + if (file.PrimaryRegistrantId != cmd.RegistrantUserId) throw new InvalidOperationException($"Registrant {cmd.RegistrantUserId} does not match file {cmd.EvacuationFileNumber} primary registrant which is {file.PrimaryRegistrantUserId}"); + + await evacuationRepository.Manage(new Resources.Evacuations.OptoutSelfServe { EvacuationFileNumber = cmd.EvacuationFileNumber }); } public async Task Handle(DraftSelfServeSupportQuery query) { - var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = query.EvacuationFileId })).Items.SingleOrDefault(); - if (file == null) throw new NotFoundException("file not found", query.EvacuationFileId); - if (file.NeedsAssessment.EligibilityCheck == null) throw new BusinessValidationException($"File {query.EvacuationFileId} is not eligible for self serve"); + var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = query.EvacuationFileNumber })).Items.SingleOrDefault(); + if (file == null) throw new NotFoundException("file not found", query.EvacuationFileNumber); + if (file.PrimaryRegistrantUserId != query.RegistrantUserId) throw new InvalidOperationException($"Registrant {query.RegistrantUserId} does not match file {query.EvacuationFileNumber} primary registrant which is {file.PrimaryRegistrantUserId}"); + if (file.NeedsAssessment.EligibilityCheck == null) throw new BusinessValidationException($"File {query.EvacuationFileNumber} is not eligible for self serve"); var task = (await taskRepository.QueryTask(new TaskQuery { ById = file.NeedsAssessment.EligibilityCheck.TaskNumber, ByStatus = [Resources.Tasks.TaskStatus.Active] })).Items.SingleOrDefault() as EssTask; if (task == null) throw new NotFoundException("task not found", file.NeedsAssessment.EligibilityCheck.TaskNumber); @@ -373,13 +379,15 @@ public async Task Handle(DraftSelfServeSuppo public async System.Threading.Tasks.Task Handle(CheckEligibileForSelfServeCommand cmd) { - var ct = CancellationToken.None; + var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = cmd.EvacuationFileNumber })).Items.SingleOrDefault(); + if (file == null) throw new NotFoundException("file not found", cmd.EvacuationFileNumber); + if (file.PrimaryRegistrantUserId != cmd.RegistrantUserId) throw new InvalidOperationException($"Registrant {cmd.RegistrantUserId} does not match file {cmd.EvacuationFileNumber} primary registrant which is {file.PrimaryRegistrantUserId}"); - var eligibilityResult = ((ValidateSelfServeSupportsEligibilityResponse)await supportingEngine.Validate(new ValidateSelfServeSupportsEligibility(cmd.EvacuationFileId), ct)).Eligibility; + var eligibilityResult = ((ValidateSelfServeSupportsEligibilityResponse)await supportingEngine.Validate(new ValidateSelfServeSupportsEligibility(cmd.EvacuationFileNumber), default)).Eligibility; var response = await evacuationRepository.Manage(new Resources.Evacuations.AddEligibilityCheck { - EvacuationFileNumber = cmd.EvacuationFileId, + EvacuationFileNumber = cmd.EvacuationFileNumber, Eligible = eligibilityResult.Eligible, TaskNumber = eligibilityResult.TaskNumber, HomeAddressReferenceId = eligibilityResult.HomeAddressReferenceId, @@ -393,8 +401,9 @@ public async System.Threading.Tasks.Task Handle(CheckEligibileForSelfSer public async Task Handle(EligibilityCheckQuery query) { - var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = query.EvacuationFileId })).Items.SingleOrDefault(); - if (file == null) throw new NotFoundException("file not found", query.EvacuationFileId); + var file = (await evacuationRepository.Query(new Resources.Evacuations.EvacuationFilesQuery { FileId = query.EvacuationFileNumber })).Items.SingleOrDefault(); + if (file == null) throw new NotFoundException("file not found", query.EvacuationFileNumber); + if (file.PrimaryRegistrantUserId != query.RegistrantUserId) throw new InvalidOperationException($"Registrant {query.RegistrantUserId} does not match file {query.EvacuationFileNumber} primary registrant which is {file.PrimaryRegistrantUserId}"); var eligibility = file.NeedsAssessment.EligibilityCheck?.Eligible == true ? new SupportEligibility diff --git a/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs b/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs index 9f49f9d23..b9a4c86ba 100644 --- a/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs +++ b/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs @@ -276,42 +276,43 @@ private static async Task ParallelLoadEvacuationFileAsync(EssContext ctx, era_ev { ctx.AttachTo(nameof(EssContext.era_evacuationfiles), file); - var loadTasks = new[] + var loadTasks = new List(); + + if (file.era_era_evacuationfile_era_animal_ESSFileid == null) loadTasks.Add(ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_animal_ESSFileid), ct)); + if (file.era_era_evacuationfile_era_essfilenote_ESSFileID == null) loadTasks.Add(ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_essfilenote_ESSFileID), ct)); + if (file.era_TaskId == null) loadTasks.Add(ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_TaskId), ct)); + if (file.era_Registrant == null) loadTasks.Add(ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_Registrant), ct)); + if (file.era_era_evacuationfile_era_evacueesupport_ESSFileId == null) loadTasks.Add(ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_evacueesupport_ESSFileId), ct)); + loadTasks.Add(Task.Run(async () => { - ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_animal_ESSFileid), ct), - ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_essfilenote_ESSFileID), ct), - ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_TaskId), ct), - ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_evacueesupport_ESSFileId), ct), - Task.Run(async () => + if (file.era_CurrentNeedsAssessmentid == null) await ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_CurrentNeedsAssessmentid), ct); + ctx.AttachTo(nameof(EssContext.era_needassessments), file.era_CurrentNeedsAssessmentid); + if (file.era_CurrentNeedsAssessmentid.era_TaskNumber == null) await ctx.LoadPropertyAsync(file.era_CurrentNeedsAssessmentid, nameof(era_needassessment.era_TaskNumber), ct); + if (file.era_CurrentNeedsAssessmentid.era_EligibilityCheck == null) await ctx.LoadPropertyAsync(file.era_CurrentNeedsAssessmentid, nameof(era_needassessment.era_EligibilityCheck), ct); + if (file.era_CurrentNeedsAssessmentid.era_EligibilityCheck != null) { - if (file.era_CurrentNeedsAssessmentid == null) await ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_CurrentNeedsAssessmentid), ct); - ctx.AttachTo(nameof(EssContext.era_needassessments), file.era_CurrentNeedsAssessmentid); - if (file.era_CurrentNeedsAssessmentid.era_TaskNumber==null) await ctx.LoadPropertyAsync(file.era_CurrentNeedsAssessmentid, nameof(era_needassessment.era_TaskNumber), ct); - if (file.era_CurrentNeedsAssessmentid.era_EligibilityCheck==null) await ctx.LoadPropertyAsync(file.era_CurrentNeedsAssessmentid, nameof(era_needassessment.era_EligibilityCheck), ct); - if (file.era_CurrentNeedsAssessmentid.era_EligibilityCheck != null) - { - ctx.AttachTo(nameof(EssContext.era_eligibilitychecks), file.era_CurrentNeedsAssessmentid.era_EligibilityCheck); - await ctx.LoadPropertyAsync(file.era_CurrentNeedsAssessmentid.era_EligibilityCheck, nameof(era_eligibilitycheck.era_Task)); - } - - var members = await ctx.era_householdmembers - .Expand(m => m.era_Registrant) - .Where(m => m._era_evacuationfileid_value == file.era_evacuationfileid) - .GetAllPagesAsync(ct); - - file.era_era_evacuationfile_era_householdmember_EvacuationFileid = new Collection( - members.Where(m => m.era_Registrant == null || m.era_Registrant.statecode == (int)EntityState.Active).ToArray()); - - var naHouseholdMembers = (await ctx.era_era_householdmember_era_needassessmentset - .Where(m => m.era_needassessmentid == file._era_currentneedsassessmentid_value) - .GetAllPagesAsync(ct)) - .ToArray(); - - file.era_CurrentNeedsAssessmentid.era_era_householdmember_era_needassessment = new Collection( - file.era_era_evacuationfile_era_householdmember_EvacuationFileid - .Where(m => naHouseholdMembers.Any(nam => nam.era_householdmemberid == m.era_householdmemberid)).ToArray()); - }) - }; + ctx.AttachTo(nameof(EssContext.era_eligibilitychecks), file.era_CurrentNeedsAssessmentid.era_EligibilityCheck); + await ctx.LoadPropertyAsync(file.era_CurrentNeedsAssessmentid.era_EligibilityCheck, nameof(era_eligibilitycheck.era_Task)); + } + + var members = await ctx.era_householdmembers + .Expand(m => m.era_Registrant) + .Where(m => m._era_evacuationfileid_value == file.era_evacuationfileid) + .GetAllPagesAsync(ct); + + file.era_era_evacuationfile_era_householdmember_EvacuationFileid = new Collection( + members.Where(m => m.era_Registrant == null || m.era_Registrant.statecode == (int)EntityState.Active).ToArray()); + + var naHouseholdMembers = (await ctx.era_era_householdmember_era_needassessmentset + .Where(m => m.era_needassessmentid == file._era_currentneedsassessmentid_value) + .GetAllPagesAsync(ct)) + .ToArray(); + + file.era_CurrentNeedsAssessmentid.era_era_householdmember_era_needassessment = new Collection( + file.era_era_evacuationfile_era_householdmember_EvacuationFileid + .Where(m => naHouseholdMembers.Any(nam => nam.era_householdmemberid == m.era_householdmemberid)).ToArray()); + })); + await Task.WhenAll(loadTasks); } @@ -378,7 +379,15 @@ private static async Task> QueryEvacuationFiles( if (!shouldQueryFiles) return Array.Empty(); - var filesQuery = ctx.era_evacuationfiles.Expand(f => f.era_CurrentNeedsAssessmentid).Where(f => f.statecode == (int)EntityState.Active); + var filesQuery = ctx.era_evacuationfiles + .Expand(f => f.era_CurrentNeedsAssessmentid) + .Expand(f => f.era_Registrant) + .Expand(f => f.era_era_evacuationfile_era_animal_ESSFileid) + .Expand(f => f.era_era_evacuationfile_era_animal_ESSFileid) + .Expand(f => f.era_era_evacuationfile_era_essfilenote_ESSFileID) + .Expand(f => f.era_TaskId) + .Expand(f => f.era_era_evacuationfile_era_evacueesupport_ESSFileId) + .Where(f => f.statecode == (int)EntityState.Active); if (!string.IsNullOrEmpty(query.FileId)) filesQuery = filesQuery.Where(f => f.era_name == query.FileId); if (!string.IsNullOrEmpty(query.ManualFileId)) filesQuery = filesQuery.Where(f => f.era_paperbasedessfile == query.ManualFileId); diff --git a/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs b/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs index 7133de0f0..35629732a 100644 --- a/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs +++ b/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs @@ -253,6 +253,14 @@ private static async Task> Search(EssContext ctx !query.ByStatus.HasValue) throw new ArgumentException("Supports query must have at least one criteria", nameof(query)); + IQueryable supportsQuery = ctx.era_evacueesupports + .Expand(s => s.era_EvacuationFileId) + .Expand(s => s.era_EvacuationFileId) + .Expand(s => s.era_era_householdmember_era_evacueesupport) + .Expand(s => s.era_era_evacueesupport_era_supportflag_EvacueeSupport) + .Expand(s => s.era_era_etransfertransaction_era_evacueesuppo) + .Expand(s => s.era_NeedsAssessmentID); + // search a specific file if (!string.IsNullOrEmpty(query.ByEvacuationFileId)) { @@ -262,20 +270,9 @@ private static async Task> Search(EssContext ctx .SingleOrDefault(); if (file == null) return Array.Empty(); - ctx.AttachTo(nameof(EssContext.era_evacuationfiles), file); - await ctx.LoadPropertyAsync(file, nameof(era_evacuationfile.era_era_evacuationfile_era_evacueesupport_ESSFileId), ct); - var supports = file.era_era_evacuationfile_era_evacueesupport_ESSFileId.AsQueryable(); - if (!string.IsNullOrEmpty(query.ById)) supports = supports.Where(s => s.era_name == query.ById); - if (!string.IsNullOrEmpty(query.ByManualReferralId)) supports = supports.Where(s => s.era_manualsupport == query.ByManualReferralId); - if (query.ByStatus.HasValue) supports = supports.Where(s => s.statuscode == (int)query.ByStatus.Value); - supports = supports.OrderBy(s => s.createdon); - - return supports; + supportsQuery = supportsQuery.Where(s => s._era_evacuationfileid_value == file.era_evacuationfileid); } - // search all supports - IQueryable supportsQuery = ctx.era_evacueesupports; - if (!string.IsNullOrEmpty(query.ById)) supportsQuery = supportsQuery.Where(s => s.era_name == query.ById); if (!string.IsNullOrEmpty(query.ByManualReferralId)) supportsQuery = supportsQuery.Where(s => s.era_manualsupport == query.ByManualReferralId); if (query.ByStatus.HasValue) supportsQuery = supportsQuery.Where(s => s.statuscode == (int)query.ByStatus.Value); @@ -290,14 +287,16 @@ private static async Task LoadSupportDetails(EssContext ctx, era_evacueesupport ctx.AttachTo(nameof(EssContext.era_evacueesupports), support); var tasks = new List(); - tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_EvacuationFileId), ct)); - tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_era_householdmember_era_evacueesupport), ct)); - tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_era_evacueesupport_era_supportflag_EvacueeSupport), ct)); - tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_era_etransfertransaction_era_evacueesuppo), ct)); + if (support.era_EvacuationFileId == null) tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_EvacuationFileId), ct)); + if (support.era_NeedsAssessmentID == null) tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_NeedsAssessmentID), ct)); + if (support.era_era_householdmember_era_evacueesupport == null) tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_era_householdmember_era_evacueesupport), ct)); + if (support.era_era_evacueesupport_era_supportflag_EvacueeSupport == null) tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_era_evacueesupport_era_supportflag_EvacueeSupport), ct)); + if (support.era_era_etransfertransaction_era_evacueesuppo == null) tasks.Add(ctx.LoadPropertyAsync(support, nameof(era_evacueesupport.era_era_etransfertransaction_era_evacueesuppo), ct)); await Task.WhenAll(tasks); - var task = await ctx.era_tasks.Where(t => t.era_taskid == support.era_EvacuationFileId._era_taskid_value).SingleOrDefaultAsync(); + if (support.era_NeedsAssessmentID?._era_tasknumber_value == null) throw new InvalidOperationException($"Support {support.era_name} needs assessment has no task"); + var task = await ctx.era_tasks.ByKey(support.era_NeedsAssessmentID._era_tasknumber_value).GetValueAsync(ct); if (task == null) throw new InvalidOperationException($"Support {support.era_name} has no task"); support.era_EvacuationFileId.era_TaskId = task; diff --git a/ess/src/API/EMBC.Tests.Integration.ESS/DynamicsTestData.cs b/ess/src/API/EMBC.Tests.Integration.ESS/DynamicsTestData.cs index e27c9835f..5c3b31e13 100644 --- a/ess/src/API/EMBC.Tests.Integration.ESS/DynamicsTestData.cs +++ b/ess/src/API/EMBC.Tests.Integration.ESS/DynamicsTestData.cs @@ -120,7 +120,7 @@ public DynamicsTestData(IEssContextFactory essContextFactory) if (evacuationfile == null) { - evacuationfile = CreateEvacuationFile(essContext, this.testContact, testPrefix + "-digital"); + evacuationfile = CreateEvacuationFile(essContext, this.testContact, activeTask, testPrefix + "-digital"); } else { @@ -135,7 +135,7 @@ public DynamicsTestData(IEssContextFactory essContextFactory) if (paperEvacuationfile == null) { - paperEvacuationfile = CreateEvacuationFile(essContext, this.testContact, testPrefix + "-paper", testPrefix + "-paper"); + paperEvacuationfile = CreateEvacuationFile(essContext, this.testContact, inactiveTask, testPrefix + "-paper", testPrefix + "-paper"); CreateEvacueeSupports(essContext, paperEvacuationfile, this.testContact, this.team1Tier4Member, testPrefix); } else @@ -284,7 +284,7 @@ private contact CreateContact(EssContext essContext) return contact; } - private era_evacuationfile CreateEvacuationFile(EssContext essContext, contact primaryContact, string fileId, string? paperFileNumber = null) + private era_evacuationfile CreateEvacuationFile(EssContext essContext, contact primaryContact, era_task? task, string fileId, string? paperFileNumber = null) { var file = new era_evacuationfile() { @@ -309,7 +309,13 @@ private era_evacuationfile CreateEvacuationFile(EssContext essContext, contact p essContext.SetLink(file, nameof(era_evacuationfile.era_CurrentNeedsAssessmentid), needsAssessment); essContext.AddLink(file, nameof(era_evacuationfile.era_needsassessment_EvacuationFile), needsAssessment); essContext.SetLink(file, nameof(era_evacuationfile.era_Registrant), primaryContact); - + if (task != null) + { + essContext.SetLink(file, nameof(era_evacuationfile.era_TaskId), task); + essContext.SetLink(needsAssessment, nameof(era_needassessment.era_TaskNumber), task); + file.era_TaskId = task; + needsAssessment.era_TaskNumber = task; + } var primaryMember = new era_householdmember { era_householdmemberid = Guid.NewGuid(), @@ -353,6 +359,7 @@ private era_evacuationfile CreateEvacuationFile(EssContext essContext, contact p } file.era_era_evacuationfile_era_householdmember_EvacuationFileid = new Collection(householdMembers); + file.era_CurrentNeedsAssessmentid = needsAssessment; return file; } @@ -389,6 +396,7 @@ private void CreateEvacueeSupports(EssContext essContext, era_evacuationfile fil { essContext.AddToera_evacueesupports(support); essContext.AddLink(file, nameof(era_evacuationfile.era_era_evacuationfile_era_evacueesupport_ESSFileId), support); + essContext.AddLink(file.era_CurrentNeedsAssessmentid, nameof(era_needassessment.era_era_needassessment_era_evacueesupport_NeedsAssessmentID), support); essContext.SetLink(support, nameof(era_evacueesupport.era_IssuedById), creator); } @@ -396,6 +404,7 @@ private void CreateEvacueeSupports(EssContext essContext, era_evacuationfile fil { essContext.AddToera_evacueesupports(support); essContext.AddLink(file, nameof(era_evacuationfile.era_era_evacuationfile_era_evacueesupport_ESSFileId), support); + essContext.AddLink(file.era_CurrentNeedsAssessmentid, nameof(era_needassessment.era_era_needassessment_era_evacueesupport_NeedsAssessmentID), support); essContext.SetLink(support, nameof(era_evacueesupport.era_IssuedById), creator); essContext.SetLink(support, nameof(era_evacueesupport.era_PayeeId), contact); } diff --git a/ess/src/API/EMBC.Tests.Integration.ESS/Engines/Supporting/SelfServeTests.cs b/ess/src/API/EMBC.Tests.Integration.ESS/Engines/Supporting/SelfServeTests.cs index 49f177580..6444df82b 100644 --- a/ess/src/API/EMBC.Tests.Integration.ESS/Engines/Supporting/SelfServeTests.cs +++ b/ess/src/API/EMBC.Tests.Integration.ESS/Engines/Supporting/SelfServeTests.cs @@ -68,7 +68,7 @@ public async Task ValidateEligibility_ShelterReferral_False() [Fact] public async Task ValidateEligibility_DuplicateSupport_False() { - var (file, _) = await CreateTestSubjects(); + var (file, _) = await CreateTestSubjects(taskNumber: TestData.ActiveTaskId); var actualFile = await GetFile(file.Id); var previousSupports = new[] { @@ -82,7 +82,7 @@ public async Task ValidateEligibility_DuplicateSupport_False() [Fact] public async Task ValidateEligibility_NotDuplicateSupport_True() { - var (file, _) = await CreateTestSubjects(); + var (file, _) = await CreateTestSubjects(taskNumber: TestData.ActiveTaskId); var actualFile = await GetFile(file.Id); var previousSupports = new[] { @@ -129,10 +129,7 @@ public async Task GenerateSelfServeSupports_ShelterAllowance_Generated() supports.Supports.ShouldNotBeEmpty(); } - private async Task<(EvacuationFile file, RegistrantProfile registrantProfile)> CreateTestSubjects( - int numberOfHoldholdMembers = 5, - bool? eligibleAddress = true, - IEnumerable? needs = null) + private async Task<(EvacuationFile file, RegistrantProfile registrantProfile)> CreateTestSubjects(string? taskNumber = null, int numberOfHoldholdMembers = 5, bool? eligibleAddress = true, IEnumerable? needs = null) { var registrant = TestHelper.CreateRegistrantProfile(); if (eligibleAddress == null) @@ -143,7 +140,7 @@ public async Task GenerateSelfServeSupports_ShelterAllowance_Generated() registrant.HomeAddress = TestHelper.CreateSelfServeIneligibleAddress(); registrant.Id = await SaveRegistrant(registrant); - var file = TestHelper.CreateNewTestEvacuationFile(registrant, null); + var file = TestHelper.CreateNewTestEvacuationFile(registrant, taskNumber); file.PrimaryRegistrantId = registrant.Id; file.NeedsAssessment.HouseholdMembers = file.NeedsAssessment.HouseholdMembers.Take(numberOfHoldholdMembers).ToList(); file.NeedsAssessment.Needs = needs ?? [IdentifiedNeed.ShelterAllowance, IdentifiedNeed.Clothing, IdentifiedNeed.Incidentals, IdentifiedNeed.Food]; diff --git a/ess/src/API/EMBC.Tests.Integration.ESS/Managers/Events/SupportTests.cs b/ess/src/API/EMBC.Tests.Integration.ESS/Managers/Events/SupportTests.cs index 48291d444..d919bedbb 100644 --- a/ess/src/API/EMBC.Tests.Integration.ESS/Managers/Events/SupportTests.cs +++ b/ess/src/API/EMBC.Tests.Integration.ESS/Managers/Events/SupportTests.cs @@ -423,10 +423,10 @@ await manager.Handle(new ProcessSupportsCommand [Fact] public async Task CheckEligibility_Created() { - var eligibilityId = await manager.Handle(new CheckEligibileForSelfServeCommand { EvacuationFileId = TestData.EvacuationFileId }); + var eligibilityId = await manager.Handle(new CheckEligibileForSelfServeCommand { RegistrantUserId = TestData.ContactUserId, EvacuationFileNumber = TestData.EvacuationFileId }); eligibilityId.ShouldNotBeNull(); - var eligibility = await manager.Handle(new EligibilityCheckQuery { EvacuationFileId = TestData.EvacuationFileId }); + var eligibility = await manager.Handle(new EligibilityCheckQuery { RegistrantUserId = TestData.ContactUserId, EvacuationFileNumber = TestData.EvacuationFileId }); eligibility.ShouldNotBeNull(); } @@ -441,7 +441,7 @@ public async Task ProcessSelfServeSupports_Supports_SupportsCreated() file.NeedsAssessment.HouseholdMembers = file.NeedsAssessment.HouseholdMembers.Take(5); file.NeedsAssessment.Needs = [IdentifiedNeed.Clothing, IdentifiedNeed.ShelterAllowance, IdentifiedNeed.Incidentals, IdentifiedNeed.Food]; file.Id = await manager.Handle(new SubmitEvacuationFileCommand { File = file }); - await manager.Handle(new CheckEligibileForSelfServeCommand { EvacuationFileId = file.Id }); + await manager.Handle(new CheckEligibileForSelfServeCommand { RegistrantUserId = registrant.UserId, EvacuationFileNumber = file.Id }); file = (await manager.Handle(new EvacuationFilesQuery { FileId = file.Id })).Items.ShouldHaveSingleItem(); var from = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified); @@ -450,7 +450,7 @@ public async Task ProcessSelfServeSupports_Supports_SupportsCreated() var supportDays = (new[] { fromDay, fromDay.AddDays(1), fromDay.AddDays(2) }); var etransferDetails = new ETransferDetails { - ContactEmail = registrant.Email, + ContactEmail = registrant.Email ?? "test@test.gov.bc.ca", ETransferEmail = registrant.Email, ETransferMobile = registrant.Phone, RecipientName = $"{registrant.FirstName} {registrant.LastName}" @@ -468,7 +468,7 @@ await manager.Handle(new ProcessSelfServeSupportsCommand { Supports = supports, ETransferDetails = etransferDetails, - EvacuationFileId = file.Id, + EvacuationFileNumber = file.Id, }); var updatedFile = (await manager.Handle(new EvacuationFilesQuery { FileId = file.Id })).Items.ShouldHaveSingleItem(); diff --git a/registrants/src/API/EMBC.Registrants.API/Controllers/SupportsController.cs b/registrants/src/API/EMBC.Registrants.API/Controllers/SupportsController.cs index d6ee4eb69..663920911 100644 --- a/registrants/src/API/EMBC.Registrants.API/Controllers/SupportsController.cs +++ b/registrants/src/API/EMBC.Registrants.API/Controllers/SupportsController.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; @@ -18,12 +20,14 @@ namespace EMBC.Registrants.API.Controllers; [Authorize] public class SupportsController(IMessagingClient messagingClient, IMapper mapper) : ControllerBase { + private string currentUserId => User.FindFirstValue(JwtRegisteredClaimNames.Sub); + /// /// Checks if a file is eligible for self-serve supports /// - /// The file id to check + /// /// - /// A decision if the file is eligibile or not + /// Eligiility results [HttpGet("eligible")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] @@ -31,8 +35,17 @@ public class SupportsController(IMessagingClient messagingClient, IMapper mapper [Authorize] public async Task> CheckSelfServeEligibility(string evacuationFileId, CancellationToken ct) { - await messagingClient.Send(new CheckEligibileForSelfServeCommand { EvacuationFileId = evacuationFileId }, ct); - var eligilityCheck = (await messagingClient.Send(new EligibilityCheckQuery { EvacuationFileId = evacuationFileId }, ct)).Eligibility; + await messagingClient.Send(new CheckEligibileForSelfServeCommand + { + RegistrantUserId = currentUserId, + EvacuationFileNumber = evacuationFileId + }, ct); + var eligilityCheck = (await messagingClient.Send(new EligibilityCheckQuery + { + RegistrantUserId = currentUserId, + EvacuationFileNumber = evacuationFileId + }, ct)).Eligibility; + return Ok(new EligibilityCheck { EvacuationFileId = evacuationFileId, @@ -43,38 +56,77 @@ public async Task> CheckSelfServeEligibility(stri }); } + /// + /// Calculate self serve supports for a file + /// + /// + /// + /// Self serve support details [HttpGet("draft")] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetDraftSupports(string evacuationFileId, CancellationToken ct) { - var response = await messagingClient.Send(new DraftSelfServeSupportQuery { EvacuationFileId = evacuationFileId }, ct); + var response = await messagingClient.Send(new DraftSelfServeSupportQuery + { + RegistrantUserId = currentUserId, + EvacuationFileNumber = evacuationFileId + }, ct); return Ok(mapper.Map(response)); } + /// + /// Calculate the self serve supports amounts for a file + /// + /// + /// + /// + /// Self serve support details [HttpPost("draft")] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> CalculateAmounts(string evacuationFileId, IEnumerable supports, CancellationToken ct) { - var response = await messagingClient.Send(new DraftSelfServeSupportQuery { EvacuationFileId = evacuationFileId, Items = mapper.Map>(supports) }, ct); + var response = await messagingClient.Send(new DraftSelfServeSupportQuery + { + RegistrantUserId = currentUserId, + EvacuationFileNumber = evacuationFileId, + Items = mapper.Map>(supports) + }, ct); return Ok(mapper.Map>(response.Items)); } + /// + /// Opt out of self serve supports + /// + /// + /// + /// [HttpPost("optout")] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task OptOut(string evacuationFileId, CancellationToken ct) { - await messagingClient.Send(new OptOutSelfServeCommand { EvacuationFileId = evacuationFileId }, ct); + await messagingClient.Send(new OptOutSelfServeCommand + { + RegistrantUserId = currentUserId, + EvacuationFileNumber = evacuationFileId + }, ct); return Ok(); } + /// + /// Submit self serve supports + /// + /// + /// + /// + /// [HttpPost] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -84,7 +136,8 @@ public async Task>> SubmitSupports(string evacuat if (evacuationFileId != request.EvacuationFileId) return TypedResults.BadRequest(evacuationFileId); await messagingClient.Send(new ProcessSelfServeSupportsCommand { - EvacuationFileId = evacuationFileId, + RegistrantUserId = currentUserId, + EvacuationFileNumber = evacuationFileId, Supports = mapper.Map>(request.Supports), ETransferDetails = mapper.Map(request.ETransferDetails) }, ct); diff --git a/shared/src/EMBC.ESS.Shared.Contracts/Events/SelfServeSupports.cs b/shared/src/EMBC.ESS.Shared.Contracts/Events/SelfServeSupports.cs index 8a4fe7f23..698289397 100644 --- a/shared/src/EMBC.ESS.Shared.Contracts/Events/SelfServeSupports.cs +++ b/shared/src/EMBC.ESS.Shared.Contracts/Events/SelfServeSupports.cs @@ -6,12 +6,14 @@ namespace EMBC.ESS.Shared.Contracts.Events.SelfServe; public record CheckEligibileForSelfServeCommand : Command { - public string EvacuationFileId { get; set; } + public string RegistrantUserId { get; set; } + public string EvacuationFileNumber { get; set; } } public record EligibilityCheckQuery : Query { - public string EvacuationFileId { get; set; } + public string RegistrantUserId { get; set; } + public string EvacuationFileNumber { get; set; } } public record EligibilityCheckQueryResponse @@ -21,12 +23,14 @@ public record EligibilityCheckQueryResponse public record OptOutSelfServeCommand : Command { - public string EvacuationFileId { get; set; } + public string RegistrantUserId { get; set; } + public string EvacuationFileNumber { get; set; } } public record DraftSelfServeSupportQuery : Query { - public string EvacuationFileId { get; set; } + public string RegistrantUserId { get; set; } + public string EvacuationFileNumber { get; set; } public IEnumerable? Items { get; set; } } @@ -38,7 +42,8 @@ public record DraftSelfServeSupportQueryResponse public record ProcessSelfServeSupportsCommand : Command { - public string EvacuationFileId { get; set; } + public string RegistrantUserId { get; set; } + public string EvacuationFileNumber { get; set; } public IEnumerable Supports { get; set; } = []; public ETransferDetails ETransferDetails { get; set; } } From 39eacd4e17d7d184629b6dde865842e806b28889 Mon Sep 17 00:00:00 2001 From: Yossi Tamari Date: Wed, 15 May 2024 17:01:14 -0700 Subject: [PATCH 2/5] nuget package updates --- .../EMBC.ESS.Utilities.Cas/EMBC.ESS.Utilities.Cas.csproj | 2 +- .../EMBC.ESS.Utilities.Dynamics.csproj | 2 +- .../EMBC.Tests.Integration.ESS.csproj | 2 +- oauth-server/src/API/OAuthServer/OAuthServer.csproj | 8 ++++---- .../API/EMBC.Registrants.API/EMBC.Registrants.API.csproj | 2 +- .../API/EMBC.Responders.API/EMBC.Responders.API.csproj | 2 +- .../EMBC.Utilities.Hosting/EMBC.Utilities.Hosting.csproj | 4 ++-- .../EMBC.Utilities.Messaging.csproj | 2 +- shared/src/EMBC.Utilities/EMBC.Utilities.csproj | 2 +- .../src/API/EMBC.Suppliers.API/EMBC.Suppliers.API.csproj | 8 ++++---- .../EMBC.Tests.Integration.Suppliers.API.csproj | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ess/src/API/EMBC.ESS.Utilities.Cas/EMBC.ESS.Utilities.Cas.csproj b/ess/src/API/EMBC.ESS.Utilities.Cas/EMBC.ESS.Utilities.Cas.csproj index f96a98387..5cc5f8129 100644 --- a/ess/src/API/EMBC.ESS.Utilities.Cas/EMBC.ESS.Utilities.Cas.csproj +++ b/ess/src/API/EMBC.ESS.Utilities.Cas/EMBC.ESS.Utilities.Cas.csproj @@ -19,7 +19,7 @@ - + diff --git a/ess/src/API/EMBC.ESS.Utilities.Dynamics/EMBC.ESS.Utilities.Dynamics.csproj b/ess/src/API/EMBC.ESS.Utilities.Dynamics/EMBC.ESS.Utilities.Dynamics.csproj index 238bd3016..5df132ccf 100644 --- a/ess/src/API/EMBC.ESS.Utilities.Dynamics/EMBC.ESS.Utilities.Dynamics.csproj +++ b/ess/src/API/EMBC.ESS.Utilities.Dynamics/EMBC.ESS.Utilities.Dynamics.csproj @@ -38,7 +38,7 @@ - + diff --git a/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj b/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj index fdd40c531..bfabf14c9 100644 --- a/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj +++ b/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj @@ -13,7 +13,7 @@ - + diff --git a/oauth-server/src/API/OAuthServer/OAuthServer.csproj b/oauth-server/src/API/OAuthServer/OAuthServer.csproj index 65b570662..a02656f82 100644 --- a/oauth-server/src/API/OAuthServer/OAuthServer.csproj +++ b/oauth-server/src/API/OAuthServer/OAuthServer.csproj @@ -21,9 +21,9 @@ - - - + + + @@ -32,7 +32,7 @@ - + diff --git a/registrants/src/API/EMBC.Registrants.API/EMBC.Registrants.API.csproj b/registrants/src/API/EMBC.Registrants.API/EMBC.Registrants.API.csproj index 6c1f259a6..7947cb87e 100644 --- a/registrants/src/API/EMBC.Registrants.API/EMBC.Registrants.API.csproj +++ b/registrants/src/API/EMBC.Registrants.API/EMBC.Registrants.API.csproj @@ -23,7 +23,7 @@ - + diff --git a/responders/src/API/EMBC.Responders.API/EMBC.Responders.API.csproj b/responders/src/API/EMBC.Responders.API/EMBC.Responders.API.csproj index af45efbed..143854377 100644 --- a/responders/src/API/EMBC.Responders.API/EMBC.Responders.API.csproj +++ b/responders/src/API/EMBC.Responders.API/EMBC.Responders.API.csproj @@ -21,7 +21,7 @@ - + diff --git a/shared/src/EMBC.Utilities.Hosting/EMBC.Utilities.Hosting.csproj b/shared/src/EMBC.Utilities.Hosting/EMBC.Utilities.Hosting.csproj index 03d248ad5..4209cf4be 100644 --- a/shared/src/EMBC.Utilities.Hosting/EMBC.Utilities.Hosting.csproj +++ b/shared/src/EMBC.Utilities.Hosting/EMBC.Utilities.Hosting.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/shared/src/EMBC.Utilities.Messaging/EMBC.Utilities.Messaging.csproj b/shared/src/EMBC.Utilities.Messaging/EMBC.Utilities.Messaging.csproj index 3ece16f8d..616a315b8 100644 --- a/shared/src/EMBC.Utilities.Messaging/EMBC.Utilities.Messaging.csproj +++ b/shared/src/EMBC.Utilities.Messaging/EMBC.Utilities.Messaging.csproj @@ -23,7 +23,7 @@ - + diff --git a/shared/src/EMBC.Utilities/EMBC.Utilities.csproj b/shared/src/EMBC.Utilities/EMBC.Utilities.csproj index 6596e5b47..befbe0036 100644 --- a/shared/src/EMBC.Utilities/EMBC.Utilities.csproj +++ b/shared/src/EMBC.Utilities/EMBC.Utilities.csproj @@ -20,7 +20,7 @@ - + diff --git a/suppliers/src/API/EMBC.Suppliers.API/EMBC.Suppliers.API.csproj b/suppliers/src/API/EMBC.Suppliers.API/EMBC.Suppliers.API.csproj index e79083a42..53aa2b52e 100644 --- a/suppliers/src/API/EMBC.Suppliers.API/EMBC.Suppliers.API.csproj +++ b/suppliers/src/API/EMBC.Suppliers.API/EMBC.Suppliers.API.csproj @@ -17,9 +17,9 @@ - - - + + + @@ -30,7 +30,7 @@ - + all diff --git a/suppliers/src/API/EMBC.Tests.Integration.Suppliers.API/EMBC.Tests.Integration.Suppliers.API.csproj b/suppliers/src/API/EMBC.Tests.Integration.Suppliers.API/EMBC.Tests.Integration.Suppliers.API.csproj index 0f94fb641..c799b1a0c 100644 --- a/suppliers/src/API/EMBC.Tests.Integration.Suppliers.API/EMBC.Tests.Integration.Suppliers.API.csproj +++ b/suppliers/src/API/EMBC.Tests.Integration.Suppliers.API/EMBC.Tests.Integration.Suppliers.API.csproj @@ -7,7 +7,7 @@ - + From 27b26a78be5c3d1f8c27d5432204da74b87d3412 Mon Sep 17 00:00:00 2001 From: Yossi Tamari Date: Wed, 15 May 2024 17:04:44 -0700 Subject: [PATCH 3/5] fixed version --- .../EMBC.Tests.Integration.ESS.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj b/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj index bfabf14c9..81d1930b6 100644 --- a/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj +++ b/ess/src/API/EMBC.Tests.Integration.ESS/EMBC.Tests.Integration.ESS.csproj @@ -13,7 +13,7 @@ - + From 7fb69f02fc681f22214f0f274f3627c990bc9540 Mon Sep 17 00:00:00 2001 From: Yossi Tamari Date: Wed, 15 May 2024 17:23:32 -0700 Subject: [PATCH 4/5] removed double expand --- ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs b/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs index 35629732a..004b6c7c3 100644 --- a/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs +++ b/ess/src/API/EMBC.ESS/Resources/Supports/SupportRepository.cs @@ -254,7 +254,6 @@ private static async Task> Search(EssContext ctx throw new ArgumentException("Supports query must have at least one criteria", nameof(query)); IQueryable supportsQuery = ctx.era_evacueesupports - .Expand(s => s.era_EvacuationFileId) .Expand(s => s.era_EvacuationFileId) .Expand(s => s.era_era_householdmember_era_evacueesupport) .Expand(s => s.era_era_evacueesupport_era_supportflag_EvacueeSupport) From f83c58ae97a6ad78b2587d7159d24bb57c5d80fc Mon Sep 17 00:00:00 2001 From: Yossi Tamari Date: Wed, 15 May 2024 17:26:01 -0700 Subject: [PATCH 5/5] another duplicate expand --- .../API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs b/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs index b9a4c86ba..679e17a1e 100644 --- a/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs +++ b/ess/src/API/EMBC.ESS/Resources/Evacuations/EvacuationRepository.cs @@ -383,7 +383,6 @@ private static async Task> QueryEvacuationFiles( .Expand(f => f.era_CurrentNeedsAssessmentid) .Expand(f => f.era_Registrant) .Expand(f => f.era_era_evacuationfile_era_animal_ESSFileid) - .Expand(f => f.era_era_evacuationfile_era_animal_ESSFileid) .Expand(f => f.era_era_evacuationfile_era_essfilenote_ESSFileID) .Expand(f => f.era_TaskId) .Expand(f => f.era_era_evacuationfile_era_evacueesupport_ESSFileId)