Skip to content

Commit

Permalink
1492: Synchronizations follow up (#303)
Browse files Browse the repository at this point in the history
* Show more specific statuses

* Edge case: pinwheel account may not be created in CBV yet

* Remove vestigial

* Transition the page correctly as soon as full sync has completed

* Add test for new method

* Coalesce some statuses to completed for other jobs

* Remove question mark

* Set locale manually

* Update app/app/models/pinwheel_account.rb

Co-authored-by: Tom Dooner <[email protected]>

---------

Co-authored-by: Tom Dooner <[email protected]>
  • Loading branch information
allthesignals and tdooner authored Oct 3, 2024
1 parent d953842 commit 852e044
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 82 deletions.
4 changes: 0 additions & 4 deletions app/app/channels/paystubs_channel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ def check_pinwheel_account_synchrony
broadcast_to(@cbv_flow, {
event: "cbv.status_update",
account_id: pinwheel_account.pinwheel_account_id,
employment: pinwheel_account.job_completed?("employment"),
identity: pinwheel_account.job_completed?("identity"),
paystubs: pinwheel_account.job_completed?("paystubs"),
income: pinwheel_account.job_completed?("income"),
has_fully_synced: pinwheel_account.has_fully_synced?
})
end
Expand Down
8 changes: 0 additions & 8 deletions app/app/controllers/cbv/synchronizations_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
class Cbv::SynchronizationsController < Cbv::BaseController
helper_method :job_completed?

def show
account_id = params[:user][:account_id]

Expand All @@ -10,10 +8,4 @@ def show
redirect_to cbv_flow_payment_details_path(user: { account_id: @pinwheel_account.pinwheel_account_id })
end
end

private

def job_completed?(job)
@pinwheel_account.present? && @pinwheel_account.job_completed?(job)
end
end
5 changes: 3 additions & 2 deletions app/app/controllers/webhooks/pinwheel/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ def create
track_account_synced_event(@cbv_flow, pinwheel_account)

PaystubsChannel.broadcast_to(@cbv_flow, {
event: "cbv.payroll_data_available",
account_id: params["payload"]["account_id"]
event: "cbv.status_update",
account_id: params["payload"]["account_id"],
has_fully_synced: true
})
end
end
Expand Down
5 changes: 5 additions & 0 deletions app/app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,9 @@ def feedback_form_url
APPLICANT_FEEDBACK_FORM
end
end

# some job statuses we consider completed even if they failed
def coalesce_to_completed(status)
[ :unsupported, :failed ].include?(status) ? :completed : status
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,10 @@ import { Controller } from "@hotwired/stimulus"
import * as ActionCable from '@rails/actioncable'

export default class extends Controller {
static targets = ["form", "userAccountId", "employmentJob", "identityJob", "paystubsJob", "incomeJob"];
static targets = ["form", "userAccountId"];

cable = ActionCable.createConsumer();

updateIndicatorStatus(element, completed) {
if (completed) {
element.querySelector('.completed').classList.remove('display-none');
element.querySelector('.in-progress').classList.add('display-none');
} else {
element.querySelector('.completed').classList.add('display-none');
element.querySelector('.in-progress').classList.remove('display-none');
}
}

connect() {
this.cable.subscriptions.create({ channel: 'PaystubsChannel', account_id: this.userAccountIdTarget.value }, {
connected: () => {
Expand All @@ -31,11 +21,6 @@ export default class extends Controller {
this.userAccountIdTarget.value = accountId;
this.formTarget.submit();
}

this.updateIndicatorStatus(this.employmentJobTarget, data.employment);
this.updateIndicatorStatus(this.identityJobTarget, data.identity);
this.updateIndicatorStatus(this.paystubsJobTarget, data.paystubs);
this.updateIndicatorStatus(this.incomeJobTarget, data.income);
}
}
});
Expand Down
18 changes: 16 additions & 2 deletions app/app/models/pinwheel_account.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
class PinwheelAccount < ApplicationRecord
belongs_to :cbv_flow

after_update_commit {
I18n.with_locale(cbv_flow.cbv_flow_invitation.language) do
broadcast_replace target: self, partial: "cbv/synchronizations/indicators", locals: { pinwheel_account: self }
end
}

EVENTS_MAP = {
"employment.added" => :employment_synced_at,
"income.added" => :income_synced_at,
Expand Down Expand Up @@ -29,11 +35,19 @@ def job_succeeded?(job)
supported_jobs.include?(job) && send(sync_column).present? && send(error_column).blank?
end

def job_completed?(job)
def synchronization_status(job)
error_column, sync_column = event_columns_for(job)
return nil unless error_column.present?

supported_jobs.include?(job) && (send(sync_column).present? || send(error_column).present?)
if supported_jobs.exclude?(job)
:unsupported
elsif job_succeeded?(job)
:succeeded
elsif supported_jobs.include?(job) && (send(sync_column).blank? && send(error_column).blank?)
:in_progress
elsif supported_jobs.include?(job) && (send(error_column).present?)
:failed
end
end

private
Expand Down
47 changes: 37 additions & 10 deletions app/app/views/cbv/synchronizations/_indicator.html.erb
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
<svg class="in-progress <%= completed ? "display-none" : "" %> usa-icon border-05 rotate border-base-light radius-pill padding-1 usa-icon--size-5" aria-hidden="true" focusable="false" role="img">
<use
xlink:href="<%= asset_path("@uswds/uswds/dist/img/sprite.svg#autorenew") %>"
></use>
</svg>
<% if status == :in_progress %>
<div class="grid-row">
<svg class="usa-icon border-05 rotate border-base-light radius-pill padding-1 usa-icon--size-5" aria-hidden="true" focusable="false" role="img">
<use
xlink:href="<%= asset_path("@uswds/uswds/dist/img/sprite.svg#autorenew") %>"
></use>
</svg>
</div>
<div class="grid-row">
<span class="margin-top-05 text-thin"><%= label %></span>
</div>
<% end %>
<svg class="completed <%= !completed ? "display-none" : "" %> usa-icon border-05 bg-primary text-white border-primary radius-pill padding-1 usa-icon--size-5" aria-hidden="true" focusable="false" role="img">
<use
xlink:href="<%= asset_path("@uswds/uswds/dist/img/sprite.svg#check") %>"
></use>
</svg>
<% if status == :succeeded || status == :completed %>
<div class="grid-row">
<svg class="usa-icon border-05 bg-primary text-white border-primary radius-pill padding-1 usa-icon--size-5" aria-hidden="true" focusable="false" role="img">
<use
xlink:href="<%= asset_path("@uswds/uswds/dist/img/sprite.svg#check") %>"
></use>
</svg>
</div>
<div class="grid-row">
<span class="margin-top-05 text-bold text-primary"><%= label %></span>
</div>
<% end %>
<% if status == :failed %>
<div class="grid-row">
<svg class="usa-icon border-05 bg-base-darker text-white border-base-darker radius-pill padding-1 usa-icon--size-5" aria-hidden="true" focusable="false" role="img">
<use
xlink:href="<%= asset_path("@uswds/uswds/dist/img/sprite.svg#priority_high") %>"
></use>
</svg>
</div>
<div class="grid-row">
<span class="margin-top-05 text-bold"><%= label %></span>
</div>
<% end %>
22 changes: 22 additions & 0 deletions app/app/views/cbv/synchronizations/_indicators.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="grid-row" id="<%= dom_id pinwheel_account %>">
<div
class="tablet:grid-col-2 grid-col-fill"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { label: t(".income"), status: coalesce_to_completed(pinwheel_account.synchronization_status("income")) } %>
</div>
<div
class="tablet:grid-col-2 grid-col-fill"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { label: t(".employment"), status: coalesce_to_completed(pinwheel_account.synchronization_status("employment")) } %>
</div>
<div
class="tablet:grid-col-2 grid-col-fill"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { label: t(".paystubs"), status: pinwheel_account.synchronization_status("paystubs") } %>
</div>
<div
class="tablet:grid-col-2 grid-col-fill"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { label: t(".identity"), status: coalesce_to_completed(pinwheel_account.synchronization_status("identity")) } %>
</div>
</div>
34 changes: 4 additions & 30 deletions app/app/views/cbv/synchronizations/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,9 @@
<div
class="grid-container"
>
<div class="grid-row">
<div
class="tablet:grid-col-2 grid-col-fill"
data-cbv-synchronizations-target="incomeJob"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { completed: job_completed?("income") } %>
<h4 class="margin-top-2px"><%= t(".jobs.income") %></h4>
</div>
<div
class="tablet:grid-col-2 grid-col-fill"
data-cbv-synchronizations-target="employmentJob"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { completed: job_completed?("employment") } %>
<h4 class="margin-top-2px"><%= t(".jobs.employment") %></h4>
</div>
<div
class="tablet:grid-col-2 grid-col-fill"
data-cbv-synchronizations-target="paystubsJob"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { completed: job_completed?("paystubs") } %>
<h4 class="margin-top-2px"><%= t(".jobs.paystubs") %></h4>
</div>
<div
class="tablet:grid-col-2 grid-col-fill"
data-cbv-synchronizations-target="identityJob"
>
<%= render partial: "cbv/synchronizations/indicator", locals: { completed: job_completed?("identity") } %>
<h4 class="margin-top-2px"><%= t(".jobs.identity") %></h4>
</div>
</div>
<%= turbo_stream_from(@pinwheel_account) %>
<% if @pinwheel_account.present? %>
<%= render partial: "cbv/synchronizations/indicators", locals: { pinwheel_account: @pinwheel_account } %>
<% end %>
</div>
</div>
10 changes: 5 additions & 5 deletions app/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,14 @@ en:
update:
consent_to_authorize_warning: You must check the legal agreement checkbox to proceed.
synchronizations:
indicators:
employment: Employment
identity: Personal details
income: Income
paystubs: Paystubs
show:
fetching_payroll_description: This may take a few minutes. Please keep this window open while we work on this.
header: We’re gathering your payment details from your employer
jobs:
employment: Employment
identity: Personal details
income: Income
paystubs: Paystubs
date:
formats:
default: "%Y-%m-%d"
Expand Down
10 changes: 5 additions & 5 deletions app/config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,14 @@ es:
update:
consent_to_authorize_warning: Debe marcar la casilla de acuerdo legal para proceder.
synchronizations:
indicators:
employment: Empleo
identity: Datos personales
income: Ingresos
paystubs: Recibos de pago
show:
fetching_payroll_description: Esto puede tardar unos minutos. Mantenga esta ventana abierta mientras trabajamos en esto.
header: Estamos recopilando los datos de pago de su empleador
jobs:
employment: Empleo
identity: Datos personales
income: Ingresos
paystubs: Recibos de pago
date:
abbr_day_names:
- Dom
Expand Down
10 changes: 10 additions & 0 deletions app/spec/helpers/application_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,14 @@
end
end
end

describe "#coalesce_to_completed" do
it "returns succeeded when the status is failed" do
expect(helper.coalesce_to_completed(:failed)).to eq(:completed)
end

it "returns in progress when the status is in progress" do
expect(helper.coalesce_to_completed(:in_progress)).to eq(:in_progress)
end
end
end
30 changes: 30 additions & 0 deletions app/spec/models/pinwheel_account_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,34 @@
end
end
end

describe "#synchronization_status" do
context "when status is succeeded" do
it "returns succeeded" do
pinwheel_account.update!(income_synced_at: Time.current)
expect(pinwheel_account.synchronization_status('income')).to eq(:succeeded)
end
end

context "when status is failed" do
it "returns failed" do
pinwheel_account.update!(income_synced_at: Time.current, income_errored_at: Time.current)
expect(pinwheel_account.synchronization_status('income')).to eq(:failed)
end
end

context "when status is in_progress" do
it "returns in_progress" do
pinwheel_account.update!(income_synced_at: nil, income_errored_at: nil)
expect(pinwheel_account.synchronization_status('income')).to eq(:in_progress)
end
end

context "when status is unsupported" do
it "returns unsupported" do
pinwheel_account.update!(supported_jobs: supported_jobs.reject { |job| job == 'income' })
expect(pinwheel_account.synchronization_status('income')).to eq(:unsupported)
end
end
end
end

0 comments on commit 852e044

Please sign in to comment.