Merge pull request #11135 from Matt-Yorkley/vouchers

Vouchers part 2
This commit is contained in:
Filipe
2023-07-13 12:50:32 +01:00
committed by GitHub
29 changed files with 535 additions and 496 deletions

View File

@@ -9,14 +9,11 @@ module Admin
end
def create
voucher_params = permitted_resource_params.merge(enterprise: @enterprise)
@voucher = Voucher.create(voucher_params)
@voucher = Voucher.create(permitted_resource_params.merge(enterprise: @enterprise))
if @voucher.save
redirect_to(
"#{edit_admin_enterprise_path(@enterprise)}#vouchers_panel",
flash: { success: flash_message_for(@voucher, :successfully_created) }
)
flash[:success] = flash_message_for(@voucher, :successfully_created)
redirect_to edit_admin_enterprise_path(@enterprise, anchor: :vouchers_panel)
else
flash[:error] = @voucher.errors.full_messages.to_sentence
render :new

View File

@@ -14,7 +14,7 @@ module CheckoutCallbacks
prepend_before_action :require_order_cycle
prepend_before_action :require_distributor_chosen
before_action :load_order, :associate_user, :load_saved_addresses, :load_saved_credit_cards
before_action :load_order, :associate_user, :load_saved_addresses
before_action :load_shipping_methods, if: -> { params[:step] == "details" }
before_action :ensure_order_not_completed
@@ -30,8 +30,6 @@ module CheckoutCallbacks
@order.manual_shipping_selection = true
@order.checkout_processing = true
@voucher_adjustment = @order.voucher_adjustments.first
redirect_to(main_app.shop_path) && return if redirect_to_shop?
redirect_to_cart_path && return unless valid_order_line_items?
end
@@ -43,11 +41,6 @@ module CheckoutCallbacks
@order.ship_address ||= finder.ship_address
end
def load_saved_credit_cards
@saved_credit_cards = spree_current_user&.credit_cards&.with_payment_profile.to_a
@selected_card = nil
end
def load_shipping_methods
@shipping_methods = available_shipping_methods.sort { |a, b| a.name.casecmp(b.name) }
end

View File

@@ -25,12 +25,12 @@ class SplitCheckoutController < ::BaseController
redirect_to_step_based_on_order unless params[:step]
check_step if params[:step]
flash_error_when_no_shipping_method_available if available_shipping_methods.none?
return if available_shipping_methods.any?
flash[:error] = I18n.t('split_checkout.errors.no_shipping_methods_available')
end
def update
return process_voucher if params[:apply_voucher].present?
if confirm_order || update_order
return if performed?
@@ -60,27 +60,6 @@ class SplitCheckoutController < ::BaseController
replace("#flashes", partial("shared/flashes", locals: { flashes: flash }))
end
def render_voucher_section_or_redirect
respond_to do |format|
format.cable_ready { render_voucher_section }
format.html { redirect_to checkout_step_path(:payment) }
end
end
# Using the power of cable_car we replace only the #voucher_section instead of reloading the page
def render_voucher_section
render(
status: :ok,
cable_ready: cable_car.replace(
"#voucher-section",
partial(
"split_checkout/voucher_section",
locals: { order: @order, voucher_adjustment: @order.voucher_adjustments.first }
)
)
)
end
def order_error_messages
# Remove ship_address.* errors if no shipping method is not selected
remove_ship_address_errors if no_ship_address_needed?
@@ -125,10 +104,6 @@ class SplitCheckoutController < ::BaseController
end
end
def flash_error_when_no_shipping_method_available
flash[:error] = I18n.t('split_checkout.errors.no_shipping_methods_available')
end
def check_payments_adjustments
@order.payments.each(&:ensure_correct_adjustment)
end
@@ -201,40 +176,6 @@ class SplitCheckoutController < ::BaseController
selected_shipping_method.first.require_ship_address == false
end
def process_voucher
if add_voucher
VoucherAdjustmentsService.calculate(@order)
render_voucher_section_or_redirect
elsif @order.errors.present?
render_error
end
end
def add_voucher
if params.dig(:order, :voucher_code).blank?
@order.errors.add(:voucher, I18n.t('split_checkout.errors.voucher_not_found'))
return false
end
# Fetch Voucher
voucher = Voucher.find_by(code: params[:order][:voucher_code], enterprise: @order.distributor)
if voucher.nil?
@order.errors.add(:voucher, I18n.t('split_checkout.errors.voucher_not_found'))
return false
end
adjustment = voucher.create_adjustment(voucher.code, @order)
unless adjustment.valid?
@order.errors.add(:voucher, I18n.t('split_checkout.errors.add_voucher_error'))
adjustment.errors.each { |error| @order.errors.import(error) }
return false
end
true
end
def summary_step?
params[:step] == "summary"
end
@@ -262,6 +203,7 @@ class SplitCheckoutController < ::BaseController
def validate_payment!
return true if params.dig(:order, :payments_attributes, 0, :payment_method_id).present?
return true if @order.zero_priced_order?
@order.errors.add :payment_method, I18n.t('split_checkout.errors.select_a_payment_method')
end

View File

