Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16] ART: Filter PoA results list #20255

Merged
merged 7 commits into from
Jan 22, 2025
Merged

Conversation

pixiitech
Copy link
Contributor

Summary

  • This work is behind a feature toggle (flipper): YES
  • Description Allow sending of status=Pending or status=Completed param to the power_of_attorney_requests endpoint to filter the list
  • (If bug, how to reproduce) feature
  • (What is the solution, why is this the solution?) Forward And Filter By Status In POA Request List Endpoint va.gov-team#98714
  • (Which team do you work for, does your team own the maintenance of this component?) ART, yes
  • (If introducing a flipper, what is the success criteria being targeted?) ??

Related issue(s)

Testing done

  • New code is covered by unit tests

  • Describe what the old behavior was prior to the change
    power_of_attorney_requests endpoint would return a list of all PoA request without filtering capability

  • Describe the steps required to verify your changes are working as expected. Exclusively stating 'Specs run' is NOT acceptable as appropriate testing
    Run rails accredited_representative_portal:seed in development
    accessing the power_of_attorney_requests endpoint with a logged in user with the ?status=Pending should yield 12 PoA requests
    accessing the power_of_attorney_requests endpoint with a logged in user with the ?status=Completed should yield 111 PoA requests

  • If this work is behind a flipper:

    • Tests need to be written for both the flipper on and flipper off scenarios. Docs.
    • What is the testing plan for rolling out the feature?
    • ?

Screenshots

Note: Optional

What areas of the site does it impact?

(Describe what parts of the site are impacted andifcode touched other areas)
Accredited Representative Portal

Acceptance criteria

  • I fixed|updated|added unit tests and integration tests for each feature (if applicable).
  • No error nor warning in the console.
  • Events are being sent to the appropriate logging solution
  • Documentation has been updated (link to documentation)
  • No sensitive information (i.e. PII/credentials/internal URLs/etc.) is captured in logging, hardcoded, or specs
  • Feature/bug has a monitor built into Datadog (if applicable)
  • If app impacted requires authentication, did you login to a local build and verify all authenticated routes work as expected
  • I added a screenshot of the developed feature

Requested Feedback

(OPTIONAL)What should the reviewers know in addition to the above. Is there anything specific you wish the reviewer to assist with. Do you have any concerns with this PR, why?

@pixiitech pixiitech changed the base branch from master to art/serializers/match_front_end_data January 13, 2025 20:18
@pixiitech pixiitech changed the title Art/poa requests/filter poa list 16: Art/poa requests/filter poa list Jan 13, 2025
@pixiitech pixiitech changed the title 16: Art/poa requests/filter poa list [16] ART: Filter PoA results list Jan 13, 2025
Copy link
Contributor

@nihil2501 nihil2501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final tweak

Comment on lines 27 to 39
poa_requests = poa_request_scope.includes(includes).limit(100)
rel = poa_request_scope

if params[:status]&.downcase == 'pending'
rel = rel.unresolved
elsif params[:status]&.downcase == 'completed'
rel = rel.resolved
elsif params[:status].present? # throw 400 for other non-blank statuses
raise Common::Exceptions::BadRequest.new(
errors: "Invalid status parameter. Values accepted: 'pending' or 'completed'."
)
end

poa_requests = rel.includes(includes).limit(100)
Copy link
Contributor

@nihil2501 nihil2501 Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's represent this enum with a module defined in this controller:

module Statuses
  ALL = [
    PENDING = 'pending',
    COMPLETED = 'completed'
  ].freeze
end

And then represent exhaustively matching against it with a case statement:

rel = poa_request_scope
status = params[:status].presence

