diff --git a/app/services/bulk_upload/sales/year2026/row_parser.rb b/app/services/bulk_upload/sales/year2026/row_parser.rb index c686fee44..bdb4f5282 100644 --- a/app/services/bulk_upload/sales/year2026/row_parser.rb +++ b/app/services/bulk_upload/sales/year2026/row_parser.rb @@ -152,7 +152,7 @@ class BulkUpload::Sales::Year2026::RowParser }.freeze ERROR_BASE_KEY = "validations.sales.2026.bulk_upload".freeze - SERVICE_CHARGE_FORMAT = /\A(\d+(\.\d+)?|R)\z/i + NUMBER_OR_R_FORMAT = /\A(\d+(\.\d+)?|R)\z/i CASE_INSENSITIVE_FIELDS = [ :field_29, # Age of buyer 1 @@ -1269,25 +1269,25 @@ private end def has_mscharge_value - return unless mscharge.present? && mscharge.match?(SERVICE_CHARGE_FORMAT) + return unless mscharge.present? && mscharge.match?(NUMBER_OR_R_FORMAT) mscharge.casecmp?("R") ? 0 : 1 end def mscharge_value - return unless mscharge.present? && mscharge.match?(SERVICE_CHARGE_FORMAT) && !mscharge.casecmp?("R") + return unless mscharge.present? && mscharge.match?(NUMBER_OR_R_FORMAT) && !mscharge.casecmp?("R") mscharge.to_d end def hasservicechargeschanged_value - return unless field_126.present? && field_126.match?(SERVICE_CHARGE_FORMAT) + return unless field_126.present? && field_126.match?(NUMBER_OR_R_FORMAT) field_126.casecmp?("R") ? 2 : 1 end def newservicecharges_value - return unless field_126.present? && field_126.match?(SERVICE_CHARGE_FORMAT) && !field_126.casecmp?("R") + return unless field_126.present? && field_126.match?(NUMBER_OR_R_FORMAT) && !field_126.casecmp?("R") field_126.to_d end @@ -1424,21 +1424,21 @@ private def validate_service_charge_fields message = I18n.t("#{ERROR_BASE_KEY}.mscharge.invalid") - if shared_ownership_initial_purchase? && field_107.present? && !field_107.match?(SERVICE_CHARGE_FORMAT) + if shared_ownership_initial_purchase? && field_107.present? && !field_107.match?(NUMBER_OR_R_FORMAT) errors.add(:field_107, message) end if staircasing? - if field_125.present? && !field_125.match?(SERVICE_CHARGE_FORMAT) + if field_125.present? && !field_125.match?(NUMBER_OR_R_FORMAT) errors.add(:field_125, message) end - if field_126.present? && !field_126.match?(SERVICE_CHARGE_FORMAT) + if field_126.present? && !field_126.match?(NUMBER_OR_R_FORMAT) errors.add(:field_126, I18n.t("#{ERROR_BASE_KEY}.newservicecharges.invalid")) end end - if discounted_ownership? && field_136.present? && !field_136.match?(SERVICE_CHARGE_FORMAT) + if discounted_ownership? && field_136.present? && !field_136.match?(NUMBER_OR_R_FORMAT) errors.add(:field_136, message) end end diff --git a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb index 4a81c12d8..4aaa0a707 100644 --- a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb @@ -2056,6 +2056,12 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when blank" do let(:attributes) { valid_attributes.merge(field_10: "2", field_107: nil) } + it "does not add a bulk upload format validation error but adds a site validation error" do + parser.valid? + expect(parser.errors[:field_107]).not_to include(I18n.t("validations.sales.2026.bulk_upload.mscharge.invalid")) + expect(parser.errors[:field_107]).to include("You must answer property service charges.") + end + it "does not set has_mscharge or mscharge" do log = parser.log expect(log["has_mscharge"]).to be_nil @@ -2066,6 +2072,11 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when negative" do let(:attributes) { valid_attributes.merge(field_10: "2", field_107: "-100") } + it "adds a validation error" do + parser.valid? + expect(parser.errors[:field_107]).to include(I18n.t("validations.sales.2026.bulk_upload.mscharge.invalid")) + end + it "does not set has_mscharge or mscharge" do log = parser.log expect(log["has_mscharge"]).to be_nil @@ -2185,6 +2196,12 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when blank" do let(:attributes) { valid_attributes.merge(field_125: nil) } + it "does not add a bulk upload format validation error but adds a site validation error" do + parser.valid? + expect(parser.errors[:field_125]).not_to include(I18n.t("validations.sales.2026.bulk_upload.mscharge.invalid")) + expect(parser.errors[:field_125]).to include("You must answer property service charges.") + end + it "does not set has_mscharge or mscharge" do log = parser.log expect(log["has_mscharge"]).to be_nil @@ -2195,6 +2212,11 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when negative" do let(:attributes) { valid_attributes.merge(field_125: "-100") } + it "adds a validation error" do + parser.valid? + expect(parser.errors[:field_125]).to include(I18n.t("validations.sales.2026.bulk_upload.mscharge.invalid")) + end + it "does not set has_mscharge or mscharge" do log = parser.log expect(log["has_mscharge"]).to be_nil @@ -2312,6 +2334,11 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when blank" do let(:attributes) { valid_attributes.merge(field_8: "2", field_136: nil) } + it "does not add a validation error" do + parser.valid? + expect(parser.errors[:field_136]).to be_blank + end + it "does not set has_mscharge or mscharge" do log = parser.log expect(log["has_mscharge"]).to be_nil @@ -2322,6 +2349,11 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when negative" do let(:attributes) { valid_attributes.merge(field_8: "2", field_136: "-100") } + it "adds a validation error" do + parser.valid? + expect(parser.errors[:field_136]).to include(I18n.t("validations.sales.2026.bulk_upload.mscharge.invalid")) + end + it "does not set has_mscharge or mscharge" do log = parser.log expect(log["has_mscharge"]).to be_nil @@ -2349,6 +2381,26 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when set to 0" do let(:attributes) { valid_attributes.merge(field_126: "0") } + it "does not add a validation error" do + parser.valid? + expect(parser.errors[:field_126]).to be_blank + end + + it "sets hasservicechargeschanged to yes and newservicecharges to 0" do + log = parser.log + expect(log["hasservicechargeschanged"]).to eq(1) + expect(log["newservicecharges"]).to eq(0) + end + end + + context "when set to 0.0" do + let(:attributes) { valid_attributes.merge(field_126: "0.0") } + + it "does not add a validation error" do + parser.valid? + expect(parser.errors[:field_126]).to be_blank + end + it "sets hasservicechargeschanged to yes and newservicecharges to 0" do log = parser.log expect(log["hasservicechargeschanged"]).to eq(1) @@ -2359,6 +2411,26 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when set to R" do let(:attributes) { valid_attributes.merge(field_126: "R") } + it "does not add a validation error" do + parser.valid? + expect(parser.errors[:field_126]).to be_blank + end + + it "sets hasservicechargeschanged to no and does not set newservicecharges" do + log = parser.log + expect(log["hasservicechargeschanged"]).to eq(2) + expect(log["newservicecharges"]).to be_nil + end + end + + context "when set to lowercase r" do + let(:attributes) { valid_attributes.merge(field_126: "r") } + + it "does not add a validation error" do + parser.valid? + expect(parser.errors[:field_126]).to be_blank + end + it "sets hasservicechargeschanged to no and does not set newservicecharges" do log = parser.log expect(log["hasservicechargeschanged"]).to eq(2) @@ -2384,6 +2456,12 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when blank" do let(:attributes) { valid_attributes.merge(field_126: nil) } + it "does not add a bulk upload format validation error but adds a site validation error" do + parser.valid? + expect(parser.errors[:field_126]).not_to include(I18n.t("validations.sales.2026.bulk_upload.newservicecharges.invalid")) + expect(parser.errors[:field_126]).to include("You must answer service charge will change.") + end + it "does not set hasservicechargeschanged or newservicecharges" do log = parser.log expect(log["hasservicechargeschanged"]).to be_nil @@ -2394,6 +2472,11 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do context "when negative" do let(:attributes) { valid_attributes.merge(field_126: "-150") } + it "adds a validation error" do + parser.valid? + expect(parser.errors[:field_126]).to include(I18n.t("validations.sales.2026.bulk_upload.newservicecharges.invalid")) + end + it "does not set hasservicechargeschanged or newservicecharges" do log = parser.log expect(log["hasservicechargeschanged"]).to be_nil