@@ -1,32 +1,77 @@
# frozen_string_literal: true
class VoucherAdjustmentsController < BaseController
include CablecarResponses
before_action :set_order
def create
if add_voucher
VoucherAdjustmentsService.calculate(@order)
@order.update_totals_and_states
update_payment_section
elsif @order.errors.present?
render_error
end
end
def destroy
@order = current_order
@order.voucher_adjustments.find_by(id: params[:id])&.destroy
respond_to do |format|
format.cable_ready { render_voucher_section }
format.html { redirect_to checkout_step_path(:payment) }
end
update_payment_section
end
private
# Using the power of cable_car we replace only the #voucher_section instead of reloading the page
def render_voucher_section
render(
status: :ok,
cable_ready: cable_car.replace(
def set_order
@order = current_order
end
def add_voucher
if voucher_params[:voucher_code].blank?
@order.errors.add(:voucher_code, I18n.t('split_checkout.errors.voucher_not_found'))
return false
end
voucher = Voucher.find_by(code: voucher_params[:voucher_code], enterprise: @order.distributor)
if voucher.nil?
@order.errors.add(:voucher_code, I18n.t('split_checkout.errors.voucher_not_found'))
return false
end
adjustment = voucher.create_adjustment(voucher.code, @order)
unless adjustment.valid?
@order.errors.add(:voucher_code, I18n.t('split_checkout.errors.add_voucher_error'))
adjustment.errors.each { |error| @order.errors.import(error) }
return false
end
true
end
def update_payment_section
render cable_ready: cable_car.replace(
selector: "#checkout-payment-methods",
html: render_to_string(partial: "split_checkout/payment", locals: { step: "payment" })
)
end
def render_error
flash.now[:error] = @order.errors.full_messages.to_sentence
render status: :unprocessable_entity, cable_ready: cable_car.
replace("#flashes", partial("shared/flashes", locals: { flashes: flash })).
replace(
"#voucher-section",
partial(
"split_checkout/voucher_section",
locals: { order: @order, voucher_adjustment: @order.voucher_adjustments.first }
)
)
)
end
def voucher_params
params.require(:order).permit(:voucher_code)
end
end

View File

@@ -120,6 +120,8 @@ module CheckoutHelper
end
def payment_or_shipping_price(method, order)
return unless method
price = method.compute_amount(order)
if price.zero?
t('checkout_method_free')

View File

@@ -5,11 +5,13 @@ module Spree
def payment_method(payment)
# hack to allow us to retrieve the name of a "deleted" payment method
id = payment.payment_method_id
return if id.nil?
Spree::PaymentMethod.find_with_destroyed(id)
end
def payment_method_name(payment)
payment_method(payment).name
payment_method(payment)&.name
end
end
end

View File

@@ -23,7 +23,7 @@ module Spree
go_to_state :delivery
go_to_state :payment, if: ->(order) {
order.update_totals
order.payment_required?
order.payment_required? || order.zero_priced_order?
}
go_to_state :confirmation
go_to_state :complete
@@ -219,6 +219,12 @@ module Spree
total.to_f > 0.0 && !skip_payment_for_subscription?
end
# There are items present in the order, but either the items have zero price,
# or the order's total has been modified (maybe discounted) to zero.
def zero_priced_order?
line_items.count.positive? && total.zero?
end
# Returns the relevant zone (if any) to be used for taxation purposes.
# Uses default tax zone unless there is a specific match
def tax_zone
@@ -615,6 +621,10 @@ module Spree
raise Core::GatewayError, Spree.t(:no_pending_payments) if pending_payments.empty?
pending_payments.each do |payment|
if payment.amount.zero? && zero_priced_order?
payment.update_columns(state: "completed", captured_at: Time.zone.now)
end
break if payment_total >= total
yield payment

View File

@@ -19,8 +19,10 @@ class VoucherAdjustmentsService
# For now we just assume it is either all tax included in price or all tax excluded from price.
if order.additional_tax_total.positive?
handle_tax_excluded_from_price(order, amount)
else
elsif order.included_tax_total.positive?
handle_tax_included_in_price(order, amount)
else
adjustment.amount = amount
end
# Move to closed state

View File

@@ -1,155 +1,156 @@
.medium-6
= f.fields :bill_address, model: @order.bill_address do |bill_address|
%div.checkout-substep
-# YOUR DETAILS
%div.checkout-title
= t("split_checkout.step1.contact_information.title")
= form_with url: checkout_update_path(checkout_step), model: @order, method: :put, data: { remote: "true" } do |f|
.medium-6
= f.fields :bill_address, model: @order.bill_address do |bill_address|
%div.checkout-substep
-# YOUR DETAILS
%div.checkout-title
= t("split_checkout.step1.contact_information.title")
.two-columns-inputs
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= f.label :email, t("split_checkout.step1.contact_information.email.label")
= f.text_field :email, { placeholder: " " }
= f.error_message_on :email
.two-columns-inputs
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= f.label :email, t("split_checkout.step1.contact_information.email.label")
= f.text_field :email, { placeholder: " " }
= f.error_message_on :email
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= bill_address.label :phone, t("split_checkout.step1.contact_information.phone.label")
= bill_address.text_field :phone, { placeholder: " " }
= f.error_message_on "bill_address.phone"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= bill_address.label :phone, t("split_checkout.step1.contact_information.phone.label")
= bill_address.text_field :phone, { placeholder: " " }
= f.error_message_on "bill_address.phone"
%div.checkout-substep
-# BILLING ADDRESS
%div.checkout-title
= t("split_checkout.step1.billing_address.title")
%div.checkout-substep
-# BILLING ADDRESS
%div.checkout-title
= t("split_checkout.step1.billing_address.title")
.two-columns-inputs
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= bill_address.label :firstname, t("split_checkout.step1.billing_address.first_name.label")
= bill_address.text_field :firstname, { placeholder: " " }
= f.error_message_on "bill_address.firstname"
.two-columns-inputs
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= bill_address.label :firstname, t("split_checkout.step1.billing_address.first_name.label")
= bill_address.text_field :firstname, { placeholder: " " }
= f.error_message_on "bill_address.firstname"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= bill_address.label :lastname, t("split_checkout.step1.billing_address.last_name.label")
= bill_address.text_field :lastname, { placeholder: " " }
= f.error_message_on "bill_address.lastname"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= bill_address.label :address1, t("split_checkout.step1.address.address1.label")
= bill_address.text_field :address1, { placeholder: " " }
= f.error_message_on "bill_address.address1"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= bill_address.label :address2, t("split_checkout.step1.address.address2.label")
= bill_address.text_field :address2, { placeholder: " " }
= f.error_message_on "bill_address.address2"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= bill_address.label :city, t("split_checkout.step1.address.city.label")
= bill_address.text_field :city, { placeholder: " " }
= f.error_message_on "bill_address.city"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= bill_address.label :zipcode, t("split_checkout.step1.address.zipcode.label")
= bill_address.text_field :zipcode, { placeholder: " " }
= f.error_message_on "bill_address.zipcode"
%div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states }
- bill_address_country = @order.bill_address.country || DefaultCountry.country
%div.checkout-input
= bill_address.label :country_id, t("split_checkout.step1.address.country_id.label")
= bill_address.select :country_id, countries, { selected: bill_address_country.id }, { "data-dependent-select-target": "source", "data-action": "dependent-select#handleSelectChange" }
%div.checkout-input
= bill_address.label :state_id, t("split_checkout.step1.address.state_id.label")
= bill_address.select :state_id, states_for_country(bill_address_country), { selected: @order.bill_address&.state_id }, { "data-dependent-select-target": "select" }
- if spree_current_user
%div.checkout-input
= f.check_box :save_bill_address
= f.label :save_bill_address, t(:checkout_default_bill_address)
%div.checkout-substep{ "data-controller": "toggle shippingmethod" }
- selected_shipping_method = @order.shipping_method&.id || params[:shipping_method_id]
%div.checkout-title
= t("split_checkout.step1.shipping_info.title")
- display_ship_address = false
- ship_method_description = nil
- selected_shipping_method ||= @shipping_methods[0].id if @shipping_methods.length == 1
- @shipping_methods.each do |shipping_method|
- ship_method_is_selected = shipping_method.id == selected_shipping_method.to_i
%div.checkout-input.checkout-input-radio
= fields_for shipping_method do |shipping_method_form|
= shipping_method_form.radio_button :name, shipping_method.id,
id: "shipping_method_#{shipping_method.id}",
checked: ship_method_is_selected,
name: "shipping_method_id",
"data-requireAddress": shipping_method.require_ship_address,
"data-action": "toggle#toggle shippingmethod#selectShippingMethod",
"data-toggle-show": shipping_method.require_ship_address
= shipping_method_form.label shipping_method.id, shipping_method.name, {for: "shipping_method_" + shipping_method.id.to_s }
%em.fees= payment_or_shipping_price(shipping_method, @order)
- display_ship_address = display_ship_address || (ship_method_is_selected && shipping_method.require_ship_address)
%div.checkout-input{"data-shippingmethod-target": "shippingMethodDescription", "data-shippingmethodid": shipping_method.id , style: "display: #{ship_method_is_selected ? 'block' : 'none'}" }
#distributor_address.panel
- if shipping_method.description.present?
%span #{shipping_method.description}
%br/
%br/
- if @order.order_cycle.pickup_time_for(@order.distributor)
= t :checkout_ready_for
= @order.order_cycle.pickup_time_for(@order.distributor)
= f.error_message_on :shipping_method, standalone: true
%div.checkout-input{ "data-toggle-target": "content", style: "display: #{display_ship_address ? 'block' : 'none'}" }
= f.check_box :ship_address_same_as_billing, { id: "ship_address_same_as_billing", name: "ship_address_same_as_billing", "data-action": "shippingmethod#showHideShippingAddress", "data-shippingmethod-target": "shippingAddressCheckbox", checked: shipping_and_billing_match?(@order) }, 1, nil
= f.label :ship_address_same_as_billing, t(:checkout_address_same), { for: "ship_address_same_as_billing" }
%div{"data-shippingmethod-target": "shippingMethodAddress", style: "display: #{!display_ship_address || shipping_and_billing_match?(@order) ? 'none' : 'block'}" }
= f.fields :ship_address, model: @order.ship_address do |ship_address|
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :address1, t("split_checkout.step1.address.address1.label")
= ship_address.text_field :address1, { placeholder: " " }
= f.error_message_on "ship_address.address1"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
= bill_address.label :lastname, t("split_checkout.step1.billing_address.last_name.label")
= bill_address.text_field :lastname, { placeholder: " " }
= f.error_message_on "bill_address.lastname"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :address2, t("split_checkout.step1.address.address2.label")
= ship_address.text_field :address2, { placeholder: " " }
= f.error_message_on "ship_address.address2"
= bill_address.label :address1, t("split_checkout.step1.address.address1.label")
= bill_address.text_field :address1, { placeholder: " " }
= f.error_message_on "bill_address.address1"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :city, t("split_checkout.step1.address.city.label")
= ship_address.text_field :city, { placeholder: " " }
= f.error_message_on "ship_address.city"
= bill_address.label :address2, t("split_checkout.step1.address.address2.label")
= bill_address.text_field :address2, { placeholder: " " }
= f.error_message_on "bill_address.address2"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :zipcode, t("split_checkout.step1.address.zipcode.label")
= ship_address.text_field :zipcode, { placeholder: " " }
= f.error_message_on "ship_address.zipcode"
= bill_address.label :city, t("split_checkout.step1.address.city.label")
= bill_address.text_field :city, { placeholder: " " }
= f.error_message_on "bill_address.city"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= bill_address.label :zipcode, t("split_checkout.step1.address.zipcode.label")
= bill_address.text_field :zipcode, { placeholder: " " }
= f.error_message_on "bill_address.zipcode"
%div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states }
- ship_address_country = @order.ship_address.country || DefaultCountry.country
- bill_address_country = @order.bill_address.country || DefaultCountry.country
%div.checkout-input
= ship_address.label :country_id, t("split_checkout.step1.address.country_id.label")
= ship_address.select :country_id, countries, { selected: ship_address_country.id }, { "data-dependent-select-target": "source", "data-action": "dependent-select#handleSelectChange" }
= bill_address.label :country_id, t("split_checkout.step1.address.country_id.label")
= bill_address.select :country_id, countries, { selected: bill_address_country.id }, { "data-dependent-select-target": "source", "data-action": "dependent-select#handleSelectChange" }
%div.checkout-input
= ship_address.label :state_id, t("split_checkout.step1.address.state_id.label")
= ship_address.select :state_id, states_for_country(ship_address_country), { selected: @order.ship_address&.state_id }, { "data-dependent-select-target": "select" }
= bill_address.label :state_id, t("split_checkout.step1.address.state_id.label")
= bill_address.select :state_id, states_for_country(bill_address_country), { selected: @order.bill_address&.state_id }, { "data-dependent-select-target": "select" }
- if spree_current_user
%div.checkout-input
= f.check_box :save_bill_address
= f.label :save_bill_address, t(:checkout_default_bill_address)
%div.checkout-substep{ "data-controller": "toggle shippingmethod" }
- selected_shipping_method = @order.shipping_method&.id || params[:shipping_method_id]
%div.checkout-title
= t("split_checkout.step1.shipping_info.title")
- display_ship_address = false
- ship_method_description = nil
- selected_shipping_method ||= @shipping_methods[0].id if @shipping_methods.length == 1
- @shipping_methods.each do |shipping_method|
- ship_method_is_selected = shipping_method.id == selected_shipping_method.to_i
%div.checkout-input.checkout-input-radio
= fields_for shipping_method do |shipping_method_form|
= shipping_method_form.radio_button :name, shipping_method.id,
id: "shipping_method_#{shipping_method.id}",
checked: ship_method_is_selected,
name: "shipping_method_id",
"data-requireAddress": shipping_method.require_ship_address,
"data-action": "toggle#toggle shippingmethod#selectShippingMethod",
"data-toggle-show": shipping_method.require_ship_address
= shipping_method_form.label shipping_method.id, shipping_method.name, {for: "shipping_method_" + shipping_method.id.to_s }
%em.fees= payment_or_shipping_price(shipping_method, @order)
- display_ship_address = display_ship_address || (ship_method_is_selected && shipping_method.require_ship_address)
%div.checkout-input{"data-shippingmethod-target": "shippingMethodDescription", "data-shippingmethodid": shipping_method.id , style: "display: #{ship_method_is_selected ? 'block' : 'none'}" }
#distributor_address.panel
- if shipping_method.description.present?
%span #{shipping_method.description}
%br/
%br/
- if @order.order_cycle.pickup_time_for(@order.distributor)
= t :checkout_ready_for
= @order.order_cycle.pickup_time_for(@order.distributor)
= f.error_message_on :shipping_method, standalone: true
- if spree_current_user
%div.checkout-input{ "data-toggle-target": "content", style: "display: #{display_ship_address ? 'block' : 'none'}" }
= f.check_box :save_ship_address
= f.label :save_ship_address, t(:checkout_default_ship_address)
= f.check_box :ship_address_same_as_billing, { id: "ship_address_same_as_billing", name: "ship_address_same_as_billing", "data-action": "shippingmethod#showHideShippingAddress", "data-shippingmethod-target": "shippingAddressCheckbox", checked: shipping_and_billing_match?(@order) }, 1, nil
= f.label :ship_address_same_as_billing, t(:checkout_address_same), { for: "ship_address_same_as_billing" }
.div.checkout-input
= f.label :special_instructions, t(:checkout_instructions)
= f.text_area :special_instructions, size: "60x4"
%div{"data-shippingmethod-target": "shippingMethodAddress", style: "display: #{!display_ship_address || shipping_and_billing_match?(@order) ? 'none' : 'block'}" }
= f.fields :ship_address, model: @order.ship_address do |ship_address|
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :address1, t("split_checkout.step1.address.address1.label")
= ship_address.text_field :address1, { placeholder: " " }
= f.error_message_on "ship_address.address1"
%div.checkout-submit
= f.submit t("split_checkout.step1.submit"), class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false
%a.button.cancel{href: main_app.cart_path}
= t("split_checkout.step1.cancel")
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :address2, t("split_checkout.step1.address.address2.label")
= ship_address.text_field :address2, { placeholder: " " }
= f.error_message_on "ship_address.address2"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :city, t("split_checkout.step1.address.city.label")
= ship_address.text_field :city, { placeholder: " " }
= f.error_message_on "ship_address.city"
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
= ship_address.label :zipcode, t("split_checkout.step1.address.zipcode.label")
= ship_address.text_field :zipcode, { placeholder: " " }
= f.error_message_on "ship_address.zipcode"
%div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states }
- ship_address_country = @order.ship_address.country || DefaultCountry.country
%div.checkout-input
= ship_address.label :country_id, t("split_checkout.step1.address.country_id.label")
= ship_address.select :country_id, countries, { selected: ship_address_country.id }, { "data-dependent-select-target": "source", "data-action": "dependent-select#handleSelectChange" }
%div.checkout-input
= ship_address.label :state_id, t("split_checkout.step1.address.state_id.label")
= ship_address.select :state_id, states_for_country(ship_address_country), { selected: @order.ship_address&.state_id }, { "data-dependent-select-target": "select" }
- if spree_current_user
%div.checkout-input{ "data-toggle-target": "content", style: "display: #{display_ship_address ? 'block' : 'none'}" }
= f.check_box :save_ship_address
= f.label :save_ship_address, t(:checkout_default_ship_address)
.div.checkout-input
= f.label :special_instructions, t(:checkout_instructions)
= f.text_area :special_instructions, size: "60x4"
%div.checkout-submit
= f.submit t("split_checkout.step1.submit"), class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false
%a.button.cancel{href: main_app.cart_path}
= t("split_checkout.step1.cancel")

