Files
openfoodnetwork/app/services/checkout/form_data_adapter.rb
2020-07-15 16:46:09 +02:00

89 lines
2.9 KiB
Ruby

# frozen_string_literal: true
# Adapts checkout form data (params) so that the order can be directly saved to the database
module Checkout
class FormDataAdapter
attr_reader :params, :shipping_method_id
def initialize(params, order, current_user)
@params = params.dup
@order = order
@current_user = current_user
move_payment_source_to_payment_attributes!
fill_in_card_type
set_amount_in_payments_attributes
construct_saved_card_attributes if @params[:order][:existing_card_id]
@shipping_method_id = @params[:order].delete(:shipping_method_id)
end
private
# For payment step, filter order parameters to produce the expected
# nested attributes for a single payment and its source,
# discarding attributes for payment methods other than the one selected
def move_payment_source_to_payment_attributes!
return unless @params[:payment_source].present? &&
payment_source_params = delete_payment_source_params!
@params[:order][:payments_attributes].first[:source_attributes] = payment_source_params
end
# Ensures cc_type is always passed to the model by inferring the type when
# the frontend didn't provide it. This fixes Pin Payments specifically
# although it might be useful for future payment gateways.
#
# More details: app/assets/javascripts/darkswarm/services/checkout.js.coffee#L70-L98
def fill_in_card_type
return unless payment_source_attributes
return if payment_source_attributes.dig(:number).blank?
payment_source_attributes[:cc_type] ||= card_brand(payment_source_attributes[:number])
end
def payment_source_attributes
@payment_source_attributes ||=
params[:order][:payments_attributes]&.first&.dig(:source_attributes)
end
def card_brand(number)
ActiveMerchant::Billing::CreditCard.brand?(number)
end
def delete_payment_source_params!
@params.delete(:payment_source)[
@params[:order][:payments_attributes].first[:payment_method_id].underscore
]
end
def set_amount_in_payments_attributes
return unless @params[:order][:payments_attributes]
@params[:order][:payments_attributes].first[:amount] = @order.total
end
def construct_saved_card_attributes
existing_card_id = @params[:order].delete(:existing_card_id)
return if existing_card_id.blank?
add_to_payment_attributes(existing_card_id)
@params[:order][:payments_attributes].first.delete :source_attributes
end
def add_to_payment_attributes(existing_card_id)
credit_card = Spree::CreditCard.find(existing_card_id)
if credit_card.try(:user_id).blank? || credit_card.user_id != @current_user.try(:id)
raise Spree::Core::GatewayError, I18n.t(:invalid_credit_card)
end
@params[:order][:payments_attributes].first[:source] = credit_card
end
end
end