Class: Coupon::DeleteDiscount

Inherits:
Object
  • Object
show all
Defined in:
app/services/coupon/delete_discount.rb

Overview

This service class is responsible for deleting a discount from an itemizable
and ensuring the total integrity is correct

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Instance Method Details

#perform(discount, options = {}) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/services/coupon/delete_discount.rb', line 11

def perform(discount, options = {})
  errors = []
  itemizable = discount.itemizable
  if itemizable.nil?
    errors << 'Discount is orphaned and cannot be deleted'
  elsif itemizable.editing_locked? && !options[:skip_lock_check]
    errors << "Discount cannot be deleted, #{itemizable.class.name} is locked"
  else
    lock_key = "#{itemizable.class.name.downcase}_#{itemizable.id}".freeze
    itemizable.with_advisory_lock(lock_key, timeout_seconds: 120) do
      # Check if auto coupons are disabled on this order
      auto_coupons_disabled = itemizable.try(:disable_auto_coupon) == true

      if discount.blacklisted
        # Un-blacklist (enable) the discount instead of destroying it
        # This preserves manually-added discounts and prevents them from being
        # removed during recalculation when auto-apply coupons are processed
        discount.blacklisted = false
        discount.amount = 0 # Reset amount so it gets recalculated
        discount.save
      elsif discount.blacklistable? && !(auto_coupons_disabled && discount.auto_apply)
        # Blacklist the discount to remember it was manually disabled
        # BUT if auto coupons are disabled on the order, skip blacklisting and destroy instead
        discount.mark_as_blacklisted unless Coupon::SKIP_BLACKLISTING_COUPON_CODES.include?(discount.code)
        discount.save
      else
        # Destroy in these cases:
        # 1. Auto coupons disabled + this is an auto-apply discount (no need to blacklist)
        # 2. Discount is not blacklistable (manual discount being removed)
        discount.destroy
      end
      # Set flag to trigger discount recalculation after removing a coupon
      itemizable.update_column(:recalculate_discounts, true)
      itemizable.reload
      itemizable.reset_discount
      itemizable.calculate_tax_for_all_lines
    end
  end

  Result.new(success: errors.blank?, errors: errors)
end