View File

@@ -1,8 +1,5 @@
- content_for :injection_data do
= inject_saved_credit_cards
%div.checkout-step{"class": if checkout_step?(:summary) then "checkout-summary" end}
= form_with url: checkout_update_path(checkout_step), model: @order, method: :put,
data: { remote: "true" } do |form|
= render "split_checkout/#{checkout_step}", f: form
%div.checkout-step{ class: "#{'checkout-summary' if checkout_step?(:summary)}" }
= render "split_checkout/#{checkout_step}"

View File

@@ -1,37 +1,44 @@
.medium-6
%div.checkout-substep{"data-controller": "paymentmethod"}
= render partial: "split_checkout/voucher_section", formats: [:cable_ready], locals: { order: @order, voucher_adjustment: @voucher_adjustment }
%div.checkout-title
= t("split_checkout.step2.payment_method.title")
.medium-6#checkout-payment-methods
- if feature?(:vouchers, spree_current_user) && @order.distributor.vouchers.present?
%div.checkout-substep
= render partial: "split_checkout/voucher_section", locals: { order: @order, voucher_adjustment: @order.voucher_adjustments.first }
- selected_payment_method = @order.payments&.with_state(:checkout)&.first&.payment_method_id
- selected_payment_method ||= available_payment_methods[0].id if available_payment_methods.length == 1
- available_payment_methods.each do |payment_method|
%div.checkout-input.checkout-input-radio
= f.radio_button :payment_method_id, payment_method.id,
id: "payment_method_#{payment_method.id}",
name: "order[payments_attributes][][payment_method_id]",
checked: (payment_method.id == selected_payment_method),
"data-action": "paymentmethod#selectPaymentMethod",
"data-paymentmethod-id": "#{payment_method.id}",
"data-paymentmethod-target": "input"
= f.label :payment_method_id, "#{payment_method.name}", for: "payment_method_#{payment_method.id}"
%em.fees=payment_or_shipping_price(payment_method, @order)
= form_with url: checkout_update_path(local_assigns[:step] || checkout_step), model: @order, method: :put, data: { remote: "true" } do |f|
%div.checkout-substep{"data-controller": "paymentmethod"}
%div.checkout-title
= t("split_checkout.step2.payment_method.title")
.paymentmethod-container{"data-paymentmethod-id": "#{payment_method.id}", style: "display: #{payment_method.id == selected_payment_method ? "block" : "none"}"}
- if payment_method.description && !payment_method.description.empty?
.paymentmethod-description.panel
#{payment_method.description}
.paymentmethod-form
= render partial: "split_checkout/payment/#{payment_method.method_type}", locals: { payment_method: payment_method, f: f }
- if @order.zero_priced_order?
%h3= t(:no_payment_required)
= hidden_field_tag "order[payments_attributes][][amount]", 0
- else
- selected_payment_method = @order.payments&.with_state(:checkout)&.first&.payment_method_id
- selected_payment_method ||= available_payment_methods[0].id if available_payment_methods.length == 1
- available_payment_methods.each do |payment_method|
%div.checkout-input.checkout-input-radio
= f.radio_button :payment_method_id, payment_method.id,
id: "payment_method_#{payment_method.id}",
name: "order[payments_attributes][][payment_method_id]",
checked: (payment_method.id == selected_payment_method),
"data-action": "paymentmethod#selectPaymentMethod",
"data-paymentmethod-id": "#{payment_method.id}",
"data-paymentmethod-target": "input"
= f.label :payment_method_id, "#{payment_method.name}", for: "payment_method_#{payment_method.id}"
%em.fees=payment_or_shipping_price(payment_method, @order)
= f.error_message_on :payment_method, standalone: true
%div.checkout-substep
= t("split_checkout.step2.explaination")
.paymentmethod-container{"data-paymentmethod-id": "#{payment_method.id}", style: "display: #{payment_method.id == selected_payment_method ? "block" : "none"}"}
- if payment_method.description && !payment_method.description.empty?
.paymentmethod-description.panel
#{payment_method.description}
.paymentmethod-form
= render partial: "split_checkout/payment/#{payment_method.method_type}", locals: { payment_method: payment_method, f: f }
%div.checkout-submit
= f.submit t("split_checkout.step2.submit"), class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false
%a.button.cancel{href: main_app.checkout_step_path(:details)}
= t("split_checkout.step2.cancel")
= f.error_message_on :payment_method, standalone: true
%div.checkout-substep
= t("split_checkout.step2.explaination")
%div.checkout-submit
= f.submit t("split_checkout.step2.submit"), class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false
%a.button.cancel{href: main_app.checkout_step_path(:details)}
= t("split_checkout.step2.cancel")

