Class: Checkout::ServiceForm

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::API, ActiveModel::Attributes, ActiveModel::Validations, ActiveModel::Validations::Callbacks, Models::ValidationErrorReporting, StripAttributes
Defined in:
app/forms/checkout/service_form.rb

Overview

Form object backing the SmartService checkout form.

Collects the service address, date, and preferred timeframe for an
order's SmartService line items, then persists the address on the
customer and creates or updates the linked SupportCase ticket.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new_from_cart(cart) ⇒ Checkout::ServiceForm

Builds a form pre-filled from the order and its pending support case.

Uses the first open pending-service-payment support case's service
address when present, falling back to the customer's billing address;
also clears guest placeholder names on the customer.

Parameters:

  • cart (Order)

    the order the service form is for

Returns:



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/forms/checkout/service_form.rb', line 181

def self.new_from_cart(cart)
  # We get the first support case open linked to the order.
  support_case = cart.support_cases&.services&.pending_service_payment&.first
  cu = cart.customer
  address = if support_case.present?
              support_case&.service_address
            else
              cu.billing_address
            end
  cu.contacts.build if cu.customer.contacts.empty?
  cu.clear_names if cu.has_guest_name?
  cu.clear_individual_names if cu.has_guest_individual_name?
  cu.save
  service_form = new(
    customer_id: cu.id,
    order_id: cart.id,
    service_address: Checkout::StreetAddress.new(
      street1: address.try(:street1),
      street2: address.try(:street2),
      state_code: address.try(:state_code),
      postal_code: address.try(:zip),
      city: address.try(:city),
      country_iso: address.try(:country_iso3),
      residential_address: address.try(:is_residential),
      requires_liftgate: address.try(:requires_liftgate),
      has_loading_dock: address.try(:has_loading_dock),
      is_construction_site: address.try(:is_construction_site),
      limited_access: address.try(:limited_access),
      requires_appointment: address.try(:requires_appointment)
    )
  )
  if support_case.present?
    service_form.support_case_id = support_case.id
    service_form.service_date = support_case.service_date
    service_form.service_timeframe = support_case.preferred_service_timeframe
  end
  service_form
end

Instance Method Details

#build_service_address(address) ⇒ Address

Copies the form's service address onto a customer address record.

Parameters:

  • address (Address)

    the customer address to populate

Returns:

  • (Address)

    the populated address (not yet saved)



161
162
163
164
165
166
167
168
169
170
171
# File 'app/forms/checkout/service_form.rb', line 161

def build_service_address(address)
  address.street1 = service_address.street1
  address.street2 = service_address.street2
  address.city = service_address.city
  address.person_name = contact_name if contact_name
  address.state_code = service_address.state_code
  address.zip = service_address.postal_code
  address.country_iso3 = Country.find_by(iso: service_address.country_iso).iso3
  address.disable_address_correction = true
  address
end

#build_service_description(service, service_timeframe) ⇒ String

Builds the HTML description for the support case.

Parameters:

  • service (String)

    semicolon-separated service item names

  • service_timeframe (String)

    the preferred service timeframe

Returns:

  • (String)

    HTML fragment listing the requested services and timeframe



148
149
150
151
152
153
154
155
# File 'app/forms/checkout/service_form.rb', line 148

def build_service_description(service, service_timeframe)
  res = "<p>Customer requested: </p>"
  service.split(';').each do |ser|
    res += "<li>#{ser}</li>"
  end
  res += "<br><p>Preferred time frame is <b>#{service_timeframe}</b></p>"
  res
end

#create_ticket(service) ⇒ SupportCase

Creates a new SmartService support case for the order.

Parameters:

  • service (String)

    semicolon-separated service item names

Returns:

  • (SupportCase)

    the newly created (possibly invalid) support case



113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'app/forms/checkout/service_form.rb', line 113

def create_ticket(service)
  sc = SupportCase.new(case_type: 'SmartService')
  sc.send(:set_case_number)
  sc.state = 'pending_service_payment'
  sc.description = build_service_description(service, service_timeframe)
  sc.priority = 'Low'
  sc.service = service
  sc.service_address_id = @service_address.id if is_onsite_service?
  sc.service_date = service_date
  sc.preferred_service_timeframe = service_timeframe
  sc.build_participants_and_rooms(order_id: cart.id)
  sc.save
  sc
end

#is_onsite_service?Boolean

Whether the order's service is delivered on-site (as opposed to remote).

Returns:

  • (Boolean)

    true when no remote-service line item is on the order



48
49
50
# File 'app/forms/checkout/service_form.rb', line 48

def is_onsite_service?
  !is_remote_service?
end

#is_remote_service?Boolean

Whether the order contains any remote-service line items.

Returns:

  • (Boolean)

    true when at least one line item is a remote service



55
56
57
# File 'app/forms/checkout/service_form.rb', line 55

def is_remote_service?
  Order.find(order_id).line_items.joins(:item).merge(Item.remote_services).any?
end

#persisted?Boolean

Form objects are never persisted.

Returns:

  • (Boolean)

    always false



41
42
43
# File 'app/forms/checkout/service_form.rb', line 41

def persisted?
  false
end

#saveBoolean

Validates the form and persists the service address and support case.

For on-site services, reuses a matching customer address or builds a
new one; then creates or updates the SmartService support case linked
to the order.

Returns:

  • (Boolean)

    true when the support case was saved without errors



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
# File 'app/forms/checkout/service_form.rb', line 66

def save
  self.cart = Order.find(order_id)
  unless valid?
    errors.add(:base, 'Service form not valid')
    Rails.logger.debug("Saving Service form error")
    return false
  end

  if is_onsite_service?
    # First we save the address to the customer address list
    cu = cart.customer

    existing_address = cu.all_addresses.find do |a|
      a.full_address(false).casecmp(service_address.full_address(false)).zero?
    end
    if existing_address.present?
      @service_address = existing_address
    elsif service_address.address_complete?
      @service_address = build_service_address(cu.addresses.new)
    else
      Rails.logger.error("Service address provided is not complete. Service schedule will fail. cart_id: #{cart.id}, address: #{service_address.full_address(true)}")
      service_address.errors.add(:base, "The address provided is missing some information. Please review all fields.")
    end

    if @service_address && !@service_address.is_a?(Checkout::StreetAddress)
      @service_address.save
    else
      errors.add(:base, 'Service address missing')
      return false
    end
  end

  # Then we create or update the support case
  @support_case = SupportCase.find(support_case_id) if support_case_id.present?
  @support_case = if @support_case.present?
                    update_ticket(cart.line_items.smartservice_items.map { |a| a.item.name }.join('; '))
                  else
                    create_ticket(cart.line_items.smartservice_items.map { |a| a.item.name }.join('; '))
                  end

  @support_case.errors.blank?
end

#update_ticket(service) ⇒ SupportCase

Updates the existing support case with the current form values.

Parameters:

  • service (String)

    semicolon-separated service item names

Returns:

  • (SupportCase)

    the updated (possibly invalid) support case



132
133
134
135
136
137
138
139
140
141
# File 'app/forms/checkout/service_form.rb', line 132

def update_ticket(service)
  sc = @support_case
  sc.description = build_service_description(service, service_timeframe)
  sc.service = service
  sc.service_address_id = @service_address.id if is_onsite_service?
  sc.service_date = service_date
  sc.preferred_service_timeframe = service_timeframe
  sc.save
  sc
end