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..de60361 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,13 @@ 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 = 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 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..2079bc1 100644 --- a/spec/models/application_spec.rb +++ b/spec/models/application_spec.rb @@ -175,11 +175,48 @@ 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(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) + 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 @@ -211,11 +248,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)