rel =
  case status
  when Statuses::PENDING
    rel.unresolved
  when Statuses::COMPLETED
    rel.resolved
  when NilClass
    rel
  else
    # Throw 400 for unexpected, non-blank statuses
    raise ActionController::BadRequest.new(<<~MSG.squish)
      Invalid status parameter.
      Must be one of (#{Statuses::ALL.join(', ')})
    MSG
  end

Note:

  • Use of ActionController::BadRequest for now, which mirrors how we're using other native Rails controller exceptions for now in our semi-shared exception handling
  • Even stricter about inputs (no downcase or other normalization), since we shouldn't present clients a loose API contract

Copy link
Contributor Author

@pixiitech pixiitech Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were measures I added to prevent extra frustration if the frontend accidentally sent a lowercase version but that's ok. I still think we should ignore an empty status string (this rewrite will throw a 400) Nevermind I see the use of presence

Copy link
Contributor

@nihil2501 nihil2501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActionController::BadRequest

@@ -23,6 +23,13 @@ module PowerOfAttorneyRequests
status: :unprocessable_entity
)
end

rescue_from Common::Exceptions::BadRequest do |e|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would need to handle ActionController::BadRequest now since we switched to raising that.

@nihil2501 nihil2501 force-pushed the art/serializers/match_front_end_data branch from d3bcc6c to a07f73c Compare January 16, 2025 00:51
Copy link
Contributor

@nihil2501 nihil2501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple additional things.


it 'throws an error if any other status filter provided' do
get('/accredited_representative_portal/v0/power_of_attorney_requests?status=delete_all')
expect(response).to have_http_status(:internal_server_error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be :bad_request after we reflect the changed exception type in our exception rendering.

Comment on lines 24 to 26
AccreditedRepresentativePortal::PowerOfAttorneyForm.delete_all
AccreditedRepresentativePortal::PowerOfAttorneyRequestResolution.delete_all
AccreditedRepresentativePortal::PowerOfAttorneyRequest.delete_all
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need these. I think we make our test suite run with transaction-oriented database cleaning on a per-spec-example basis and I think the let! is defeating that idea. Kind of just guessing, but I tried changing to let and causing the creation at the top of each spec example and I didn't need the delete_all's. There are very few delete_all's in the spec suite. For now, let's use let and cause the creation at the top of each example.

@pixiitech pixiitech force-pushed the art/poa-requests/filter-poa-list branch from b2b6092 to ac0540e Compare January 16, 2025 18:45
nihil2501
nihil2501 previously approved these changes Jan 16, 2025
Copy link
Contributor

@nihil2501 nihil2501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@va-vfs-bot va-vfs-bot temporarily deployed to art/poa-requests/filter-poa-list/main/main January 16, 2025 19:28 Inactive
@ojbucao ojbucao force-pushed the art/serializers/match_front_end_data branch 2 times, most recently from 9d322dd to a7955d6 Compare January 17, 2025 21:52
Base automatically changed from art/serializers/match_front_end_data to master January 17, 2025 22:06
@stevenjcumming stevenjcumming dismissed nihil2501’s stale review January 17, 2025 22:06

The base branch was changed.

@pixiitech pixiitech force-pushed the art/poa-requests/filter-poa-list branch 2 times, most recently from a5bc0bc to 98ab588 Compare January 21, 2025 16:40
@ojbucao ojbucao force-pushed the art/poa-requests/filter-poa-list branch from 98ab588 to d4765a5 Compare January 22, 2025 17:12
@ojbucao ojbucao marked this pull request as ready for review January 22, 2025 17:20
@ojbucao ojbucao requested a review from a team as a code owner January 22, 2025 17:20
Copy link
Contributor

@stevenjcumming stevenjcumming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned this in another PR https://github.com/department-of-veterans-affairs/vets-api/pull/20321/files

Please remove the Statuses module and use the constants directly

 PENDING = 'pending'.freeze
 COMPLETED = 'completed'.freeze
 ALL = [PENDING, COMPLETED].freeze

@pixiitech
Copy link
Contributor Author

pixiitech commented Jan 22, 2025

I mentioned this in another PR https://github.com/department-of-veterans-affairs/vets-api/pull/20321/files

Please remove the Statuses module and use the constants directly

 PENDING = 'pending'.freeze
 COMPLETED = 'completed'.freeze
 ALL = [PENDING, COMPLETED].freeze

Screenshot 2025-01-22 at 4 01 08 PM

Linter is making me remove the .freeze on the first two lines

Rebased with master and pushed

@stevenjcumming
Copy link
Contributor

I mentioned this in another PR https://github.com/department-of-veterans-affairs/vets-api/pull/20321/files
Please remove the Statuses module and use the constants directly

 PENDING = 'pending'.freeze
 COMPLETED = 'completed'.freeze
 ALL = [PENDING, COMPLETED].freeze

Screenshot 2025-01-22 at 4 01 08 PM

Linter is making me remove the .freeze on the first two lines

Rebased with master and pushed

Sorry, old habit die hard.. no need to freeze

@nihil2501
Copy link
Contributor

nihil2501 commented Jan 22, 2025

@stevenjcumming @pixiitech Is it a requirement to remove the namespacing of our related constants? This is a pattern I have used and seen in many many places and indeed would encourage elsewhere within our module. This seems like more of a stylistic suggestion.

Without the scoping I'd at least ask for the variable name to now reflect the repeated constant name prefix STATUS_ or something, since otherwise the name ALL is not a sufficiently explanatory constant name.

TL;DR: can we merge this with the original namespacing?

@stevenjcumming
Copy link
Contributor

stevenjcumming commented Jan 22, 2025

@stevenjcumming @pixiitech Is it a requirement to remove the namespacing of our related constants? This is a pattern I have used and seen in many many places and indeed would encourage elsewhere within our module. This seems like more of a stylistic suggestion.

Without the scoping I'd at least ask for the variable name to now reflect the repeated constant name prefix STATUS_ or something, since otherwise the name ALL is not a sufficiently explanatory constant name.

TL;DR: can we merge this with the original namespacing?

@nihil2501 It is stylistic. I'm not a fan of it, unless it's used in outside the class (no issue with that).

Prefixes are fine, you can call is STATUSES = [], or use a hash, etc. I meant to just illustrate my intent not specifically suggest that, apologies for the confusion.

can we merge this with the original namespacing?
=> I really don't like it, but I know you have a deadline so I'll approve it if you feel strongly about it

@pixiitech pixiitech force-pushed the art/poa-requests/filter-poa-list branch from 812046b to 26f41ac Compare January 22, 2025 21:41
@pixiitech
Copy link
Contributor Author

@stevenjcumming @pixiitech Is it a requirement to remove the namespacing of our related constants? This is a pattern I have used and seen in many many places and indeed would encourage elsewhere within our module. This seems like more of a stylistic suggestion.
Without the scoping I'd at least ask for the variable name to now reflect the repeated constant name prefix STATUS_ or something, since otherwise the name ALL is not a sufficiently explanatory constant name.
TL;DR: can we merge this with the original namespacing?

@nihil2501 It is stylistic. I'm not a fan of it, unless it's used in outside the class (no issue with that).

Prefixes are fine, you can call is STATUSES = [], or use a hash, etc. I meant to just illustrate my intent not specifically suggest that, apologies for the confusion.

can we merge this with the original namespacing? => I really don't like it, but I know you have a deadline so I'll approve it if you feel strongly about it

dropped last commit and rebased

@nihil2501
Copy link
Contributor

@stevenjcumming I think I see the perspective about internal versus external. Of the other options I'd probably prefer:

STATUSES = {
  PENDING: 'pending',
  COMPLETED: 'completed'
}

STATUSES.values # to get all of them

In any event, this code is going to be modified more and more heavily to an encapsulated module for doing all the things that one needs to do for searching: defaulting, query building, invalidity, etc. So here I just wanted to suggest by example that that kind of encapsulation is forthcoming.

@ojbucao ojbucao merged commit 640aeb7 into master Jan 22, 2025
22 checks passed
@ojbucao ojbucao deleted the art/poa-requests/filter-poa-list branch January 22, 2025 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants