diff --git a/app/models/voucher.rb b/app/models/voucher.rb index 60bf1b8cf2e..ec28a0b264d 100644 --- a/app/models/voucher.rb +++ b/app/models/voucher.rb @@ -11,7 +11,20 @@ class Voucher < ApplicationRecord dependent: :nullify validates :code, presence: true, uniqueness: { scope: :enterprise_id } - validates :amount, presence: true, numericality: { greater_than: 0 } + validates :amount, + presence: true, + numericality: { greater_than: 0 }, + if: ->(v) { v.voucher_type == FLAT_RATE } + validates :amount, + presence: true, + numericality: { greater_than: 0, less_than_or_equal_to: 100 }, + if: ->(v) { v.voucher_type == PERCENTAGE_RATE } + + FLAT_RATE = 'flat'.freeze + PERCENTAGE_RATE = 'percentage'.freeze + TYPES = [FLAT_RATE, PERCENTAGE_RATE].freeze + + validates :voucher_type, inclusion: TYPES def display_value Spree::Money.new(amount) diff --git a/db/migrate/20230508035306_add_type_to_vouchers.rb b/db/migrate/20230508035306_add_type_to_vouchers.rb new file mode 100644 index 00000000000..54a6cceec48 --- /dev/null +++ b/db/migrate/20230508035306_add_type_to_vouchers.rb @@ -0,0 +1,5 @@ +class AddTypeToVouchers < ActiveRecord::Migration[7.0] + def change + add_column :vouchers, :voucher_type, :string, limit: 255 + end +end diff --git a/db/schema.rb b/db/schema.rb index 1241b84131b..7f9a44a35b3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1211,6 +1211,7 @@ t.bigint "enterprise_id" t.datetime "deleted_at", precision: nil t.decimal "amount", precision: 10, scale: 2, default: "0.0", null: false + t.string "voucher_type", limit: 255 t.index ["code", "enterprise_id"], name: "index_vouchers_on_code_and_enterprise_id", unique: true t.index ["deleted_at"], name: "index_vouchers_on_deleted_at" t.index ["enterprise_id"], name: "index_vouchers_on_enterprise_id" diff --git a/spec/factories/voucher_factory.rb b/spec/factories/voucher_factory.rb index c02de3fb52d..d9076b91f7e 100644 --- a/spec/factories/voucher_factory.rb +++ b/spec/factories/voucher_factory.rb @@ -1,8 +1,15 @@ # frozen_string_literal: true FactoryBot.define do - factory :voucher do + factory :voucher_flat_rate, class: Voucher do enterprise { build(:distributor_enterprise) } + voucher_type { Voucher::FLAT_RATE } amount { 15 } end + + factory :voucher_percentage, class: Voucher do + enterprise { build(:distributor_enterprise) } + voucher_type { Voucher::PERCENTAGE_RATE } + amount { rand(1..100) } + end end diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 526ebb71b06..41da596822f 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -1439,7 +1439,7 @@ def advance_to_delivery_state(order) describe "#voucher_adjustments" do let(:distributor) { create(:distributor_enterprise) } let(:order) { create(:order, user: user, distributor: distributor) } - let(:voucher) { create(:voucher, code: 'new_code', enterprise: order.distributor) } + let(:voucher) { create(:voucher_flat_rate, code: 'new_code', enterprise: order.distributor) } context "when no voucher adjustment" do it 'returns an empty array' do diff --git a/spec/models/voucher_spec.rb b/spec/models/voucher_spec.rb index 0c62a814968..5c717f9926c 100644 --- a/spec/models/voucher_spec.rb +++ b/spec/models/voucher_spec.rb @@ -11,15 +11,31 @@ end describe 'validations' do - subject { build(:voucher, code: 'new_code', enterprise: enterprise) } + subject { build(:voucher_flat_rate, code: 'new_code', enterprise: enterprise) } it { is_expected.to validate_presence_of(:code) } it { is_expected.to validate_uniqueness_of(:code).scoped_to(:enterprise_id) } it { is_expected.to validate_presence_of(:amount) } - it { is_expected.to validate_numericality_of(:amount).is_greater_than(0) } + it { is_expected.to validate_inclusion_of(:voucher_type).in_array(Voucher::TYPES) } + + context "when voucher_type is flat rate" do + it { is_expected.to validate_numericality_of(:amount).is_greater_than(0) } + end + + context "when voucher_type is percentage rate" do + subject { build(:voucher_percentage, code: 'new_code', enterprise: enterprise) } + + it do + is_expected.to validate_numericality_of(:amount) + .is_greater_than(0) + .is_less_than_or_equal_to(100) + end + end end describe '#compute_amount' do + subject { create(:voucher_flat_rate, code: 'new_code', enterprise: enterprise, amount: 10) } + let(:order) { create(:order_with_totals) } context 'when order total is more than the voucher' do @@ -42,7 +58,9 @@ describe '#create_adjustment' do subject(:adjustment) { voucher.create_adjustment(voucher.code, order) } - let(:voucher) { create(:voucher, code: 'new_code', enterprise: enterprise, amount: 25) } + let(:voucher) do + create(:voucher_flat_rate, code: 'new_code', enterprise: enterprise, amount: 25) + end let(:order) { create(:order_with_line_items, line_items_count: 3, distributor: enterprise) } it 'includes an amount of 0' do diff --git a/spec/requests/voucher_adjustments_spec.rb b/spec/requests/voucher_adjustments_spec.rb index fc533473b86..fbfc9afebd9 100644 --- a/spec/requests/voucher_adjustments_spec.rb +++ b/spec/requests/voucher_adjustments_spec.rb @@ -6,7 +6,7 @@ let(:user) { order.user } let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) } let(:order) { create( :order_with_line_items, line_items_count: 1, distributor: distributor) } - let(:voucher) { create(:voucher, code: 'some_code', enterprise: distributor) } + let(:voucher) { create(:voucher_flat_rate, code: 'some_code', enterprise: distributor) } let!(:adjustment) { voucher.create_adjustment(voucher.code, order) } before do diff --git a/spec/services/voucher_adjustments_service_spec.rb b/spec/services/voucher_adjustments_service_spec.rb index 4f182363340..80862970fb5 100644 --- a/spec/services/voucher_adjustments_service_spec.rb +++ b/spec/services/voucher_adjustments_service_spec.rb @@ -5,7 +5,9 @@ describe VoucherAdjustmentsService do describe '.calculate' do let(:enterprise) { build(:enterprise) } - let(:voucher) { create(:voucher, code: 'new_code', enterprise: enterprise, amount: 10) } + let(:voucher) do + create(:voucher_flat_rate, code: 'new_code', enterprise: enterprise, amount: 10) + end context 'when voucher covers the order total' do subject { order.voucher_adjustments.first } diff --git a/spec/system/consumer/split_checkout_spec.rb b/spec/system/consumer/split_checkout_spec.rb index 148f2a212c0..3715badd794 100644 --- a/spec/system/consumer/split_checkout_spec.rb +++ b/spec/system/consumer/split_checkout_spec.rb @@ -721,7 +721,7 @@ context "with voucher available" do let!(:voucher) do - create(:voucher, code: 'some_code', enterprise: distributor, amount: 15) + create(:voucher_flat_rate, code: 'some_code', enterprise: distributor, amount: 15) end before do @@ -1114,7 +1114,9 @@ end describe "vouchers" do - let(:voucher) { create(:voucher, code: 'some_code', enterprise: distributor, amount: 6) } + let(:voucher) do + create(:voucher_flat_rate, code: 'some_code', enterprise: distributor, amount: 6) + end before do voucher.create_adjustment(voucher.code, order)