Class: Order::Splitter

Inherits:
Object
  • Object
show all
Defined in:
app/services/order/splitter.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(original_order, options = {}) ⇒ Splitter

Returns a new instance of Splitter.



4
5
6
7
8
# File 'app/services/order/splitter.rb', line 4

def initialize(original_order, options = {})
  @options = options
  @order = original_order
  @logger = options[:logger] || Rails.logger
end

Instance Attribute Details

#last_messageObject

Returns the value of attribute last_message.



2
3
4
# File 'app/services/order/splitter.rb', line 2

def last_message
  @last_message
end

#last_statusObject

Returns the value of attribute last_status.



2
3
4
# File 'app/services/order/splitter.rb', line 2

def last_status
  @last_status
end

#loggerObject

Returns the value of attribute logger.



2
3
4
# File 'app/services/order/splitter.rb', line 2

def logger
  @logger
end

#new_orderObject

Returns the value of attribute new_order.



2
3
4
# File 'app/services/order/splitter.rb', line 2

def new_order
  @new_order
end

#orderObject

Returns the value of attribute order.



2
3
4
# File 'app/services/order/splitter.rb', line 2

def order
  @order
end

Instance Method Details

#split_selected(line_items, txid = nil) ⇒ Object



10
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'app/services/order/splitter.rb', line 10

def split_selected(line_items, txid = nil)
  if @order.is_store_transfer?
    @last_status = :invalid
    @last_message = 'Cannot split a store transfer. Cancel the ST order and start new store transfers.'
    return @last_status
  end
  if @order.payments.bread_payments&.any?
    @last_status = :invalid
    @last_message = 'Cannot split an order paid with Bread financing. Please create a separate order.'
    return @last_status
  end
  # if @order.includes_schedulable_service?
  #   @last_status = :invalid
  #   @last_message = 'Cannot split an order with service items. Please create a separate order for the goods and leave the service items in this order.'
  #   return @last_status
  # end
  qty_arr = []
  total_qty = 0
  @order.line_items.non_shipping.each do |li|
    qty = line_items[li.id.to_s.to_sym].to_i
    qty_arr << qty
    total_qty += qty
  end

  if total_qty > 0
    Order.transaction do
      @order.uncommit_line_items # remove all the commits first
      @new_order = @order.deep_dup
      @new_order.txid = txid
      @new_order.do_not_detect_shipping = true # otherwise this results in a $^%$^% loop in set_totals of itemizable
      @new_order.single_origin = false # reset this back to the default settings
      line_items_to_remove = []

      @order.line_items.parents_only.non_shipping.each do |li|
        qty = line_items[li.id.to_s.to_sym].to_i
        bo_qty = li.quantity - qty

        if bo_qty > 0
          line_item_options = {  quantity: bo_qty,
                                 price: li.price,
                                 discounted_price: li.price, # Reset to original
                                 catalog_item_id: li.catalog_item.id,
                                 sequence: li.sequence,
                                 edi_reference: li.edi_reference,
                                 edi_line_number: li.edi_line_number,
                                 do_not_autosave: true }
          @new_order.do_not_detect_shipping = true # otherwise this results in a $^%$^% loop in set_totals of itemizable
          @new_order.add_line_item(line_item_options)
        end

        if qty > 0
          li.quantity = qty
          li.save!
        else
          line_items_to_remove << li
        end
      end

      line_items_to_remove.each do |li|
        @order.do_not_detect_shipping = true # otherwise this results in a $^%$^% loop in set_totals of itemizable
        @order.remove_line_item(li, li.quantity)
      end

      if (cc_payment = @order.payments.credit_cards.all_authorized.first) && cc_vault = cc_payment.credit_card_vault
        cc_vault.update(hidden: false) if cc_vault.hidden?
        @new_order.default_credit_card_vault = cc_vault
      end

      # Remove EDI price match rules since we split the order
      @new_order.price_match = nil
      @order.price_match = nil

      @new_order.do_not_detect_shipping = true # otherwise this results in a $^%$^% loop in set_totals of itemizable
      @new_order.save

    end

    # Do this outside of the transaction

    @new_order.discounts.fixed_dollar.destroy_all # here we do not duplicate discounts for coupons with fixed dollar coupons to avoid doubling their fixed discount
    @new_order.do_not_detect_shipping = true # otherwise this results in a $^%$^% loop in set_totals of itemizable
    @new_order.save
    @new_order.need_to_recalculate_shipping
    @new_order.save
    # FIXSPLIT @new_order.commit_line_items(3.working.days.since(Date.current))
    @order.single_origin = false # reset this back the the default setting, in case there are drop ship items involved
    @new_order.do_not_detect_shipping = true # otherwise this results in a $^%$^% loop in set_totals of itemizable
    @order.cr_hold # put it in cr hold as they need to check the shipping options
    @order.line_items.reload # Clear cached line_items to avoid FK violation on deleted items

    # Invalidate cached material alerts since line items have changed
    @order.invalidate_material_alerts!
    @new_order.invalidate_material_alerts! if @new_order.persisted?

    @order.commit_line_items(3.working.days.since(Date.current))
    @new_order.save
    @order.need_to_recalculate_shipping
    @order.save

    if @new_order.deliveries.present?
      po_payment = @order.payments.all_authorized.where(category: [Payment::PO, Payment::VPO, Payment::CHECK, Payment::CASH]).first
      cc_payment = @order.payments.all_authorized.where(category: Payment::CREDIT_CARD).first

      paypal_payment = @order.payments.all_authorized.where(category: Payment::PAYPAL).first

      if po_payment
        attrs = {
          currency: po_payment.currency,
          category: po_payment.category,
          po_number: po_payment.po_number,
          amount: @new_order.total
        }
        Payment::OrderProcessor.new(@new_order, attrs).process
      elsif cc_payment && cc_payment.credit_card_vault.present?
        split_cc_payment(cc_payment)
      elsif paypal_payment
        split_paypal_payment(paypal_payment)
      end

      if @new_order.includes_schedulable_service? && (scs = @order.support_cases.services.open_cases).any?
        # ensure we get the service order linked to the support case
        scs.each do |sc|
          sc.orders << @new_order unless sc.order_ids.include?(@new_order.id)
        end
      end

      @new_order.reload # Because we added some prepayments potentially
      @new_order.commit_line_items(3.working.days.since(Date.current))
      if @new_order.balance > 0
        @new_order.pending_payment
      else
        @new_order.back_order
      end
    end

    @last_status = :ok
  else
    @last_status = :invalid
    @last_message = 'Split order must have some quantity of line items. To back order the entire order, select the "Back Order Entire Order" button.'
  end
end