View File

@@ -1,103 +1,111 @@
.summary-main
= render partial: "split_checkout/already_ordered" if show_bought_items? && checkout_step?(:summary)
.checkout-substep
.checkout-title
= t("split_checkout.step3.delivery_details.title")
%a.summary-edit{href: main_app.checkout_step_path(:details)}
= t("split_checkout.step3.delivery_details.edit")
= form_with url: checkout_update_path(checkout_step), model: @order, method: :put, data: { remote: "true" } do |f|
.summary-main
= render partial: "split_checkout/already_ordered" if show_bought_items? && checkout_step?(:summary)
.checkout-substep
.checkout-title
= t("split_checkout.step3.delivery_details.title")
%a.summary-edit{href: main_app.checkout_step_path(:details)}
= t("split_checkout.step3.delivery_details.edit")
.summary-subtitle
= @order.shipping_method.name
%em.fees= payment_or_shipping_price(@order.shipping_method, @order)
.two-columns
%div
.summary-subtitle
= t("split_checkout.step3.delivery_details.address")
%span
= @order.bill_address.firstname
= @order.bill_address.lastname
%div
= @order.bill_address.phone
.summary-subtitle
= @order.shipping_method.name
%em.fees= payment_or_shipping_price(@order.shipping_method, @order)
.two-columns
%div
= @order.user.email if @order.user
%br
%div
= @order.bill_address.address1
- unless @order.bill_address.address2.blank?
.summary-subtitle
= t("split_checkout.step3.delivery_details.address")
%span
= @order.bill_address.firstname
= @order.bill_address.lastname
%div
= @order.bill_address.address2
%div
= @order.bill_address.city
%div
= @order.bill_address.state
%div
= @order.bill_address.zipcode
%div
= @order.bill_address.country
- if @order.special_instructions.present?
= @order.bill_address.phone
%div
= @order.user.email if @order.user
%br
%em
= @order.special_instructions
- if @order.shipping_method.description.present?
%div
.summary-subtitle
= t("split_checkout.step3.delivery_details.instructions")
%div
= @order.shipping_method.description
%hr
= @order.bill_address.address1
- unless @order.bill_address.address2.blank?
%div
= @order.bill_address.address2
%div
= @order.bill_address.city
%div
= @order.bill_address.state
%div
= @order.bill_address.zipcode
%div
= @order.bill_address.country
- if @order.special_instructions.present?
%br
%em
= @order.special_instructions
- if @order.shipping_method.description.present?
%div
.summary-subtitle
= t("split_checkout.step3.delivery_details.instructions")
%div
= @order.shipping_method.description
.checkout-substep
.checkout-title
= t("split_checkout.step3.payment_method.title")
%a.summary-edit{href: main_app.checkout_step_path(:payment)}
= t("split_checkout.step3.payment_method.edit")
.two-columns
%div
%hr
.checkout-substep
.checkout-title
= t("split_checkout.step3.payment_method.title")
%a.summary-edit{href: main_app.checkout_step_path(:payment)}
= t("split_checkout.step3.payment_method.edit")
.two-columns
- payment_method = last_payment_method(@order)
= payment_method&.name
%em.fees=payment_or_shipping_price(payment_method, @order)
- if payment_method&.description.present?
%div
.summary-subtitle
= t("split_checkout.step3.payment_method.instructions")
- if payment_method
= payment_method.name
%em.fees
= payment_or_shipping_price(payment_method, @order)
- elsif @order.zero_priced_order?
%h4= t(:no_payment_required)
- if payment_method&.description.present?
%div
= last_payment_method(@order)&.description
.summary-subtitle
= t("split_checkout.step3.payment_method.instructions")
%div
= payment_method&.description
%div.checkout-substep
%div.checkout-title
= t("split_checkout.step3.order.title")
%a.summary-edit{href: main_app.cart_path}
= t("split_checkout.step3.order.edit")
= render 'spree/orders/summary', order: @order, display_footer: false
%div.checkout-substep
%div.checkout-title
= t("split_checkout.step3.order.title")
%a.summary-edit{href: main_app.cart_path}
= t("split_checkout.step3.order.edit")
= render 'spree/orders/summary', order: @order, display_footer: false
.summary-right{ "data-controller": "sticky", "data-sticky-target": "container" }
.summary-right-line.total
.summary-right-line-label= t :order_total_price
.summary-right-line-value#order_total= @order.display_total.to_html
.summary-right-line
.summary-right-line-label= t :order_produce
.summary-right-line-value= display_checkout_subtotal(@order)
.summary-right{ "data-controller": "sticky", "data-sticky-target": "container" }
.summary-right-line.total
.summary-right-line-label= t :order_total_price
.summary-right-line-value#order_total= @order.display_total.to_html
- checkout_adjustments_for(@order, exclude: [:line_item]).reverse_each do |adjustment|
.summary-right-line
-if adjustment.originator_type == 'Voucher'
.summary-right-line-label.voucher= adjustment.label
.summary-right-line-value.voucher= adjustment.display_amount.to_html
-else
.summary-right-line-label= adjustment.label
.summary-right-line-value= adjustment.display_amount.to_html
.summary-right-line-label= t :order_produce
.summary-right-line-value= display_checkout_subtotal(@order)
- if @order.total_tax > 0
.summary-right-line
.summary-right-line-label= t :order_includes_tax
.summary-right-line-value#tax-row= display_checkout_tax_total(@order)
.checkout-submit
- if any_terms_required?(@order.distributor)
= render partial: "terms_and_conditions", locals: { f: f }
= f.submit t("split_checkout.step3.submit"), name: "confirm_order", class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false
- checkout_adjustments_for(@order, exclude: [:line_item]).reverse_each do |adjustment|
.summary-right-line
- if adjustment.originator_type == 'Voucher'
.summary-right-line-label.voucher
= "#{t(:voucher)}:"
= adjustment.label
.summary-right-line-value.voucher= adjustment.display_amount.to_html
- else
.summary-right-line-label= adjustment.label
.summary-right-line-value= adjustment.display_amount.to_html
- if @order.total_tax > 0
.summary-right-line
.summary-right-line-label= t :order_includes_tax
.summary-right-line-value#tax-row= display_checkout_tax_total(@order)
.checkout-submit
- if any_terms_required?(@order.distributor)
= render partial: "terms_and_conditions", locals: { f: f }
= f.submit t("split_checkout.step3.submit"), name: "confirm_order", class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false

