mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-04 02:31:33 +00:00
Merge branch 'master' into 8457-missng-translation-or-between-buttons
This commit is contained in:
29
Gemfile.lock
29
Gemfile.lock
@@ -106,8 +106,8 @@ GEM
|
||||
activerecord (6.1.4.4)
|
||||
activemodel (= 6.1.4.4)
|
||||
activesupport (= 6.1.4.4)
|
||||
activerecord-import (1.2.0)
|
||||
activerecord (>= 3.2)
|
||||
activerecord-import (1.3.0)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
pg
|
||||
activerecord-session_store (2.0.0)
|
||||
@@ -220,9 +220,10 @@ GEM
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
ddtrace (0.53.0)
|
||||
ffi (~> 1.0)
|
||||
ddtrace (0.54.1)
|
||||
debase-ruby_core_source (= 0.10.12)
|
||||
msgpack
|
||||
debase-ruby_core_source (0.10.12)
|
||||
debugger-linecache (1.2.0)
|
||||
devise (4.8.0)
|
||||
bcrypt (~> 3.0)
|
||||
@@ -269,7 +270,7 @@ GEM
|
||||
concurrent-ruby (~> 1.1)
|
||||
websocket-driver (>= 0.6, < 0.8)
|
||||
ffaker (2.20.0)
|
||||
ffi (1.15.4)
|
||||
ffi (1.15.5)
|
||||
flipper (0.20.4)
|
||||
flipper-active_record (0.20.4)
|
||||
activerecord (>= 5.0, < 7)
|
||||
@@ -344,7 +345,7 @@ GEM
|
||||
letter_opener (1.7.0)
|
||||
launchy (~> 2.2)
|
||||
libv8-node (15.14.0.1)
|
||||
listen (3.7.0)
|
||||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.13.0)
|
||||
@@ -398,7 +399,7 @@ GEM
|
||||
parallel (1.21.0)
|
||||
paranoia (2.4.3)
|
||||
activerecord (>= 4.0, < 6.2)
|
||||
parser (3.0.2.0)
|
||||
parser (3.1.0.0)
|
||||
ast (~> 2.4.1)
|
||||
paypal-sdk-core (0.3.4)
|
||||
multi_json (~> 1.0)
|
||||
@@ -461,9 +462,9 @@ GEM
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.4.2)
|
||||
loofah (~> 2.3)
|
||||
rails-i18n (6.0.0)
|
||||
rails-i18n (7.0.1)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 7)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (6.1.4.4)
|
||||
actionpack (= 6.1.4.4)
|
||||
@@ -471,7 +472,7 @@ GEM
|
||||
method_source
|
||||
rake (>= 0.13)
|
||||
thor (~> 1.0)
|
||||
rainbow (3.0.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
ransack (2.4.2)
|
||||
activerecord (>= 5.2.4)
|
||||
@@ -482,7 +483,7 @@ GEM
|
||||
ffi (~> 1.0)
|
||||
redcarpet (3.5.1)
|
||||
redis (4.5.1)
|
||||
regexp_parser (2.1.1)
|
||||
regexp_parser (2.2.0)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
responders (3.0.1)
|
||||
@@ -547,9 +548,9 @@ GEM
|
||||
rubocop-ast (>= 1.12.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.12.0)
|
||||
rubocop-ast (1.15.1)
|
||||
parser (>= 3.0.1.1)
|
||||
rubocop-rails (2.12.4)
|
||||
rubocop-rails (2.13.2)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.7.0, < 2.0)
|
||||
@@ -613,7 +614,7 @@ GEM
|
||||
activerecord (>= 5.1)
|
||||
state_machines-activemodel (>= 0.8.0)
|
||||
stringex (2.8.5)
|
||||
stripe (5.39.0)
|
||||
stripe (5.42.0)
|
||||
temple (0.8.2)
|
||||
test-prof (1.0.7)
|
||||
test-unit (3.5.0)
|
||||
|
||||
@@ -3,3 +3,9 @@ angular.module('Darkswarm').directive 'auth', (AuthenticationService) ->
|
||||
link: (scope, elem, attrs) ->
|
||||
elem.bind "click", ->
|
||||
AuthenticationService.open '/' + attrs.auth
|
||||
|
||||
window.addEventListener "login:modal:open", ->
|
||||
AuthenticationService.open '/login'
|
||||
|
||||
scope.$on "$destroy", ->
|
||||
window.removeEventListener "login:modal:open"
|
||||
|
||||
@@ -16,16 +16,10 @@ class SplitCheckoutController < ::BaseController
|
||||
helper OrderHelper
|
||||
|
||||
def edit
|
||||
return redirect_to_step unless params[:step]
|
||||
|
||||
return redirect_to_guest if !spree_current_user &&
|
||||
!@order.distributor.allow_guest_orders? &&
|
||||
params[:step] != "guest"
|
||||
redirect_to_step unless params[:step]
|
||||
end
|
||||
|
||||
def update
|
||||
return redirect_to_guest if !spree_current_user && !@order.distributor.allow_guest_orders?
|
||||
|
||||
if confirm_order || update_order
|
||||
clear_invalid_payments
|
||||
advance_order_state
|
||||
@@ -33,10 +27,9 @@ class SplitCheckoutController < ::BaseController
|
||||
else
|
||||
flash.now[:error] = I18n.t('split_checkout.errors.global')
|
||||
|
||||
render operations: cable_car.
|
||||
render status: :unprocessable_entity, operations: cable_car.
|
||||
replace("#checkout", partial("split_checkout/checkout")).
|
||||
replace("#flashes", partial("shared/flashes", locals: { flashes: flash })),
|
||||
status: :unprocessable_entity
|
||||
replace("#flashes", partial("shared/flashes", locals: { flashes: flash }))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,9 +40,10 @@ class SplitCheckoutController < ::BaseController
|
||||
end
|
||||
|
||||
def confirm_order
|
||||
return unless @order.confirmation? && params[:confirm_order]
|
||||
return unless summary_step? && @order.confirmation?
|
||||
return unless validate_summary! && @order.errors.empty?
|
||||
|
||||
@order.customer.touch :terms_and_conditions_accepted_at
|
||||
@order.confirm!
|
||||
end
|
||||
|
||||
@@ -58,17 +52,27 @@ class SplitCheckoutController < ::BaseController
|
||||
|
||||
@order.select_shipping_method(params[:shipping_method_id])
|
||||
@order.update(order_params)
|
||||
send("validate_#{params[:step]}!")
|
||||
|
||||
validate_current_step!
|
||||
|
||||
@order.errors.empty?
|
||||
end
|
||||
|
||||
def summary_step?
|
||||
params[:step] == "summary"
|
||||
end
|
||||
|
||||
def advance_order_state
|
||||
return if @order.complete?
|
||||
|
||||
OrderWorkflow.new(@order).advance_checkout(raw_params.slice(:shipping_method_id))
|
||||
end
|
||||
|
||||
def validate_current_step!
|
||||
step = ([params[:step]] & ["details", "payment", "summary"]).first
|
||||
send("validate_#{step}!")
|
||||
end
|
||||
|
||||
def validate_details!
|
||||
return true if params[:shipping_method_id].present?
|
||||
|
||||
@@ -83,6 +87,7 @@ class SplitCheckoutController < ::BaseController
|
||||
|
||||
def validate_summary!
|
||||
return true if params[:accept_terms]
|
||||
return true unless TermsOfService.required?(@order.distributor)
|
||||
|
||||
@order.errors.add(:terms_and_conditions, t("split_checkout.errors.terms_not_accepted"))
|
||||
end
|
||||
@@ -91,13 +96,7 @@ class SplitCheckoutController < ::BaseController
|
||||
@order_params ||= Checkout::Params.new(@order, params).call
|
||||
end
|
||||
|
||||
def redirect_to_guest
|
||||
redirect_to checkout_step_path(:guest)
|
||||
end
|
||||
|
||||
def redirect_to_step
|
||||
return redirect_to_guest if !spree_current_user && !params[:step]
|
||||
|
||||
case @order.state
|
||||
when "cart", "address", "delivery"
|
||||
redirect_to checkout_step_path(:details)
|
||||
|
||||
@@ -7,21 +7,25 @@ module TermsAndConditionsHelper
|
||||
end
|
||||
|
||||
def render_terms_and_conditions
|
||||
if platform_terms_required? && terms_and_conditions_activated?
|
||||
if platform_terms_required? && distributor_terms_required?
|
||||
render("checkout/all_terms_and_conditions")
|
||||
elsif platform_terms_required?
|
||||
render "checkout/platform_terms_of_service"
|
||||
elsif terms_and_conditions_activated?
|
||||
elsif distributor_terms_required?
|
||||
render "checkout/terms_and_conditions"
|
||||
end
|
||||
end
|
||||
|
||||
def platform_terms_required?
|
||||
Spree::Config.shoppers_require_tos
|
||||
def any_terms_required?(distributor)
|
||||
TermsOfService.required?(distributor)
|
||||
end
|
||||
|
||||
def terms_and_conditions_activated?
|
||||
current_order.distributor.terms_and_conditions.file?
|
||||
def platform_terms_required?
|
||||
TermsOfService.platform_terms_required?
|
||||
end
|
||||
|
||||
def distributor_terms_required?
|
||||
TermsOfService.distributor_terms_required?(current_order.distributor)
|
||||
end
|
||||
|
||||
def all_terms_and_conditions_already_accepted?
|
||||
|
||||
@@ -30,7 +30,7 @@ module Spree
|
||||
go_to_state :complete
|
||||
end
|
||||
|
||||
attr_accessor :use_billing, :checkout_processing
|
||||
attr_accessor :use_billing, :checkout_processing, :save_bill_address, :save_ship_address
|
||||
|
||||
token_resource
|
||||
|
||||
@@ -104,6 +104,8 @@ module Spree
|
||||
before_save :update_shipping_fees!, if: :complete?
|
||||
before_save :update_payment_fees!, if: :complete?
|
||||
|
||||
after_save_commit DefaultAddressUpdater
|
||||
|
||||
# -- Scopes
|
||||
scope :not_empty, -> {
|
||||
left_outer_joins(:line_items).where.not(spree_line_items: { id: nil })
|
||||
|
||||
@@ -24,6 +24,7 @@ module Checkout
|
||||
def apply_strong_parameters
|
||||
@order_params = params.require(:order).permit(
|
||||
:email, :shipping_method_id, :special_instructions, :existing_card_id,
|
||||
:save_bill_address, :save_ship_address,
|
||||
bill_address_attributes: ::PermittedAttributes::Address.attributes,
|
||||
ship_address_attributes: ::PermittedAttributes::Address.attributes,
|
||||
payments_attributes: [
|
||||
|
||||
42
app/services/default_address_updater.rb
Normal file
42
app/services/default_address_updater.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class DefaultAddressUpdater
|
||||
def self.after_commit(order)
|
||||
return unless order.save_bill_address || order.save_ship_address
|
||||
|
||||
new(order).call
|
||||
end
|
||||
|
||||
def initialize(order)
|
||||
@order = order
|
||||
end
|
||||
|
||||
def call
|
||||
assign_bill_addresses
|
||||
assign_ship_addresses
|
||||
|
||||
customer.save
|
||||
user&.save
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :order
|
||||
|
||||
delegate :save_ship_address, :save_bill_address, :customer, :user,
|
||||
:bill_address_id, :ship_address_id, to: :order
|
||||
|
||||
def assign_bill_addresses
|
||||
return unless save_bill_address
|
||||
|
||||
customer.bill_address_id = bill_address_id
|
||||
user&.bill_address_id = bill_address_id
|
||||
end
|
||||
|
||||
def assign_ship_addresses
|
||||
return unless save_ship_address
|
||||
|
||||
customer.ship_address_id = ship_address_id
|
||||
user&.ship_address_id = ship_address_id
|
||||
end
|
||||
end
|
||||
@@ -10,4 +10,16 @@ class TermsOfService
|
||||
TermsOfServiceFile.updated_at
|
||||
end
|
||||
end
|
||||
|
||||
def self.required?(distributor)
|
||||
platform_terms_required? || distributor_terms_required?(distributor)
|
||||
end
|
||||
|
||||
def self.platform_terms_required?
|
||||
Spree::Config.shoppers_require_tos
|
||||
end
|
||||
|
||||
def self.distributor_terms_required?(distributor)
|
||||
distributor.terms_and_conditions.file?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%checkout.row#checkout
|
||||
.small-12.medium-12.columns
|
||||
= render partial: "split_checkout/tabs" unless checkout_step?(:guest)
|
||||
= render partial: "split_checkout/tabs"
|
||||
= render partial: "split_checkout/form"
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
|
||||
- if spree_current_user||true
|
||||
%div.checkout-input
|
||||
= f.check_box :checkout_default_bill_address
|
||||
= f.label :checkout_default_bill_address, t(:checkout_default_bill_address)
|
||||
= 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]
|
||||
@@ -136,8 +136,8 @@
|
||||
|
||||
- if spree_current_user
|
||||
%div.checkout-input{ "data-toggle-target": "content", style: "display: none" }
|
||||
= f.check_box :default_ship_address, { id: "default_ship_address", name: "default_ship_address" }
|
||||
= f.label :default_ship_address, t(:checkout_default_ship_address), { for: "default_ship_address" }
|
||||
= 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)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
.medium-10
|
||||
%div.checkout-guest-title
|
||||
= t :checkout_headline
|
||||
.checkout-step
|
||||
.medium-10
|
||||
%div.checkout-guest-title
|
||||
= t :checkout_headline
|
||||
|
||||
%div.checkout-submit{ class: "#{@order.distributor.allow_guest_orders? ? 'checkout-submit-inline' : 'medium-6' }" }
|
||||
%a.primary.button{href: main_app.login_path}
|
||||
= t :label_login
|
||||
-if @order.distributor.allow_guest_orders?
|
||||
%span.checkout-submit-or
|
||||
%div.checkout-submit{ class: "#{@order.distributor.allow_guest_orders? ? 'checkout-submit-inline' : 'medium-6' }" }
|
||||
%button.button.primary{ "data-action": "click->guest-checkout#login" }
|
||||
= t :label_login
|
||||
-if @order.distributor.allow_guest_orders?
|
||||
%span.checkout-submit-or
|
||||
|
||||
%button.button.cancel{ "data-action": "click->guest-checkout#guestSelected" }
|
||||
= t :checkout_as_guest
|
||||
|
||||
%a.button.cancel{href: main_app.checkout_step_path(:details)}
|
||||
= t :checkout_as_guest
|
||||
|
||||
@@ -71,15 +71,16 @@
|
||||
|
||||
= render 'spree/orders/summary', order: @order
|
||||
|
||||
%div.checkout-substep.medium-6
|
||||
%div.checkout-input
|
||||
= f.check_box :accept_terms, { id: "accept_terms", name: "accept_terms", "checked": "#{all_terms_and_conditions_already_accepted?}" }, 1, nil
|
||||
= f.label :accept_terms, t('split_checkout.step3.terms_and_conditions.message_html', terms_and_conditions_link: link_to( t("split_checkout.step3.terms_and_conditions.link_text"), @order.distributor.terms_and_conditions.url, target: '_blank'), tos_link: link_to_platform_terms), { for: "accept_terms" }
|
||||
- if any_terms_required?(@order.distributor)
|
||||
%div.checkout-substep.medium-6
|
||||
%div.checkout-input
|
||||
= f.check_box :accept_terms, { id: "accept_terms", name: "accept_terms", "checked": "#{all_terms_and_conditions_already_accepted?}" }, 1, nil
|
||||
= f.label :accept_terms, t('split_checkout.step3.terms_and_conditions.message_html', terms_and_conditions_link: link_to( t("split_checkout.step3.terms_and_conditions.link_text"), @order.distributor.terms_and_conditions.url, target: '_blank'), tos_link: link_to_platform_terms), { for: "accept_terms" }
|
||||
|
||||
= f.error_message_on :terms_and_conditions, standalone: true
|
||||
= f.error_message_on :terms_and_conditions, standalone: true
|
||||
|
||||
%div.checkout-input
|
||||
= t("split_checkout.step3.agree")
|
||||
%div.checkout-input
|
||||
= t("split_checkout.step3.agree")
|
||||
|
||||
%div.checkout-submit.medium-6
|
||||
= f.submit t("split_checkout.step3.submit"), name: "confirm_order", class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
.sub-header.show-for-medium-down
|
||||
= render partial: "shopping_shared/order_cycles"
|
||||
|
||||
= render partial: "checkout"
|
||||
.row{ "data-controller": "guest-checkout", "data-guest-checkout-distributor-value": @order.distributor.id }
|
||||
%div{ style: "display: #{spree_current_user ? 'block' : 'none'}", "data-guest-checkout-target": "checkout" }
|
||||
= render partial: "checkout"
|
||||
|
||||
- unless spree_current_user
|
||||
%div{ style: "display: block", "data-guest-checkout-target": "guest" }
|
||||
= render partial: "guest"
|
||||
|
||||
= render partial: "shared/footer"
|
||||
|
||||
35
app/webpacker/controllers/guest_checkout_controller.js
Normal file
35
app/webpacker/controllers/guest_checkout_controller.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Controller } from "stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["checkout", "guest"];
|
||||
static values = {
|
||||
distributor: String,
|
||||
session: { type: String, default: "guest-checkout" }
|
||||
};
|
||||
|
||||
connect() {
|
||||
if(!this.hasGuestTarget) { return }
|
||||
|
||||
if(this.usingGuestCheckout()) {
|
||||
this.showCheckout();
|
||||
}
|
||||
}
|
||||
|
||||
login() {
|
||||
window.dispatchEvent(new Event("login:modal:open"))
|
||||
}
|
||||
|
||||
showCheckout() {
|
||||
this.checkoutTarget.style.display = "block";
|
||||
this.guestTarget.style.display = "none";
|
||||
}
|
||||
|
||||
guestSelected() {
|
||||
this.showCheckout();
|
||||
sessionStorage.setItem(this.sessionValue, this.distributorValue);
|
||||
}
|
||||
|
||||
usingGuestCheckout() {
|
||||
return sessionStorage.getItem(this.sessionValue) === this.distributorValue
|
||||
}
|
||||
}
|
||||
@@ -1353,6 +1353,7 @@ de_DE:
|
||||
terms_and_conditions: "Allgemeinen Geschäftsbedingungen (AGB)"
|
||||
failed: "Der Bestellabschluss ist fehlgeschlagen. Bitte geben Sie uns Bescheid, damit wir Ihre Bestellung dennoch bearbeiten können."
|
||||
payment_cancelled_due_to_stock: "Zahlung storniert: Der Bestellabschluss konnte aufgrund von Problemen mit dem Lagerbestand nicht abgeschlossen werden."
|
||||
order_not_loaded: "Keine gültige Bestellung für den Bestellabschluss gefunden."
|
||||
shops:
|
||||
hubs:
|
||||
show_closed_shops: "Geschlossene Läden anzeigen"
|
||||
@@ -3215,7 +3216,6 @@ de_DE:
|
||||
notice_messages:
|
||||
variant_deleted: "Produktvariante wurde gelöscht"
|
||||
or: "oder"
|
||||
order_processed_successfully: "Ihre Bestellung wurde erfolgreich verarbeitet."
|
||||
payment_method_not_supported: "Zahlungsart wird nicht unterstützt"
|
||||
resend_authorization_email: "Autorisierungs-E-Mail erneut senden"
|
||||
rma_credit: "Gutschrift aus Retour"
|
||||
|
||||
@@ -1351,6 +1351,7 @@ en_FR:
|
||||
terms_and_conditions: "Terms and Conditions"
|
||||
failed: "The checkout failed. Please let us know so that we can process your order."
|
||||
payment_cancelled_due_to_stock: "Payment cancelled: the checkout could not be completed due to stock issues."
|
||||
order_not_loaded: "No valid order found for checkout processing"
|
||||
shops:
|
||||
hubs:
|
||||
show_closed_shops: "Show closed shops"
|
||||
@@ -3206,7 +3207,6 @@ en_FR:
|
||||
notice_messages:
|
||||
variant_deleted: "Variant deleted"
|
||||
or: "Or"
|
||||
order_processed_successfully: "Order processed successfully"
|
||||
payment_method_not_supported: "Payment method not supported"
|
||||
resend_authorization_email: "Resend authorization email"
|
||||
rma_credit: "RMA credit"
|
||||
|
||||
@@ -1353,6 +1353,7 @@ fr:
|
||||
terms_and_conditions: "CGU & CGV"
|
||||
failed: "La validation du paiement a échoué. Contactez-nous afin de finaliser votre commande."
|
||||
payment_cancelled_due_to_stock: "Paiement annulé : la commande n'a pas été finalisée car un ou plusieurs articles ne sont plus en stock."
|
||||
order_not_loaded: "Aucune commande n'a été trouvée pour poursuivre le parcours d'achat."
|
||||
shops:
|
||||
hubs:
|
||||
show_closed_shops: "Afficher les boutiques fermées"
|
||||
@@ -3235,7 +3236,6 @@ fr:
|
||||
notice_messages:
|
||||
variant_deleted: "Variante supprimée"
|
||||
or: "Ou"
|
||||
order_processed_successfully: "Commande traitée avec succès"
|
||||
payment_method_not_supported: "Mode de paiement non pris en charge"
|
||||
resend_authorization_email: "Renvoyer l'e-mail d'autorisation"
|
||||
rma_credit: "Crédit ARM"
|
||||
|
||||
@@ -72,6 +72,44 @@ ru:
|
||||
missing: "У клиента нет карты, с которой начисляется оплата."
|
||||
processing_error: "Произошла ошибка при обработке карты."
|
||||
rate_limit: "Произошла ошибка из-за того, что запросы попали в API слишком быстро. Сообщите нам, если вы постоянно сталкиваетесь с этой ошибкой."
|
||||
authentication_required: "Карта была отклонена, так как транзакция требует аутентификации."
|
||||
approve_with_id: "Платеж не может быть авторизован."
|
||||
call_issuer: "Карта была отклонена по неизвестной причине."
|
||||
card_not_supported: "Карта не поддерживает этот тип покупки."
|
||||
card_velocity_exceeded: "Клиент превысил баланс или кредитный лимит, доступный на его карте."
|
||||
currency_not_supported: "Карта не поддерживает указанную валюту."
|
||||
do_not_honor: "Карта была отклонена по неизвестной причине."
|
||||
do_not_try_again: "Карта была отклонена по неизвестной причине."
|
||||
duplicate_transaction: "Слишком часто была отправлена транзакция с одинаковой суммой и данными кредитной карты."
|
||||
fraudulent: "Платеж был отклонен, так как Stripe подозревает, что это мошенничество."
|
||||
generic_decline: "Карта была отклонена по неизвестной причине."
|
||||
incorrect_pin: "Введен неверный PIN-код. Этот код отклонения применяется только к платежам, совершенным с помощью устройства для чтения карт."
|
||||
insufficient_funds: "На карте недостаточно средств для совершения покупки."
|
||||
invalid_account: "Карта или счет, к которому привязана карта, недействительны."
|
||||
invalid_amount: "Сумма платежа недействительна или превышает допустимую сумму."
|
||||
invalid_pin: "Введен неверный PIN-код. Этот код отклонения применяется только к платежам, совершенным с помощью устройства для чтения карт."
|
||||
issuer_not_available: "Не удалось связаться с эмитентом карты, поэтому платеж не мог быть авторизован."
|
||||
lost_card: "Платеж был отклонен, поскольку заявлено, что карта утеряна."
|
||||
merchant_blacklist: "Платеж был отклонен, поскольку пользователь Stripe в черном списке."
|
||||
new_account_information_available: "Карта или счет, к которому привязана карта, недействительны."
|
||||
no_action_taken: "Карта была отклонена по неизвестной причине."
|
||||
not_permitted: "Оплата не разрешена."
|
||||
offline_pin_required: "Карта была отклонена, так как требует PIN-код."
|
||||
online_or_offline_pin_required: "Карта была отклонена, так как требует PIN-код."
|
||||
pickup_card: "Карту нельзя использовать для этого платежа (возможно, она была утеряна или украдена)."
|
||||
pin_try_exceeded: "Превышено допустимое количество попыток ввода PIN-кода."
|
||||
reenter_transaction: "Платеж не может быть обработан эмитентом по неизвестной причине."
|
||||
restricted_card: "Карту нельзя использовать для этого платежа (возможно, она была утеряна или украдена)."
|
||||
revocation_of_all_authorizations: "Карта была отклонена по неизвестной причине."
|
||||
revocation_of_authorization: "Карта была отклонена по неизвестной причине."
|
||||
security_violation: "Карта была отклонена по неизвестной причине."
|
||||
service_not_allowed: "Карта была отклонена по неизвестной причине."
|
||||
stolen_card: "Платеж был отклонен, поскольку карта была украдена."
|
||||
stop_payment_order: "Карта была отклонена по неизвестной причине."
|
||||
testmode_decline: "Был использован номер тестовой карты Stripe."
|
||||
transaction_not_allowed: "Карта была отклонена по неизвестной причине."
|
||||
try_again_later: "Карта была отклонена по неизвестной причине."
|
||||
withdrawal_count_limit_exceeded: "Клиент превысил баланс или кредитный лимит, доступный на его карте."
|
||||
activemodel:
|
||||
attributes:
|
||||
order_management/reports/enterprise_fee_summary/parameters:
|
||||
@@ -138,6 +176,9 @@ ru:
|
||||
already_registered: "Этот адрес электронной почты уже зарегистрирован. Пожалуйста, войдите, чтобы продолжить, или вернитесь и используйте другой адрес электронной почты."
|
||||
success:
|
||||
logged_in_succesfully: "Вы успешно вошли"
|
||||
sessions:
|
||||
signed_out: "Выполнен выход."
|
||||
already_signed_out: "Выполнен выход."
|
||||
user_passwords:
|
||||
spree_user:
|
||||
updated_not_active: "Ваш пароль был сброшен, но ваш адрес электронной почты еще не подтвержден."
|
||||
@@ -1313,6 +1354,7 @@ ru:
|
||||
terms_and_conditions: "Условия и Положения"
|
||||
failed: "Оформить заказ не удалось. Сообщите нам, чтобы мы могли обработать ваш заказ."
|
||||
payment_cancelled_due_to_stock: "Платеж отменен: оформление заказа не может быть выполнено из-за проблем на складе."
|
||||
order_not_loaded: "Не найден действительный заказ для оформления"
|
||||
shops:
|
||||
hubs:
|
||||
show_closed_shops: "Показать закрытые магазины"
|
||||
@@ -3221,7 +3263,6 @@ ru:
|
||||
notice_messages:
|
||||
variant_deleted: "Вариант удален"
|
||||
or: "Или"
|
||||
order_processed_successfully: "Заказ успешно обработан"
|
||||
payment_method_not_supported: "Способ оплаты не поддерживается"
|
||||
resend_authorization_email: "Повторно отправить письмо для авторизации"
|
||||
rma_credit: "Кредит RMA"
|
||||
|
||||
@@ -87,7 +87,7 @@ Openfoodnetwork::Application.routes.draw do
|
||||
constraints SplitCheckoutConstraint.new do
|
||||
get '/checkout', to: 'split_checkout#edit'
|
||||
|
||||
constraints step: /(guest|details|payment|summary)/ do
|
||||
constraints step: /(details|payment|summary)/ do
|
||||
get '/checkout/:step', to: 'split_checkout#edit', as: :checkout_step
|
||||
put '/checkout/:step', to: 'split_checkout#update', as: :checkout_update
|
||||
end
|
||||
|
||||
198
spec/controllers/split_checkout_controller_spec.rb
Normal file
198
spec/controllers/split_checkout_controller_spec.rb
Normal file
@@ -0,0 +1,198 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe SplitCheckoutController, type: :controller do
|
||||
let(:user) { order.user }
|
||||
let(:address) { create(:address) }
|
||||
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
||||
let(:order_cycle) { create(:order_cycle, distributors: [distributor]) }
|
||||
let(:exchange) { order_cycle.exchanges.outgoing.first }
|
||||
let(:order) {
|
||||
create(:order_with_line_items, line_items_count: 1, distributor: distributor,
|
||||
order_cycle: order_cycle)
|
||||
}
|
||||
let(:payment_method) { distributor.payment_methods.first }
|
||||
let(:shipping_method) { distributor.shipping_methods.first }
|
||||
|
||||
before do
|
||||
allow(Flipper).to receive(:enabled?).with(:split_checkout) { true }
|
||||
allow(Flipper).to receive(:enabled?).with(:split_checkout, anything) { true }
|
||||
|
||||
exchange.variants << order.line_items.first.variant
|
||||
allow(controller).to receive(:current_order) { order }
|
||||
allow(controller).to receive(:spree_current_user) { user }
|
||||
end
|
||||
|
||||
describe "#edit" do
|
||||
it "renders the checkout" do
|
||||
get :edit, params: { step: "details" }
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
|
||||
it "redirects to current step if no step is given" do
|
||||
get :edit
|
||||
expect(response).to redirect_to checkout_step_path(:details)
|
||||
end
|
||||
|
||||
context "when line items in the cart are not valid" do
|
||||
before { allow(controller).to receive(:valid_order_line_items?) { false } }
|
||||
|
||||
it "redirects to cart" do
|
||||
get :edit
|
||||
expect(response).to redirect_to cart_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
let(:checkout_params) { {} }
|
||||
let(:params) { { step: step }.merge(checkout_params) }
|
||||
|
||||
context "details step" do
|
||||
let(:step) { "details" }
|
||||
|
||||
context "with incomplete data" do
|
||||
let(:checkout_params) { { order: { email: user.email } } }
|
||||
|
||||
it "returns 422 and some feedback" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response.status).to eq 422
|
||||
expect(flash[:error]).to eq "Saving failed, please update the highlighted fields."
|
||||
expect(order.reload.state).to eq "cart"
|
||||
end
|
||||
end
|
||||
|
||||
context "with complete data" do
|
||||
let(:checkout_params) do
|
||||
{
|
||||
order: {
|
||||
email: user.email,
|
||||
bill_address_attributes: address.to_param,
|
||||
ship_address_attributes: address.to_param
|
||||
},
|
||||
shipping_method_id: shipping_method.id
|
||||
}
|
||||
end
|
||||
|
||||
it "updates and redirects to payment step" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response).to redirect_to checkout_step_path(:payment)
|
||||
expect(order.reload.state).to eq "payment"
|
||||
end
|
||||
|
||||
describe "saving default addresses" do
|
||||
it "updates default bill address on user and customer" do
|
||||
put :update, params: params.merge({ order: { save_bill_address: true } })
|
||||
|
||||
expect(order.customer.bill_address).to eq(order.bill_address)
|
||||
expect(order.user.bill_address).to eq(order.bill_address)
|
||||
end
|
||||
|
||||
it "updates default ship address on user and customer" do
|
||||
put :update, params: params.merge({ order: { save_ship_address: true } })
|
||||
|
||||
expect(order.customer.ship_address).to eq(order.ship_address)
|
||||
expect(order.user.ship_address).to eq(order.ship_address)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "payment step" do
|
||||
let(:step) { "payment" }
|
||||
|
||||
before do
|
||||
order.bill_address = address
|
||||
order.ship_address = address
|
||||
order.select_shipping_method shipping_method.id
|
||||
OrderWorkflow.new(order).advance_to_payment
|
||||
end
|
||||
|
||||
context "with incomplete data" do
|
||||
let(:checkout_params) { { order: { email: user.email } } }
|
||||
|
||||
it "returns 422 and some feedback" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response.status).to eq 422
|
||||
expect(flash[:error]).to eq "Saving failed, please update the highlighted fields."
|
||||
expect(order.reload.state).to eq "payment"
|
||||
end
|
||||
end
|
||||
|
||||
context "with complete data" do
|
||||
let(:checkout_params) do
|
||||
{
|
||||
order: {
|
||||
payments_attributes: [
|
||||
{ payment_method_id: payment_method.id }
|
||||
]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it "updates and redirects to payment step" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response).to redirect_to checkout_step_path(:summary)
|
||||
expect(order.reload.state).to eq "confirmation"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "summary step" do
|
||||
let(:step) { "summary" }
|
||||
|
||||
before do
|
||||
order.bill_address = address
|
||||
order.ship_address = address
|
||||
order.select_shipping_method shipping_method.id
|
||||
OrderWorkflow.new(order).advance_to_payment
|
||||
|
||||
order.payments << build(:payment, amount: order.total, payment_method: payment_method)
|
||||
order.next
|
||||
end
|
||||
|
||||
describe "confirming the order" do
|
||||
it "completes the order and redirects to order confirmation" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response).to redirect_to order_path(order)
|
||||
expect(order.reload.state).to eq "complete"
|
||||
end
|
||||
end
|
||||
|
||||
context "when accepting T&Cs is required" do
|
||||
before do
|
||||
allow(TermsOfService).to receive(:platform_terms_required?) { true }
|
||||
end
|
||||
|
||||
describe "submitting without accepting the T&Cs" do
|
||||
let(:checkout_params) { {} }
|
||||
|
||||
it "returns 422 and some feedback" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response.status).to eq 422
|
||||
expect(flash[:error]).to eq "Saving failed, please update the highlighted fields."
|
||||
expect(order.reload.state).to eq "confirmation"
|
||||
end
|
||||
end
|
||||
|
||||
describe "submitting and accepting the T&Cs" do
|
||||
let(:checkout_params) { { accept_terms: true } }
|
||||
|
||||
it "completes the order and redirects to order confirmation" do
|
||||
put :update, params: params
|
||||
|
||||
expect(response).to redirect_to order_path(order)
|
||||
expect(order.reload.state).to eq "complete"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -14,34 +14,36 @@ module SplitCheckoutHelper
|
||||
end
|
||||
|
||||
def fill_out_details
|
||||
# Section: Your Details
|
||||
within(:xpath, './/div[@class="checkout-substep"][1]') do
|
||||
fill_in "First Name", with: "Will"
|
||||
fill_in "Last Name", with: "Marshall"
|
||||
fill_in "Email", with: "test@test.com"
|
||||
fill_in "Phone", with: "0468363090"
|
||||
end
|
||||
fill_in "First Name", with: "Will"
|
||||
fill_in "Last Name", with: "Marshall"
|
||||
fill_in "Email", with: "test@test.com"
|
||||
fill_in "Phone", with: "0468363090"
|
||||
end
|
||||
|
||||
def fill_out_billing_address
|
||||
# Section: Your Billing Address
|
||||
within(:xpath, './/div[@class="checkout-substep"][2]') do
|
||||
fill_in "Address", with: "Rue de la Vie, 77"
|
||||
fill_in "City", with: "Melbourne"
|
||||
fill_in "Postcode", with: "3066"
|
||||
select "Australia", from: "Country"
|
||||
select "Victoria", from: "State"
|
||||
end
|
||||
fill_in "order_bill_address_attributes_address1", with: "Rue de la Vie, 77"
|
||||
fill_in "order_bill_address_attributes_address2", with: "2nd floor"
|
||||
fill_in "order_bill_address_attributes_city", with: "Melbourne"
|
||||
fill_in "order_bill_address_attributes_zipcode", with: "3066"
|
||||
select "Australia", from: "order_bill_address_attributes_country_id"
|
||||
select "Victoria", from: "order_bill_address_attributes_state_id"
|
||||
end
|
||||
|
||||
def fill_out_shipping_address
|
||||
# Section: Delivery Address
|
||||
within(:xpath, './/div[@class="checkout-substep"][3]') do
|
||||
fill_in "Address", with: "Rue de la Vie, 66"
|
||||
fill_in "City", with: "Perth"
|
||||
fill_in "Postcode", with: "2899"
|
||||
select "Australia", from: "Country"
|
||||
select "New South Wales", from: "State"
|
||||
end
|
||||
fill_in "order_ship_address_attributes_address1", with: "Rue de la Vie, 66"
|
||||
fill_in "order_ship_address_attributes_address2", with: "3rd floor"
|
||||
fill_in "order_ship_address_attributes_city", with: "Perth"
|
||||
fill_in "order_ship_address_attributes_zipcode", with: "6603"
|
||||
select "Australia", from: "order_ship_address_attributes_country_id"
|
||||
select "New South Wales", from: "order_ship_address_attributes_state_id"
|
||||
end
|
||||
|
||||
def fill_notes(text)
|
||||
fill_in 'Any comments or special instructions?', with: text.to_s
|
||||
end
|
||||
|
||||
def proceed_to_payment
|
||||
click_button "Next - Payment method"
|
||||
expect(page).to have_button("Next - Order summary")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -53,27 +53,18 @@ describe "As a consumer, I want to checkout my order", js: true do
|
||||
|
||||
context "guest checkout when distributor doesn't allow guest orders" do
|
||||
before do
|
||||
visit checkout_path
|
||||
visit checkout_step_path(:details)
|
||||
end
|
||||
|
||||
it "should display the split checkout login page" do
|
||||
expect(page).to have_content distributor.name
|
||||
expect(page).to have_current_path("/checkout/guest")
|
||||
expect(page).to have_content("Ok, ready to checkout?")
|
||||
expect(page).to have_content("Login")
|
||||
expect(page).to have_no_content("Checkout as guest")
|
||||
end
|
||||
|
||||
it "should be redirected if user enter the url" do
|
||||
order.update(state: "payment")
|
||||
get checkout_step_path(:details)
|
||||
expect(response).to have_http_status(:redirect)
|
||||
expect(page).to have_current_path("/checkout/guest")
|
||||
end
|
||||
|
||||
it "should redirect to the login page when clicking the login button" do
|
||||
it "should show the login modal when clicking the login button" do
|
||||
click_on "Login"
|
||||
expect(page).to have_current_path "/"
|
||||
expect(page).to have_selector ".login-modal"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -84,9 +75,8 @@ describe "As a consumer, I want to checkout my order", js: true do
|
||||
visit checkout_path
|
||||
end
|
||||
|
||||
it "should display the split checkout login/guest page" do
|
||||
it "should display the split checkout login/guest form" do
|
||||
expect(page).to have_content distributor.name
|
||||
expect(page).to have_current_path("/checkout/guest")
|
||||
expect(page).to have_content("Ok, ready to checkout?")
|
||||
expect(page).to have_content("Login")
|
||||
expect(page).to have_content("Checkout as guest")
|
||||
@@ -95,7 +85,6 @@ describe "As a consumer, I want to checkout my order", js: true do
|
||||
it "should display the split checkout details page" do
|
||||
click_on "Checkout as guest"
|
||||
expect(page).to have_content distributor.name
|
||||
expect(page).to have_current_path("/checkout/details")
|
||||
expect(page).to have_content("1 - Your details")
|
||||
expect(page).to have_selector("div.checkout-tab.selected", text: "1 - Your details")
|
||||
expect(page).to have_content("2 - Payment method")
|
||||
@@ -122,7 +111,7 @@ describe "As a consumer, I want to checkout my order", js: true do
|
||||
choose free_shipping.name
|
||||
|
||||
click_button "Next - Payment method"
|
||||
expect(page).to have_current_path("/checkout/payment")
|
||||
expect(page).to have_button("Next - Order summary")
|
||||
end
|
||||
|
||||
context "when order is state: 'payment'" do
|
||||
@@ -154,24 +143,83 @@ describe "As a consumer, I want to checkout my order", js: true do
|
||||
end
|
||||
|
||||
it "redirects the user to the Payment Method step" do
|
||||
fill_in 'Any comments or special instructions?', with: "SpEcIaL NoTeS"
|
||||
click_button "Next - Payment method"
|
||||
expect(page).to have_current_path("/checkout/payment")
|
||||
fill_notes("SpEcIaL NoTeS")
|
||||
proceed_to_payment
|
||||
end
|
||||
end
|
||||
|
||||
describe "selecting a delivery shipping method and submiting the form" do
|
||||
describe "selecting a delivery method" do
|
||||
before do
|
||||
choose shipping_with_fee.name
|
||||
uncheck "ship_address_same_as_billing"
|
||||
end
|
||||
|
||||
it "redirects the user to the Payment Method step" do
|
||||
fill_out_shipping_address
|
||||
fill_in 'Any comments or special instructions?', with: "SpEcIaL NoTeS"
|
||||
click_button "Next - Payment method"
|
||||
expect(page).to have_current_path("/checkout/payment")
|
||||
context "with same shipping and billing address" do
|
||||
before do
|
||||
check "ship_address_same_as_billing"
|
||||
end
|
||||
it "does not display the shipping address form" do
|
||||
expect(page).not_to have_field "order_ship_address_attributes_address1"
|
||||
end
|
||||
|
||||
it "redirects the user to the Payment Method step, when submiting the form" do
|
||||
proceed_to_payment
|
||||
# asserts whether shipping and billing addresses are the same
|
||||
ship_add_id = order.reload.ship_address_id
|
||||
bill_add_id = order.reload.bill_address_id
|
||||
expect(Spree::Address.where(id: bill_add_id).pluck(:address1) ==
|
||||
Spree::Address.where(id: ship_add_id).pluck(:address1)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context "with different shipping and billing address" do
|
||||
before do
|
||||
uncheck "ship_address_same_as_billing"
|
||||
end
|
||||
it "displays the shipping address form and the option to save it as default" do
|
||||
expect(page).to have_field "order_ship_address_attributes_address1"
|
||||
end
|
||||
|
||||
it "displays error messages when submitting incomplete billing address" do
|
||||
click_button "Next - Payment method"
|
||||
expect(page).to have_content "Saving failed, please update the highlighted fields."
|
||||
expect(page).to have_field("Address", with: "")
|
||||
expect(page).to have_field("City", with: "")
|
||||
expect(page).to have_field("Postcode", with: "")
|
||||
expect(page).to have_content("can't be blank", count: 3)
|
||||
end
|
||||
|
||||
it "fills in shipping details and redirects the user to the Payment Method step,
|
||||
when submiting the form" do
|
||||
fill_out_shipping_address
|
||||
fill_notes("SpEcIaL NoTeS")
|
||||
proceed_to_payment
|
||||
# asserts whether shipping and billing addresses are the same
|
||||
ship_add_id = Spree::Order.first.ship_address_id
|
||||
bill_add_id = Spree::Order.first.bill_address_id
|
||||
expect(Spree::Address.where(id: bill_add_id).pluck(:address1) ==
|
||||
Spree::Address.where(id: ship_add_id).pluck(:address1)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "not filling out delivery details" do
|
||||
before do
|
||||
fill_in "Email", with: ""
|
||||
end
|
||||
it "should display error when fields are empty" do
|
||||
click_button "Next - Payment method"
|
||||
expect(page).to have_content("Saving failed, please update the highlighted fields")
|
||||
expect(page).to have_field("First Name", with: "")
|
||||
expect(page).to have_field("Last Name", with: "")
|
||||
expect(page).to have_field("Email", with: "")
|
||||
expect(page).to have_content("is invalid")
|
||||
expect(page).to have_field("Phone number", with: "")
|
||||
expect(page).to have_field("Address", with: "")
|
||||
expect(page).to have_field("City", with: "")
|
||||
expect(page).to have_field("Postcode", with: "")
|
||||
expect(page).to have_content("can't be blank", count: 7)
|
||||
expect(page).to have_content("Select a shipping method")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user