From 2efa918ecebf04cc2eddd0b408593f4f75427a51 Mon Sep 17 00:00:00 2001 From: Gabriel Zurita Date: Wed, 10 Apr 2024 11:07:00 -0600 Subject: [PATCH] Arf.78633/arp mock data (#16218) * arf.78633 add mock POA request data to ARP Engine * arf.78633 migrate mock POA request data structure to expected LH response See Slack comment and thread: https://dsva.slack.com/archives/C06ABHUNBRS/p1712333756404439?thread_ts=1712263855.274379&cid=C06ABHUNBRS * arf.78633 update POA request accept/deny action to match WIP Dash/api Added a LH API cutover note, too. See PR: https://github.com/department-of-veterans-affairs/vets-api/pull/16125/files * arf.78633 update ARP engine PoaRecordGenerator to retorn procId --- .../services/fetch_poa_requests.rb | 50 + .../power_of_attorney_requests_controller.rb | 76 +- .../config/routes.rb | 2 +- .../spec/fixtures/poa_records.json | 1117 +++++++++++++++++ ...er_of_attorney_requests_controller_spec.rb | 52 +- .../spec/support/poa_record_generator.rb | 95 ++ 6 files changed, 1378 insertions(+), 14 deletions(-) create mode 100644 modules/accredited_representative_portal/app/controllers/accredited_representative_portal/services/fetch_poa_requests.rb create mode 100644 modules/accredited_representative_portal/spec/fixtures/poa_records.json create mode 100644 modules/accredited_representative_portal/spec/support/poa_record_generator.rb diff --git a/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/services/fetch_poa_requests.rb b/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/services/fetch_poa_requests.rb new file mode 100644 index 00000000000..c251e8bd22f --- /dev/null +++ b/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/services/fetch_poa_requests.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module AccreditedRepresentativePortal + module Services + # The FetchPoaRequests service is responsible for retrieving Power of Attorney (POA) request records + # based on provided Power of Attorney codes. This class currently reads from a JSON file as a temporary + # source of data. In the future, this service will be updated to fetch POA requests directly from the + # Lighthouse API once the appropriate endpoint is ready. + # + # This service is a part of the interim solution to support development and testing of the Accredited + # Representative portal. The use of a static JSON file allows for the simulation of interacting with + # an API and facilitates the frontend development process. + # + # Example usage: + # fetcher = AccreditedRepresentativePortal::Services::FetchPoaRequests.new(['A1Q', '091']) + # result = fetcher.call + # puts result # => { 'records': [...], 'meta': { 'totalRecords': '...' } } + # + # TODO: This class is slated for update to use the Lighthouse API once the appropriate endpoint + # is available. For more information on the transition plan, refer to: + # https://app.zenhub.com/workspaces/accredited-representative-facing-team-65453a97a9cc36069a2ad1d6/issues/gh/department-of-veterans-affairs/va.gov-team/80195 + class FetchPoaRequests + # Initializes the FetchPoaRequests service with the given POA codes. + # @param poa_codes [Array] an array of POA codes to filter the POA requests. + def initialize(poa_codes) + @poa_codes = poa_codes + end + + # Fetches POA request records filtered by the initialized POA codes. + # Currently reads from a static JSON file as a data source. + # @return [Hash] A hash containing the filtered records and metadata. + def call + file_path = Rails.root.join('modules', 'accredited_representative_portal', 'spec', 'fixtures', + 'poa_records.json') + file_data = File.read(file_path) + all_records_json = JSON.parse(file_data) + all_records = all_records_json['records'] + + filtered_records = all_records.select do |record| + @poa_codes.include?(record['attributes']['poaCode']) + end + + { 'records' => filtered_records, 'meta' => { 'totalRecords' => filtered_records.count.to_s } } + rescue => e + Rails.logger.error "Failed to fetch POA requests: #{e.message}" + { 'data' => [], 'meta' => { 'totalRecords' => '0' } } + end + end + end +end diff --git a/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/v0/power_of_attorney_requests_controller.rb b/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/v0/power_of_attorney_requests_controller.rb index 42776201a91..6c5aef3a7da 100644 --- a/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/v0/power_of_attorney_requests_controller.rb +++ b/modules/accredited_representative_portal/app/controllers/accredited_representative_portal/v0/power_of_attorney_requests_controller.rb @@ -4,17 +4,77 @@ module AccreditedRepresentativePortal module V0 class PowerOfAttorneyRequestsController < ApplicationController def accept - # TODO: The ID will be either a veteran_id or a poa_id - # id = params[:id] - # NOTE: the below is a placeholder for the acceptance logic - render json: { message: 'Accepted' }, status: :ok + id = params[:proc_id] + result = update_poa_request(id, 'Accepted') + + if result[:success] + render json: { message: 'Accepted' }, status: :ok + else + render json: { error: result[:error] }, status: :unprocessable_entity + end end def decline - # TODO: The ID will be either a veteran_id or a poa_id - # id = params[:id] - # NOTE: the below is a placeholder for the deny logic - render json: { message: 'Declined' }, status: :ok + id = params[:proc_id] + result = update_poa_request(id, 'Declined') + + if result[:success] + render json: { message: 'Declined' }, status: :ok + else + render json: { error: result[:error] }, status: :unprocessable_entity + end + end + + def index + poa_codes = permitted_params[:poa_codes]&.split(',') || [] + + return render json: { error: 'POA codes are required' }, status: :bad_request if poa_codes.blank? + + poa_requests = AccreditedRepresentativePortal::Services::FetchPoaRequests.new(poa_codes).call + + render json: { records: poa_requests['records'], records_count: poa_requests['meta']['totalRecords'].to_i }, + status: :ok + end + + private + + def permitted_params + params.permit(:poa_codes) + end + + # TODO: This class is slated for update to use the Lighthouse API once the appropriate endpoint + # is available. For more information on the transition plan, refer to: + # https://app.zenhub.com/workspaces/accredited-representative-facing-team-65453a97a9cc36069a2ad1d6/issues/gh/department-of-veterans-affairs/va.gov-team/80195 + def update_poa_request(proc_id, action) + # TODO: Update the below to use the RepresentativeUser's profile data + # representative = { + # first_name: 'John', + # last_name: 'Doe' + # } + + # Simulating the interaction with an external service to update POA. + # In real implementation, this method will make an actual API call. + # service_response = ClaimsApi::ManageRepresentativeService.new.update_poa_request( + # representative:, + # proc_id: + # ) + + if %w[Accepted Declined].include?(action) + { + success: true, + response: { + proc_id:, + action:, + status: 'updated', + dateRequestActioned: Time.current.iso8601, + secondaryStatus: action == 'Accepted' ? 'obsolete' : 'cancelled' + } + } + else + { success: false, error: 'Invalid action' } + end + rescue => e + { success: false, error: e.message } end end end diff --git a/modules/accredited_representative_portal/config/routes.rb b/modules/accredited_representative_portal/config/routes.rb index 439562bc341..6f348e335fb 100644 --- a/modules/accredited_representative_portal/config/routes.rb +++ b/modules/accredited_representative_portal/config/routes.rb @@ -2,7 +2,7 @@ AccreditedRepresentativePortal::Engine.routes.draw do namespace :v0, defaults: { format: :json } do - resources :power_of_attorney_requests, only: [] do + resources :power_of_attorney_requests, only: [:index] do member do post :accept post :decline diff --git a/modules/accredited_representative_portal/spec/fixtures/poa_records.json b/modules/accredited_representative_portal/spec/fixtures/poa_records.json new file mode 100644 index 00000000000..956a084a366 --- /dev/null +++ b/modules/accredited_representative_portal/spec/fixtures/poa_records.json @@ -0,0 +1,1117 @@ +{ + "records": [ + { + "procId": "9942820247", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-28", + "dateRequestActioned": "2024-05-05", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Dale", + "lastName": "Hills", + "city": "Haleyland", + "state": "TN", + "zip": "73538", + "country": "Albania", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "7158421739", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Refugio", + "lastName": "Pollich", + "middleName": "Erdman", + "participantID": "2152444888", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "clarita@marvin.example", + "firstName": "Cinderella", + "lastName": "Baumbach" + } + } + }, + { + "procId": "4206885703", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-10", + "dateRequestActioned": "2024-04-13", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Whitney", + "lastName": "Stoltenberg", + "city": "Lake Evita", + "state": "AL", + "zip": "27906", + "country": "Antigua and Barbuda", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "9440452403", + "relationship": "Child" + }, + "veteran": { + "firstName": "Bob", + "lastName": "McDermott", + "middleName": "Herman", + "participantID": "8635486958", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "leon.fritsch@kulas.example", + "firstName": "Andres", + "lastName": "Spencer" + } + } + }, + { + "procId": "6538972520", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-23", + "dateRequestActioned": "2024-04-28", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Bernie", + "lastName": "Kuphal", + "city": "North Theo", + "state": "IN", + "zip": "57624", + "country": "Niue", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "7820124603", + "relationship": "Parent" + }, + "veteran": { + "firstName": "Cristopher", + "lastName": "Heaney", + "middleName": "Jakubowski", + "participantID": "5751314148", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "belle@collier-zieme.test", + "firstName": "Bobby", + "lastName": "Robel" + } + } + }, + { + "procId": "1545078041", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-16", + "dateRequestActioned": "2024-04-21", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Miguel", + "lastName": "Stracke", + "city": "East Marisolbury", + "state": "KY", + "zip": "38747", + "country": "Greenland", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "1900423684", + "relationship": "Parent" + }, + "veteran": { + "firstName": "Elidia", + "lastName": "Lehner", + "middleName": "Gulgowski", + "participantID": "8469999212", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "jewell@okon.test", + "firstName": "Jordan", + "lastName": "Pagac" + } + } + }, + { + "procId": "2740225884", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-11", + "dateRequestActioned": "2024-05-01", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Haydee", + "lastName": "Robel", + "city": "North Marcelinoside", + "state": "WV", + "zip": "37916", + "country": "Thailand", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "4355283680", + "relationship": "Child" + }, + "veteran": { + "firstName": "Nery", + "lastName": "Reilly", + "middleName": "Hessel", + "participantID": "3103541588", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "chong@terry.example", + "firstName": "Darrick", + "lastName": "Keeling" + } + } + }, + { + "procId": "1852457399", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-04-01", + "dateRequestActioned": "2024-04-28", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Brenda", + "lastName": "Schowalter", + "city": "Port Harry", + "state": "NE", + "zip": "25128", + "country": "Mozambique", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "6406503016", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Roxy", + "lastName": "Leuschke", + "middleName": "Morissette", + "participantID": "7156298434", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "major@carter.example", + "firstName": "Annette", + "lastName": "Rodriguez" + } + } + }, + { + "procId": "4081328722", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-14", + "dateRequestActioned": "2024-04-27", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Larry", + "lastName": "Kessler", + "city": "New Yukiko", + "state": "UT", + "zip": "87363-8157", + "country": "Jersey", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "8901124888", + "relationship": "Spouse" + }, + "veteran": { + "firstName": "Effie", + "lastName": "Reilly", + "middleName": "Schmeler", + "participantID": "4267563093", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "winford_swaniawski@altenwerth.test", + "firstName": "Mariam", + "lastName": "Abernathy" + } + } + }, + { + "procId": "9954357683", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-11", + "dateRequestActioned": "2024-04-27", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Steven", + "lastName": "Fay", + "city": "Lake Mai", + "state": "TX", + "zip": "81365-6236", + "country": "Cabo Verde", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "2155221172", + "relationship": "Spouse" + }, + "veteran": { + "firstName": "Boyd", + "lastName": "Herman", + "middleName": "Graham", + "participantID": "5323184877", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "angelita.kuhlman@corkery-collins.example", + "firstName": "Geoffrey", + "lastName": "Willms" + } + } + }, + { + "procId": "5254792179", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-04-03", + "dateRequestActioned": "2024-04-20", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Edmundo", + "lastName": "Purdy", + "city": "Port Jeromyville", + "state": "MA", + "zip": "36198-3784", + "country": "Cambodia", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "4405853933", + "relationship": "Spouse" + }, + "veteran": { + "firstName": "Hassan", + "lastName": "Bernier", + "middleName": "Christiansen", + "participantID": "4143003298", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "antonio@murazik.test", + "firstName": "Mose", + "lastName": "Gulgowski" + } + } + }, + { + "procId": "9622796898", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-14", + "dateRequestActioned": "2024-04-12", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Noah", + "lastName": "Langosh", + "city": "Kertzmannburgh", + "state": "IA", + "zip": "69720", + "country": "Comoros", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "7967611020", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Krystin", + "lastName": "Nicolas", + "middleName": "Smitham", + "participantID": "5205712033", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "ethelene.bins@kirlin.example", + "firstName": "Nestor", + "lastName": "Goodwin" + } + } + }, + { + "procId": "8754621135", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-08", + "dateRequestActioned": "2024-04-27", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Juana", + "lastName": "Grady", + "city": "North Scarlet", + "state": "MO", + "zip": "69137", + "country": "Spain", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "2954642877", + "relationship": "Child" + }, + "veteran": { + "firstName": "Dorothea", + "lastName": "Nikolaus", + "middleName": "Feil", + "participantID": "1359697723", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "harris.predovic@hickle.example", + "firstName": "Lindsey", + "lastName": "Green" + } + } + }, + { + "procId": "3217671507", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-28", + "dateRequestActioned": "2024-04-30", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Lawerence", + "lastName": "Miller", + "city": "New Nicolasshire", + "state": "VA", + "zip": "54181", + "country": "Saint Pierre and Miquelon", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "4447702721", + "relationship": "Child" + }, + "veteran": { + "firstName": "Erwin", + "lastName": "Zboncak", + "middleName": "Walsh", + "participantID": "7496852392", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "jefferson@grimes-hegmann.test", + "firstName": "Man", + "lastName": "Ritchie" + } + } + }, + { + "procId": "6109624522", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-08", + "dateRequestActioned": "2024-04-21", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Gale", + "lastName": "Moen", + "city": "Starkberg", + "state": "OH", + "zip": "78205-5340", + "country": "Greece", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "6033466916", + "relationship": "Child" + }, + "veteran": { + "firstName": "Leon", + "lastName": "Dach", + "middleName": "Smitham", + "participantID": "2248396374", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "noe@yundt.test", + "firstName": "Shirl", + "lastName": "Kohler" + } + } + }, + { + "procId": "3546805044", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-16", + "dateRequestActioned": "2024-04-08", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Reed", + "lastName": "Ruecker", + "city": "South Rosannetown", + "state": "TN", + "zip": "77931-8169", + "country": "Papua New Guinea", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "6557732976", + "relationship": "Child" + }, + "veteran": { + "firstName": "Tessie", + "lastName": "Corkery", + "middleName": "Sporer", + "participantID": "6032892024", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "marcelina_keebler@schaden.example", + "firstName": "Claudio", + "lastName": "Moore" + } + } + }, + { + "procId": "5157897360", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-10", + "dateRequestActioned": "2024-05-01", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Morris", + "lastName": "Rippin", + "city": "Port Rosiotown", + "state": "AR", + "zip": "56024-8810", + "country": "Saint Vincent and the Grenadines", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "6590052993", + "relationship": "Parent" + }, + "veteran": { + "firstName": "Zandra", + "lastName": "Greenfelder", + "middleName": "Rippin", + "participantID": "5779628693", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "carrol_hauck@paucek-oberbrunner.test", + "firstName": "Latashia", + "lastName": "Graham" + } + } + }, + { + "procId": "7680796959", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-28", + "dateRequestActioned": "2024-04-06", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Geoffrey", + "lastName": "Schroeder", + "city": "Rickeyview", + "state": "MN", + "zip": "94866-8087", + "country": "Saint Pierre and Miquelon", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "9909988926", + "relationship": "Child" + }, + "veteran": { + "firstName": "Gonzalo", + "lastName": "Miller", + "middleName": "Rosenbaum", + "participantID": "1396051298", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "willow@white.test", + "firstName": "Joseph", + "lastName": "Robel" + } + } + }, + { + "procId": "1503143583", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-11", + "dateRequestActioned": "2024-04-18", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Leigh", + "lastName": "Bergnaum", + "city": "West George", + "state": "NV", + "zip": "49718-4159", + "country": "Senegal", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "1748245535", + "relationship": "Child" + }, + "veteran": { + "firstName": "Joan", + "lastName": "MacGyver", + "middleName": "Cruickshank", + "participantID": "3077111270", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "tory@mraz.test", + "firstName": "Irma", + "lastName": "Kub" + } + } + }, + { + "procId": "8489633597", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-24", + "dateRequestActioned": "2024-04-21", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Tuyet", + "lastName": "Skiles", + "city": "South Kendrick", + "state": "KY", + "zip": "89464", + "country": "Portugal", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "4324476034", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Verona", + "lastName": "Abbott", + "middleName": "Toy", + "participantID": "4793172236", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "jeremiah_ryan@heller-blick.test", + "firstName": "Shane", + "lastName": "Stamm" + } + } + }, + { + "procId": "9238210701", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-06", + "dateRequestActioned": "2024-04-28", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Serita", + "lastName": "Gislason", + "city": "East Cyrusmouth", + "state": "WY", + "zip": "61149-8042", + "country": "Syrian Arab Republic", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "3346818434", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Sherilyn", + "lastName": "McClure", + "middleName": "Windler", + "participantID": "9956501498", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "georgie@crooks-stoltenberg.example", + "firstName": "Andy", + "lastName": "Gerhold" + } + } + }, + { + "procId": "2385422076", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-06", + "dateRequestActioned": "2024-05-04", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Bryon", + "lastName": "Boehm", + "city": "Feestside", + "state": "LA", + "zip": "66933-3057", + "country": "Guinea-Bissau", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "8279129687", + "relationship": "Spouse" + }, + "veteran": { + "firstName": "Kristopher", + "lastName": "Kovacek", + "middleName": "Lueilwitz", + "participantID": "4008725460", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "lynna.romaguera@borer.example", + "firstName": "Min", + "lastName": "Homenick" + } + } + }, + { + "procId": "5385001943", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-21", + "dateRequestActioned": "2024-04-22", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Lynwood", + "lastName": "Hamill", + "city": "South Felipehaven", + "state": "ID", + "zip": "79379", + "country": "United States of America", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "4207789506", + "relationship": "Parent" + }, + "veteran": { + "firstName": "Ellsworth", + "lastName": "Hintz", + "middleName": "Treutel", + "participantID": "3417319641", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "dewayne.goyette@krajcik.test", + "firstName": "Les", + "lastName": "Barrows" + } + } + }, + { + "procId": "4290146937", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-04-02", + "dateRequestActioned": "2024-04-16", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Phillip", + "lastName": "Lesch", + "city": "South Susannehaven", + "state": "NC", + "zip": "74990-8341", + "country": "Djibouti", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "7646626729", + "relationship": "Child" + }, + "veteran": { + "firstName": "Jeanna", + "lastName": "Prohaska", + "middleName": "Spencer", + "participantID": "6014125455", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "paul_hamill@hoppe.test", + "firstName": "Faustino", + "lastName": "Kreiger" + } + } + }, + { + "procId": "8254468195", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-28", + "dateRequestActioned": "2024-04-30", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Alva", + "lastName": "Kovacek", + "city": "Danielbury", + "state": "ND", + "zip": "72835", + "country": "Estonia", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "9067297261", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Vicky", + "lastName": "Emard", + "middleName": "Hartmann", + "participantID": "5103708939", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "shanda_terry@walter.example", + "firstName": "Brandon", + "lastName": "Mann" + } + } + }, + { + "procId": "1385844527", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-09", + "dateRequestActioned": "2024-04-15", + "declinedReason": null, + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Izetta", + "lastName": "Bode", + "city": "Tiannaview", + "state": "LA", + "zip": "60072", + "country": "Colombia", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "5961069692", + "relationship": "Spouse" + }, + "veteran": { + "firstName": "Bryon", + "lastName": "Auer", + "middleName": "Nikolaus", + "participantID": "1214142631", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "asley.morar@jakubowski.test", + "firstName": "Marty", + "lastName": "Crooks" + } + } + }, + { + "procId": "7013291891", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "pending", + "dateRequestReceived": "2024-03-24", + "dateRequestActioned": "2024-05-01", + "declinedReason": null, + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Clifford", + "lastName": "Olson", + "city": "West Karly", + "state": "PA", + "zip": "68378", + "country": "Kenya", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "3750399936", + "relationship": "Parent" + }, + "veteran": { + "firstName": "Cortez", + "lastName": "Abernathy", + "middleName": "O'Connell", + "participantID": "9462383093", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "margrett@krajcik.example", + "firstName": "Dominque", + "lastName": "Dibbert" + } + } + }, + { + "procId": "4913724953", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "obsolete", + "dateRequestReceived": "2024-03-30", + "dateRequestActioned": "2024-05-02", + "declinedReason": "Expedita consequatur temporibus dicta.", + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Grant", + "lastName": "Graham", + "city": "Lake Ellen", + "state": "MN", + "zip": "79618-0070", + "country": "Benin", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "1160880217", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Alfredo", + "lastName": "Ziemann", + "middleName": "Skiles", + "participantID": "2733143615", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "kisha@ortiz.example", + "firstName": "Emerson", + "lastName": "Bradtke" + } + } + }, + { + "procId": "3825558136", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "canceled", + "dateRequestReceived": "2024-03-21", + "dateRequestActioned": "2024-04-19", + "declinedReason": "Quaerat deserunt ratione officiis.", + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Alec", + "lastName": "Kub", + "city": "Torphychester", + "state": "AK", + "zip": "39971-6644", + "country": "Lesotho", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "4566622083", + "relationship": "Child" + }, + "veteran": { + "firstName": "Bernardo", + "lastName": "Witting", + "middleName": "Feeney", + "participantID": "3241314281", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "dahlia_harris@welch-gislason.test", + "firstName": "Marshall", + "lastName": "Willms" + } + } + }, + { + "procId": "7002867330", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "canceled", + "dateRequestReceived": "2024-03-19", + "dateRequestActioned": "2024-05-05", + "declinedReason": "Ratione placeat velit aspernatur.", + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Galen", + "lastName": "Leffler", + "city": "North Kristineside", + "state": "OR", + "zip": "52077-7654", + "country": "Finland", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "8415906652", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Cristobal", + "lastName": "Harvey", + "middleName": "Pouros", + "participantID": "8418705577", + "sensitivityLevel": "Medium" + }, + "VSORepresentative": { + "email": "stacy@king.example", + "firstName": "Barton", + "lastName": "Jones" + } + } + }, + { + "procId": "1647587150", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "A1Q", + "secondaryStatus": "canceled", + "dateRequestReceived": "2024-03-30", + "dateRequestActioned": "2024-04-26", + "declinedReason": "Eos nobis ut ipsum.", + "healthInfoAuth": "Y", + "changeAddressAuth": "Y", + "claimant": { + "firstName": "Mackenzie", + "lastName": "Reynolds", + "city": "Lowellbury", + "state": "WA", + "zip": "64999-3531", + "country": "Cocos (Keeling) Islands", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "8115232468", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Glennis", + "lastName": "Buckridge", + "middleName": "Koch", + "participantID": "7817266608", + "sensitivityLevel": "Low" + }, + "VSORepresentative": { + "email": "dalia.harris@strosin.test", + "firstName": "Herschel", + "lastName": "Wolf" + } + } + }, + { + "procId": "6307005458", + "type": "powerOfAttorneyRequest", + "attributes": { + "poaCode": "091", + "secondaryStatus": "obsolete", + "dateRequestReceived": "2024-03-25", + "dateRequestActioned": "2024-05-05", + "declinedReason": "Ea voluptate in ad.", + "healthInfoAuth": "N", + "changeAddressAuth": "N", + "claimant": { + "firstName": "Jerry", + "lastName": "Kutch", + "city": "Millietown", + "state": "MN", + "zip": "66052-8399", + "country": "Republic of Korea", + "militaryPO": null, + "militaryPostalCode": null, + "participantID": "3372098647", + "relationship": "Friend" + }, + "veteran": { + "firstName": "Val", + "lastName": "Ledner", + "middleName": "Reichel", + "participantID": "1914871616", + "sensitivityLevel": "High" + }, + "VSORepresentative": { + "email": "ralph.satterfield@schuppe-koch.example", + "firstName": "Donald", + "lastName": "Kuhlman" + } + } + } + ], + "meta": { + "totalRecords": "30" + } +} \ No newline at end of file diff --git a/modules/accredited_representative_portal/spec/requests/accredited_representative_portal/v0/power_of_attorney_requests_controller_spec.rb b/modules/accredited_representative_portal/spec/requests/accredited_representative_portal/v0/power_of_attorney_requests_controller_spec.rb index 21f5ee3b2a0..98403db53ea 100644 --- a/modules/accredited_representative_portal/spec/requests/accredited_representative_portal/v0/power_of_attorney_requests_controller_spec.rb +++ b/modules/accredited_representative_portal/spec/requests/accredited_representative_portal/v0/power_of_attorney_requests_controller_spec.rb @@ -12,9 +12,10 @@ end describe 'POST /accept' do + let(:proc_id) { '123' } + it 'returns a successful response with an accepted message' do - id = '123' - post "/accredited_representative_portal/v0/power_of_attorney_requests/#{id}/accept" + post "/accredited_representative_portal/v0/power_of_attorney_requests/#{proc_id}/accept" expect(response).to have_http_status(:ok) json = JSON.parse(response.body) expect(json['message']).to eq('Accepted') @@ -22,12 +23,53 @@ end describe 'POST /decline' do - it 'returns a successful response with an accepted message' do - id = '123' - post "/accredited_representative_portal/v0/power_of_attorney_requests/#{id}/decline" + let(:proc_id) { '123' } + + it 'returns a successful response with a declined message' do + post "/accredited_representative_portal/v0/power_of_attorney_requests/#{proc_id}/decline" expect(response).to have_http_status(:ok) json = JSON.parse(response.body) expect(json['message']).to eq('Declined') end end + + describe 'GET /index' do + context 'when valid POA codes are provided' do + it 'returns a successful response with matching POA requests' do + get '/accredited_representative_portal/v0/power_of_attorney_requests', params: { poa_codes: '091,A1Q' } + expect(response).to have_http_status(:ok) + json = JSON.parse(response.body) + expect(json['records']).to be_an_instance_of(Array) + expect(json['records_count']).to eq(json['records'].size) + end + end + + context 'when no POA codes are provided' do + it 'returns a bad request status with an error message' do + get '/accredited_representative_portal/v0/power_of_attorney_requests' + expect(response).to have_http_status(:bad_request) + json = JSON.parse(response.body) + expect(json['error']).to eq('POA codes are required') + end + end + + context 'when POA codes parameter is empty' do + it 'returns a bad request status with an error message' do + get '/accredited_representative_portal/v0/power_of_attorney_requests', params: { poa_codes: '' } + expect(response).to have_http_status(:bad_request) + expect(JSON.parse(response.body)['error']).to eq('POA codes are required') + end + end + + context 'when there are no records for the provided POA codes' do + it 'returns an empty records array and zero records count' do + get '/accredited_representative_portal/v0/power_of_attorney_requests', params: { poa_codes: 'XYZ,ABC' } + expect(response).to have_http_status(:ok) + json = JSON.parse(response.body) + expect(json['records']).to be_an_instance_of(Array) + expect(json['records']).to be_empty + expect(json['records_count']).to eq(0) + end + end + end end diff --git a/modules/accredited_representative_portal/spec/support/poa_record_generator.rb b/modules/accredited_representative_portal/spec/support/poa_record_generator.rb new file mode 100644 index 00000000000..5da28c938d9 --- /dev/null +++ b/modules/accredited_representative_portal/spec/support/poa_record_generator.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +# The module provides a method to save generated data to a JSON file, +# useful for seeding databases or loading mock data during development. +# +# Using the generator in the Rails console: +# 1. Start the console: `bundle exec rails c`. +# 2. Load the generator: +# `require Rails.root.join('modules/accredited_representative_portal', +# 'spec/support/poa_record_generator.rb')`. +# 3. Generate POA records: `PoaRecordGenerator.generate(num_records: 30)`. +# 4. Save to a file: `PoaRecordGenerator.generate_and_save_to_file(num_records: 30)`. +module PoaRecordGenerator + class << self + require 'faker' + require 'json' + + # Generates a hash with POA request records and associated metadata. + # @param num_records [Integer] The number of POA records to generate. + # @return [Hash] A hash containing the generated records and metadata. + def generate(num_records: 30) + Faker::UniqueGenerator.clear + + records = num_records.times.map do |i| + status = i < 25 ? 'pending' : %w[obsolete expired canceled].sample + { + procId: Faker::Number.unique.number(digits: 10).to_s, + type: 'powerOfAttorneyRequest', + attributes: generate_attributes(i, status) + } + end + + { records:, meta: { totalRecords: num_records.to_s } } + end + + # Generates POA request records and saves them to a specified JSON file. + # @param num_records [Integer] The number of POA records to generate. + # @param file_path [String] The file path to write the JSON data to. + def generate_and_save_to_file(num_records: 30, + file_path: 'modules/accredited_representative_portal/spec/fixtures/poa_records.json') + poa_data = generate(num_records:) + File.write(file_path, JSON.pretty_generate(poa_data)) + end + + private + + def generate_attributes(index, status) + { + poaCode: index.even? ? 'A1Q' : '091', + secondaryStatus: status, + dateRequestReceived: Faker::Date.backward(days: 30).iso8601, + dateRequestActioned: Faker::Date.forward(days: 30).iso8601, + declinedReason: status == 'pending' ? nil : Faker::Lorem.sentence, + healthInfoAuth: index.even? ? 'Y' : 'N', + changeAddressAuth: index.even? ? 'Y' : 'N', + claimant: generate_claimant, + veteran: generate_veteran, + VSORepresentative: generate_representative + } + end + + def generate_claimant + { + firstName: Faker::Name.first_name, + lastName: Faker::Name.last_name, + city: Faker::Address.city, + state: Faker::Address.state_abbr, + zip: Faker::Address.zip, + country: Faker::Address.country, + militaryPO: nil, + militaryPostalCode: nil, + participantID: Faker::Number.unique.number(digits: 10).to_s, + relationship: %w[Spouse Child Parent Friend].sample + } + end + + def generate_veteran + { + firstName: Faker::Name.first_name, + lastName: Faker::Name.last_name, + middleName: Faker::Name.middle_name, + participantID: Faker::Number.unique.number(digits: 10).to_s, + sensitivityLevel: %w[Low Medium High].sample + } + end + + def generate_representative + { + email: Faker::Internet.email, + firstName: Faker::Name.first_name, + lastName: Faker::Name.last_name + } + end + end +end