diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb index 32bf2a716..7cd24183c 100644 --- a/app/models/validations/sales/sale_information_validations.rb +++ b/app/models/validations/sales/sale_information_validations.rb @@ -42,7 +42,7 @@ module Validations::Sales::SaleInformationValidations record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_after_1980") end - if record.saledate.present? && record.initialpurchase > record.saledate + if record.saledate.present? && ((record.initialpurchase > record.saledate) || (record.initialpurchase == record.saledate && record.form.start_year_2026_or_later?)) record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate") record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date") end @@ -55,11 +55,11 @@ module Validations::Sales::SaleInformationValidations record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_1980") end - if record.saledate.present? && record.lasttransaction > record.saledate + if record.saledate.present? && ((record.lasttransaction > record.saledate) || (record.lasttransaction == record.saledate && record.form.start_year_2026_or_later?)) record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate") record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date") end - if record.initialpurchase.present? && record.lasttransaction < record.initialpurchase + if record.initialpurchase.present? && ((record.lasttransaction < record.initialpurchase) || (record.lasttransaction == record.initialpurchase && record.form.start_year_2026_or_later?)) record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction") record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase") end diff --git a/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake new file mode 100644 index 000000000..11ff853a1 --- /dev/null +++ b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake @@ -0,0 +1,15 @@ +desc "We tightened the validation between initial purchase date in 2026, last transaction date and sale date so the two can no longer be equal. To avoid invalid logs we clear initialpurchase if it equals saledate and if initialpurchase = lasttransaction we clear both" +task fix_sales_logs_with_invalid_initialpurchase_lasttransaction: :environment do + initial_purchase_equal_lasttransaction_logs = SalesLog.filter_by_year_or_later(2026).where("initialpurchase = lasttransaction") + lasttransaction_equal_saledate_logs = SalesLog.filter_by_year_or_later(2026).where("lasttransaction = saledate") + + # this one must happen first since this will always result in a log that passes date validations + puts "Updating #{initial_purchase_equal_lasttransaction_logs.count} logs where initialpurchase = lasttransaction, #{initial_purchase_equal_lasttransaction_logs.map(&:id)}" + initial_purchase_equal_lasttransaction_logs.update!(initialpurchase: nil, lasttransaction: nil) + + # this one could fail if lasttransaction == saledate == initialpurchase, but the above case will have already reset these logs + puts "Updating #{lasttransaction_equal_saledate_logs.count} logs where lasttransaction = saledate, #{lasttransaction_equal_saledate_logs.map(&:id)}" + lasttransaction_equal_saledate_logs.update!(lasttransaction: nil) + + puts "Done" +end diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index 8d4eb4cea..04f71b198 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -252,12 +252,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end context "when initial purchase date == saledate" do - let(:record) { build(:sales_log, initialpurchase: current_collection_start_date, saledate: current_collection_start_date) } + let(:record) { build(:sales_log, initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) } - it "does not add an error" do - sale_information_validator.validate_staircasing_initial_purchase_date(record) + context "and 2025", metadata: { year: 25 } do + let(:start_year) { 2025 } - expect(record.errors[:initialpurchase]).not_to be_present + it "does not add an error" do + sale_information_validator.validate_staircasing_initial_purchase_date(record) + + expect(record.errors[:lasttransaction]).not_to be_present + end + end + + context "and 2026", metadata: { year: 26 } do + let(:start_year) { 2026 } + + it "adds error" do + sale_information_validator.validate_staircasing_initial_purchase_date(record) + + expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")]) + expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")]) + end end end end @@ -315,12 +330,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end context "when last transaction date == saledate" do - let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, saledate: current_collection_start_date) } + let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) } - it "does not add an error" do - sale_information_validator.validate_staircasing_last_transaction_date(record) + context "and 2025", metadata: { year: 25 } do + let(:start_year) { 2025 } - expect(record.errors[:lasttransaction]).not_to be_present + it "does not add an error" do + sale_information_validator.validate_staircasing_last_transaction_date(record) + + expect(record.errors[:lasttransaction]).not_to be_present + end + end + + context "and 2026", metadata: { year: 26 } do + let(:start_year) { 2026 } + + it "adds error" do + sale_information_validator.validate_staircasing_last_transaction_date(record) + + expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")]) + expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")]) + end end end @@ -346,12 +376,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end context "when last transaction date == initial purchase date" do - let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, initialpurchase: current_collection_start_date) } + let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year) + 1.day) } - it "does not add an error" do - sale_information_validator.validate_staircasing_last_transaction_date(record) + context "and 2025", metadata: { year: 25 } do + let(:start_year) { 2025 } - expect(record.errors[:lasttransaction]).not_to be_present + it "does not add an error" do + sale_information_validator.validate_staircasing_last_transaction_date(record) + + expect(record.errors[:lasttransaction]).not_to be_present + end + end + + context "and 2026", metadata: { year: 26 } do + let(:start_year) { 2026 } + + it "adds error" do + sale_information_validator.validate_staircasing_last_transaction_date(record) + + expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")]) + expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")]) + end end end end