From bd132ce477ecfe272d1415112e3b0b66a5a68e99 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 4 Jan 2025 12:01:34 +0530 Subject: [PATCH] Store country band details in database --- app/controllers/country_bands_controller.rb | 2 +- app/models/country_band.rb | 39 +---------------- app/models/country_band_detail.rb | 6 +++ app/views/country_bands/_show_band.html.erb | 8 ++-- app/views/country_bands/index.html.erb | 4 +- ...41225030959_create_country_band_details.rb | 14 +++++++ ...225031242_populate_country_band_details.rb | 42 +++++++++++++++++++ db/schema.rb | 12 +++++- lib/dues_calculator.rb | 10 +++-- 9 files changed, 87 insertions(+), 50 deletions(-) create mode 100644 app/models/country_band_detail.rb create mode 100644 db/migrate/20241225030959_create_country_band_details.rb create mode 100644 db/migrate/20241225031242_populate_country_band_details.rb diff --git a/app/controllers/country_bands_controller.rb b/app/controllers/country_bands_controller.rb index 1ba7f09fc3..6ea3937743 100644 --- a/app/controllers/country_bands_controller.rb +++ b/app/controllers/country_bands_controller.rb @@ -10,7 +10,7 @@ def index def edit @number = id_from_params - unless CountryBand::BANDS.keys.include?(@number) + unless CountryBandDetail.distinct.pluck(:number).include?(@number) flash[:danger] = "Unknown band number" return redirect_to country_bands_path end diff --git a/app/models/country_band.rb b/app/models/country_band.rb index 1e713a972a..43d10915a9 100644 --- a/app/models/country_band.rb +++ b/app/models/country_band.rb @@ -1,46 +1,9 @@ # frozen_string_literal: true class CountryBand < ApplicationRecord - BANDS = { - 0 => { - value: 0.00, - }, - 1 => { - value: 0.19, - }, - 2 => { - value: 0.32, - }, - 3 => { - value: 0.45, - }, - 4 => { - value: 2.28, - }, - 5 => { - value: 3.00, - }, - }.freeze - - # According to WCA's current dues policy, the due amount per competitor is equivalent - # to this percent of registration fee. Only used if this due amount per competitor is - # larger than the due amount per competitor calculated from the competition's country band. - PERCENT_REGISTRATION_FEE_USED_FOR_DUE_AMOUNT = 0.15 - - def self.percent_registration_fee_used_for_due_amount(country_band) - return 0 if country_band.nil? - if country_band >= 3 - 0.15 - elsif country_band >= 1 - 0.05 - else - 0.00 - end - end - belongs_to :country, foreign_key: :iso2, primary_key: :iso2 + belongs_to :country_band_detail, foreign_key: :number, primary_key: :number validates_inclusion_of :iso2, in: Country::WCA_COUNTRY_ISO_CODES - validates_inclusion_of :number, in: BANDS.keys.freeze def country Country.find_by_iso2(self.iso2) diff --git a/app/models/country_band_detail.rb b/app/models/country_band_detail.rb new file mode 100644 index 0000000000..efd46e25a2 --- /dev/null +++ b/app/models/country_band_detail.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class CountryBandDetail < ApplicationRecord + scope :active, -> { where(end_date: nil).or(inactive.invert_where) } + scope :inactive, -> { where(end_date: ..Date.today) } +end diff --git a/app/views/country_bands/_show_band.html.erb b/app/views/country_bands/_show_band.html.erb index ec25489639..ca800f0da2 100644 --- a/app/views/country_bands/_show_band.html.erb +++ b/app/views/country_bands/_show_band.html.erb @@ -1,12 +1,12 @@
- <%= t("country_bands.band_title", number: number) %> - (<%= t("country_bands.due_value", value: data[:value]) %>) + <%= t("country_bands.band_title", number: country_band_detail.number) %> + (<%= t("country_bands.due_value", value: country_band_detail.due_amount_per_competitor_in_cents.to_f / 100) %>) <% if current_user&.can_admin_finances? %> - <%= link_to(ui_icon("pencil alt"), edit_country_band_path(id: number)) %> + <%= link_to(ui_icon("pencil alt"), edit_country_band_path(id: country_band_detail.number)) %> <% end %>
- <% (@country_bands_by_number[number] || []).map(&:country).sort_by(&:name).each do |c| %> + <% (@country_bands_by_number[country_band_detail.number] || []).map(&:country).sort_by(&:name).each do |c| %>
<%= flag_icon c.iso2 %>
diff --git a/app/views/country_bands/index.html.erb b/app/views/country_bands/index.html.erb index 395439736a..3bb3eeb37d 100644 --- a/app/views/country_bands/index.html.erb +++ b/app/views/country_bands/index.html.erb @@ -14,8 +14,8 @@
- <% CountryBand::BANDS.each do |number, data| %> - <%= render "show_band", number: number, data: data %> + <% CountryBandDetail.active.order(:number).each do |country_band_detail| %> + <%= render "show_band", country_band_detail: country_band_detail %> <% end %>
diff --git a/db/migrate/20241225030959_create_country_band_details.rb b/db/migrate/20241225030959_create_country_band_details.rb new file mode 100644 index 0000000000..ad16e10257 --- /dev/null +++ b/db/migrate/20241225030959_create_country_band_details.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class CreateCountryBandDetails < ActiveRecord::Migration[7.2] + def change + create_table :country_band_details do |t| + t.integer "number", null: false + t.date "start_date", null: false + t.date "end_date" + t.integer "due_amount_per_competitor_in_cents", null: false + t.integer "due_percent_registration_fee", null: false + t.timestamps + end + end +end diff --git a/db/migrate/20241225031242_populate_country_band_details.rb b/db/migrate/20241225031242_populate_country_band_details.rb new file mode 100644 index 0000000000..f87ce794eb --- /dev/null +++ b/db/migrate/20241225031242_populate_country_band_details.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class PopulateCountryBandDetails < ActiveRecord::Migration[7.2] + def change + CountryBandDetail.create!( + number: 0, + start_date: '2018-01-01', + due_amount_per_competitor_in_cents: 0, + due_percent_registration_fee: 0, + ) + CountryBandDetail.create!( + number: 1, + start_date: '2018-01-01', + due_amount_per_competitor_in_cents: 19, + due_percent_registration_fee: 5, + ) + CountryBandDetail.create!( + number: 2, + start_date: '2018-01-01', + due_amount_per_competitor_in_cents: 32, + due_percent_registration_fee: 5, + ) + CountryBandDetail.create!( + number: 3, + start_date: '2018-01-01', + due_amount_per_competitor_in_cents: 45, + due_percent_registration_fee: 15, + ) + CountryBandDetail.create!( + number: 4, + start_date: '2018-01-01', + due_amount_per_competitor_in_cents: 228, + due_percent_registration_fee: 15, + ) + CountryBandDetail.create!( + number: 5, + start_date: '2018-01-01', + due_amount_per_competitor_in_cents: 300, + due_percent_registration_fee: 15, + ) + end +end diff --git a/db/schema.rb b/db/schema.rb index 76cf2d624c..cde87543bf 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_11_24_050607) do +ActiveRecord::Schema[7.2].define(version: 2024_12_25_031242) do create_table "Competitions", id: { type: :string, limit: 32, default: "" }, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.string "name", limit: 50, default: "", null: false t.string "cityName", limit: 50, default: "", null: false @@ -665,6 +665,16 @@ t.datetime "updated_at", null: false end + create_table "country_band_details", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| + t.integer "number", null: false + t.date "start_date", null: false + t.date "end_date" + t.integer "due_amount_per_competitor_in_cents", null: false + t.integer "due_percent_registration_fee", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "country_bands", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.integer "number", null: false t.string "iso2", limit: 2, null: false diff --git a/lib/dues_calculator.rb b/lib/dues_calculator.rb index 536d807c6f..5d4b381be7 100644 --- a/lib/dues_calculator.rb +++ b/lib/dues_calculator.rb @@ -24,10 +24,12 @@ def self.dues_per_competitor_in_usd(country_iso2, base_entry_fee_lowest_denomina DuesCalculator.update_exchange_rates_if_needed input_money_us_dollars = Money.new(base_entry_fee_lowest_denomination, currency_code).exchange_to("USD") - registration_fee_dues_us_dollars = input_money_us_dollars * CountryBand.percent_registration_fee_used_for_due_amount(country_band) - country_band_dues_us_dollars = country_band.present? && country_band > 0 ? CountryBand::BANDS[country_band][:value] : 0 - # times 100 because Money require lowest currency subunit, which is cents for USD - country_band_dues_us_dollars_money = Money.new(country_band_dues_us_dollars * 100, "USD") + country_band_detail = CountryBandDetail.find_by(number: country_band) + return nil unless country_band_detail + + registration_fee_dues_us_dollars = input_money_us_dollars * country_band_detail.due_percent_registration_fee.to_f/100 + # cent is given directly because Money require lowest currency subunit, which is cents for USD + country_band_dues_us_dollars_money = Money.new(country_band_detail.due_amount_per_competitor_in_cents, "USD") [registration_fee_dues_us_dollars, country_band_dues_us_dollars_money].max rescue Money::Currency::UnknownCurrency, CurrencyUnavailable