From 1045804894f7cb0a52a0c6fbb88248ff4313f5de Mon Sep 17 00:00:00 2001 From: Matt Gardner Date: Thu, 27 Feb 2025 11:49:10 -0500 Subject: [PATCH] FFS-2466: Rename PinwheelAccount model to PayrollAccount (#470) * Rename pinwheel account to payroll account * Rename table * Rename table --- app/app/channels/paystubs_channel.rb | 2 +- .../cbv/employer_searches_controller.rb | 2 +- .../cbv/missing_results_controller.rb | 2 +- .../cbv/payment_details_controller.rb | 2 +- .../controllers/cbv/summaries_controller.rb | 8 +-- .../cbv/synchronizations_controller.rb | 2 +- .../webhooks/pinwheel/events_controller.rb | 10 ++-- app/app/helpers/cbv/pinwheel_data_helper.rb | 12 ++--- app/app/javascript/utilities/api.js | 3 +- app/app/models/cbv_flow.rb | 4 +- ...pinwheel_account.rb => payroll_account.rb} | 2 +- ...27162123_rename_pinwheel_accounts_table.rb | 5 ++ app/db/schema.rb | 8 +-- .../cbv/employer_searches_controller_spec.rb | 6 +-- .../cbv/entries_controller_spec.rb | 2 +- .../cbv/missing_results_controller_spec.rb | 2 +- .../cbv/payment_details_controller_spec.rb | 12 ++--- .../cbv/summaries_controller_spec.rb | 2 +- .../cbv/synchronization_failures_spec.rb | 6 +-- .../controllers/cbv/synchronizations_spec.rb | 10 ++-- .../pinwheel/events_controller_spec.rb | 20 +++---- app/spec/factories/cbv_flow.rb | 4 +- ...pinwheel_account.rb => payroll_account.rb} | 2 +- .../helpers/cbv/pinwheel_data_helper_spec.rb | 4 +- app/spec/mailers/caseworker_mailer_spec.rb | 2 +- .../previews/caseworker_mailer_preview.rb | 8 +-- ...ccount_spec.rb => payroll_account_spec.rb} | 50 +++++++++--------- app/spec/services/pdf_service_spec.rb | 6 +-- docs/app/rendered/database-schema.pdf | Bin 39264 -> 38286 bytes 29 files changed, 101 insertions(+), 97 deletions(-) rename app/app/models/{pinwheel_account.rb => payroll_account.rb} (97%) create mode 100644 app/db/migrate/20250227162123_rename_pinwheel_accounts_table.rb rename app/spec/factories/{pinwheel_account.rb => payroll_account.rb} (87%) rename app/spec/models/{pinwheel_account_spec.rb => payroll_account_spec.rb} (54%) diff --git a/app/app/channels/paystubs_channel.rb b/app/app/channels/paystubs_channel.rb index ca6e4639e..09e56f556 100644 --- a/app/app/channels/paystubs_channel.rb +++ b/app/app/channels/paystubs_channel.rb @@ -9,7 +9,7 @@ def subscribed private def check_pinwheel_account_synchrony - pinwheel_account = PinwheelAccount.find_by_pinwheel_account_id(params["account_id"]) + pinwheel_account = PayrollAccount.find_by_pinwheel_account_id(params["account_id"]) if pinwheel_account.present? broadcast_to(@cbv_flow, { diff --git a/app/app/controllers/cbv/employer_searches_controller.rb b/app/app/controllers/cbv/employer_searches_controller.rb index 2b03bee06..5e6a373fb 100644 --- a/app/app/controllers/cbv/employer_searches_controller.rb +++ b/app/app/controllers/cbv/employer_searches_controller.rb @@ -7,7 +7,7 @@ class Cbv::EmployerSearchesController < Cbv::BaseController def show @query = search_params[:query] @employers = @query.blank? ? [] : provider_search(@query) - @has_pinwheel_account = @cbv_flow.pinwheel_accounts.any? + @has_pinwheel_account = @cbv_flow.payroll_accounts.any? @selected_tab = search_params[:type] || "payroll" case search_params[:type] diff --git a/app/app/controllers/cbv/missing_results_controller.rb b/app/app/controllers/cbv/missing_results_controller.rb index 2dc46be5b..11982a57d 100644 --- a/app/app/controllers/cbv/missing_results_controller.rb +++ b/app/app/controllers/cbv/missing_results_controller.rb @@ -2,7 +2,7 @@ class Cbv::MissingResultsController < Cbv::BaseController before_action :track_missing_results_event, only: :show def show - @has_pinwheel_account = @cbv_flow.pinwheel_accounts.any? + @has_pinwheel_account = @cbv_flow.payroll_accounts.any? end def track_missing_results_event diff --git a/app/app/controllers/cbv/payment_details_controller.rb b/app/app/controllers/cbv/payment_details_controller.rb index 2bef3750a..b1c2b43fc 100644 --- a/app/app/controllers/cbv/payment_details_controller.rb +++ b/app/app/controllers/cbv/payment_details_controller.rb @@ -17,7 +17,7 @@ class Cbv::PaymentDetailsController < Cbv::BaseController def show account_id = params[:user][:account_id] - @pinwheel_account = @cbv_flow.pinwheel_accounts.find_by(pinwheel_account_id: account_id) + @pinwheel_account = @cbv_flow.payroll_accounts.find_by(pinwheel_account_id: account_id) # security check - make sure the account_id is associated with the current cbv_flow_id if @pinwheel_account.nil? diff --git a/app/app/controllers/cbv/summaries_controller.rb b/app/app/controllers/cbv/summaries_controller.rb index 0fb376727..e571923f1 100644 --- a/app/app/controllers/cbv/summaries_controller.rb +++ b/app/app/controllers/cbv/summaries_controller.rb @@ -119,7 +119,7 @@ def transmit_to_caseworker employments: @employments, incomes: @incomes, identities: @identities, - payments_grouped_by_employer: summarize_by_employer(@payments, @employments, @incomes, @identities, @cbv_flow.pinwheel_accounts), + payments_grouped_by_employer: summarize_by_employer(@payments, @employments, @incomes, @identities, @cbv_flow.payroll_accounts), has_consent: has_consent } ) @@ -164,7 +164,7 @@ def transmit_to_caseworker end def generate_csv - pinwheel_account = PinwheelAccount.find_by(cbv_flow_id: @cbv_flow.id) + pinwheel_account = PayrollAccount.find_by(cbv_flow_id: @cbv_flow.id) data = { client_id: @cbv_flow.cbv_applicant.agency_id_number, @@ -195,7 +195,7 @@ def track_transmitted_event(cbv_flow, payments) cbv_applicant_id: cbv_flow.cbv_applicant_id, cbv_flow_id: cbv_flow.id, invitation_id: cbv_flow.cbv_flow_invitation_id, - account_count: cbv_flow.pinwheel_accounts.count, + account_count: cbv_flow.payroll_accounts.count, paystub_count: payments.count, account_count_with_additional_information: cbv_flow.additional_information.values.count { |info| info["comment"].present? }, @@ -213,7 +213,7 @@ def track_accessed_income_summary_event(cbv_flow, payments) cbv_flow_id: cbv_flow.id, cbv_applicant_id: cbv_flow.cbv_applicant_id, invitation_id: cbv_flow.cbv_flow_invitation_id, - account_count: cbv_flow.pinwheel_accounts.count, + account_count: cbv_flow.payroll_accounts.count, paystub_count: payments.count, account_count_with_additional_information: cbv_flow.additional_information.values.count { |info| info["comment"].present? }, diff --git a/app/app/controllers/cbv/synchronizations_controller.rb b/app/app/controllers/cbv/synchronizations_controller.rb index f4e2b3d52..1e2511b88 100644 --- a/app/app/controllers/cbv/synchronizations_controller.rb +++ b/app/app/controllers/cbv/synchronizations_controller.rb @@ -27,6 +27,6 @@ def redirect_if_sync_finished def set_pinwheel_account account_id = params[:user][:account_id] - @pinwheel_account = @cbv_flow.pinwheel_accounts.find_by(pinwheel_account_id: account_id) + @pinwheel_account = @cbv_flow.payroll_accounts.find_by(pinwheel_account_id: account_id) end end diff --git a/app/app/controllers/webhooks/pinwheel/events_controller.rb b/app/app/controllers/webhooks/pinwheel/events_controller.rb index 6c05ebf2a..7c06abe50 100644 --- a/app/app/controllers/webhooks/pinwheel/events_controller.rb +++ b/app/app/controllers/webhooks/pinwheel/events_controller.rb @@ -12,20 +12,20 @@ def create if params["event"] == "account.added" supported_jobs = get_supported_jobs(params["payload"]["platform_id"]) - PinwheelAccount + PayrollAccount .create_with(cbv_flow: @cbv_flow, supported_jobs: supported_jobs) .find_or_create_by(pinwheel_account_id: params["payload"]["account_id"]) track_account_created_event(@cbv_flow, params["payload"]["platform_name"]) end - if PinwheelAccount::EVENTS_MAP.keys.include?(params["event"]) - pinwheel_account = PinwheelAccount.find_by_pinwheel_account_id(params["payload"]["account_id"]) + if PayrollAccount::EVENTS_MAP.keys.include?(params["event"]) + pinwheel_account = PayrollAccount.find_by_pinwheel_account_id(params["payload"]["account_id"]) if pinwheel_account.present? - pinwheel_account.update!(PinwheelAccount::EVENTS_MAP[params["event"]] => Time.now) + pinwheel_account.update!(PayrollAccount::EVENTS_MAP[params["event"]] => Time.now) if params.dig("payload", "outcome") == "error" || params.dig("payload", "outcome") == "pending" - pinwheel_account.update!(PinwheelAccount::EVENTS_ERRORS_MAP[params["event"]] => Time.now) + pinwheel_account.update!(PayrollAccount::EVENTS_ERRORS_MAP[params["event"]] => Time.now) end if pinwheel_account.has_fully_synced? diff --git a/app/app/helpers/cbv/pinwheel_data_helper.rb b/app/app/helpers/cbv/pinwheel_data_helper.rb index 25a27b06b..cb66d210c 100644 --- a/app/app/helpers/cbv/pinwheel_data_helper.rb +++ b/app/app/helpers/cbv/pinwheel_data_helper.rb @@ -16,7 +16,7 @@ def set_payments(account_id = nil) end def set_employments - @employments = @cbv_flow.pinwheel_accounts.map do |pinwheel_account| + @employments = @cbv_flow.payroll_accounts.map do |pinwheel_account| next unless pinwheel_account.job_succeeded?("employment") pinwheel.fetch_employment(account_id: pinwheel_account.pinwheel_account_id) @@ -24,7 +24,7 @@ def set_employments end def set_incomes - @incomes = @cbv_flow.pinwheel_accounts.map do |pinwheel_account| + @incomes = @cbv_flow.payroll_accounts.map do |pinwheel_account| next unless pinwheel_account.job_succeeded?("income") pinwheel.fetch_income(account_id: pinwheel_account.pinwheel_account_id) @@ -32,7 +32,7 @@ def set_incomes end def set_identities - @identities = @cbv_flow.pinwheel_accounts.map do |pinwheel_account| + @identities = @cbv_flow.payroll_accounts.map do |pinwheel_account| next unless pinwheel_account.job_succeeded?("identity") pinwheel.fetch_identity(account_id: pinwheel_account.pinwheel_account_id) @@ -43,7 +43,7 @@ def hours_by_earning_category(earnings) end def payments_grouped_by_employer - summarize_by_employer(@payments, @employments, @incomes, @identities, @cbv_flow.pinwheel_accounts) + summarize_by_employer(@payments, @employments, @incomes, @identities, @cbv_flow.payroll_accounts) end def total_gross_income @@ -74,7 +74,7 @@ def summarize_by_employer(payments, employments, incomes, identities, pinwheel_a private def fetch_paystubs(from_pay_date, to_pay_date) - @cbv_flow.pinwheel_accounts.flat_map do |pinwheel_account| + @cbv_flow.payroll_accounts.flat_map do |pinwheel_account| next [] unless pinwheel_account.job_succeeded?("paystubs") fetch_paystubs_for_account_id(pinwheel_account.pinwheel_account_id, from_pay_date, to_pay_date) @@ -90,7 +90,7 @@ def fetch_paystubs_for_account_id(account_id, from_pay_date, to_pay_date) end def does_pinwheel_account_support_job?(account_id, job) - pinwheel_account = PinwheelAccount.find_by_pinwheel_account_id(account_id) + pinwheel_account = PayrollAccount.find_by_pinwheel_account_id(account_id) return false unless pinwheel_account pinwheel_account.job_succeeded?(job) diff --git a/app/app/javascript/utilities/api.js b/app/app/javascript/utilities/api.js index 8ee35fc18..0fdb5cf0d 100644 --- a/app/app/javascript/utilities/api.js +++ b/app/app/javascript/utilities/api.js @@ -15,10 +15,9 @@ export const trackUserAction = async (eventName, attributes) => { }).then(response => response.json()); } - export const fetchToken = (response_type, id, locale) => { return fetchInternal(PINWHEEL_TOKENS_GENERATE, { method: 'post', body: JSON.stringify({ response_type, id, locale }), }) -}; \ No newline at end of file +}; diff --git a/app/app/models/cbv_flow.rb b/app/app/models/cbv_flow.rb index 54d76ffb6..8ab968186 100644 --- a/app/app/models/cbv_flow.rb +++ b/app/app/models/cbv_flow.rb @@ -1,5 +1,5 @@ class CbvFlow < ApplicationRecord - has_many :pinwheel_accounts, dependent: :destroy + has_many :payroll_accounts, dependent: :destroy belongs_to :cbv_flow_invitation, optional: true belongs_to :cbv_applicant, optional: true validates :client_agency_id, inclusion: Rails.application.config.client_agencies.client_agency_ids @@ -28,6 +28,6 @@ def self.create_from_invitation(cbv_flow_invitation) end def has_account_with_required_data? - pinwheel_accounts.any?(&:has_required_data?) + payroll_accounts.any?(&:has_required_data?) end end diff --git a/app/app/models/pinwheel_account.rb b/app/app/models/payroll_account.rb similarity index 97% rename from app/app/models/pinwheel_account.rb rename to app/app/models/payroll_account.rb index 13755d5ff..64cbb92ee 100644 --- a/app/app/models/pinwheel_account.rb +++ b/app/app/models/payroll_account.rb @@ -1,4 +1,4 @@ -class PinwheelAccount < ApplicationRecord +class PayrollAccount < ApplicationRecord belongs_to :cbv_flow after_update_commit { diff --git a/app/db/migrate/20250227162123_rename_pinwheel_accounts_table.rb b/app/db/migrate/20250227162123_rename_pinwheel_accounts_table.rb new file mode 100644 index 000000000..05ae4a0ef --- /dev/null +++ b/app/db/migrate/20250227162123_rename_pinwheel_accounts_table.rb @@ -0,0 +1,5 @@ +class RenamePinwheelAccountsTable < ActiveRecord::Migration[7.1] + def change + rename_table :pinwheel_accounts, :payroll_accounts + end +end diff --git a/app/db/schema.rb b/app/db/schema.rb index aa6d9b34d..ffeedbe43 100644 --- a/app/db/schema.rb +++ b/app/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_02_06_012936) do +ActiveRecord::Schema[7.1].define(version: 2025_02_27_162123) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -80,7 +80,7 @@ t.index ["cbv_flow_invitation_id"], name: "index_cbv_flows_on_cbv_flow_invitation_id" end - create_table "pinwheel_accounts", force: :cascade do |t| + create_table "payroll_accounts", force: :cascade do |t| t.bigint "cbv_flow_id", null: false t.string "pinwheel_account_id" t.datetime "paystubs_synced_at", precision: nil @@ -94,7 +94,7 @@ t.datetime "paystubs_errored_at", precision: nil t.datetime "identity_errored_at", precision: nil t.datetime "identity_synced_at", precision: nil - t.index ["cbv_flow_id"], name: "index_pinwheel_accounts_on_cbv_flow_id" + t.index ["cbv_flow_id"], name: "index_payroll_accounts_on_cbv_flow_id" end create_table "users", force: :cascade do |t| @@ -119,5 +119,5 @@ add_foreign_key "cbv_flow_invitations", "users" add_foreign_key "cbv_flows", "cbv_flow_invitations" - add_foreign_key "pinwheel_accounts", "cbv_flows" + add_foreign_key "payroll_accounts", "cbv_flows" end diff --git a/app/spec/controllers/cbv/employer_searches_controller_spec.rb b/app/spec/controllers/cbv/employer_searches_controller_spec.rb index 21fd8dc86..5daef2306 100644 --- a/app/spec/controllers/cbv/employer_searches_controller_spec.rb +++ b/app/spec/controllers/cbv/employer_searches_controller_spec.rb @@ -100,9 +100,9 @@ render_views - context "when the user at least one pinwheel_account associated with their cbv_flow" do + context "when the user at least one payroll_account associated with their cbv_flow" do it "renders the view with a link to the summary page" do - create(:pinwheel_account, cbv_flow_id: cbv_flow.id) + create(:payroll_account, cbv_flow_id: cbv_flow.id) get :show, params: { query: "no_results" } expect(response).to be_successful expect(response.body).to include("continue to review your income report") @@ -110,7 +110,7 @@ end end - context "when the user has does not have a pinwheel_account associated with their cbv_flow" do + context "when the user has does not have a payroll_account associated with their cbv_flow" do it "renders the view with a link to exit income verification" do get :show, params: { query: "no_results" } expect(response).to be_successful diff --git a/app/spec/controllers/cbv/entries_controller_spec.rb b/app/spec/controllers/cbv/entries_controller_spec.rb index fb9476d3a..b045b2bab 100644 --- a/app/spec/controllers/cbv/entries_controller_spec.rb +++ b/app/spec/controllers/cbv/entries_controller_spec.rb @@ -134,7 +134,7 @@ existing_cbv_flow.update(confirmation_code: "FOOBAR") end let!(:connected_account) do - create(:pinwheel_account, + create(:payroll_account, cbv_flow: existing_cbv_flow, pinwheel_account_id: SecureRandom.uuid, created_at: 4.minutes.ago diff --git a/app/spec/controllers/cbv/missing_results_controller_spec.rb b/app/spec/controllers/cbv/missing_results_controller_spec.rb index e94c1457c..63dec1c39 100644 --- a/app/spec/controllers/cbv/missing_results_controller_spec.rb +++ b/app/spec/controllers/cbv/missing_results_controller_spec.rb @@ -16,7 +16,7 @@ end context "when the user has already linked a pinwheel account" do - let!(:pinwheel_account) { create(:pinwheel_account, cbv_flow: cbv_flow) } + let!(:payroll_account) { create(:payroll_account, cbv_flow: cbv_flow) } it "renders successfully" do get :show diff --git a/app/spec/controllers/cbv/payment_details_controller_spec.rb b/app/spec/controllers/cbv/payment_details_controller_spec.rb index a1b8a6b12..bc1d7bea2 100644 --- a/app/spec/controllers/cbv/payment_details_controller_spec.rb +++ b/app/spec/controllers/cbv/payment_details_controller_spec.rb @@ -13,9 +13,9 @@ let(:income_errored_at) { nil } let(:paystubs_errored_at) { nil } let(:employment_errored_at) { nil } - let!(:pinwheel_account) do + let!(:payroll_account) do create( - :pinwheel_account, + :payroll_account, cbv_flow: cbv_flow, pinwheel_account_id: account_id, supported_jobs: supported_jobs, @@ -45,7 +45,7 @@ .with("ApplicantViewedPaymentDetails", anything, hash_including( cbv_flow_id: cbv_flow.id, invitation_id: cbv_flow.cbv_flow_invitation_id, - pinwheel_account_id: pinwheel_account.id, + pinwheel_account_id: payroll_account.id, payments_length: 1, has_employment_data: true, has_paystubs_data: true, @@ -57,7 +57,7 @@ .with("ApplicantViewedPaymentDetails", anything, hash_including( cbv_flow_id: cbv_flow.id, invitation_id: cbv_flow.cbv_flow_invitation_id, - pinwheel_account_id: pinwheel_account.id, + pinwheel_account_id: payroll_account.id, payments_length: 1, has_employment_data: true, has_paystubs_data: true, @@ -197,8 +197,8 @@ end it "redirects to the entry page when the resolved pinwheel_account is present, but does not match the current session" do - existing_pinwheel_account = create(:pinwheel_account) - get :show, params: { user: { account_id: existing_pinwheel_account.pinwheel_account_id } } + existing_payroll_account = create(:payroll_account) + get :show, params: { user: { account_id: existing_payroll_account.pinwheel_account_id } } expect(response).to redirect_to(cbv_flow_entry_url) expect(flash[:slim_alert]).to be_present expect(flash[:slim_alert][:message]).to eq(I18n.t("cbv.error_no_access")) diff --git a/app/spec/controllers/cbv/summaries_controller_spec.rb b/app/spec/controllers/cbv/summaries_controller_spec.rb index 320a10d73..d1d3ad614 100644 --- a/app/spec/controllers/cbv/summaries_controller_spec.rb +++ b/app/spec/controllers/cbv/summaries_controller_spec.rb @@ -30,7 +30,7 @@ "public_key" => @public_key }) - cbv_flow.pinwheel_accounts.first.update(pinwheel_account_id: "03e29160-f7e7-4a28-b2d8-813640e030d3") + cbv_flow.payroll_accounts.first.update(pinwheel_account_id: "03e29160-f7e7-4a28-b2d8-813640e030d3") end around do |ex| diff --git a/app/spec/controllers/cbv/synchronization_failures_spec.rb b/app/spec/controllers/cbv/synchronization_failures_spec.rb index aba91eea4..4de671029 100644 --- a/app/spec/controllers/cbv/synchronization_failures_spec.rb +++ b/app/spec/controllers/cbv/synchronization_failures_spec.rb @@ -11,7 +11,7 @@ end context "when the user has already linked a pinwheel account" do - let!(:pinwheel_account) { create(:pinwheel_account, cbv_flow: cbv_flow) } + let!(:payroll_account) { create(:payroll_account, cbv_flow: cbv_flow) } it "shows continue to report button" do get :show @@ -19,8 +19,8 @@ end end - context "when the user has no successful pinwheel_accounts" do - let!(:pinwheel_account) { create(:pinwheel_account, :with_paystubs_errored, cbv_flow: cbv_flow) } + context "when the user has no successful payroll_accounts" do + let!(:payroll_account) { create(:payroll_account, :with_paystubs_errored, cbv_flow: cbv_flow) } it "shows cta button" do get :show diff --git a/app/spec/controllers/cbv/synchronizations_spec.rb b/app/spec/controllers/cbv/synchronizations_spec.rb index a420d9aa9..8a630ea42 100644 --- a/app/spec/controllers/cbv/synchronizations_spec.rb +++ b/app/spec/controllers/cbv/synchronizations_spec.rb @@ -5,7 +5,7 @@ let(:cbv_flow) { create(:cbv_flow) } - let(:pinwheel_account) { create(:pinwheel_account, cbv_flow: cbv_flow) } + let(:payroll_account) { create(:payroll_account, cbv_flow: cbv_flow) } before do session[:cbv_flow_id] = cbv_flow.id @@ -13,16 +13,16 @@ describe "#update" do it "redirects to the payment details page" do - patch :update, params: { user: { account_id: pinwheel_account.pinwheel_account_id } } + patch :update, params: { user: { account_id: payroll_account.pinwheel_account_id } } - expect(response).to redirect_to(cbv_flow_payment_details_path(user: { account_id: pinwheel_account.pinwheel_account_id })) + expect(response).to redirect_to(cbv_flow_payment_details_path(user: { account_id: payroll_account.pinwheel_account_id })) end context "when the paystubs synchronization fails" do it "redirects to the synchronization failures page" do - pinwheel_account = create(:pinwheel_account, :with_paystubs_errored, cbv_flow: cbv_flow) + payroll_account = create(:payroll_account, :with_paystubs_errored, cbv_flow: cbv_flow) - patch :update, params: { user: { account_id: pinwheel_account.pinwheel_account_id } } + patch :update, params: { user: { account_id: payroll_account.pinwheel_account_id } } expect(response).to redirect_to(cbv_flow_synchronization_failures_path) end diff --git a/app/spec/controllers/webhooks/pinwheel/events_controller_spec.rb b/app/spec/controllers/webhooks/pinwheel/events_controller_spec.rb index 36b2104b6..b76463e14 100644 --- a/app/spec/controllers/webhooks/pinwheel/events_controller_spec.rb +++ b/app/spec/controllers/webhooks/pinwheel/events_controller_spec.rb @@ -60,9 +60,9 @@ expect do post :create, params: valid_params - end.to change(PinwheelAccount, :count).by(1) + end.to change(PayrollAccount, :count).by(1) - pinwheel_account = PinwheelAccount.last + pinwheel_account = PayrollAccount.last expect(pinwheel_account).to have_attributes( cbv_flow_id: cbv_flow.id, supported_jobs: include(*supported_jobs), @@ -78,7 +78,7 @@ it "discards the webhook" do expect do post :create, params: valid_params - end.not_to change(PinwheelAccount, :count) + end.not_to change(PayrollAccount, :count) expect(response).to be_unauthorized end @@ -94,17 +94,17 @@ "outcome" => "success" } end - let(:pinwheel_account) { PinwheelAccount.create!(cbv_flow: cbv_flow, supported_jobs: supported_jobs, pinwheel_account_id: account_id) } + let(:payroll_account) { PayrollAccount.create!(cbv_flow: cbv_flow, supported_jobs: supported_jobs, pinwheel_account_id: account_id) } - it "updates the PinwheelAccount object with the current timestamp" do + it "updates the PayrollAccount object with the current timestamp" do expect { post :create, params: valid_params } - .to change { pinwheel_account.reload.paystubs_synced_at } + .to change { payroll_account.reload.paystubs_synced_at } .from(nil) .to(within(1.second).of(Time.now)) end it "sends events when fully synced" do - pinwheel_account.update( + payroll_account.update( created_at: 5.minutes.ago, employment_synced_at: Time.now, income_synced_at: Time.now, @@ -155,11 +155,11 @@ "outcome" => "pending" } end - let(:pinwheel_account) { PinwheelAccount.create!(cbv_flow: cbv_flow, supported_jobs: supported_jobs, pinwheel_account_id: account_id) } + let(:payroll_account) { PayrollAccount.create!(cbv_flow: cbv_flow, supported_jobs: supported_jobs, pinwheel_account_id: account_id) } - it "updates the PinwheelAccount object with an error state" do + it "updates the PayrollAccount object with an error state" do expect { post :create, params: valid_params } - .to change { pinwheel_account.reload.paystubs_errored_at } + .to change { payroll_account.reload.paystubs_errored_at } .from(nil) .to(within(1.second).of(Time.now)) end diff --git a/app/spec/factories/cbv_flow.rb b/app/spec/factories/cbv_flow.rb index b6550ee26..837311a92 100644 --- a/app/spec/factories/cbv_flow.rb +++ b/app/spec/factories/cbv_flow.rb @@ -18,8 +18,8 @@ end after(:build) do |cbv_flow, evaluator| - cbv_flow.pinwheel_accounts = [ - create(:pinwheel_account, cbv_flow: cbv_flow, supported_jobs: evaluator.supported_jobs, employment_errored_at: evaluator.employment_errored_at) + cbv_flow.payroll_accounts = [ + create(:payroll_account, cbv_flow: cbv_flow, supported_jobs: evaluator.supported_jobs, employment_errored_at: evaluator.employment_errored_at) ] end end diff --git a/app/spec/factories/pinwheel_account.rb b/app/spec/factories/payroll_account.rb similarity index 87% rename from app/spec/factories/pinwheel_account.rb rename to app/spec/factories/payroll_account.rb index 15e358bd4..69b7d49c8 100644 --- a/app/spec/factories/pinwheel_account.rb +++ b/app/spec/factories/payroll_account.rb @@ -1,5 +1,5 @@ FactoryBot.define do - factory :pinwheel_account, class: "PinwheelAccount" do + factory :payroll_account, class: "PayrollAccount" do cbv_flow pinwheel_account_id { SecureRandom.uuid } paystubs_synced_at { DateTime.now } diff --git a/app/spec/helpers/cbv/pinwheel_data_helper_spec.rb b/app/spec/helpers/cbv/pinwheel_data_helper_spec.rb index b84231e44..ea8852867 100644 --- a/app/spec/helpers/cbv/pinwheel_data_helper_spec.rb +++ b/app/spec/helpers/cbv/pinwheel_data_helper_spec.rb @@ -28,12 +28,12 @@ let!(:cbv_flow) { create(:cbv_flow, :with_pinwheel_account) } before do - cbv_flow.pinwheel_accounts.first.update(pinwheel_account_id: account_id) + cbv_flow.payroll_accounts.first.update(pinwheel_account_id: account_id) end describe "aggregate payments" do it "groups by employer" do - summarized = helper.summarize_by_employer(payments, [ employment ], [ incomes ], [ identities ], cbv_flow.pinwheel_accounts) + summarized = helper.summarize_by_employer(payments, [ employment ], [ incomes ], [ identities ], cbv_flow.payroll_accounts) expect(summarized).to be_a(Hash) expect(summarized).to include(account_id) expect(summarized[account_id]).to match(hash_including( diff --git a/app/spec/mailers/caseworker_mailer_spec.rb b/app/spec/mailers/caseworker_mailer_spec.rb index 55081d94f..3d1643e28 100644 --- a/app/spec/mailers/caseworker_mailer_spec.rb +++ b/app/spec/mailers/caseworker_mailer_spec.rb @@ -12,7 +12,7 @@ consented_to_authorized_use_at: Time.now )} let(:caseworker_email) { cbv_flow.cbv_flow_invitation.user.email } - let(:account_id) { cbv_flow.pinwheel_accounts.first.pinwheel_account_id } + let(:account_id) { cbv_flow.payroll_accounts.first.pinwheel_account_id } let(:payments) { stub_payments(account_id) } let(:employments) { stub_employments(account_id) } let(:incomes) { stub_incomes(account_id) } diff --git a/app/spec/mailers/previews/caseworker_mailer_preview.rb b/app/spec/mailers/previews/caseworker_mailer_preview.rb index cb24c4446..244fd2ca0 100644 --- a/app/spec/mailers/previews/caseworker_mailer_preview.rb +++ b/app/spec/mailers/previews/caseworker_mailer_preview.rb @@ -13,10 +13,10 @@ def summary_email :completed, cbv_flow_invitation: invitation ) - payments = stub_post_processed_payments(cbv_flow.pinwheel_accounts.first.pinwheel_account_id) - employments = stub_employments(cbv_flow.pinwheel_accounts.first.pinwheel_account_id) - incomes = stub_incomes(cbv_flow.pinwheel_accounts.first.pinwheel_account_id) - identities = stub_identities(cbv_flow.pinwheel_accounts.first.pinwheel_account_id) + payments = stub_post_processed_payments(cbv_flow.payroll_accounts.first.pinwheel_account_id) + employments = stub_employments(cbv_flow.payroll_accounts.first.pinwheel_account_id) + incomes = stub_incomes(cbv_flow.payroll_accounts.first.pinwheel_account_id) + identities = stub_identities(cbv_flow.payroll_accounts.first.pinwheel_account_id) CaseworkerMailer.with( email_address: invitation.email_address, diff --git a/app/spec/models/pinwheel_account_spec.rb b/app/spec/models/payroll_account_spec.rb similarity index 54% rename from app/spec/models/pinwheel_account_spec.rb rename to app/spec/models/payroll_account_spec.rb index 64f83a9b5..68cbc831b 100644 --- a/app/spec/models/pinwheel_account_spec.rb +++ b/app/spec/models/payroll_account_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -RSpec.describe PinwheelAccount, type: :model do +RSpec.describe PayrollAccount, type: :model do let(:account_id) { SecureRandom.uuid } let(:supported_jobs) { %w[income paystubs employment] } let!(:cbv_flow) { create(:cbv_flow, case_number: "ABC1234", pinwheel_token_id: "abc-def-ghi", client_agency_id: "sandbox") } - let!(:pinwheel_account) do - create(:pinwheel_account, + let!(:payroll_account) do + create(:payroll_account, cbv_flow: cbv_flow, pinwheel_account_id: account_id, supported_jobs: supported_jobs, @@ -21,15 +21,15 @@ describe "#has_fully_synced?" do context "when income is supported" do it "returns true when all are synced" do - pinwheel_account.update!(income_synced_at: Time.current) - expect(pinwheel_account.has_fully_synced?).to be_truthy + payroll_account.update!(income_synced_at: Time.current) + expect(payroll_account.has_fully_synced?).to be_truthy end context "when income_synced_at is nil" do let(:income_synced_at) { nil } it "returns false when income_synced_at is nil" do - expect(pinwheel_account.has_fully_synced?).to be_falsey + expect(payroll_account.has_fully_synced?).to be_falsey end end end @@ -39,7 +39,7 @@ let(:income_synced_at) { nil } it "returns true when income_synced_at is nil" do - expect(pinwheel_account.has_fully_synced?).to be_truthy + expect(payroll_account.has_fully_synced?).to be_truthy end end end @@ -47,27 +47,27 @@ describe "#job_succeeded?" do context "when job is supported" do it "returns false when income is supported but not yet synced" do - pinwheel_account.update!(income_synced_at: nil) - expect(pinwheel_account.job_succeeded?('income')).to be_falsey + payroll_account.update!(income_synced_at: nil) + expect(payroll_account.job_succeeded?('income')).to be_falsey end it "returns true when income is supported and it succeeded" do - pinwheel_account.update!(income_synced_at: Time.current) - expect(pinwheel_account.job_succeeded?('income')).to be_truthy + payroll_account.update!(income_synced_at: Time.current) + expect(payroll_account.job_succeeded?('income')).to be_truthy end end context "when job is supported but it errored out" do it "returns false when income is supported but it errored out" do - pinwheel_account.update!(income_synced_at: Time.current) - pinwheel_account.update!(income_errored_at: Time.current) - expect(pinwheel_account.job_succeeded?('income')).to be_falsey + payroll_account.update!(income_synced_at: Time.current) + payroll_account.update!(income_errored_at: Time.current) + expect(payroll_account.job_succeeded?('income')).to be_falsey end it "returns false when employment is supported but it errored out" do - pinwheel_account.update!(employment_synced_at: Time.current) - pinwheel_account.update!(employment_errored_at: Time.current) - expect(pinwheel_account.job_succeeded?('employment')).to be_falsey + payroll_account.update!(employment_synced_at: Time.current) + payroll_account.update!(employment_errored_at: Time.current) + expect(payroll_account.job_succeeded?('employment')).to be_falsey end end end @@ -75,29 +75,29 @@ 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) + payroll_account.update!(income_synced_at: Time.current) + expect(payroll_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) + payroll_account.update!(income_synced_at: Time.current, income_errored_at: Time.current) + expect(payroll_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) + payroll_account.update!(income_synced_at: nil, income_errored_at: nil) + expect(payroll_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) + payroll_account.update!(supported_jobs: supported_jobs.reject { |job| job == 'income' }) + expect(payroll_account.synchronization_status('income')).to eq(:unsupported) end end end diff --git a/app/spec/services/pdf_service_spec.rb b/app/spec/services/pdf_service_spec.rb index 2c3a4eafa..f6e7436ee 100644 --- a/app/spec/services/pdf_service_spec.rb +++ b/app/spec/services/pdf_service_spec.rb @@ -16,12 +16,12 @@ cbv_flow_invitation: invitation ) end - let(:account_id) { cbv_flow.pinwheel_accounts.first.pinwheel_account_id } + let(:account_id) { cbv_flow.payroll_accounts.first.pinwheel_account_id } let(:payments) { stub_payments(account_id) } let(:employments) { stub_employments(account_id) } let(:incomes) { stub_incomes(account_id) } let(:identities) { stub_identities(account_id) } - let(:payments_grouped_by_employer) { summarize_by_employer(payments, employments, incomes, identities, cbv_flow.pinwheel_accounts) } + let(:payments_grouped_by_employer) { summarize_by_employer(payments, employments, incomes, identities, cbv_flow.payroll_accounts) } let(:variables) do { is_caseworker: true, @@ -37,7 +37,7 @@ let(:ma_user) { create(:user, email: "test@example.com", client_agency_id: 'ma') } before do - cbv_flow.pinwheel_accounts.first.update(pinwheel_account_id: "03e29160-f7e7-4a28-b2d8-813640e030d3") + cbv_flow.payroll_accounts.first.update(pinwheel_account_id: "03e29160-f7e7-4a28-b2d8-813640e030d3") end describe "#generate" do diff --git a/docs/app/rendered/database-schema.pdf b/docs/app/rendered/database-schema.pdf index 7a5cb52da82faab6efddc8edd3e6db28387ffd5a..3c89a99369ccea082e4df38a775a1c7bc88165e0 100644 GIT binary patch delta 10900 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 delta 11852 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 GPeux_G5VSS