View File

@@ -1,19 +0,0 @@
%div#voucher-section
- if order.distributor.vouchers.present?
.checkout-title
= t("split_checkout.step2.voucher.apply_voucher")
.checkout-input
.two-columns-inputs.voucher{"data-controller": "toggle-button-disabled"}
- if voucher_adjustment.present?
%span.button.voucher-added
%i.ofn-i_051-check-big
= t("split_checkout.step2.voucher.voucher", voucher_amount: voucher_adjustment.originator.display_value)
= link_to t("split_checkout.step2.voucher.remove_code"), voucher_adjustment_path(id: voucher_adjustment.id), method: "delete", data: { confirm: t("split_checkout.step2.voucher.confirm_delete") }
- # This might not be true, ie payment method including a fee which wouldn't be covered by voucher or tax implication raising total to be bigger than the voucher amount ?
- if voucher_adjustment.originator.amount > order.total
.checkout-input
%span.formError.standalone
= t("split_checkout.step2.voucher.warning_forfeit_remaining_amount")
- else
= text_field_tag "[order][voucher_code]", params.dig(:order, :voucher_code), data: { action: "input->toggle-button-disabled#inputIsChanged", }, placeholder: t("split_checkout.step2.voucher.placeholder") , class: "voucher"
= submit_tag t("split_checkout.step2.voucher.apply"), name: "apply_voucher", disabled: true, class: "button cancel voucher", "data-disable-with": false, data: { "toggle-button-disabled-target": "button" }

