diff --git a/app/assets/stylesheets/darkswarm/account.scss b/app/assets/stylesheets/darkswarm/account.scss
index bb6701f15d..d73e4b7367 100644
--- a/app/assets/stylesheets/darkswarm/account.scss
+++ b/app/assets/stylesheets/darkswarm/account.scss
@@ -99,7 +99,6 @@
.transaction-group {}
table {
- width: 100%;
border-radius: $radius-medium $radius-medium 0 0;
tr:nth-of-type(even) {
@@ -143,3 +142,29 @@
width: 10%;
}
}
+
+table {
+ &.full {
+ width: 100%;
+ }
+
+ &.top-rounded {
+ border-radius: $radius-medium $radius-medium 0 0;
+ }
+}
+
+// Note this relies on the
using `.show-for-large-up` as well.
+.requiring-authorization tr {
+ position: relative;
+
+ th:last-child {
+ position: absolute;
+ // The following calculation is the equivalent of:
+ //
+ // $table-cell-padding + 2 * browser's default border-spacing + 2 * table border
+ //
+ // Unfortunately we can't use Scss's interpolation
+ // https://sass-lang.com/documentation/interpolation. We're using a too old version perhaps?
+ right: calc(12px + 2*2px + 2*1px);
+ }
+}
diff --git a/app/assets/stylesheets/darkswarm/tables.scss b/app/assets/stylesheets/darkswarm/tables.scss
index b2632d52f1..35c61d26b0 100644
--- a/app/assets/stylesheets/darkswarm/tables.scss
+++ b/app/assets/stylesheets/darkswarm/tables.scss
@@ -1,9 +1,11 @@
+$table-cell-padding: 12px;
+
table {
thead tr, tbody tr {
th, td {
box-sizing: border-box;
- padding-left: 12px;
- padding-right: 12px;
+ padding-left: $table-cell-padding;
+ padding-right: $table-cell-padding;
overflow: hidden;
}
}
diff --git a/app/assets/stylesheets/darkswarm/ui.scss b/app/assets/stylesheets/darkswarm/ui.scss
index a9a43b0b5f..c13c51f024 100644
--- a/app/assets/stylesheets/darkswarm/ui.scss
+++ b/app/assets/stylesheets/darkswarm/ui.scss
@@ -61,6 +61,13 @@
@include border-radius(0.5em);
outline: none;
+
+ &.x-small {
+ padding: 0.5rem 0.75rem;
+ font-size: $text-xs;
+ font-weight: 600;
+ margin: 0;
+ }
}
.button.primary, button.primary {
diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb
index c9ee2e15fe..93350cd187 100644
--- a/app/controllers/spree/users_controller.rb
+++ b/app/controllers/spree/users_controller.rb
@@ -13,6 +13,7 @@ module Spree
before_action :enable_embedded_shopfront
def show
+ @payments_requiring_action = PaymentsRequiringAction.new(spree_current_user).query
@orders = orders_collection
customers = spree_current_user.customers
diff --git a/app/models/spree/payment.rb b/app/models/spree/payment.rb
index f2ac9ee02e..0896defdc3 100644
--- a/app/models/spree/payment.rb
+++ b/app/models/spree/payment.rb
@@ -49,6 +49,7 @@ module Spree
scope :pending, -> { with_state('pending') }
scope :failed, -> { with_state('failed') }
scope :valid, -> { where('state NOT IN (?)', %w(failed invalid)) }
+ scope :authorization_action_required, -> { where.not(cvv_response_message: nil) }
# order state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
state_machine initial: :checkout do
diff --git a/app/queries/payments_requiring_action.rb b/app/queries/payments_requiring_action.rb
new file mode 100644
index 0000000000..f8cc1bc2bc
--- /dev/null
+++ b/app/queries/payments_requiring_action.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class PaymentsRequiringAction
+ def initialize(user)
+ @user = user
+ end
+
+ def query
+ Spree::Payment.joins(:order).where("spree_orders.user_id = ?", user.id).
+ authorization_action_required
+ end
+
+ private
+
+ attr_reader :user
+end
diff --git a/app/views/spree/users/_fat.html.haml b/app/views/spree/users/_fat.html.haml
index 56439d0e19..dfbcfade38 100644
--- a/app/views/spree/users/_fat.html.haml
+++ b/app/views/spree/users/_fat.html.haml
@@ -16,8 +16,6 @@
%td.order3.show-for-large-up
%i{"ng-class" => "{'ofn-i_012-warning': payment.state == 'invalid' || payment.state == 'void' || payment.state == 'failed'}"}
%span{"ng-bind" => "::'spree.payment_states.' + payment.state | t | capitalize"}
- %span{"ng-if" => "payment.cvv_response_message.length > 0" }
- %a{"ng-href" => "{{payment.cvv_response_message}}", "ng-bind" => "::'spree.payment_states.authorise' | t | capitalize" }
%td.order4.show-for-large-up
%td.order5.text-right{"ng-class" => "{'credit' : payment.amount > 0, 'debit' : payment.amount < 0, 'paid' : payment.amount == 0}","ng-bind" => "::payment.amount | localizeCurrency"}
%td.order6.show-for-large-up
diff --git a/app/views/spree/users/_transactions.html.haml b/app/views/spree/users/_transactions.html.haml
index 6c8bea5353..e36d6c9382 100644
--- a/app/views/spree/users/_transactions.html.haml
+++ b/app/views/spree/users/_transactions.html.haml
@@ -1,4 +1,27 @@
%script{ type: "text/ng-template", id: "account/transactions.html" }
+ - if @payments_requiring_action.present?
+ .active_table.requiring-authorization
+ %h3= t(".authorisation_required")
+ %table.full.top-rounded
+ %tr
+ %th= t :transaction
+ %th= t :transaction_date
+ %th.show-for-large-up= t :payment_state
+ %th.text-right= t :value
+ %tbody
+ - @payments_requiring_action.each do |payment|
+ %tr
+ %td
+ = link_to payment.order.number, main_app.order_path(payment.order)
+ %td
+ = payment.updated_at.strftime("%Y-%m-%d")
+ %td
+ %a{ href: "#{payment.cvv_response_message}" }
+ %button.x-small
+ = t(".authorise")
+ %td.text-right
+ = payment.display_amount
+
.active_table.orders{"ng-controller" => "OrdersCtrl", "ng-cloak" => true}
%h3.my-orders= t(".transaction_history")
%distributor.active_table_node.row.animate-repeat{"ng-if" => "Orders.shops.length > 0", "ng-repeat" => "shop in Orders.shops",
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 113c4f672a..d47778e18d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -3732,6 +3732,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
past_orders: Past Orders
transactions:
transaction_history: Transaction History
+ authorisation_required: Authorisation Required
+ authorise: Authorize
open_orders:
order: Order
shop: Shop
diff --git a/spec/features/consumer/account/payments_spec.rb b/spec/features/consumer/account/payments_spec.rb
new file mode 100644
index 0000000000..9f6ddf33c9
--- /dev/null
+++ b/spec/features/consumer/account/payments_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+feature "Payments requiring action", js: true do
+ include AuthenticationHelper
+
+ describe "as a logged in user" do
+ let(:user) { create(:user) }
+ let(:order) { create(:order, user: user) }
+
+ before do
+ login_as user
+ end
+
+ context "there is a payment requiring authorization" do
+ let!(:payment) do
+ create(:payment, order: order, cvv_response_message: "https://stripe.com/redirect")
+ end
+
+ it "shows a table of payments requiring authorization" do
+ visit "/account"
+
+ find("a", :text => %r{#{I18n.t('spree.users.show.tabs.transactions')}}i).click
+ expect(page).to have_content I18n.t("spree.users.transactions.authorisation_required")
+ end
+ end
+
+ context "there are no payments requiring authorization" do
+ let!(:payment) do
+ create(:payment, order: order, cvv_response_message: nil)
+ end
+
+ it "does not show the table of payments requiring authorization" do
+ visit "/account"
+
+ find("a", :text => %r{#{I18n.t('spree.users.show.tabs.transactions')}}i).click
+ expect(page).to_not have_content I18n.t("spree.users.transactions.authorisation_required")
+ end
+ end
+ end
+end
diff --git a/spec/queries/payments_requiring_action_spec.rb b/spec/queries/payments_requiring_action_spec.rb
new file mode 100644
index 0000000000..a3af3af3cd
--- /dev/null
+++ b/spec/queries/payments_requiring_action_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PaymentsRequiringAction do
+ let(:user) { create(:user) }
+ let(:order) { create(:order, user: user) }
+ subject(:payments_requiring_action) { described_class.new(user) }
+
+ describe '#query' do
+ context "payment has a cvv_response_message" do
+ let(:payment) do
+ create(:payment, order: order, cvv_response_message: "https://stripe.com/redirect")
+ end
+
+ it "finds the payment" do
+ expect(payments_requiring_action.query.all).to include(payment)
+ end
+ end
+
+ context "payment has no cvv_response_message" do
+ let(:payment) do
+ create(:payment, order: order, cvv_response_message: nil)
+ end
+
+ it "does not find the payment" do
+ expect(payments_requiring_action.query.all).to_not include(payment)
+ end
+ end
+ end
+end
|