Skip to content

Commit

Permalink
Merge pull request #6024 from solidusio/backport/v4.4/pr-6013
Browse files Browse the repository at this point in the history
[v4.4] Add can apply to promotions
  • Loading branch information
tvdeyen authored Dec 6, 2024
2 parents 2f82f59 + 38c4e1a commit 099fc05
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 1 deletion.
2 changes: 1 addition & 1 deletion promotions/app/models/solidus_promotions/order_adjuster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def initialize(order, dry_run_promotion: nil)
def call
order.reset_current_discounts

return order if (!SolidusPromotions.config.recalculate_complete_orders && order.complete?) || order.shipped?
return order unless SolidusPromotions::Promotion.order_activatable?(order)

discounted_order = DiscountOrder.new(order, promotions, dry_run: dry_run).call

Expand Down
10 changes: 10 additions & 0 deletions promotions/app/models/solidus_promotions/promotion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module SolidusPromotions
class Promotion < Spree::Base
UNACTIVATABLE_ORDER_STATES = ["awaiting_return", "returned", "canceled"]

include Spree::SoftDeletable

belongs_to :category, class_name: "SolidusPromotions::PromotionCategory",
Expand Down Expand Up @@ -59,6 +61,14 @@ def self.ordered_lanes
lanes.sort_by(&:last).to_h
end

def self.order_activatable?(order)
return false if UNACTIVATABLE_ORDER_STATES.include?(order.state)
return false if order.shipped?
return false if order.complete? && !SolidusPromotions.config.recalculate_complete_orders

true
end

self.allowed_ransackable_associations = ["codes"]
self.allowed_ransackable_attributes = %w[name customer_label path promotion_category_id lane updated_at]
self.allowed_ransackable_scopes = %i[active with_discarded]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ def apply
self
end

def can_apply?
SolidusPromotions::Promotion.order_activatable?(order)
end

def remove
if promotion.blank?
set_error_code :coupon_code_not_found
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,15 @@ def expect_adjustment_creation(adjustable:, promotion:)
)
end
end

describe "#can_apply?" do
let(:order) { double("Order").as_null_object }

subject { described_class.new(order).can_apply? }

it "forwards to SolidusPromotions::Promotion.order_activatable?" do
expect(SolidusPromotions::Promotion).to receive(:order_activatable?).with(order)
subject
end
end
end
52 changes: 52 additions & 0 deletions promotions/spec/models/solidus_promotions/promotion_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -686,4 +686,56 @@
expect(subject).to be_nil
end
end

describe ".order_activatable" do
let(:order) { create :order }

subject { described_class.order_activatable?(order) }

it "is true" do
expect(subject).to be true
end

context "when the order is in the cart state" do
let(:order) { create :order, state: "cart" }

it { is_expected.to be true }
end

context "when the order is shipped" do
let(:order) { create :order, state: "complete", shipment_state: "shipped" }

it { is_expected.to be false }
end

context "when the order is completed but not shipped" do
let(:order) { create :order, state: "complete", shipment_state: "ready" }

it { is_expected.to be true }

context "when the promotion system is configured to prohibit applying promotions to completed orders" do
before { stub_spree_preferences(SolidusPromotions.configuration, recalculate_complete_orders: false) }

it { is_expected.to be false }
end
end

context "when the order is canceled" do
let(:order) { create :order, state: "canceled" }

it { is_expected.to be false }
end

context "when the order is awaiting return" do
let(:order) { create :order, state: "awaiting_return" }

it { is_expected.to be false }
end

context "when the order is returned" do
let(:order) { create :order, state: "returned" }

it { is_expected.to be false }
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe "Adjustments", type: :feature do
stub_authorization!

let!(:ship_address) { create(:address) }
let!(:tax_zone) { create(:global_zone) } # will include the above address
let!(:tax_rate) { create(:tax_rate, name: "Sales Tax", amount: 0.20, zone: tax_zone, tax_categories: [tax_category]) }

let!(:line_item) { order.line_items[0] }

let(:tax_category) { create(:tax_category) }
let(:variant) { create(:variant, tax_category:) }
let(:preferences) { {} }

before(:each) do
stub_spree_preferences(SolidusPromotions.configuration, preferences)
order.recalculate

visit spree.admin_path
click_link "Orders"
uncheck "Only show complete orders"
click_button "Filter Results"
within_row(1) { click_icon :edit }
click_link "Adjustments"
end

let!(:order) { create(:order, line_items_attributes: [{ price: 10, variant: }]) }

context "when the order is completed" do
let!(:order) do
create(
:completed_order_with_totals,
line_items_attributes: [{ price: 10, variant: }],
ship_address:
)
end

let!(:adjustment) { order.adjustments.create!(order:, label: "Rebate", amount: 10) }

it "shows adjustments" do
expect(page).to have_content("Adjustments")
end

context "when the promotion system is configured to allow applying promotions to completed orders" do
it "shows input field for promotion code" do
expect(page).to have_content("Adjustments")
expect(page).to have_field("coupon_code")
end
end

context "when the promotion system is configured to not allow applying promotions to completed orders" do
let(:preferences) { { recalculate_complete_orders: false } }

it "does not show input field for promotion code" do
expect(page).to have_content("Adjustments")
expect(page).not_to have_field("coupon_code")
end
end
end

it "shows the input field for applying a promotion" do
expect(page).to have_field("coupon_code")
end

context "creating a manual adjustment" do
let!(:adjustment_reason) { create(:adjustment_reason, name: "Friendly customer") }
before do
click_link "New Adjustment"
end

it "creates a new adjustment" do
fill_in "adjustment_amount", with: "5"
fill_in "adjustment_label", with: "Test Adjustment"
select "Friendly customer", from: "Reason"
click_button "Continue"
expect(page).to have_content("Adjustment has been successfully created!")
expect(page).to have_content("Test Adjustment")
end
end
end

0 comments on commit 099fc05

Please sign in to comment.