View File

@@ -0,0 +1,25 @@
%div#voucher-section
.checkout-title
= t("split_checkout.step2.voucher.apply_voucher")
.checkout-input{"data-controller": "toggle-button-disabled"}
= form_with url: voucher_adjustments_path, model: @order, method: :post, data: { remote: true } do |form|
- if voucher_adjustment.present?
.two-columns-inputs.voucher
%span.button.voucher-added
%i.ofn-i_051-check-big
= t("split_checkout.step2.voucher.voucher", voucher_amount: voucher_adjustment.originator.display_value)
= link_to t("split_checkout.step2.voucher.remove_code"), voucher_adjustment_path(id: voucher_adjustment.id), method: "delete", data: { confirm: t("split_checkout.step2.voucher.confirm_delete") }
- # This might not be true, ie payment method including a fee which wouldn't be covered by voucher or tax implication raising total to be bigger than the voucher amount ?
- if voucher_adjustment.originator.amount > order.pre_discount_total
.checkout-input
%span.formError.standalone
= t("split_checkout.step2.voucher.warning_forfeit_remaining_amount")
- else
.two-columns-inputs
%div.checkout-input
= form.text_field :voucher_code, value: params.dig(:order, :voucher_code), data: { action: "input->toggle-button-disabled#inputIsChanged" }, placeholder: t("split_checkout.step2.voucher.placeholder"), class: "voucher"
= form.error_message_on :voucher_code
%div.checkout-input
= form.submit t("split_checkout.step2.voucher.apply"), disabled: true, class: "button cancel voucher-button", "data-disable-with": false, data: { "toggle-button-disabled-target": "button" }

View File

@@ -1,15 +1,17 @@
- saved_credit_cards = spree_current_user&.credit_cards&.with_payment_profile.to_a
%div{"data-controller": "stripe-cards", "data-paymentmethod-id": "#{payment_method.id}" }
- if @saved_credit_cards.any?
- if saved_credit_cards.any?
.checkout-input
%label
= t('split_checkout.step2.form.stripe.use_saved_card')
= select_tag :existing_card_id,
options_for_select(stripe_card_options(@saved_credit_cards) + [[t('split_checkout.step2.form.stripe.create_new_card'), ""]], @selected_card),
options_for_select(stripe_card_options(saved_credit_cards) + [[t('split_checkout.step2.form.stripe.create_new_card'), ""]], nil),
{ "data-action": "change->stripe-cards#onSelectCard", "data-stripe-cards-target": "select" }
%div{"data-stripe-cards-target": "stripeelements"}
.checkout-input
- if @saved_credit_cards.none?
- if saved_credit_cards.none?
%label
= t('split_checkout.step2.form.stripe.use_new_card')

View File

@@ -11,7 +11,9 @@
%tr{class: "#{cycle('odd', 'even')}"}
%td= pretty_time(payment.created_at)
%td.align-center= payment.display_amount.to_html
%td.align-center= link_to payment_method_name(payment), spree.admin_order_payment_path(@order, payment)
%td.align-center
- if payment.payment_method_id
= link_to payment_method_name(payment), spree.admin_order_payment_path(@order, payment)
%td.align-center
%span{class: "state #{payment.state}"}= t(payment.state, scope: "spree.payment_states", default: payment.state.capitalize)
%td.actions

View File

@@ -12,6 +12,8 @@
%tr.total
%td.text-right{:colspan => "3"}
%strong
- if adjustment.originator_type == "Voucher"
= "#{t(:voucher)}:"
= adjustment.label
%td.text-right.total
%span= adjustment.display_amount.to_html

View File

@@ -11,11 +11,15 @@
%strong
= order.display_total.to_html
.pad
.text-big
= t :order_payment
%strong= last_payment_method(order)&.name
%p.text-small.text-skinny.pre-line.word-wrap
%em= last_payment_method(order)&.description
- if (order_payment_method = last_payment_method(order))
.text-big
= t :order_payment
%strong= order_payment_method&.name
%p.text-small.text-skinny.pre-line.word-wrap
%em= order_payment_method&.description
- else
.text-big
= t(:no_payment_required)
.order-summary.text-small
%strong

View File

@@ -412,22 +412,18 @@
justify-content: normal;
align-items: center;
input {
width: 50%;
}
a {
color: inherit;
}
}
.button {
&.cancel {
width: 30%;
border-radius: 0.5em;
padding:0;
height: 2.5em;
background-color: $teal-400
}
.voucher-button {
&.cancel {
width: 30%;
border-radius: 0.35em;
padding:0;
height: 2.5em;
background-color: $teal-400
}
}

View File

@@ -450,6 +450,7 @@ en:
none: None
notes: Notes
error: Error
voucher: Voucher
processing_payment: "Processing payment..."
no_pending_payments: "No pending payments"
invalid_payment_state: "Invalid payment state: %{state}"
@@ -2124,6 +2125,7 @@ en:
order_not_paid: NOT PAID
order_total: Total order
order_payment: "Paying via:"
no_payment_required: "No payment required"
order_billing_address: Billing address
order_delivery_on: Delivery on
order_delivery_address: Delivery address

View File

@@ -112,7 +112,7 @@ Openfoodnetwork::Application.routes.draw do
get '/:id/shop', to: 'enterprises#shop', as: 'enterprise_shop'
get "/enterprises/:permalink", to: redirect("/") # Legacy enterprise URL
resources :voucher_adjustments, only: [:destroy]
resources :voucher_adjustments, only: [:create, :destroy]
get 'sitemap.xml', to: 'sitemap#index', defaults: { format: 'xml' }

View File

@@ -23,7 +23,7 @@ module Reporting
def total_by_payment_method(orders, pay_method)
orders.map(&:payments).flatten.select { |payment|
payment.completed? && payment.payment_method.name.to_s.include?(pay_method)
payment.completed? && payment.payment_method&.name.to_s.include?(pay_method)
}.sum(&:amount)
end
end

View File

@@ -17,7 +17,7 @@ module Reporting
{
payment_state: proc { |payments| payment_state(payments.first.order) },
distributor: proc { |payments| payments.first.order.distributor.name },
payment_type: proc { |payments| payments.first.payment_method.name },
payment_type: proc { |payments| payments.first.payment_method&.name },
total_price: proc { |payments| payments.sum(&:amount) }
}
end

View File

@@ -212,6 +212,26 @@ describe SplitCheckoutController, type: :controller do
end
end
context "with a zero-priced order" do
let(:params) do
{ step: "payment", order: { payments_attributes: [{ amount: 0 }] } }
end
before do
order.line_items.first.update(price: 0)
order.update_totals_and_states
end
it "allows proceeding to confirmation" do
put :update, params: params
expect(response).to redirect_to checkout_step_path(:summary)
expect(order.reload.state).to eq "confirmation"
expect(order.payments.count).to eq 1
expect(order.payments.first.amount).to eq 0
end
end
context "with a saved credit card" do
let!(:saved_card) { create(:stored_credit_card, user: user) }
let(:checkout_params) do
@@ -233,73 +253,6 @@ describe SplitCheckoutController, type: :controller do
expect(order.payments.first.source.id).to eq saved_card.id
end
end
describe "Vouchers" do
let(:voucher) { create(:voucher, code: 'some_code', enterprise: distributor) }
describe "adding a voucher" do
let(:checkout_params) do
{
apply_voucher: "true",
order: {
voucher_code: voucher.code
}
}
end
it "adds a voucher to the order" do
# Set the headers to simulate a cable_ready request
request.headers["accept"] = "text/vnd.cable-ready.json"
put :update, params: params
expect(response.status).to eq(200)
expect(order.reload.voucher_adjustments.length).to eq(1)
end
context "when voucher doesn't exist" do
let(:checkout_params) do
{
apply_voucher: "true",
order: {
voucher_code: "non_voucher"
}
}
end
it "returns 422 and an error message" do
put :update, params: params
expect(response.status).to eq 422
expect(flash[:error]).to match "Voucher Not found"
end
end
context "when adding fails" do
it "returns 422 and an error message" do
# Create a non valid adjustment
adjustment = build(:adjustment, label: nil)
allow(voucher).to receive(:create_adjustment).and_return(adjustment)
allow(Voucher).to receive(:find_by).and_return(voucher)
put :update, params: params
expect(response.status).to eq 422
expect(flash[:error]).to match(
"There was an error while adding the voucher and Label can't be blank"
)
end
end
context "with an html request" do
it "redirects to the payment step" do
put :update, params: params
expect(response).to redirect_to(checkout_step_path(:payment))
end
end
end
end
end
context "summary step" do

View File

@@ -50,5 +50,22 @@ module Spree
order.process_payments!
end
context "with a zero-priced order" do
let!(:zero_order) {
create(:order, state: "payment", line_items: [create(:line_item, price: 0)])
}
let!(:zero_payment) { create(:payment, order: zero_order, amount: 0, state: "checkout") }
let(:updater) { OrderManagement::Order::Updater.new(zero_order) }
it "processes payments successfully" do
zero_order.process_payments!
updater.update_payment_state
expect(zero_order.payment_state).to eq "paid"
expect(zero_payment.reload.state).to eq "completed"
expect(zero_payment.captured_at).to_not be_nil
end
end
end
end

View File

@@ -4,55 +4,96 @@ require 'spec_helper'
describe VoucherAdjustmentsController, type: :request do
let(:user) { order.user }
let(:address) { create(:address) }
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:order) { create( :order_with_line_items, line_items_count: 1, distributor: distributor) }
let(:order_cycle) { create(:order_cycle, distributors: [distributor]) }
let(:exchange) { order_cycle.exchanges.outgoing.first }
let(:order) do
create(
:order_with_line_items,
line_items_count: 1,
distributor: distributor,
order_cycle: order_cycle,
bill_address: address,
ship_address: address
)
end
let(:shipping_method) { distributor.shipping_methods.first }
let(:voucher) { create(:voucher, code: 'some_code', enterprise: distributor) }
let!(:adjustment) { voucher.create_adjustment(voucher.code, order) }
before do
# Make sure the order is created by the order user, the factory doesn't set ip properly
order.created_by = user
order.save!
order.update!(created_by: user)
order.select_shipping_method shipping_method.id
OrderWorkflow.new(order).advance_to_payment
sign_in user
end
describe "DELETE voucher_adjustments/:id" do
let(:cable_ready_header) { { accept: "text/vnd.cable-ready.json" } }
describe "POST voucher_adjustments" do
let(:params) { { order: { voucher_code: voucher.code } } }
context "with a cable ready request" do
it "deletes the voucher adjustment" do
delete("/voucher_adjustments/#{adjustment.id}", headers: cable_ready_header)
it "adds a voucher to the user's current order" do
post "/voucher_adjustments", params: params
expect(order.voucher_adjustments.length).to eq(0)
end
expect(response).to be_successful
expect(order.reload.voucher_adjustments.length).to eq(1)
end
it "render a succesful response" do
delete("/voucher_adjustments/#{adjustment.id}", headers: cable_ready_header)
context "when voucher doesn't exist" do
let(:params) { { order: { voucher_code: "non_voucher" } } }
expect(response).to be_successful
end
it "returns 422 and an error message" do
post "/voucher_adjustments", params: params
context "when adjustment doesn't exits" do
it "does nothing" do
delete "/voucher_adjustments/-1", headers: cable_ready_header
expect(order.voucher_adjustments.length).to eq(1)
end
it "render a succesful response" do
delete "/voucher_adjustments/-1", headers: cable_ready_header
expect(response).to be_successful
end
expect(response).to be_unprocessable
expect(flash[:error]).to match "Voucher code Not found"
end
end
context "with an html request" do
it "redirect to checkout payment step" do
delete "/voucher_adjustments/#{adjustment.id}"
context "when adding fails" do
it "returns 422 and an error message" do
# Create a non valid adjustment
bad_adjustment = build(:adjustment, label: nil)
allow(voucher).to receive(:create_adjustment).and_return(bad_adjustment)
allow(Voucher).to receive(:find_by).and_return(voucher)
expect(response).to redirect_to(checkout_step_path(:payment))
post "/voucher_adjustments", params: params
expect(response).to be_unprocessable
expect(flash[:error]).to match(
"There was an error while adding the voucher and Label can't be blank"
)
end
end
end
describe "DELETE voucher_adjustments/:id" do
let!(:adjustment) { voucher.create_adjustment(voucher.code, order) }
it "deletes the voucher adjustment" do
delete "/voucher_adjustments/#{adjustment.id}"
expect(order.voucher_adjustments.reload.length).to eq(0)
end
it "render a success response" do
delete "/voucher_adjustments/#{adjustment.id}"
expect(response).to be_successful
end
context "when adjustment doesn't exits" do
it "does nothing" do
delete "/voucher_adjustments/-1"
expect(order.voucher_adjustments.reload.length).to eq(1)
end
it "render a success response" do
delete "/voucher_adjustments/-1"
expect(response).to be_successful
end
end
end

