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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f5fbabf9c4012193962576f7ef67838e17e382740ad3860ab9c9f527ce86787
4
- data.tar.gz: 71f6af17259b5b62ee66b2fd993bb085dc8411ad8040c21fa0a3bc639381c655
3
+ metadata.gz: 5523fdde5cab838b117069bf24a20a0bc0509265ebbccc033447eb2d5faa9f95
4
+ data.tar.gz: 4c4040b7ba4845fb531005e97cd18096d3fb915be1c8a041d1fbbdff649d811e
5
5
  SHA512:
6
- metadata.gz: 60eff8ba4e046b46575a23c98daf14b0ba07cf548041826590ac49c3bf193cde6632437baeae38bfe011f37a3cae0e7d3d5d444aeeb0340a0990d1c93a88ce2b
7
- data.tar.gz: 9b91126b76b01d50fefc86b31d1a163dfe8164c523f69a2c3a523a827c632faaf0b0b5e13e0174b01450078dd32754a76157b5c4338b39b16b47a10ca1d25c59
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
@@ -45,7 +45,7 @@ module EffectiveOrdersHelper
45
45
  when :deluxe
46
46
  'Pay Now'
47
47
  when :deluxe_delayed
48
- 'Save now and charge me later'
48
+ 'Save card and charge me later'
49
49
  when :etransfer
50
50
  'Pay by E-transfer'
51
51
  when :free
@@ -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', dependent: :nullify
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 Authorize Payment and Complete Payment
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
- # Authorize Payment
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
- # Params passed into Authorize Payment
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 in a secure way
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
- validates :delayed_payment_intent, presence: { message: 'please provide your card information' }, if: -> { delayed? && deferred? }
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 delayed_payment_date_future?
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 delayed_payment_date_future?
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')} for the full amount
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.delayed_payment_date_future?
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
- %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.
20
+ - if order.deferred? && order.delayed?
21
+ %p Your existing #{order.delayed_payment_method} will be charged on the payment date.
21
22
 
22
- - provider_locals = { order: order, deferred_url: deferred_url, declined_url: declined_url }
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
- - EffectiveOrders.delayed_providers.each do |provider|
25
- = render partial: "/effective/orders/#{provider}/form", locals: provider_locals
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.delayed_payment_date_future?
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
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrders
2
- VERSION = '6.12.3'.freeze
2
+ VERSION = '6.13.0'.freeze
3
3
  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.12.3
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-05-31 00:00:00.000000000 Z
11
+ date: 2024-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails