-
Notifications
You must be signed in to change notification settings - Fork 2
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
FFS-2110: Update flow to read/write indexing data to CbvApplicant #438
Conversation
* Move all validations and logic for indexing fields onto CbvApplicant. * Use `accepts_nested_attributes_for` and `fields_for` to forward <form> inputs directly into that object * Add `site_id` to CbvApplicant since it will be a pain to go backwards to either the CbvFlow or CbvFlowInvitation to get the site_id in all of the places it's used. * Write all the fields to CbvFlowInvitation as well, just for safekeeping until we drop them from there. Test updates: * Update factory for CbvFlow and CbvFlowInvitation to also create a cbv_applicant. Tests can override the fields of the applicant by passing in `cbv_applicant_attributes` to the factory when creating either the flow or the invitation.
It's slightly nicer than having a setter for the attributes.
* Convert the `has_one` relationships into `has_many` * Add redaction logic
…ow-use-new-database * origin/main: FFS-2295: Help modal (#417)
Convert from an errors hash including nested errors (for example, for `cbv_applicant.first_name`) to match the API request structure (to `agency_partner_metadata.first_name`).
If `Rails.application.load_tasks` is called multiple times, than any invocation of a Rake task will actually happen multiple times. This is problematic for non-idempotent Rake tasks (like `users:promote_to_service_account`). Let's prevent this issue by just loading the tasks in the "rails_helper.rb" file so they're always available.
…ow-use-new-database * origin/main: Fix flaky rake tests by always loading Rake tasks once (#439)
If an identity job fails for a Pinwheel account, it will put a `nil` in this array, which will break our Pinwheel post-processing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing!! My only complaint is that we will continue to write those attributes to cbv_flow_invitation... should I make a ticket to remove that?
error_message: e.message) | ||
return redirect_to caseworker_dashboard_path(site_id: params[:site_id]) | ||
end | ||
|
||
if @cbv_flow_invitation.errors.any? | ||
@cbv_flow_invitation.errors.delete(:cbv_applicant) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. During an error scenario, because it's a separate model, we have to delete it. I'm surprised there isn't a way to configure this as part of validations? Could you say:
accepts_nested_attributes_for :asdf, :reject_if => :something_bad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only an issue because we iterate over the whole @cbv_flow_invitation.errors
hash to generate the error alert message at the top of the page (e.g. "5 Errors: [list of errors]").
With cbv_applicant
in the .errors
hash, the count one-too-many and there is an error message for cbv_applicant
that isn't meant to be user-facing.
rescue => ex | ||
Rails.logger.error "Unable to track event (ApplicantViewedHelpTopic): #{ex}" | ||
begin | ||
event_logger.track("ApplicantViewedHelpTopic", request, { | ||
topic: @help_topic, | ||
cbv_applicant_id: cbv_flow&.cbv_applicant_id, | ||
cbv_flow_id: session[:cbv_flow_id], | ||
invitation_id: cbv_flow&.cbv_flow_invitation_id, | ||
site_id: current_site&.id, | ||
flow_started_seconds_ago: cbv_flow ? (Time.now - cbv_flow.created_at).to_i : nil, | ||
language: I18n.locale | ||
}) | ||
rescue => ex | ||
Rails.logger.error "Unable to track event (ApplicantViewedHelpTopic): #{ex}" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, I don't understand why. Is it bad form to use that approach to rescues (on the method)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rescue on a method is fine in general, but I didn't like it in this case because it might accidentally rescue exceptions for the other parts of the method that aren't related to event sending. It would make debugging the situation harder because we wouldn't get the actual exception reported to NewRelic.
app/app/models/cbv_applicant.rb
Outdated
def parse_snap_application_date | ||
raw_snap_application_date = @attributes["snap_application_date"]&.value_before_type_cast | ||
return if raw_snap_application_date.is_a?(Date) | ||
|
||
if raw_snap_application_date.is_a?(ActiveSupport::TimeWithZone) || raw_snap_application_date.is_a?(Time) | ||
self.snap_application_date = raw_snap_application_date.to_date | ||
# handle ISO 8601 date format, e.g. "2021-01-01" which is Ruby's default when querying a date field | ||
elsif raw_snap_application_date.is_a?(String) && raw_snap_application_date.match?(/^\d{4}-\d{2}-\d{2}$/) | ||
self.snap_application_date = Date.parse(raw_snap_application_date) | ||
else | ||
begin | ||
new_date_format = Date.strptime(raw_snap_application_date.to_s, "%m/%d/%Y") | ||
self.snap_application_date = new_date_format | ||
rescue Date::Error => e | ||
case site_id | ||
when "ma" | ||
error = :ma_invalid_date | ||
when "nyc" | ||
error = :nyc_invalid_date | ||
else | ||
error = :default_invalid_date | ||
end | ||
errors.add(:snap_application_date, error) | ||
end | ||
end | ||
end | ||
|
||
def ma_snap_application_date_not_in_future | ||
if snap_application_date.present? && snap_application_date > Date.current | ||
errors.add(:snap_application_date, :ma_invalid_date) | ||
end | ||
end | ||
|
||
def ma_snap_application_date_not_more_than_1_year_ago | ||
if snap_application_date.present? && snap_application_date < 1.year.ago.to_date | ||
errors.add(:snap_application_date, :ma_invalid_date) | ||
end | ||
end | ||
|
||
def nyc_snap_application_date_not_in_future | ||
if snap_application_date.present? && snap_application_date > Date.current | ||
errors.add(:snap_application_date, :nyc_invalid_date) | ||
end | ||
end | ||
|
||
def nyc_snap_application_date_not_more_than_30_days_ago | ||
if snap_application_date.present? && snap_application_date < 30.day.ago.to_date | ||
errors.add(:snap_application_date, :nyc_invalid_date) | ||
end | ||
end | ||
|
||
def format_case_number | ||
return if case_number.blank? | ||
case_number.upcase! | ||
if case_number.length == 9 | ||
self.case_number = "000#{case_number}" | ||
end | ||
end | ||
|
||
def paystubs_query_begins_at | ||
PAYSTUB_REPORT_RANGE.before(snap_application_date) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't really tell from the diff but this is all copied oer from cbv_invitation, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, all were copied without modification. (I should have left a comment pointing that out, oops.)
with_options(if: :nyc_site?) do | ||
validates :case_number, format: { with: NYC_CASE_NUMBER_REGEX, message: :invalid_format } | ||
validates :client_id_number, format: { with: NYC_CLIENT_ID_REGEX, message: :invalid_format } | ||
validate :nyc_snap_application_date_not_more_than_30_days_ago | ||
validate :nyc_snap_application_date_not_in_future | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting this is slightly different from how it was written in cbv_flow_invitation... seems like nicer syntax for the same thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I tend to like using Rails's with_options
to group together similar validation rules. The with_options
helper will add whatever you pass it as an options hash to all the functions within. Helpful to make sure we don't forget to add the NYC conditional for any NYC validation rules.
next unless Time.now.after?(cbv_flow_invitation.expires_at + REDACT_UNUSED_INVITATIONS_AFTER) | ||
|
||
cbv_flow_invitation.redact! | ||
cbv_flow_invitation.cbv_applicant&.redact! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aaaaah. Need a feature in redactable, like has_redactable_fields (hi: string), dependent: :redact
or something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, was thinking about having the Redactable
module redact associations, similar to how you had it. Would be good for a future change?
@allthesignals Already created - https://jiraent.cms.gov/browse/FFS-2463 ! |
…ow-use-new-database * origin/main: FFS-2408: Rename site_id to client_agency_id (#446) FFS-2351: Change calculation of account_count to be correct in filed events (#445) Patching vulnerabilities | esbuild, net-imap (#450) Address vulnerability (#443) fix: upgrade postcss from 8.5.0 to 8.5.1 (#441) fix: upgrade sass from 1.83.2 to 1.83.4 (#440) 2401: Use different syntax (#437) updated tests for clarity fixed typo cleaned up based on PR comments removed trailing whitespace/rubocop fixes wrapped token creation for users.rake in a transaction, added test assertion to assure that the user api_access_tokens.count only changes by a factor of 1 updated vitest to v 3.0.5 address failed security scan rename vitest add github action fixed postcss build error added .vitest to git ignore updated package.json to use module setup project to work with vitest and debugging remove employer_search.spec comment out test write test scripts for pinwheel.js update apiservice to fetchInternalApiService for clarity refactored fetch into its own file refactored code to be a little more self evident remove outdated snapshots comment refactored api calls with tests added tests for trackUserAction api call move trackUserAction out of pinwheel into analytics file minor changes stub for employersearch test installed vitest
…ow-use-new-database * origin/main: FFS-2336: First sketch of multi-provider search (#442)
Ticket
Resolves FFS-2110.
Changes
Rename CbvClient -> CbvApplicant
Write CbvApplicant fields directly from Caseworker form
accepts_nested_attributes_for
andfields_for
to forwardinputs directly into that object
site_id
to CbvApplicant since it will be a pain to go backwardsto either the CbvFlow or CbvFlowInvitation to get the site_id in all
of the places it's used.
safekeeping until we drop them from there.
Test updates:
cbv_applicant. Tests can override the fields of the applicant by
passing in
cbv_applicant_attributes
to the factory when creatingeither the flow or the invitation.
Context for reviewers
Uhhh, this is a pretty big refactor. Planning to get some more eyes on this for smoke testing before merging.
TODO list (as of 2/6):
has_one
associations to cbv_flow and cbv_invitation ->has_many
CbvApplicant#set_site_id
since it should be provided by whatever creates the applicant?site_id
to the authenticated API user in Api::InvitaitonsControllerAcceptance testing
:alert: Deploy block! @ffs-eng I just merged PR [#123] and will be doing acceptance testing in demo - please don't deploy until I'm finished!
)