View File

@@ -707,6 +707,8 @@ describe "As a consumer, I want to checkout my order" do
end
describe "vouchers" do
before { Flipper.enable :vouchers }
context "with no voucher available" do
before do
visit checkout_step_path(:payment)
@@ -769,7 +771,7 @@ describe "As a consumer, I want to checkout my order" do
fill_in "Enter voucher code", with: "non_code"
click_button("Apply")
expect(page).to have_content("Voucher Not found")
expect(page).to have_content("Voucher code Not found")
end
end
end
@@ -786,9 +788,10 @@ describe "As a consumer, I want to checkout my order" do
click_on "Remove code"
end
within '.voucher' do
within '#voucher-section' do
expect(page).to have_button("Apply", disabled: true)
end
expect(order.voucher_adjustments.length).to eq(0)
end
end

View File

@@ -106,6 +106,8 @@ describe "As a consumer, I want to see adjustment breakdown" do
end
context "when using a voucher" do
before { Flipper.enable :vouchers }
let!(:voucher) do
create(:voucher, code: 'some_code', enterprise: distributor, amount: 10)
end

View File

@@ -63,6 +63,7 @@ describe "As a consumer, I want to see adjustment breakdown" do
before do
# assures tax is charged in dependence of shipping address
Spree::Config.set(tax_using_ship_address: true)
Flipper.enable :vouchers
end
describe "a not-included tax" do
@@ -115,7 +116,7 @@ describe "As a consumer, I want to see adjustment breakdown" do
expect(page).to have_selector('#tax-row', text: with_currency(1.30))
end
pending "when using a voucher" do
context "when using a voucher" do
let!(:voucher) do
create(:voucher, code: 'some_code', enterprise: distributor, amount: 10)
end
@@ -126,9 +127,11 @@ describe "As a consumer, I want to see adjustment breakdown" do
choose "Delivery"
click_button "Next - Payment method"
# add Voucher
fill_in "Enter voucher code", with: voucher.code
click_button("Apply")
expect(page).to have_selector ".voucher-added"
click_on "Next - Order summary"
click_on "Complete order"