friendlycart/solidus_friendly_promotions

Implement Free items

Closed this issue · 2 comments

Currently, the system can do only discounts. I would like us to get to a place where we can also add a line item to an order.

I envision it like this:

In every lane, before we run discounts, we run "automations", Promotion Actions that perform an action other than discounting (using a method that is different from discount, like perform, maybe?). perform should either add or remove a line item, depending on the promotion's availability for the promotion. For this to work, line items must be connected to promotion actions through a new promotion_action_id attribute on the line item.

An example spec could be something along the lines of:

  context "A promotion that creates line items", :pending do
    let(:shirt) { create(:product, name: "Shirt") }
    let(:pants) { create(:product, name: "Pants") }
    let(:promotion) { create(:friendly_promotion, name: "Free shirt with pants", apply_automatically: true) }
    let(:rule) { SolidusFriendlyPromotions::Rules::Product.new(products: [shirt], preferred_line_item_applicable: false) }
    let(:action) { SolidusFriendlyPromotions::Actions::FreeItem.new(preferred_variant_id: shirt.id) }

    let(:order) { create(:order) }

    before do
      promotion.rules << rule
      promotion.actions << action
      order.contents.add(pants.master, 1)
    end

    it "creates one line item level adjustment" do
      expect(order.adjustments).to be_empty
      expect(order.total).to eq(19.99)
      expect(order.item_total).to eq(39.98)
      expect(order.item_total_before_tax).to eq(19.99)
      expect(order.line_items.flat_map(&:adjustments).length).to eq(1)
      expect(order.line_items.length).to eq(2)
      order.contents.remove(pants.master, 1)
      # Because the pants are gone, the promo does not apply anymore, and our free shirt goes as well.
      expect(order.line_items).to be_empty
    end
  end

Concerns/questions:

  1. how to select the free item (product, taxon, specific variant, ...)
  2. do these get recreated on every order_recalculate?
  3. how/when do they get removed?
  4. how does a customer remove the free item?

Done in #75
That PR solves 1 (admins select a variant), 2 (no they don't) and 3 (they get removed when the order becomes ineligible for the promotion, regardless of by time, promotion rule, or promotion deletion).