effective_orders 6.12.4 → 6.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/datatables/admin/effective_orders_datatable.rb +1 -0
- data/app/helpers/effective_orders_helper.rb +4 -4
- data/app/models/concerns/acts_as_purchasable.rb +13 -0
- data/app/models/effective/deluxe_api.rb +39 -71
- data/app/models/effective/order.rb +16 -4
- data/app/views/effective/orders/_checkout_step2.html.haml +6 -5
- data/db/migrate/101_create_effective_orders.rb +1 -0
- data/lib/effective_orders/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4499fc477da7ba7d00a8550057e754772594ca4622fdfc498ec6ff054b19eb30
|
4
|
+
data.tar.gz: f8c09cce9f19c1e872ae4e1d27e3928d1be8ee0a29dc42d421c0a058bb8e0840
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bd284864d14aedf394014d9cbea8fca1309a8856564c6f03f5dfe606d3cf123184cbda1d6a61fbfe0b2fdbe0e23be04c9d5979d0d3e371c43e3765e4f614264
|
7
|
+
data.tar.gz: df32798cf7ebd2b0614e28befadef7f1ab391ffd0124c0748b74139f579cdcc6b8919c35c0307c47ed5fdade567a48cb54008cf765ebae39680baca5cd1874f2
|
@@ -104,6 +104,7 @@ module Admin
|
|
104
104
|
col :delayed_payment, visible: false
|
105
105
|
col :delayed_payment_date
|
106
106
|
col :delayed_payment_intent, visible: false
|
107
|
+
col :delayed_payment_total, as: :price, visible: false
|
107
108
|
col :delayed_payment_purchase_ran_at, visible: false
|
108
109
|
col :delayed_payment_purchase_result, visible: false
|
109
110
|
end
|
@@ -119,13 +119,13 @@ module EffectiveOrdersHelper
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
def render_checkout_step1(order, namespace: nil, purchased_url: nil, declined_url: nil, deferred_url: nil, skip_deferred: false)
|
123
|
-
locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, deferred_url: deferred_url, namespace: namespace, skip_deferred: skip_deferred }
|
122
|
+
def render_checkout_step1(order, namespace: nil, purchased_url: nil, declined_url: nil, deferred_url: nil, skip_deferred: false, skip_order: false)
|
123
|
+
locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, deferred_url: deferred_url, namespace: namespace, skip_deferred: skip_deferred, skip_order: skip_order }
|
124
124
|
render(partial: 'effective/orders/checkout_step1', locals: locals)
|
125
125
|
end
|
126
126
|
|
127
|
-
def render_checkout_step2(order, namespace: nil, purchased_url: nil, declined_url: nil, deferred_url: nil, skip_deferred: false)
|
128
|
-
locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, deferred_url: deferred_url, namespace: namespace, skip_deferred: skip_deferred }
|
127
|
+
def render_checkout_step2(order, namespace: nil, purchased_url: nil, declined_url: nil, deferred_url: nil, skip_deferred: false, skip_order: false)
|
128
|
+
locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, deferred_url: deferred_url, namespace: namespace, skip_deferred: skip_deferred, skip_order: skip_order }
|
129
129
|
render(partial: 'effective/orders/checkout_step2', locals: locals)
|
130
130
|
end
|
131
131
|
|
@@ -110,6 +110,15 @@ module ActsAsPurchasable
|
|
110
110
|
self[:tax_exempt] || false
|
111
111
|
end
|
112
112
|
|
113
|
+
def purchased_or_deferred?
|
114
|
+
purchased_order_id.present? || orders.any? { |order| order.purchased? || order.deferred? }
|
115
|
+
end
|
116
|
+
|
117
|
+
def purchased_or_deferred_at
|
118
|
+
order = orders.find { |order| order.purchased? } || orders.find { |order| order.deferred? }
|
119
|
+
order&.purchased_at || order&.deferred_at
|
120
|
+
end
|
121
|
+
|
113
122
|
def purchased?
|
114
123
|
purchased_order_id.present?
|
115
124
|
end
|
@@ -122,6 +131,10 @@ module ActsAsPurchasable
|
|
122
131
|
self[:purchased_at] || purchased_order.try(:purchased_at)
|
123
132
|
end
|
124
133
|
|
134
|
+
def deferred_at
|
135
|
+
self[:deferred_at] || orders.find { |order| order.deferred? }.try(:deferred_at)
|
136
|
+
end
|
137
|
+
|
125
138
|
def purchased_by?(user)
|
126
139
|
purchased_orders.any? { |order| order.purchased_by_id == user.id }
|
127
140
|
end
|
@@ -65,7 +65,7 @@ module Effective
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# After we store a payment intent we can call purchase! immediately or wait till later.
|
68
|
-
# This calls
|
68
|
+
# This calls the /payments Create Payment endpoint
|
69
69
|
# Returns true when purchased. Returns false when declined.
|
70
70
|
# The response is stored in api.payment() after this is run
|
71
71
|
def purchase!(order, payment_intent)
|
@@ -75,18 +75,10 @@ module Effective
|
|
75
75
|
|
76
76
|
# Start a purchase. Which is an Authorization and a Completion
|
77
77
|
self.purchase_response = nil
|
78
|
-
|
79
|
-
# Process Authorization
|
80
|
-
authorization = authorize_payment(order, payment_intent)
|
81
|
-
self.purchase_response = authorization
|
82
|
-
|
83
|
-
valid = [0].include?(authorization['responseCode'])
|
84
|
-
return false unless valid
|
85
|
-
|
86
|
-
## Complete Payment
|
87
|
-
payment = complete_payment(order, authorization)
|
78
|
+
payment = create_payment(order, payment_intent)
|
88
79
|
self.purchase_response = payment
|
89
80
|
|
81
|
+
# Validate
|
90
82
|
valid = [0].include?(payment['responseCode'])
|
91
83
|
return false unless valid
|
92
84
|
|
@@ -94,11 +86,35 @@ module Effective
|
|
94
86
|
true
|
95
87
|
end
|
96
88
|
|
89
|
+
# Create Payment
|
90
|
+
def create_payment(order, payment_intent)
|
91
|
+
response = post('/payments', params: create_payment_params(order, payment_intent))
|
92
|
+
|
93
|
+
# Sanity check response
|
94
|
+
raise('expected responseCode') unless response.kind_of?(Hash) && response['responseCode'].present?
|
95
|
+
|
96
|
+
# Sanity check response approved vs authorized
|
97
|
+
valid = [0].include?(response['responseCode'])
|
98
|
+
|
99
|
+
# We might be approved for an amount less than the order total. Not sure what to do here
|
100
|
+
if valid && (amountApproved = response['amountApproved']) != (amountAuthorized = order.total_to_f)
|
101
|
+
raise("expected complete payment amountApproved #{amountApproved} to be the same as the amountAuthorized #{amountAuthorized} but it was not")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Generate the card info we can store
|
105
|
+
card = card_info(payment_intent)
|
106
|
+
|
107
|
+
# Return the response merged with the card info
|
108
|
+
response.reverse_merge(card)
|
109
|
+
end
|
110
|
+
|
111
|
+
# The response from last create payment request
|
97
112
|
def payment
|
98
113
|
raise('expected purchase response to be present') unless purchase_response.kind_of?(Hash)
|
99
114
|
purchase_response
|
100
115
|
end
|
101
116
|
|
117
|
+
# Called by rake task
|
102
118
|
def purchase_delayed_orders!(orders)
|
103
119
|
now = Time.zone.now
|
104
120
|
|
@@ -144,51 +160,7 @@ module Effective
|
|
144
160
|
|
145
161
|
protected
|
146
162
|
|
147
|
-
|
148
|
-
def authorize_payment(order, payment_intent)
|
149
|
-
response = post('/payments/authorize', params: authorize_payment_params(order, payment_intent))
|
150
|
-
|
151
|
-
# Sanity check response
|
152
|
-
raise('expected responseCode') unless response.kind_of?(Hash) && response['responseCode'].present?
|
153
|
-
|
154
|
-
# Sanity check response approved vs authorized
|
155
|
-
valid = [0].include?(response['responseCode'])
|
156
|
-
|
157
|
-
# We might be approved for an amount less than the order total. Not sure what to do here
|
158
|
-
if valid && (amountApproved = response['amountApproved']) != (amountAuthorized = order.total_to_f)
|
159
|
-
raise("expected authorize payment amountApproved #{amountApproved} to be the same as the amountAuthorized #{amountAuthorized} but it was not")
|
160
|
-
end
|
161
|
-
|
162
|
-
# Generate the card info we can store
|
163
|
-
card = card_info(payment_intent)
|
164
|
-
|
165
|
-
# Return the authorization params merged with the card info
|
166
|
-
response.reverse_merge(card)
|
167
|
-
end
|
168
|
-
|
169
|
-
# Complete Payment
|
170
|
-
def complete_payment(order, authorization)
|
171
|
-
response = post('/payments/complete', params: complete_payment_params(order, authorization))
|
172
|
-
|
173
|
-
# Sanity check response
|
174
|
-
raise('expected responseCode') unless response.kind_of?(Hash) && response['responseCode'].present?
|
175
|
-
|
176
|
-
# Sanity check response approved vs authorized
|
177
|
-
valid = [0].include?(response['responseCode'])
|
178
|
-
|
179
|
-
# We might be approved for an amount less than the order total. Not sure what to do here
|
180
|
-
if valid && (amountApproved = response['amountApproved']) != (amountAuthorized = order.total_to_f)
|
181
|
-
raise("expected complete payment amountApproved #{amountApproved} to be the same as the amountAuthorized #{amountAuthorized} but it was not")
|
182
|
-
end
|
183
|
-
|
184
|
-
# The authorization information
|
185
|
-
authorization = { 'paymentId' => authorization } if authorization.kind_of?(String)
|
186
|
-
|
187
|
-
# Return the complete params merged with the authorization params
|
188
|
-
response.reverse_merge(authorization)
|
189
|
-
end
|
190
|
-
|
191
|
-
def authorize_payment_params(order, payment_intent)
|
163
|
+
def create_payment_params(order, payment_intent)
|
192
164
|
raise('expected an Effective::Order') unless order.kind_of?(Effective::Order)
|
193
165
|
|
194
166
|
token = extract_token(payment_intent)
|
@@ -232,28 +204,24 @@ module Effective
|
|
232
204
|
({ name: 'organization_id', value: order.organization_id.to_s } if order.organization_id.present?)
|
233
205
|
].compact
|
234
206
|
|
235
|
-
|
236
|
-
|
207
|
+
orderData = {
|
208
|
+
autoGenerateOrderId: true,
|
209
|
+
orderID: order.to_param,
|
210
|
+
orderIdIsUnique: true
|
211
|
+
}
|
212
|
+
|
213
|
+
# Params passed into Create Payment
|
214
|
+
params = {
|
215
|
+
paymentType: "Sale",
|
237
216
|
amount: amount,
|
238
217
|
paymentMethod: paymentMethod,
|
239
218
|
shippingAddress: shippingAddress,
|
240
219
|
customData: customData,
|
220
|
+
merchantCategory: "E-Commerce",
|
221
|
+
orderData: orderData
|
241
222
|
}.compact
|
242
223
|
end
|
243
224
|
|
244
|
-
def complete_payment_params(order, payment_intent)
|
245
|
-
raise('expected an Effective::Order') unless order.kind_of?(Effective::Order)
|
246
|
-
|
247
|
-
payment_id = extract_payment_id(payment_intent)
|
248
|
-
amount = { amount: order.total_to_f, currency: currency }
|
249
|
-
|
250
|
-
# Params passed into Complete Payment
|
251
|
-
{
|
252
|
-
paymentId: payment_id,
|
253
|
-
amount: amount
|
254
|
-
}
|
255
|
-
end
|
256
|
-
|
257
225
|
def get(endpoint, params: nil)
|
258
226
|
query = ('?' + params.compact.map { |k, v| "$#{k}=#{v}" }.join('&')) if params.present?
|
259
227
|
|
@@ -100,10 +100,11 @@ module Effective
|
|
100
100
|
delayed_payment :boolean
|
101
101
|
delayed_payment_date :date
|
102
102
|
|
103
|
-
# When the order goes to checkout we require the delayed_payment_intent
|
104
|
-
# This stores the user's card information
|
103
|
+
# When the order goes to checkout we require the delayed_payment_intent and total
|
104
|
+
# This stores the user's card information
|
105
105
|
# This is required for the order to become deferred?
|
106
106
|
delayed_payment_intent :text
|
107
|
+
delayed_payment_total :integer # Only for reference, not really used. This is the order total we showed them when they last save card info'd
|
107
108
|
|
108
109
|
# Set by the rake task that runs 1/day and processes any delayed orders before or on that day
|
109
110
|
delayed_payment_purchase_ran_at :datetime
|
@@ -192,7 +193,11 @@ module Effective
|
|
192
193
|
# Delayed Payment Validations
|
193
194
|
validates :delayed_payment_date, presence: true, if: -> { delayed_payment? }
|
194
195
|
validates :delayed_payment_date, absence: true, unless: -> { delayed_payment? }
|
195
|
-
|
196
|
+
|
197
|
+
with_options(if: -> { delayed? && deferred? }) do
|
198
|
+
validates :delayed_payment_intent, presence: { message: 'please provide your card information' }
|
199
|
+
validates :delayed_payment_total, presence: true
|
200
|
+
end
|
196
201
|
|
197
202
|
validate do
|
198
203
|
if EffectiveOrders.organization_enabled?
|
@@ -558,7 +563,7 @@ module Effective
|
|
558
563
|
return unless delayed? && deferred?
|
559
564
|
return unless delayed_payment_date_upcoming?
|
560
565
|
|
561
|
-
"Your #{delayed_payment_method} will be charged on #{delayed_payment_date.strftime('%F')}
|
566
|
+
"Your #{delayed_payment_method} will be charged $#{'%0.2f' % total_to_f} on #{delayed_payment_date.strftime('%F')}"
|
562
567
|
end
|
563
568
|
|
564
569
|
def delayed_payment_date_upcoming?
|
@@ -659,6 +664,12 @@ module Effective
|
|
659
664
|
present_order_items.each { |oi| oi.update_purchasable_attributes }
|
660
665
|
end
|
661
666
|
|
667
|
+
def update_purchasable_attributes!
|
668
|
+
raise('cannot update purchasable attributes of a purchased order') if purchased?
|
669
|
+
update_purchasable_attributes
|
670
|
+
save!
|
671
|
+
end
|
672
|
+
|
662
673
|
# Call this as a way to skip over non consequential orders
|
663
674
|
# And mark some purchasables purchased
|
664
675
|
# This is different than the Mark as Paid payment processor
|
@@ -744,6 +755,7 @@ module Effective
|
|
744
755
|
|
745
756
|
assign_attributes(
|
746
757
|
delayed_payment_intent: payment_intent,
|
758
|
+
delayed_payment_total: total(),
|
747
759
|
|
748
760
|
payment: payment_to_h(payment),
|
749
761
|
payment_card: (card.presence || 'none')
|
@@ -3,20 +3,21 @@
|
|
3
3
|
.effective-order-change-items
|
4
4
|
= link_to 'Change Addresses', effective_orders.edit_order_path(order), rel: :nofollow
|
5
5
|
|
6
|
-
|
6
|
+
- unless local_assigns[:skip_order]
|
7
|
+
= render('/effective/orders/order', order: order, no_order_actions: true)
|
7
8
|
|
8
9
|
.effective-order-purchase-actions
|
9
10
|
- provider_locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, deferred_url: deferred_url }
|
10
11
|
|
11
|
-
- if EffectiveOrders.
|
12
|
+
- if EffectiveOrders.delayed? && order.delayed?
|
13
|
+
= render partial: '/effective/orders/delayed/form', locals: provider_locals
|
14
|
+
|
15
|
+
- elsif EffectiveOrders.free? && order.free?
|
12
16
|
= render partial: '/effective/orders/free/form', locals: provider_locals
|
13
17
|
|
14
18
|
- elsif EffectiveOrders.refund? && order.refund?
|
15
19
|
= render partial: '/effective/orders/refund/form', locals: provider_locals
|
16
20
|
|
17
|
-
- elsif EffectiveOrders.delayed? && order.delayed?
|
18
|
-
= render partial: '/effective/orders/delayed/form', locals: provider_locals
|
19
|
-
|
20
21
|
- else
|
21
22
|
- if EffectiveOrders.pretend?
|
22
23
|
= render partial: '/effective/orders/pretend/form', locals: provider_locals
|
@@ -43,6 +43,7 @@ class CreateEffectiveOrders < ActiveRecord::Migration[6.0]
|
|
43
43
|
t.boolean :delayed_payment, default: false
|
44
44
|
t.date :delayed_payment_date
|
45
45
|
t.text :delayed_payment_intent
|
46
|
+
t.integer :delayed_payment_total
|
46
47
|
t.datetime :delayed_payment_purchase_ran_at
|
47
48
|
t.text :delayed_payment_purchase_result
|
48
49
|
|
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.13.1
|
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-06-
|
11
|
+
date: 2024-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|