effective_orders 6.11.0 → 6.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/effective_orders/providers/deluxe_delayed.js +32 -0
- data/app/assets/stylesheets/effective_orders/_order.scss +4 -0
- data/app/controllers/effective/concerns/purchase.rb +17 -0
- data/app/controllers/effective/orders_controller.rb +2 -0
- data/app/controllers/effective/providers/deluxe.rb +13 -25
- data/app/controllers/effective/providers/deluxe_delayed.rb +48 -0
- data/app/controllers/effective/providers/deluxe_delayed_purchase.rb +50 -0
- data/app/datatables/admin/effective_orders_datatable.rb +8 -0
- data/app/datatables/effective_orders_datatable.rb +6 -0
- data/app/helpers/effective_deluxe_delayed_helper.rb +15 -0
- data/app/helpers/effective_orders_helper.rb +2 -0
- data/app/models/effective/deluxe_api.rb +61 -0
- data/app/models/effective/order.rb +126 -43
- data/app/views/effective/orders/_checkout_step2.html.haml +7 -0
- data/app/views/effective/orders/_datatable_actions.html.haml +1 -1
- data/app/views/effective/orders/_order_deferred.html.haml +5 -1
- data/app/views/effective/orders/delayed/_form.html.haml +25 -0
- data/app/views/effective/orders/delayed/_form_purchase.html.haml +30 -0
- data/app/views/effective/orders/deluxe/_form.html.haml +1 -4
- data/app/views/effective/orders/deluxe_delayed/_css.html.haml +12 -0
- data/app/views/effective/orders/deluxe_delayed/_element.html.haml +9 -0
- data/app/views/effective/orders/deluxe_delayed/_form.html.haml +10 -0
- data/app/views/effective/orders/deluxe_delayed/_form_purchase.html.haml +18 -0
- data/app/views/effective/orders/mark_as_paid/_form.html.haml +2 -0
- data/config/effective_orders.rb +9 -0
- data/config/routes.rb +4 -1
- data/db/migrate/101_create_effective_orders.rb +6 -0
- data/lib/effective_orders/version.rb +1 -1
- data/lib/effective_orders.rb +14 -2
- data/lib/tasks/effective_orders_tasks.rake +6 -0
- metadata +12 -3
- data/app/assets/images/effective_orders/deluxe.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fac0b561dd727abc645294816cf623fb2c9bd345645b19272e510d064b0c3e8
|
4
|
+
data.tar.gz: 63728a03677c11b462de51955b4add5434fcbdd0cd7e015013ab81f1672d3da0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78754fcf99effaba035ec15bb3ae31f322b84991c9b3a40d80c995493016589d5bdfd28bab4655a5a4f8a0a01c99e5c16a01c95bc275e04ecc33e72bf499b590
|
7
|
+
data.tar.gz: 5d2ed250eca616729e602f5f5b3374ad16b71f00e8701ac70e5545b3c370900a36d58ab507835f611aab9caa5b3cf114c40ebb4f1bad4e45d6efe61b2bb727c3
|
@@ -0,0 +1,32 @@
|
|
1
|
+
// https://developer.deluxe.com/s/article-hosted-payment-form
|
2
|
+
|
3
|
+
function initializeDeluxeDelayed() {
|
4
|
+
let $deluxe = $('form[data-deluxe-delayed-checkout]:not(.initialized)');
|
5
|
+
if($deluxe.length == 0) return;
|
6
|
+
|
7
|
+
let options = $deluxe.data('deluxe-delayed-checkout');
|
8
|
+
|
9
|
+
HostedForm.init(options, {
|
10
|
+
onFailure: (data) => { $('#deluxe-delayed-checkout-errors').text(JSON.stringify(data)); },
|
11
|
+
onInvalid: (data) => { $('#deluxe-delayed-checkout-errors').text(JSON.stringify(data)); },
|
12
|
+
|
13
|
+
onSuccess: (data) => {
|
14
|
+
let value = btoa(JSON.stringify(data)); // A base64 encoded JSON object
|
15
|
+
|
16
|
+
$form = $('form[data-deluxe-delayed-checkout]').first();
|
17
|
+
$form.find('input[name="deluxe_delayed[payment_intent]"]').val(value);
|
18
|
+
$form.submit();
|
19
|
+
|
20
|
+
$('#deluxeDelayedCheckout').fadeOut('slow');
|
21
|
+
$('#deluxe-delayed-checkout-loading').text('Thank you! Saving card information. Please wait...');
|
22
|
+
},
|
23
|
+
}).then((instance) => {
|
24
|
+
$('#deluxe-delayed-checkout-loading').text('');
|
25
|
+
instance.renderHpf();
|
26
|
+
});
|
27
|
+
|
28
|
+
$deluxe.addClass('initialized');
|
29
|
+
};
|
30
|
+
|
31
|
+
$(document).ready(function() { initializeDeluxeDelayed() });
|
32
|
+
$(document).on('turbolinks:load', function() { initializeDeluxeDelayed() });
|
@@ -50,6 +50,23 @@ module Effective
|
|
50
50
|
redirect_to deferred_url.gsub(':id', @order.to_param.to_s)
|
51
51
|
end
|
52
52
|
|
53
|
+
def order_delayed(payment:, payment_intent:, provider:, card: 'none', deferred_url: nil, email: false)
|
54
|
+
@order.delay!(payment: payment, payment_intent: payment_intent, provider: provider, card: card, email: email)
|
55
|
+
|
56
|
+
Effective::Cart.where(user: current_user).destroy_all if current_user.present?
|
57
|
+
|
58
|
+
if flash[:success].blank?
|
59
|
+
if email
|
60
|
+
flash[:success] = "Delayed payment created! An email has been sent to #{@order.emails_send_to}"
|
61
|
+
else
|
62
|
+
flash[:success] = "Delayed payment created!"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
deferred_url = effective_orders.deferred_order_path(':id') if deferred_url.blank?
|
67
|
+
redirect_to deferred_url.gsub(':id', @order.to_param.to_s)
|
68
|
+
end
|
69
|
+
|
53
70
|
def order_declined(payment:, provider:, card: 'none', declined_url: nil)
|
54
71
|
@order.decline!(payment: payment, provider: provider, card: card)
|
55
72
|
|
@@ -11,41 +11,33 @@ module Effective
|
|
11
11
|
EffectiveResources.authorize!(self, :update, @order)
|
12
12
|
|
13
13
|
## Process Payment Intent
|
14
|
+
api = Effective::DeluxeApi.new
|
14
15
|
|
15
16
|
# The payment_intent is set by the Deluxe HostedPaymentForm
|
16
|
-
|
17
|
+
payment_intent_payload = deluxe_params[:payment_intent]
|
17
18
|
|
18
|
-
if
|
19
|
+
if payment_intent_payload.blank?
|
19
20
|
flash[:danger] = 'Unable to process deluxe order without payment. please try again.'
|
20
|
-
return order_not_processed(declined_url:
|
21
|
+
return order_not_processed(declined_url: deluxe_params[:declined_url])
|
21
22
|
end
|
22
23
|
|
23
24
|
# Decode the base64 encoded JSON object into a Hash
|
24
|
-
payment_intent =
|
25
|
-
|
26
|
-
raise('expected a token payment') unless payment_intent['type'] == 'Token'
|
25
|
+
payment_intent = api.decode_payment_intent_payload(payment_intent_payload)
|
26
|
+
card_info = api.card_info(payment_intent)
|
27
27
|
|
28
|
-
valid = payment_intent['status'] == 'success'
|
28
|
+
valid = (payment_intent['status'] == 'success')
|
29
29
|
|
30
30
|
if valid == false
|
31
|
-
card_info
|
32
|
-
return order_declined(payment: card_info, provider: 'deluxe', card: card_info['card'], declined_url: declined_url)
|
31
|
+
return order_declined(payment: card_info, provider: 'deluxe', card: card_info['card'], declined_url: deluxe_params[:declined_url])
|
33
32
|
end
|
34
33
|
|
35
|
-
##
|
36
|
-
|
37
|
-
valid = [0].include?(authorization['responseCode'])
|
34
|
+
## Purchase Order right now
|
35
|
+
purchased = api.purchase!(@order, payment_intent)
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
return order_declined(payment: authorization, provider: 'deluxe', card: authorization['card'], declined_url: deluxe_params[:declined_url])
|
42
|
-
end
|
43
|
-
|
44
|
-
## Complete Payment
|
45
|
-
payment = deluxe_api.complete_payment(@order, authorization)
|
46
|
-
valid = [0].include?(payment['responseCode'])
|
37
|
+
payment = api.payment
|
38
|
+
raise('expected a payment Hash') unless payment.kind_of?(Hash)
|
47
39
|
|
48
|
-
if
|
40
|
+
if purchased == false
|
49
41
|
flash[:danger] = "Payment was unsuccessful. The credit card payment failed with message: #{Array(payment['responseMessage']).to_sentence.presence || 'none'}. Please try again."
|
50
42
|
return order_declined(payment: payment, provider: 'deluxe', card: payment['card'], declined_url: deluxe_params[:declined_url])
|
51
43
|
end
|
@@ -66,10 +58,6 @@ module Effective
|
|
66
58
|
params.require(:deluxe).permit(:payment_intent, :purchased_url, :declined_url)
|
67
59
|
end
|
68
60
|
|
69
|
-
def deluxe_api
|
70
|
-
@deluxe_api ||= Effective::DeluxeApi.new
|
71
|
-
end
|
72
|
-
|
73
61
|
end
|
74
62
|
end
|
75
63
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Effective
|
2
|
+
module Providers
|
3
|
+
module DeluxeDelayed
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def deluxe_delayed
|
7
|
+
raise('deluxe provider is not available') unless EffectiveOrders.deluxe?
|
8
|
+
raise('deluxe_delayed provider is not available') unless EffectiveOrders.deluxe_delayed?
|
9
|
+
|
10
|
+
@order = Effective::Order.deep.find(params[:id])
|
11
|
+
|
12
|
+
EffectiveResources.authorize!(self, :update, @order)
|
13
|
+
|
14
|
+
## Process Payment Intent
|
15
|
+
api = Effective::DeluxeApi.new
|
16
|
+
|
17
|
+
# The payment_intent is set by the Deluxe HostedPaymentForm
|
18
|
+
payment_intent_payload = deluxe_delayed_params[:payment_intent]
|
19
|
+
|
20
|
+
if payment_intent_payload.blank?
|
21
|
+
flash[:danger] = 'Unable to process deluxe delayed order without payment intent. please try again.'
|
22
|
+
return order_not_processed(declined_url: deluxe_delayed_params[:declined_url])
|
23
|
+
end
|
24
|
+
|
25
|
+
# Decode the base64 encoded JSON object into a Hash
|
26
|
+
payment_intent = api.decode_payment_intent_payload(payment_intent_payload)
|
27
|
+
card_info = api.card_info(payment_intent)
|
28
|
+
|
29
|
+
valid = payment_intent['status'] == 'success'
|
30
|
+
|
31
|
+
if valid == false
|
32
|
+
return order_declined(payment: card_info, provider: 'deluxe_delayed', card: card_info['card'], declined_url: deluxe_delayed_params[:declined_url])
|
33
|
+
end
|
34
|
+
|
35
|
+
flash[:success] = EffectiveOrders.deluxe_delayed[:success]
|
36
|
+
|
37
|
+
order_delayed(payment: card_info, payment_intent: payment_intent_payload, provider: 'deluxe_delayed', card: card_info['card'], deferred_url: deluxe_delayed_params[:deferred_url])
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def deluxe_delayed_params
|
43
|
+
params.require(:deluxe_delayed).permit(:payment_intent, :deferred_url, :declined_url)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Effective
|
2
|
+
module Providers
|
3
|
+
module DeluxeDelayedPurchase
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
# Admin action
|
7
|
+
def deluxe_delayed_purchase
|
8
|
+
raise('deluxe_delayed_purchase provider is not available') unless EffectiveOrders.deluxe_delayed?
|
9
|
+
|
10
|
+
@order ||= Order.deep.find(params[:id])
|
11
|
+
|
12
|
+
EffectiveResources.authorize!(self, :update, @order)
|
13
|
+
EffectiveResources.authorize!(self, :admin, :effective_orders)
|
14
|
+
|
15
|
+
raise('expected a delayed? and deferred? order') unless @order.delayed? && @order.deferred?
|
16
|
+
|
17
|
+
## Purchase Order right now
|
18
|
+
api = Effective::DeluxeApi.new
|
19
|
+
|
20
|
+
purchased = api.purchase!(@order, @order.delayed_payment_intent)
|
21
|
+
payment = api.payment
|
22
|
+
|
23
|
+
if purchased == false
|
24
|
+
flash[:danger] = "Payment was unsuccessful. The credit card payment failed with message: #{Array(payment['responseMessage']).to_sentence.presence || 'none'}. Please try again."
|
25
|
+
return order_declined(payment: payment, provider: 'deluxe_delayed', card: payment['card'], declined_url: deluxe_delayed_purchase_params[:declined_url])
|
26
|
+
end
|
27
|
+
|
28
|
+
@order.assign_attributes(deluxe_delayed_purchase_params.except(:purchased_url, :declined_url, :id))
|
29
|
+
|
30
|
+
order_purchased(
|
31
|
+
payment: payment,
|
32
|
+
provider: 'deluxe_delayed',
|
33
|
+
card: payment['card'],
|
34
|
+
email: @order.send_mark_as_paid_email_to_buyer?,
|
35
|
+
skip_buyer_validations: true,
|
36
|
+
purchased_url: effective_orders.admin_order_path(@order),
|
37
|
+
current_user: nil # Admin action, we don't want to assign current_user to the order
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def deluxe_delayed_purchase_params
|
42
|
+
params.require(:effective_order).permit(
|
43
|
+
:id, :note_to_buyer, :note_internal, :send_mark_as_paid_email_to_buyer,
|
44
|
+
:purchased_url, :declined_url
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -100,6 +100,14 @@ module Admin
|
|
100
100
|
|
101
101
|
col :total, as: :price
|
102
102
|
|
103
|
+
if EffectiveOrders.delayed?
|
104
|
+
col :delayed_payment, visible: false
|
105
|
+
col :delayed_payment_date
|
106
|
+
col :delayed_payment_intent, visible: false
|
107
|
+
col :delayed_payment_purchase_ran_at, visible: false
|
108
|
+
col :delayed_payment_purchase_result, visible: false
|
109
|
+
end
|
110
|
+
|
103
111
|
if EffectiveOrders.collect_note
|
104
112
|
col :note, visible: false
|
105
113
|
end
|
@@ -60,6 +60,12 @@ class EffectiveOrdersDatatable < Effective::Datatable
|
|
60
60
|
col :surcharge, as: :price, visible: false
|
61
61
|
col(:surcharge_percent, visible: false) { |order| rate_to_percentage(order.surcharge_percent) }
|
62
62
|
|
63
|
+
if EffectiveOrders.delayed?
|
64
|
+
col :delayed_payment
|
65
|
+
col :delayed_payment_date
|
66
|
+
col :delayed_payment_intent
|
67
|
+
end
|
68
|
+
|
63
69
|
col :total, as: :price
|
64
70
|
|
65
71
|
if EffectiveOrders.collect_note
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module EffectiveDeluxeDelayedHelper
|
2
|
+
|
3
|
+
# https://developer.deluxe.com/s/article-hosted-payment-form
|
4
|
+
def deluxe_delayed_hosted_payment_form_options(order)
|
5
|
+
{
|
6
|
+
xtoken: EffectiveOrders.deluxe.fetch(:access_token),
|
7
|
+
containerId: "deluxeDelayedCheckout",
|
8
|
+
xcssid: "deluxeDelayedCheckoutCss",
|
9
|
+
xrtype: "Generate Token",
|
10
|
+
xpm: "1", # 0 = CC & ACH, 1 = CC, 2 = ACH
|
11
|
+
xautoprompt: false,
|
12
|
+
xbtntext: order_checkout_label(:deluxe_delayed)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
@@ -13,6 +13,8 @@ module Effective
|
|
13
13
|
attr_accessor :access_token
|
14
14
|
attr_accessor :currency
|
15
15
|
|
16
|
+
attr_accessor :purchase_response
|
17
|
+
|
16
18
|
def initialize(environment: nil, client_id: nil, client_secret: nil, access_token: nil, currency: nil)
|
17
19
|
self.environment = environment || EffectiveOrders.deluxe.fetch(:environment)
|
18
20
|
self.client_id = client_id || EffectiveOrders.deluxe.fetch(:client_id)
|
@@ -21,11 +23,58 @@ module Effective
|
|
21
23
|
self.currency = currency || EffectiveOrders.deluxe.fetch(:currency)
|
22
24
|
end
|
23
25
|
|
26
|
+
def payment
|
27
|
+
raise('expected purchase response to be present') unless purchase_response.kind_of?(Hash)
|
28
|
+
purchase_response
|
29
|
+
end
|
30
|
+
|
31
|
+
# This calls Authorize Payment and Complete Payment
|
32
|
+
# Returns true if all good.
|
33
|
+
# Returns false if there was an error.
|
34
|
+
# Always sets the @purchase_response which is api.payment
|
35
|
+
def purchase!(order, payment_intent)
|
36
|
+
raise('expected a deluxe_delayed payment provider') unless order.payment_provider == 'deluxe_delayed'
|
37
|
+
|
38
|
+
payment_intent = decode_payment_intent_payload(payment_intent) if payment_intent.kind_of?(String)
|
39
|
+
raise('expected payment_intent to be a Hash') unless payment_intent.kind_of?(Hash)
|
40
|
+
raise('expected a token payment') unless payment_intent['type'] == 'Token'
|
41
|
+
|
42
|
+
# Start a purchase. Which is an Authorization and a Completion
|
43
|
+
self.purchase_response = nil
|
44
|
+
|
45
|
+
# Process Authorization
|
46
|
+
authorization = authorize_payment(order, payment_intent)
|
47
|
+
self.purchase_response = authorization
|
48
|
+
|
49
|
+
valid = [0].include?(authorization['responseCode'])
|
50
|
+
return false unless valid
|
51
|
+
|
52
|
+
## Complete Payment
|
53
|
+
payment = complete_payment(order, authorization)
|
54
|
+
self.purchase_response = payment
|
55
|
+
|
56
|
+
valid = [0].include?(payment['responseCode'])
|
57
|
+
return false unless valid
|
58
|
+
|
59
|
+
# Valid purchase. This is authorized and completed.
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
24
63
|
# Health Check
|
25
64
|
def health_check
|
26
65
|
get('/')
|
27
66
|
end
|
28
67
|
|
68
|
+
def healthy?
|
69
|
+
response = health_check()
|
70
|
+
|
71
|
+
return false unless response.kind_of?(Hash)
|
72
|
+
return false unless response['timestamp'].to_s.start_with?(Time.zone.now.strftime('%Y-%m-%d'))
|
73
|
+
return false unless response['environment'].present?
|
74
|
+
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
29
78
|
# Authorize Payment
|
30
79
|
def authorize_payment(order, payment_intent)
|
31
80
|
response = post('/payments/authorize', params: authorize_payment_params(order, payment_intent))
|
@@ -191,6 +240,18 @@ module Effective
|
|
191
240
|
{ 'active_card' => active_card, 'card' => card, 'expDate' => date, 'cvv' => cvv }.compact
|
192
241
|
end
|
193
242
|
|
243
|
+
# Decode the base64 encoded JSON object into a Hash
|
244
|
+
def decode_payment_intent_payload(payload)
|
245
|
+
raise('expected a string') unless payload.kind_of?(String)
|
246
|
+
|
247
|
+
payment_intent = (JSON.parse(Base64.decode64(payload)) rescue nil)
|
248
|
+
|
249
|
+
raise('expected payment_intent to be a Hash') unless payment_intent.kind_of?(Hash)
|
250
|
+
raise('expected a token payment') unless payment_intent['type'] == 'Token'
|
251
|
+
|
252
|
+
payment_intent
|
253
|
+
end
|
254
|
+
|
194
255
|
private
|
195
256
|
|
196
257
|
def headers
|
@@ -15,7 +15,7 @@ module Effective
|
|
15
15
|
acts_as_statused(
|
16
16
|
:pending, # New orders are created in a pending state
|
17
17
|
:confirmed, # Once the order has passed checkout step 1
|
18
|
-
:deferred, # Deferred providers. cheque, etransfer or
|
18
|
+
:deferred, # Deferred providers. cheque, etransfer, phone or deluxe_delayed was selected.
|
19
19
|
:purchased, # Purchased by provider
|
20
20
|
:declined, # Declined by provider
|
21
21
|
:voided, # Voided by admin
|
@@ -94,6 +94,21 @@ module Effective
|
|
94
94
|
|
95
95
|
total :integer # Subtotal + Tax + Surcharge + Surcharge Tax
|
96
96
|
|
97
|
+
# For use with the Deluxe Delayed Payment feature
|
98
|
+
|
99
|
+
# When an order is created. These two attributes can be set to create a delayed? order
|
100
|
+
delayed_payment :boolean
|
101
|
+
delayed_payment_date :date
|
102
|
+
|
103
|
+
# When the order goes to checkout we require the delayed_payment_intent
|
104
|
+
# This stores the user's card information in a secure way
|
105
|
+
# This is required for the order to become deferred?
|
106
|
+
delayed_payment_intent :text
|
107
|
+
|
108
|
+
# Set by the rake task that runs 1/day and processes any delayed orders before or on that day
|
109
|
+
delayed_payment_purchase_ran_at :datetime
|
110
|
+
delayed_payment_purchase_result :text
|
111
|
+
|
97
112
|
timestamps
|
98
113
|
end
|
99
114
|
|
@@ -135,6 +150,16 @@ module Effective
|
|
135
150
|
scope :refunds, -> { purchased.where('total < ?', 0) }
|
136
151
|
scope :pending_refunds, -> { not_purchased.where('total < ?', 0) }
|
137
152
|
|
153
|
+
scope :delayed, -> { where(delayed_payment: true).where.not(delayed_payment_date: nil) }
|
154
|
+
scope :delayed_payment_date_past, -> { delayed.where(arel_table[:delayed_payment_date].lteq(Time.zone.today)) }
|
155
|
+
scope :delayed_payment_date_upcoming, -> { delayed.where(arel_table[:delayed_payment_date].gt(Time.zone.today)) }
|
156
|
+
|
157
|
+
# Used by the rake effective_orders:purchase_delayed_orders task
|
158
|
+
scope :delayed_ready_to_purchase, -> {
|
159
|
+
delayed.deferred.delayed_payment_date_past.where(delayed_payment_purchase_ran_at: nil)
|
160
|
+
}
|
161
|
+
|
162
|
+
|
138
163
|
# effective_reports
|
139
164
|
def reportable_scopes
|
140
165
|
{ purchased: nil, not_purchased: nil, deferred: nil, refunds: nil, pending_refunds: nil }
|
@@ -165,6 +190,11 @@ module Effective
|
|
165
190
|
|
166
191
|
validates :order_items, presence: { message: 'No items are present. Please add additional items.' }
|
167
192
|
|
193
|
+
# Delayed Payment Validations
|
194
|
+
validates :delayed_payment_date, presence: true, if: -> { delayed_payment? }
|
195
|
+
validates :delayed_payment_date, absence: true, unless: -> { delayed_payment? }
|
196
|
+
validates :delayed_payment_intent, presence: { message: 'please provide your card information' }, if: -> { delayed? && deferred? }
|
197
|
+
|
168
198
|
validate do
|
169
199
|
if EffectiveOrders.organization_enabled?
|
170
200
|
errors.add(:base, "must have a User or #{EffectiveOrders.organization_class_name || 'Organization'}") if user_id.blank? && organization_id.blank?
|
@@ -392,46 +422,12 @@ module Effective
|
|
392
422
|
purchased? ? 'Total Paid' : 'Total Due'
|
393
423
|
end
|
394
424
|
|
395
|
-
# Visa - 1234
|
396
425
|
def payment_method
|
397
|
-
|
398
|
-
|
399
|
-
provider = payment_provider if ['cheque', 'etransfer', 'phone', 'credit card'].include?(payment_provider)
|
400
|
-
|
401
|
-
# Normalize payment card
|
402
|
-
card = case payment_card.to_s.downcase.gsub(' ', '').strip
|
403
|
-
when '' then nil
|
404
|
-
when 'v', 'visa' then 'Visa'
|
405
|
-
when 'm', 'mc', 'master', 'mastercard' then 'MasterCard'
|
406
|
-
when 'a', 'ax', 'american', 'americanexpress' then 'American Express'
|
407
|
-
when 'd', 'discover' then 'Discover'
|
408
|
-
else payment_card.to_s
|
409
|
-
end
|
410
|
-
|
411
|
-
# Try again
|
412
|
-
if card == 'none' && payment['card_type'].present?
|
413
|
-
card = case payment['card_type'].to_s.downcase.gsub(' ', '').strip
|
414
|
-
when '' then nil
|
415
|
-
when 'v', 'visa' then 'Visa'
|
416
|
-
when 'm', 'mc', 'master', 'mastercard' then 'MasterCard'
|
417
|
-
when 'a', 'ax', 'american', 'americanexpress' then 'American Express'
|
418
|
-
when 'd', 'discover' then 'Discover'
|
419
|
-
else payment_card.to_s
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
last4 = if payment[:active_card] && payment[:active_card].include?('**** **** ****')
|
424
|
-
payment[:active_card][15,4]
|
425
|
-
end
|
426
|
-
|
427
|
-
last4 ||= if payment['active_card'] && payment['active_card'].include?('**** **** ****')
|
428
|
-
payment['active_card'][15,4]
|
429
|
-
end
|
430
|
-
|
431
|
-
# stripe, moneris, moneris_checkout
|
432
|
-
last4 ||= (payment['f4l4'] || payment['first6last4']).to_s.last(4)
|
426
|
+
payment_method_value if purchased?
|
427
|
+
end
|
433
428
|
|
434
|
-
|
429
|
+
def delayed_payment_method
|
430
|
+
payment_method_value if delayed?
|
435
431
|
end
|
436
432
|
|
437
433
|
def duplicate
|
@@ -538,6 +534,39 @@ module Effective
|
|
538
534
|
def refund?
|
539
535
|
total.to_i < 0
|
540
536
|
end
|
537
|
+
|
538
|
+
# A new order is created.
|
539
|
+
# If the delayed_payment and delayed_payment date are set, it's a delayed order
|
540
|
+
# A delayed order is one in which we have to capture a payment intent for the amount of the order.
|
541
|
+
# Once it's delayed and deferred we can purchase it at anytime.
|
542
|
+
def delayed?
|
543
|
+
delayed_payment? && delayed_payment_date.present?
|
544
|
+
end
|
545
|
+
|
546
|
+
def delayed_ready_to_purchase?
|
547
|
+
return false unless delayed?
|
548
|
+
return false unless deferred?
|
549
|
+
return false unless delayed_payment_intent.present?
|
550
|
+
return false if delayed_payment_date_future?
|
551
|
+
return false if delayed_payment_purchase_ran_at.present? # We ran before and probably failed
|
552
|
+
|
553
|
+
true
|
554
|
+
end
|
555
|
+
|
556
|
+
def delayed_payment_date_future?
|
557
|
+
return false unless delayed?
|
558
|
+
delayed_payment_date > Time.zone.now.to_date
|
559
|
+
end
|
560
|
+
|
561
|
+
def delayed_payment_date_today?
|
562
|
+
return false unless delayed?
|
563
|
+
delayed_payment_date == Time.zone.now.to_date
|
564
|
+
end
|
565
|
+
|
566
|
+
def delayed_payment_date_past?
|
567
|
+
return false unless delayed?
|
568
|
+
delayed_payment_date < Time.zone.now.to_date
|
569
|
+
end
|
541
570
|
|
542
571
|
def pending_refund?
|
543
572
|
return false if EffectiveOrders.buyer_purchases_refund?
|
@@ -696,6 +725,23 @@ module Effective
|
|
696
725
|
sync_quickbooks!(skip: true)
|
697
726
|
end
|
698
727
|
|
728
|
+
# This was submitted via the deluxe_delayed provider checkout
|
729
|
+
# This is a special case of a deferred provider. We require the payment_intent and payment info
|
730
|
+
def delay!(payment:, payment_intent:, provider:, card:, email: false, validate: true)
|
731
|
+
raise('expected payment intent to be a String') unless payment_intent.kind_of?(String)
|
732
|
+
raise('expected a delayed payment provider') unless EffectiveOrders.delayed_providers.include?(provider)
|
733
|
+
raise('expected a delayed payment order with a delayed_payment_date') unless delayed_payment? && delayed_payment_date.present?
|
734
|
+
|
735
|
+
assign_attributes(
|
736
|
+
delayed_payment_intent: payment_intent,
|
737
|
+
|
738
|
+
payment: payment_to_h(payment),
|
739
|
+
payment_card: (card.presence || 'none')
|
740
|
+
)
|
741
|
+
|
742
|
+
defer!(provider: provider, email: email, validate: validate)
|
743
|
+
end
|
744
|
+
|
699
745
|
def defer!(provider: 'none', email: true, validate: true)
|
700
746
|
raise('order already purchased') if purchased?
|
701
747
|
|
@@ -725,9 +771,7 @@ module Effective
|
|
725
771
|
end
|
726
772
|
rescue ActiveRecord::RecordInvalid => e
|
727
773
|
self.status = status_was
|
728
|
-
|
729
774
|
error = e.message
|
730
|
-
raise ::ActiveRecord::Rollback
|
731
775
|
end
|
732
776
|
|
733
777
|
raise "Failed to defer order: #{error || errors.full_messages.to_sentence}" unless error.nil?
|
@@ -766,9 +810,7 @@ module Effective
|
|
766
810
|
run_purchasable_callbacks(:after_decline)
|
767
811
|
rescue ActiveRecord::RecordInvalid => e
|
768
812
|
self.status = status_was
|
769
|
-
|
770
813
|
error = e.message
|
771
|
-
raise ::ActiveRecord::Rollback
|
772
814
|
end
|
773
815
|
end
|
774
816
|
|
@@ -884,6 +926,47 @@ module Effective
|
|
884
926
|
subtotal + tax
|
885
927
|
end
|
886
928
|
|
929
|
+
# Visa - 1234
|
930
|
+
def payment_method_value
|
931
|
+
provider = payment_provider if ['cheque', 'etransfer', 'phone', 'credit card'].include?(payment_provider)
|
932
|
+
provider = 'credit card' if ['deluxe_delayed'].include?(payment_provider)
|
933
|
+
|
934
|
+
# Normalize payment card
|
935
|
+
card = case payment_card.to_s.downcase.gsub(' ', '').strip
|
936
|
+
when '' then nil
|
937
|
+
when 'v', 'visa' then 'Visa'
|
938
|
+
when 'm', 'mc', 'master', 'mastercard' then 'MasterCard'
|
939
|
+
when 'a', 'ax', 'american', 'americanexpress' then 'American Express'
|
940
|
+
when 'd', 'discover' then 'Discover'
|
941
|
+
else payment_card.to_s
|
942
|
+
end
|
943
|
+
|
944
|
+
# Try again
|
945
|
+
if card == 'none' && payment['card_type'].present?
|
946
|
+
card = case payment['card_type'].to_s.downcase.gsub(' ', '').strip
|
947
|
+
when '' then nil
|
948
|
+
when 'v', 'visa' then 'Visa'
|
949
|
+
when 'm', 'mc', 'master', 'mastercard' then 'MasterCard'
|
950
|
+
when 'a', 'ax', 'american', 'americanexpress' then 'American Express'
|
951
|
+
when 'd', 'discover' then 'Discover'
|
952
|
+
else payment_card.to_s
|
953
|
+
end
|
954
|
+
end
|
955
|
+
|
956
|
+
last4 = if payment[:active_card] && payment[:active_card].include?('**** **** ****')
|
957
|
+
payment[:active_card][15,4]
|
958
|
+
end
|
959
|
+
|
960
|
+
last4 ||= if payment['active_card'] && payment['active_card'].include?('**** **** ****')
|
961
|
+
payment['active_card'][15,4]
|
962
|
+
end
|
963
|
+
|
964
|
+
# stripe, moneris, moneris_checkout
|
965
|
+
last4 ||= (payment['f4l4'] || payment['first6last4']).to_s.last(4)
|
966
|
+
|
967
|
+
[provider.presence, card.presence, last4.presence].compact.join(' - ')
|
968
|
+
end
|
969
|
+
|
887
970
|
private
|
888
971
|
|
889
972
|
def present_order_items
|
@@ -14,6 +14,9 @@
|
|
14
14
|
- elsif EffectiveOrders.refund? && order.refund?
|
15
15
|
= render partial: '/effective/orders/refund/form', locals: provider_locals
|
16
16
|
|
17
|
+
- elsif EffectiveOrders.delayed? && order.delayed?
|
18
|
+
= render partial: '/effective/orders/delayed/form', locals: provider_locals
|
19
|
+
|
17
20
|
- else
|
18
21
|
- if EffectiveOrders.pretend?
|
19
22
|
= render partial: '/effective/orders/pretend/form', locals: provider_locals
|
@@ -38,6 +41,10 @@
|
|
38
41
|
= render partial: '/effective/orders/deferred/form', locals: provider_locals
|
39
42
|
|
40
43
|
- if EffectiveResources.authorized?(controller, :admin, :effective_orders) && order.user != current_user
|
44
|
+
- if EffectiveOrders.delayed? && order.delayed? && order.deferred?
|
45
|
+
.effective-order-admin-purchase-actions
|
46
|
+
= render partial: '/effective/orders/delayed/form_purchase', locals: provider_locals
|
47
|
+
|
41
48
|
- if EffectiveOrders.mark_as_paid?
|
42
49
|
.effective-order-admin-purchase-actions
|
43
50
|
= render partial: '/effective/orders/mark_as_paid/form', locals: provider_locals
|
@@ -1,6 +1,6 @@
|
|
1
1
|
= dropdown(variation: :dropleft) do
|
2
2
|
- if EffectiveResources.authorized?(controller, :checkout, order)
|
3
|
-
= dropdown_link_to 'Checkout', effective_orders.order_path(order)
|
3
|
+
= dropdown_link_to 'Checkout', effective_orders.order_path(order), 'data-turbolinks': false
|
4
4
|
- else
|
5
5
|
= dropdown_link_to 'View', effective_orders.order_path(order)
|
6
6
|
|
@@ -6,4 +6,8 @@
|
|
6
6
|
%th Payment
|
7
7
|
%tbody
|
8
8
|
%tr
|
9
|
-
%td
|
9
|
+
%td
|
10
|
+
- if order.delayed?
|
11
|
+
Your #{order.delayed_payment_method} will be charged on #{order.delayed_payment_date.strftime('%F')} for the full amount
|
12
|
+
- else
|
13
|
+
Waiting for payment by #{order.payment_provider}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
.card
|
2
|
+
.card-body
|
3
|
+
%h2 Save Card Info
|
4
|
+
|
5
|
+
%p
|
6
|
+
= succeed('.') do
|
7
|
+
- distance = distance_of_time_in_words(Time.zone.now, order.delayed_payment_date)
|
8
|
+
|
9
|
+
The payment date for this order
|
10
|
+
|
11
|
+
- if order.delayed_payment_date_future?
|
12
|
+
is in #{distance} from now on #{order.delayed_payment_date.strftime('%F')}
|
13
|
+
- elsif order.delayed_payment_date_today?
|
14
|
+
was today
|
15
|
+
- else
|
16
|
+
was #{distance} ago on #{order.delayed_payment_date.strftime('%F')}
|
17
|
+
|
18
|
+
%p
|
19
|
+
Instead of charging your card right away, the following action will securely save a token
|
20
|
+
representing your card information. The full amount will be charged on the payment date.
|
21
|
+
|
22
|
+
- provider_locals = { order: order, deferred_url: deferred_url, declined_url: declined_url }
|
23
|
+
|
24
|
+
- EffectiveOrders.delayed_providers.each do |provider|
|
25
|
+
= render partial: "/effective/orders/#{provider}/form", locals: provider_locals
|
@@ -0,0 +1,30 @@
|
|
1
|
+
.card
|
2
|
+
.card-body
|
3
|
+
%h2 Admin: Purchase Delayed Order
|
4
|
+
|
5
|
+
- raise('unexpected purchased order') if order.purchased?
|
6
|
+
- raise('expected a deferred delayed order') unless order.delayed? && order.deferred?
|
7
|
+
- raise('expecting a payment intent') unless order.delayed_payment_intent.present?
|
8
|
+
- raise('expecting a payment method') unless order.delayed_payment_method.present?
|
9
|
+
|
10
|
+
%p
|
11
|
+
= succeed('.') do
|
12
|
+
- distance = distance_of_time_in_words(Time.zone.now, order.delayed_payment_date)
|
13
|
+
|
14
|
+
The payment date for this order
|
15
|
+
|
16
|
+
- if order.delayed_payment_date_future?
|
17
|
+
is in #{distance} from now on #{order.delayed_payment_date.strftime('%F')}
|
18
|
+
- elsif order.delayed_payment_date_today?
|
19
|
+
was today
|
20
|
+
- else
|
21
|
+
was #{distance} ago on #{order.delayed_payment_date.strftime('%F')}
|
22
|
+
|
23
|
+
%p The #{order.delayed_payment_method} on file will be charged automatically on the payment date.
|
24
|
+
|
25
|
+
%p You can also charge it right now.
|
26
|
+
|
27
|
+
- provider_locals = { order: order, purchased_url: purchased_url, declined_url: declined_url }
|
28
|
+
|
29
|
+
- EffectiveOrders.delayed_providers.each do |provider|
|
30
|
+
= render partial: "/effective/orders/#{provider}/form_purchase", locals: provider_locals
|
@@ -3,11 +3,8 @@
|
|
3
3
|
.card
|
4
4
|
.card-body
|
5
5
|
%h2 Checkout
|
6
|
-
%p
|
7
|
-
%em This checkout is powered by #{link_to('Deluxe', 'https://www.deluxe.com/', target: '_blank', class: 'btn-link')}
|
8
6
|
|
9
|
-
.
|
10
|
-
= image_tag('effective_orders/deluxe.png', alt: 'Deluxe.com Logo', width: 200)
|
7
|
+
.mt-4
|
11
8
|
|
12
9
|
= effective_form_with(scope: :deluxe, url: effective_orders.deluxe_order_path(order), data: { 'deluxe-checkout': deluxe.to_json }) do |f|
|
13
10
|
= f.hidden_field :purchased_url, value: purchased_url
|
@@ -0,0 +1,9 @@
|
|
1
|
+
.effective-deluxe-delayed-checkout
|
2
|
+
#deluxe-delayed-checkout-loading.text-center Loading...
|
3
|
+
#deluxe-delayed-checkout-errors.text-danger
|
4
|
+
|
5
|
+
%style#deluxeDelayedCheckoutCss
|
6
|
+
-# Pass in custom CSS to the Deluxe Delayed hosted payment form iframe
|
7
|
+
= render('effective/orders/deluxe_delayed/css')
|
8
|
+
|
9
|
+
#deluxeDelayedCheckout
|
@@ -0,0 +1,10 @@
|
|
1
|
+
- deluxe_delayed = deluxe_delayed_hosted_payment_form_options(order)
|
2
|
+
|
3
|
+
= effective_form_with(scope: :deluxe_delayed, url: effective_orders.deluxe_delayed_order_path(order), data: { 'deluxe-delayed-checkout': deluxe_delayed.to_json }) do |f|
|
4
|
+
= f.hidden_field :declined_url, value: declined_url
|
5
|
+
= f.hidden_field :deferred_url, value: deferred_url
|
6
|
+
|
7
|
+
-# This is set by the deluxe.js javascript on Submit
|
8
|
+
= f.hidden_field :payment_intent, required: true
|
9
|
+
|
10
|
+
= render('effective/orders/deluxe_delayed/element')
|
@@ -0,0 +1,18 @@
|
|
1
|
+
= effective_form_with(model: order, url: effective_orders.deluxe_delayed_purchase_order_path(order), method: :post) do |f|
|
2
|
+
= f.hidden_field :id
|
3
|
+
|
4
|
+
= f.hidden_field :purchased_url, value: purchased_url
|
5
|
+
= f.hidden_field :declined_url, value: declined_url
|
6
|
+
|
7
|
+
= f.check_box :send_mark_as_paid_email_to_buyer,
|
8
|
+
label: 'Yes, send a receipt email to the buyer.',
|
9
|
+
input_html: { checked: (f.object.send_mark_as_paid_email_to_buyer.nil? ? EffectiveOrders.send_order_receipts_when_mark_as_paid : f.object.send_mark_as_paid_email_to_buyer?) }
|
10
|
+
|
11
|
+
.row
|
12
|
+
.col
|
13
|
+
= f.text_area :note_to_buyer, hint: 'This message will be displayed to the buyer on the receipt.'
|
14
|
+
.col
|
15
|
+
= f.text_area :note_internal, hint: 'For or internal admin use only. This note will never be displayed to the buyer.'
|
16
|
+
|
17
|
+
= f.submit(center: true) do
|
18
|
+
= f.save 'Purchase Order from Saved Card'
|
data/config/effective_orders.rb
CHANGED
@@ -133,6 +133,15 @@ EffectiveOrders.setup do |config|
|
|
133
133
|
# currency: 'CAD'
|
134
134
|
# }
|
135
135
|
|
136
|
+
# Deluxe Delayed
|
137
|
+
# This is a deferred payment
|
138
|
+
config.deluxe_delayed = false
|
139
|
+
|
140
|
+
# config.deluxe_delayed = {
|
141
|
+
# confirm: 'Save card info for later payment',
|
142
|
+
# success: 'Thank you! You have indicated that this order will be purchased by credit card at a later date. We will save your card information securely and process the payment when the order is ready'
|
143
|
+
# }
|
144
|
+
|
136
145
|
# E-transfer
|
137
146
|
# This is an deferred payment
|
138
147
|
config.etransfer = false
|
data/config/routes.rb
CHANGED
@@ -8,7 +8,10 @@ EffectiveOrders::Engine.routes.draw do
|
|
8
8
|
post :send_buyer_receipt
|
9
9
|
|
10
10
|
post :cheque
|
11
|
-
post :deluxe
|
11
|
+
post :deluxe # 1-off payment and purchase
|
12
|
+
post :deluxe_delayed # 1-off payment_intent saving
|
13
|
+
post :deluxe_delayed_purchase # Admin action to purchase a delayed order
|
14
|
+
|
12
15
|
post :etransfer
|
13
16
|
post :free
|
14
17
|
post :mark_as_paid
|
@@ -40,6 +40,12 @@ class CreateEffectiveOrders < ActiveRecord::Migration[6.0]
|
|
40
40
|
t.integer :surcharge_tax
|
41
41
|
t.integer :total
|
42
42
|
|
43
|
+
t.boolean :delayed_payment, default: false
|
44
|
+
t.date :delayed_payment_date
|
45
|
+
t.text :delayed_payment_intent
|
46
|
+
t.datetime :delayed_payment_purchase_ran_at
|
47
|
+
t.text :delayed_payment_purchase_result
|
48
|
+
|
43
49
|
t.timestamps
|
44
50
|
end
|
45
51
|
|
data/lib/effective_orders.rb
CHANGED
@@ -42,7 +42,7 @@ module EffectiveOrders
|
|
42
42
|
:free_enabled, :mark_as_paid_enabled, :pretend_enabled, :pretend_message, :buyer_purchases_refund,
|
43
43
|
|
44
44
|
# Payment processors. false or Hash
|
45
|
-
:cheque, :deluxe, :etransfer, :moneris, :moneris_checkout, :paypal, :phone, :refund, :stripe, :subscriptions, :trial
|
45
|
+
:cheque, :deluxe, :deluxe_delayed, :etransfer, :moneris, :moneris_checkout, :paypal, :phone, :refund, :stripe, :subscriptions, :trial
|
46
46
|
]
|
47
47
|
end
|
48
48
|
|
@@ -85,10 +85,18 @@ module EffectiveOrders
|
|
85
85
|
deluxe.kind_of?(Hash)
|
86
86
|
end
|
87
87
|
|
88
|
+
def self.deluxe_delayed?
|
89
|
+
deluxe_delayed.kind_of?(Hash)
|
90
|
+
end
|
91
|
+
|
88
92
|
def self.deferred?
|
89
93
|
deferred_providers.present?
|
90
94
|
end
|
91
95
|
|
96
|
+
def self.delayed?
|
97
|
+
delayed_providers.present?
|
98
|
+
end
|
99
|
+
|
92
100
|
def self.mark_as_paid?
|
93
101
|
mark_as_paid_enabled == true
|
94
102
|
end
|
@@ -178,7 +186,11 @@ module EffectiveOrders
|
|
178
186
|
end
|
179
187
|
|
180
188
|
def self.deferred_providers
|
181
|
-
[('cheque' if cheque?), ('etransfer' if etransfer?), ('phone' if phone?)].compact
|
189
|
+
[('cheque' if cheque?), ('deluxe_delayed' if deluxe_delayed?), ('etransfer' if etransfer?), ('phone' if phone?)].compact
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.delayed_providers
|
193
|
+
[('deluxe_delayed' if deluxe_delayed?)].compact
|
182
194
|
end
|
183
195
|
|
184
196
|
def self.credit_card_payment_providers
|
@@ -66,4 +66,10 @@ namespace :effective_orders do
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
# rake effective_orders:purchase_delayed_orders
|
70
|
+
desc 'Purchases delayed orders on their delayed_payment_date for effective orders'
|
71
|
+
task purchase_delayed_orders: :environment do
|
72
|
+
puts 'Todo'
|
73
|
+
end
|
74
|
+
|
69
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_orders
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -189,12 +189,12 @@ files:
|
|
189
189
|
- MIT-LICENSE
|
190
190
|
- README.md
|
191
191
|
- app/assets/config/effective_orders_manifest.js
|
192
|
-
- app/assets/images/effective_orders/deluxe.png
|
193
192
|
- app/assets/images/effective_orders/logo.png
|
194
193
|
- app/assets/images/effective_orders/stripe.png
|
195
194
|
- app/assets/javascripts/effective_orders.js
|
196
195
|
- app/assets/javascripts/effective_orders/customers.js.coffee
|
197
196
|
- app/assets/javascripts/effective_orders/providers/deluxe.js
|
197
|
+
- app/assets/javascripts/effective_orders/providers/deluxe_delayed.js
|
198
198
|
- app/assets/javascripts/effective_orders/providers/moneris_checkout.js.coffee
|
199
199
|
- app/assets/javascripts/effective_orders/providers/stripe.js.coffee
|
200
200
|
- app/assets/javascripts/effective_orders/subscriptions.js.coffee
|
@@ -211,6 +211,8 @@ files:
|
|
211
211
|
- app/controllers/effective/orders_controller.rb
|
212
212
|
- app/controllers/effective/providers/cheque.rb
|
213
213
|
- app/controllers/effective/providers/deluxe.rb
|
214
|
+
- app/controllers/effective/providers/deluxe_delayed.rb
|
215
|
+
- app/controllers/effective/providers/deluxe_delayed_purchase.rb
|
214
216
|
- app/controllers/effective/providers/etransfer.rb
|
215
217
|
- app/controllers/effective/providers/free.rb
|
216
218
|
- app/controllers/effective/providers/mark_as_paid.rb
|
@@ -231,6 +233,7 @@ files:
|
|
231
233
|
- app/datatables/admin/report_transactions_grouped_by_qb_name_datatable.rb
|
232
234
|
- app/datatables/effective_orders_datatable.rb
|
233
235
|
- app/helpers/effective_carts_helper.rb
|
236
|
+
- app/helpers/effective_deluxe_delayed_helper.rb
|
234
237
|
- app/helpers/effective_deluxe_helper.rb
|
235
238
|
- app/helpers/effective_moneris_checkout_helper.rb
|
236
239
|
- app/helpers/effective_orders_helper.rb
|
@@ -296,9 +299,15 @@ files:
|
|
296
299
|
- app/views/effective/orders/declined.html.haml
|
297
300
|
- app/views/effective/orders/deferred.html.haml
|
298
301
|
- app/views/effective/orders/deferred/_form.html.haml
|
302
|
+
- app/views/effective/orders/delayed/_form.html.haml
|
303
|
+
- app/views/effective/orders/delayed/_form_purchase.html.haml
|
299
304
|
- app/views/effective/orders/deluxe/_css.html.haml
|
300
305
|
- app/views/effective/orders/deluxe/_element.html.haml
|
301
306
|
- app/views/effective/orders/deluxe/_form.html.haml
|
307
|
+
- app/views/effective/orders/deluxe_delayed/_css.html.haml
|
308
|
+
- app/views/effective/orders/deluxe_delayed/_element.html.haml
|
309
|
+
- app/views/effective/orders/deluxe_delayed/_form.html.haml
|
310
|
+
- app/views/effective/orders/deluxe_delayed/_form_purchase.html.haml
|
302
311
|
- app/views/effective/orders/edit.html.haml
|
303
312
|
- app/views/effective/orders/etransfer/_form.html.haml
|
304
313
|
- app/views/effective/orders/free/_form.html.haml
|
Binary file
|