effective_orders 6.12.3 → 6.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/datatables/admin/effective_orders_datatable.rb +1 -0
- data/app/helpers/effective_orders_helper.rb +1 -1
- data/app/models/concerns/acts_as_purchasable.rb +9 -0
- data/app/models/concerns/acts_as_purchasable_parent.rb +12 -1
- data/app/models/effective/deluxe_api.rb +39 -71
- data/app/models/effective/order.rb +27 -5
- data/app/views/effective/orders/_order_deferred.html.haml +1 -1
- data/app/views/effective/orders/delayed/_form.html.haml +13 -7
- data/app/views/effective/orders/delayed/_form_purchase.html.haml +1 -1
- 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: 5523fdde5cab838b117069bf24a20a0bc0509265ebbccc033447eb2d5faa9f95
|
4
|
+
data.tar.gz: 4c4040b7ba4845fb531005e97cd18096d3fb915be1c8a041d1fbbdff649d811e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36f22450eeeb3ffbd0755f9f840ae4be8ffd39d7a6ba9095005ee51044781d05a616f929adfe58b7a42678b42c85135c82dfdb572767ca527b6bd35a357e02d7
|
7
|
+
data.tar.gz: 927f6c0dcd4f715010fd073e056357a875222cc026b84159db6616c1ba2d36815017fab998f648969d39dba3950f53b7f5543a7f5319ad5fa835c6e9b8213d54
|
@@ -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
|
@@ -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
|
@@ -39,8 +39,19 @@ module ActsAsPurchasableParent
|
|
39
39
|
end
|
40
40
|
|
41
41
|
included do
|
42
|
-
has_many :orders, -> { order(:id) }, as: :parent, class_name: 'Effective::Order'
|
42
|
+
has_many :orders, -> { order(:id) }, as: :parent, class_name: 'Effective::Order'
|
43
|
+
|
43
44
|
accepts_nested_attributes_for :orders
|
45
|
+
|
46
|
+
before_destroy do
|
47
|
+
orders.each do |order|
|
48
|
+
raise('unable to destroy a purchasable_parent with purchased orders') if order.purchased?
|
49
|
+
order.voided? ? order.save! : order.void!
|
50
|
+
end
|
51
|
+
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
44
55
|
end
|
45
56
|
|
46
57
|
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?
|
@@ -548,13 +553,20 @@ module Effective
|
|
548
553
|
return false unless delayed?
|
549
554
|
return false unless deferred?
|
550
555
|
return false unless delayed_payment_intent.present?
|
551
|
-
return false if
|
556
|
+
return false if delayed_payment_date_upcoming?
|
552
557
|
return false if delayed_payment_purchase_ran_at.present? # We ran before and probably failed
|
553
558
|
|
554
559
|
true
|
555
560
|
end
|
556
561
|
|
557
|
-
def
|
562
|
+
def delayed_payment_info
|
563
|
+
return unless delayed? && deferred?
|
564
|
+
return unless delayed_payment_date_upcoming?
|
565
|
+
|
566
|
+
"Your #{delayed_payment_method} will be charged on #{delayed_payment_date.strftime('%F')} for the full amount of $#{'%0.2f' % total_to_f}"
|
567
|
+
end
|
568
|
+
|
569
|
+
def delayed_payment_date_upcoming?
|
558
570
|
return false unless delayed?
|
559
571
|
delayed_payment_date > Time.zone.now.to_date
|
560
572
|
end
|
@@ -737,6 +749,7 @@ module Effective
|
|
737
749
|
|
738
750
|
assign_attributes(
|
739
751
|
delayed_payment_intent: payment_intent,
|
752
|
+
delayed_payment_total: total(),
|
740
753
|
|
741
754
|
payment: payment_to_h(payment),
|
742
755
|
payment_card: (card.presence || 'none')
|
@@ -832,6 +845,15 @@ module Effective
|
|
832
845
|
unvoided!(skip_buyer_validations: true)
|
833
846
|
end
|
834
847
|
|
848
|
+
def deluxe_delayed_purchase!
|
849
|
+
raise('expected a delayed order') unless delayed?
|
850
|
+
raise('expected a deferred order') unless deferred?
|
851
|
+
raise('expected delayed payment intent') unless delayed_payment_intent.present?
|
852
|
+
raise('expected a deluxe_delayed payment provider') unless payment_provider == 'deluxe_delayed'
|
853
|
+
|
854
|
+
Effective::DeluxeApi.new().purchase_delayed_orders!(self)
|
855
|
+
end
|
856
|
+
|
835
857
|
# These are all the emails we send all notifications to
|
836
858
|
def emails
|
837
859
|
([purchased_by.try(:email)] + [email] + [user.try(:email)] + Array(organization.try(:billing_emails))).map(&:presence).compact.uniq
|
@@ -8,6 +8,6 @@
|
|
8
8
|
%tr
|
9
9
|
%td
|
10
10
|
- if order.delayed?
|
11
|
-
Your #{order.delayed_payment_method} will be charged on #{order.delayed_payment_date.strftime('%F')}
|
11
|
+
Your #{order.delayed_payment_method} will be charged on #{order.delayed_payment_date.strftime('%F')}
|
12
12
|
- else
|
13
13
|
Waiting for payment by #{order.payment_provider}
|
@@ -8,18 +8,24 @@
|
|
8
8
|
|
9
9
|
The payment date for this order
|
10
10
|
|
11
|
-
- if order.
|
11
|
+
- if order.delayed_payment_date_upcoming?
|
12
12
|
is in #{distance} from now on #{order.delayed_payment_date.strftime('%F')}
|
13
13
|
- elsif order.delayed_payment_date_today?
|
14
14
|
was today
|
15
15
|
- else
|
16
16
|
was #{distance} ago on #{order.delayed_payment_date.strftime('%F')}
|
17
|
+
|
18
|
+
- provider_locals = { order: order, deferred_url: deferred_url, declined_url: declined_url }
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
representing your card information. The full amount will be charged on the payment date.
|
20
|
+
- if order.deferred? && order.delayed?
|
21
|
+
%p Your existing #{order.delayed_payment_method} will be charged on the payment date.
|
21
22
|
|
22
|
-
|
23
|
+
= collapse('Change my card info') do
|
24
|
+
- EffectiveOrders.delayed_providers.each do |provider|
|
25
|
+
= render partial: "/effective/orders/#{provider}/form", locals: provider_locals
|
26
|
+
- else
|
27
|
+
%p
|
28
|
+
Please enter your card information so it can be charged on the payment date.
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
- EffectiveOrders.delayed_providers.each do |provider|
|
31
|
+
= render partial: "/effective/orders/#{provider}/form", locals: provider_locals
|
@@ -13,7 +13,7 @@
|
|
13
13
|
|
14
14
|
The payment date for this order
|
15
15
|
|
16
|
-
- if order.
|
16
|
+
- if order.delayed_payment_date_upcoming?
|
17
17
|
is in #{distance} from now on #{order.delayed_payment_date.strftime('%F')}
|
18
18
|
- elsif order.delayed_payment_date_today?
|
19
19
|
was today
|
@@ -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.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-
|
11
|
+
date: 2024-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|