From 38ccacb06335353715ac72a92e3efd8f327171b0 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Mon, 23 Mar 2026 13:22:46 -0400 Subject: [PATCH 1/3] Enhance application cost calculations to include subscription fees Updated the Application model to incorporate subscription costs in total cost and balance due calculations. Refactored the PaymentsController and ActiveAdmin views to utilize the new total_cost method, ensuring consistent handling of subscription scenarios across the application. Added tests to verify correct computation of total costs when subscriptions are selected. --- app/admin/applications.rb | 12 ++---------- app/controllers/applications_controller.rb | 4 +--- app/controllers/payments_controller.rb | 12 +++--------- app/models/application.rb | 10 ++++++++-- spec/models/application_spec.rb | 18 ++++++++++++++++++ 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/admin/applications.rb b/app/admin/applications.rb index 34b61df..55158b8 100644 --- a/app/admin/applications.rb +++ b/app/admin/applications.rb @@ -81,14 +81,10 @@ def load_index_batch_data show do ttl_paid = Payment.where(user_id: application.user_id, conf_year: application.conf_year, transaction_status: '1').pluck(:total_amount).map(&:to_f).sum / 100 - cost_lodging = Lodging.find_by(description: application.lodging_selection).cost.to_f if application.partner_registration.nil? raise "Partner registration is missing for this application (id=#{application.id}); cannot compute balance. Fix data and retry." end - cost_partner = application.partner_registration.cost.to_f - has_subscription = application.subscription - cost_subscription = ApplicationSetting.get_current_app_settings&.subscription_cost.to_f - total_cost = cost_lodging + cost_partner + (has_subscription ? cost_subscription : 0) + total_cost = application.total_cost balance_due = total_cost - ttl_paid panel "Payment Activity -- [Balance Due: #{number_to_currency(balance_due)} Total Cost: #{number_to_currency(total_cost)}]" do table_for application.user.payments.where(conf_year: application.conf_year) do @@ -193,11 +189,7 @@ def load_index_batch_data raise "Application #{application.id}: partner_registration is missing; cannot compute balance for CSV export." end ttl_paid = Payment.current_conference_payments.where(user_id: application.user_id, transaction_status: '1').pluck(:total_amount).map(&:to_f).sum / 100 - cost_lodging = Lodging.find_by(description: application.lodging_selection).cost.to_f - cost_partner = application.partner_registration.cost.to_f - has_subscription = application.subscription - cost_subscription = ApplicationSetting.get_current_app_settings&.subscription_cost.to_f - total_cost = cost_lodging + cost_partner + (has_subscription ? cost_subscription : 0) + total_cost = application.total_cost balance_due = total_cost - ttl_paid number_to_currency(balance_due) end diff --git a/app/controllers/applications_controller.rb b/app/controllers/applications_controller.rb index ec2d552..f49c43f 100644 --- a/app/controllers/applications_controller.rb +++ b/app/controllers/applications_controller.rb @@ -16,9 +16,7 @@ def index # GET /applications/1 # GET /applications/1.json def show - cost_lodging = Lodging.find_by(description: @application.lodging_selection).cost.to_f - cost_partner = @application.partner_registration.cost.to_f - @total_cost = cost_lodging + cost_partner + @total_cost = @application.total_cost end # GET /applications/new diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index 8e13430..bf50f69 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -57,11 +57,9 @@ def payment_show redirect_to root_url unless user_has_payments?(current_user) @users_current_payments = Payment.current_conference_payments.where(user_id: current_user ) @ttl_paid = Payment.current_conference_payments.where(user_id: current_user, transaction_status: '1').pluck(:total_amount).map(&:to_f).sum / 100 - cost_lodging = Lodging.find_by(description: @current_application.lodging_selection).cost.to_f - cost_partner = @current_application.partner_registration.cost.to_f @has_subscription = @current_application.subscription - @cost_subscription = current_application_settings.subscription_cost.to_f - @total_cost = cost_lodging + cost_partner + (@has_subscription ? @cost_subscription : 0) + @cost_subscription = @current_application.subscription_cost + @total_cost = @current_application.total_cost @balance_due = @total_cost - @ttl_paid @max_payment_amount = max_payment_amount_for(@balance_due) end @@ -145,11 +143,7 @@ def current_balance_due current_application return 0.0 if @current_application.nil? - cost_lodging = Lodging.find_by(description: @current_application.lodging_selection)&.cost.to_f - cost_partner = @current_application.partner_registration&.cost.to_f - has_subscription = @current_application.subscription - cost_subscription = current_application_settings.subscription_cost.to_f - total_cost = cost_lodging + cost_partner + (has_subscription ? cost_subscription : 0) + total_cost = @current_application.total_cost total_paid = Payment.current_conference_payments.where(user_id: current_user, transaction_status: '1').pluck(:total_amount).map(&:to_f).sum / 100 total_cost - total_paid end diff --git a/app/models/application.rb b/app/models/application.rb index f1424c1..2bf0bab 100644 --- a/app/models/application.rb +++ b/app/models/application.rb @@ -99,8 +99,14 @@ def partner_registration_cost self.partner_registration.cost.to_f end + def subscription_cost + return 0.0 unless subscription + + ApplicationSetting.get_current_app_settings&.subscription_cost.to_f + end + def total_cost - lodging_cost + partner_registration_cost + lodging_cost + partner_registration_cost + subscription_cost end def balance_due @@ -119,7 +125,7 @@ def balance_due_with_batch(payments_totals:, lodgings_by_desc:) ttl_paid_dollars = ttl_paid_cents / 100 cost_lodging = lodging.cost.to_f cost_partner = partner_registration.cost.to_f - total_cost = cost_lodging + cost_partner + total_cost = cost_lodging + cost_partner + subscription_cost (total_cost - ttl_paid_dollars).round(2) end diff --git a/spec/models/application_spec.rb b/spec/models/application_spec.rb index 97c4c43..ca5265b 100644 --- a/spec/models/application_spec.rb +++ b/spec/models/application_spec.rb @@ -179,8 +179,16 @@ it 'returns the sum of lodging and partner registration costs' do allow(application).to receive(:lodging_cost).and_return(100.0) allow(application).to receive(:partner_registration_cost).and_return(50.0) + allow(application).to receive(:subscription_cost).and_return(0.0) expect(application.total_cost).to eq(150.0) end + + it 'includes subscription cost when subscription is selected' do + allow(application).to receive(:lodging_cost).and_return(100.0) + allow(application).to receive(:partner_registration_cost).and_return(50.0) + allow(application).to receive(:subscription_cost).and_return(25.0) + expect(application.total_cost).to eq(175.0) + end end describe '#balance_due' do @@ -211,11 +219,21 @@ it 'returns negative balance when paid exceeds total cost (overpayment)' do app = build(:application, user_id: 100, conf_year: 2026, lodging_selection: 'Standard') allow(app).to receive(:partner_registration).and_return(double('PartnerRegistration', cost: 50.0)) + allow(app).to receive(:subscription_cost).and_return(0.0) payments_totals = { [100, 2026] => 20_000 } # $200 in cents lodgings_by_desc = { 'Standard' => double('Lodging', cost: 100.0) } expect(app.balance_due_with_batch(payments_totals: payments_totals, lodgings_by_desc: lodgings_by_desc)).to eq(-50.0) end + it 'includes subscription cost when computing balance' do + app = build(:application, user_id: 100, conf_year: 2026, lodging_selection: 'Standard', subscription: true) + allow(app).to receive(:partner_registration).and_return(double('PartnerRegistration', cost: 50.0)) + allow(app).to receive(:subscription_cost).and_return(25.0) + payments_totals = { [100, 2026] => 10_000 } # $100 in cents + lodgings_by_desc = { 'Standard' => double('Lodging', cost: 100.0) } + expect(app.balance_due_with_batch(payments_totals: payments_totals, lodgings_by_desc: lodgings_by_desc)).to eq(75.0) + end + it 'raises when partner_registration is missing (do not treat as $0)' do app = build(:application, user_id: 100, conf_year: 2026, lodging_selection: 'Unknown') allow(app).to receive(:partner_registration).and_return(nil) From cc11d228dd260ce6aab589f8b3891c4e1f1ff4be Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Mon, 23 Mar 2026 13:33:09 -0400 Subject: [PATCH 2/3] Add tests for subscription cost calculations in Application model Implemented new test cases for the `subscription_cost` method in the Application model to ensure accurate cost calculations based on subscription selection. The tests cover scenarios for unselected subscriptions, selected subscriptions with configured costs, and cases with missing settings. This enhances the overall test coverage for application cost calculations. --- spec/models/application_spec.rb | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/spec/models/application_spec.rb b/spec/models/application_spec.rb index ca5265b..2079bc1 100644 --- a/spec/models/application_spec.rb +++ b/spec/models/application_spec.rb @@ -175,18 +175,47 @@ end end + describe '#subscription_cost' do + it 'returns 0.0 when subscription is not selected' do + application.subscription = false + allow(ApplicationSetting).to receive(:get_current_app_settings) + + expect(application.subscription_cost).to eq(0.0) + expect(ApplicationSetting).not_to have_received(:get_current_app_settings) + end + + it 'returns the configured subscription cost when subscription is selected' do + application.subscription = true + mock_app_setting = double('ApplicationSetting', subscription_cost: 25.0) + allow(ApplicationSetting).to receive(:get_current_app_settings).and_return(mock_app_setting) + + expect(application.subscription_cost).to eq(25.0) + end + + it 'returns 0.0 when settings are missing' do + application.subscription = true + allow(ApplicationSetting).to receive(:get_current_app_settings).and_return(nil) + + expect(application.subscription_cost).to eq(0.0) + end + end + describe '#total_cost' do it 'returns the sum of lodging and partner registration costs' do + application.subscription = false allow(application).to receive(:lodging_cost).and_return(100.0) allow(application).to receive(:partner_registration_cost).and_return(50.0) - allow(application).to receive(:subscription_cost).and_return(0.0) + allow(ApplicationSetting).to receive(:get_current_app_settings) expect(application.total_cost).to eq(150.0) + expect(ApplicationSetting).not_to have_received(:get_current_app_settings) end it 'includes subscription cost when subscription is selected' do + application.subscription = true allow(application).to receive(:lodging_cost).and_return(100.0) allow(application).to receive(:partner_registration_cost).and_return(50.0) - allow(application).to receive(:subscription_cost).and_return(25.0) + mock_app_setting = double('ApplicationSetting', subscription_cost: 25.0) + allow(ApplicationSetting).to receive(:get_current_app_settings).and_return(mock_app_setting) expect(application.total_cost).to eq(175.0) end end From d03fdaecd6e90d751dd5c6289f54c0d1252bc25a Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Mon, 23 Mar 2026 13:34:19 -0400 Subject: [PATCH 3/3] Improve error handling in total cost calculation in PaymentsController Updated the `total_cost` method in the PaymentsController to handle potential errors when computing the total cost for applications. Added logging for exceptions to aid in debugging, ensuring that the method returns a default value of 0.0 in case of errors. This enhancement improves the robustness of payment calculations. --- app/controllers/payments_controller.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index bf50f69..de60361 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -143,7 +143,13 @@ def current_balance_due current_application return 0.0 if @current_application.nil? - total_cost = @current_application.total_cost + total_cost = begin + @current_application.total_cost + rescue StandardError => e + Rails.logger.error("Error computing total_cost for application #{@current_application.id}: #{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + 0.0 + end + total_cost = total_cost.to_f total_paid = Payment.current_conference_payments.where(user_id: current_user, transaction_status: '1').pluck(:total_amount).map(&:to_f).sum / 100 total_cost - total_paid end