diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ab78ffee..8f792d961 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Ask for confirmation before booking a slot for a member without the required tag - Corrected the documentation about BOOK_SLOT_AT_SAME_TIME - Auto-adjusts text colors based on the selected theme colors +- Fix a bug: accounting periods totals are wrong for periods closed after 2019-08-01 - Fix a bug: unable to change group if the previous was deactivated - Fix a bug: unable to create events or trainings that are not multiples of SLOT_DURATION - Fix a bug: unable to delete an unreserved event @@ -19,6 +20,7 @@ - Fix a bug: background image of the profile is not shown and wrong menu hover color - Fix a bug: do not show disabled groups and plans during availability creation - Fix a security issue: updated jquery to fix [CVE-2020-11023](https://nvd.nist.gov/vuln/detail/CVE-2020-11023) +- [TODO DEPLOY] `rails db:migrate` ## v4.3.4 2020 April 14 diff --git a/app/models/accounting_period.rb b/app/models/accounting_period.rb index 5402781f9..4a5824221 100644 --- a/app/models/accounting_period.rb +++ b/app/models/accounting_period.rb @@ -30,7 +30,7 @@ class AccountingPeriod < ApplicationRecord def invoices_with_vat(invoices) vat_service = VatHistoryService.new invoices.map do |i| - { invoice: i, vat_rate: vat_service.invoice_vat(i) } + { invoice: i, vat_rate: vat_service.invoice_vat(i) / 100.0 } end end diff --git a/app/services/vat_history_service.rb b/app/services/vat_history_service.rb index 8ced7b37c..4c03cfe71 100644 --- a/app/services/vat_history_service.rb +++ b/app/services/vat_history_service.rb @@ -11,7 +11,7 @@ class VatHistoryService end end - # return the VAT rate foe the given date + # return the VAT rate for the given date def vat_rate(date) @vat_rates = vat_history if @vat_rates.nil? diff --git a/db/migrate/20190522115230_migrate_invoice_to_invoicing_profile.rb b/db/migrate/20190522115230_migrate_invoice_to_invoicing_profile.rb index 3fb3ccd63..b99519b52 100644 --- a/db/migrate/20190522115230_migrate_invoice_to_invoicing_profile.rb +++ b/db/migrate/20190522115230_migrate_invoice_to_invoicing_profile.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true # migrate the invoices from being attached to a user to invoicing_profiles which are GDPR compliant -# frozen_string_literal:true - class MigrateInvoiceToInvoicingProfile < ActiveRecord::Migration[4.2] def up # first, check the footprints diff --git a/db/migrate/20200511075933_fix_accounting_periods.rb b/db/migrate/20200511075933_fix_accounting_periods.rb new file mode 100644 index 000000000..87f21a6fc --- /dev/null +++ b/db/migrate/20200511075933_fix_accounting_periods.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +# regenerate the accounting periods affected by the current bug (period totals are wrong due to wrong VAT computation) +class FixAccountingPeriods < ActiveRecord::Migration[5.2] + def change + # first, check the footprints + check_footprints + + # if everything is ok, proceed with migration + # remove periods (backup their parameters in memory) + periods = backup_and_remove_periods + # recreate periods from memory dump + restore_periods(periods) + end + + def check_footprints + if AccountingPeriod.count.positive? + last_period = AccountingPeriod.order(start_at: :desc).first + puts "Checking invoices footprints from #{last_period.end_at}. This may take a while..." + Invoice.where('created_at > ?', last_period.end_at).order(:id).each do |i| + raise "Invalid footprint for invoice #{i.id}" unless i.check_footprint + end + else + puts 'Checking all invoices footprints. This may take a while...' + Invoice.order(:id).all.each do |i| + raise "Invalid footprint for invoice #{i.id}" unless i.check_footprint + end + end + end + + # will return an array of hash containing the removed periods data + def backup_and_remove_periods + return [] unless AccountingPeriod.where("created_at > '2019-08-01'").count.positive? + + puts 'Removing erroneous accounting archives...' + # 1. remove protection for AccountingPeriods + execute("DROP RULE IF EXISTS accounting_periods_del_protect ON #{AccountingPeriod.arel_table.name};") + # 2. backup AccountingPeriods in memory + periods = [] + AccountingPeriod.where("created_at > '2019-08-01'").each do |p| + periods.push( + start_at: p.start_at, + end_at: p.end_at, + closed_at: p.closed_at, + closed_by: p.closed_by + ) + end + # 3. Delete periods from database + AccountingPeriod.where("created_at > '2019-08-01'").each do |ap| + execute("DELETE FROM accounting_periods WHERE ID=#{ap.id};") + end + periods + end + + def restore_periods(periods) + return unless periods.size.positive? + + # 1. recreate AccountingPeriods + puts 'Recreating accounting archives. This may take a while...' + periods.each do |p| + AccountingPeriod.create!( + start_at: p[:start_at], + end_at: p[:end_at], + closed_at: p[:closed_at], + closed_by: p[:closed_by] + ) + end + # 2. reset protection for AccountingPeriods + execute("CREATE RULE accounting_periods_del_protect AS ON DELETE TO #{AccountingPeriod.arel_table.name} DO INSTEAD NOTHING;") + end + +end diff --git a/db/schema.rb b/db/schema.rb index cbd50fd4a..b86050026 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.define(version: 2020_04_15_141809) do +ActiveRecord::Schema.define(version: 2020_05_11_075933) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -18,8 +18,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do enable_extension "unaccent" create_table "abuses", id: :serial, force: :cascade do |t| - t.string "signaled_type" t.integer "signaled_id" + t.string "signaled_type" t.string "first_name" t.string "last_name" t.string "email" @@ -48,8 +48,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do t.string "locality" t.string "country" t.string "postal_code" - t.string "placeable_type" t.integer "placeable_id" + t.string "placeable_type" t.datetime "created_at" t.datetime "updated_at" end @@ -63,8 +63,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do end create_table "assets", id: :serial, force: :cascade do |t| - t.string "viewable_type" t.integer "viewable_id" + t.string "viewable_type" t.string "attachment" t.string "type" t.datetime "created_at" @@ -132,8 +132,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do end create_table "credits", id: :serial, force: :cascade do |t| - t.string "creditable_type" t.integer "creditable_id" + t.string "creditable_type" t.integer "plan_id" t.integer "hours" t.datetime "created_at" @@ -285,8 +285,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do end create_table "invoices", id: :serial, force: :cascade do |t| - t.string "invoiced_type" t.integer "invoiced_id" + t.string "invoiced_type" t.string "stp_invoice_id" t.integer "total" t.datetime "created_at" @@ -349,15 +349,15 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do create_table "notifications", id: :serial, force: :cascade do |t| t.integer "receiver_id" - t.string "attached_object_type" t.integer "attached_object_id" + t.string "attached_object_type" t.integer "notification_type_id" t.boolean "is_read", default: false t.datetime "created_at" t.datetime "updated_at" t.string "receiver_type" t.boolean "is_send", default: false - t.jsonb "meta_data", default: "{}" + t.jsonb "meta_data", default: {} t.index ["notification_type_id"], name: "index_notifications_on_notification_type_id" t.index ["receiver_id"], name: "index_notifications_on_receiver_id" end @@ -457,8 +457,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do create_table "prices", id: :serial, force: :cascade do |t| t.integer "group_id" t.integer "plan_id" - t.string "priceable_type" t.integer "priceable_id" + t.string "priceable_type" t.integer "amount" t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -565,8 +565,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do t.text "message" t.datetime "created_at" t.datetime "updated_at" - t.string "reservable_type" t.integer "reservable_id" + t.string "reservable_type" t.integer "nb_reserve_places" t.integer "statistic_profile_id" t.index ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id" @@ -575,8 +575,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do create_table "roles", id: :serial, force: :cascade do |t| t.string "name" - t.string "resource_type" t.integer "resource_id" + t.string "resource_type" t.datetime "created_at" t.datetime "updated_at" t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" @@ -867,8 +867,8 @@ ActiveRecord::Schema.define(version: 2020_04_15_141809) do create_table "wallet_transactions", id: :serial, force: :cascade do |t| t.integer "wallet_id" - t.string "transactable_type" t.integer "transactable_id" + t.string "transactable_type" t.string "transaction_type" t.integer "amount" t.datetime "created_at", null: false