effective_orders 5.9.4 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35bd45132852365a2cc570b4b6a7fbbf5cc62d42cd9f506710da80a0c77daf82
4
- data.tar.gz: e97f9869c710bdfb91cfa35b6b0bc091b429b175cdc7af9b066283d02d90bac6
3
+ metadata.gz: f548373346f66befb20e325b166d275eff0444b9b8d2865f87c37d8116d32b0d
4
+ data.tar.gz: c2cdbd728306010ba79e3847fd59578e3b51afbf2764021b3581767bad0d6831
5
5
  SHA512:
6
- metadata.gz: 02036ff52d79eaa0c47e6f2353f23b33d6168222abe6337a77880fb7c48d0c7de7b1960235ed2b2dcb9e304aac36b8bddbbf0f1132fee7395bed3638be80c2bd
7
- data.tar.gz: 1929601f0588f3cefde7eec8ceec3f796b03822406e9ae1533507a783c3f0867a5c408f21a9954c12eaa225c912817044102c869d1a334660f328a80a9381a2c
6
+ metadata.gz: 027327c45635652ad18bf89f0597d3c22156adf9ba04a527014c5aae2daed01a92f50dd6d134cf7afc5a34b6ca02daae7b69e73fd801269bf22f75e07f61cc16
7
+ data.tar.gz: 54576594dab1cd9a569e7c37aab4cf945b8670628d92868a85a8d068a212a8f175cf31c0955fbb933fb618efde82cd9a0d090cb8a83446c876ea74b0a9b10c0a
@@ -1,31 +1,37 @@
1
1
  .effective-order {
2
2
  table {
3
- clear: both;
4
- margin-bottom: 25px;
3
+ .quantity { width: 0%; }
5
4
 
6
- tfoot {
7
- > tr:first-child {
8
- border-top: 20px solid transparent;
9
- }
5
+ .price {
6
+ text-align: right;
7
+ padding-left: 2rem;
8
+ }
10
9
 
11
- th {
10
+ tfoot {
11
+ th, td {
12
12
  border: none;
13
13
  text-align: right;
14
- padding-right: 65px;
14
+ white-space: nowrap;
15
15
  }
16
16
 
17
- td {
18
- text-align: right;
17
+ // This is the first column
18
+ th { width: 100%; }
19
+
20
+ tr.single-line {
21
+ td { border-top: solid 1px; }
22
+ }
23
+
24
+ tr.double-line {
25
+ td { border-top: double 4px; }
19
26
  }
20
27
 
21
- .actions { border: none; }
28
+ .amount-owing { font-style: italic; }
29
+ .total { font-style: italic; }
22
30
  }
23
31
  }
24
-
25
- .price { text-align: right; }
26
32
  }
27
33
 
28
- // Print - Resend Receipt. Ontop of order.
34
+ // Print - Resend Receipt. Ontop of order.
29
35
  .effective-order-actions {
30
36
  text-align: right;
31
37
  margin-bottom: 0.5rem;
@@ -28,7 +28,7 @@ class Admin::EffectiveOrdersDatatable < Effective::Datatable
28
28
  end
29
29
 
30
30
  datatable do
31
- order :id, :desc
31
+ order :updated_at
32
32
 
33
33
  bulk_actions_col
34
34
 
@@ -66,20 +66,19 @@ class Admin::EffectiveOrdersDatatable < Effective::Datatable
66
66
  end
67
67
 
68
68
  col :payment_method
69
- col :payment_provider
69
+ col :payment_provider, label: 'Provider', visible: false, search: { collection: EffectiveOrders.admin_payment_providers }
70
+ col :payment_card, label: 'Card', visible: false
70
71
 
71
72
  col :subtotal, as: :price, visible: false
73
+
72
74
  col :tax, as: :price, visible: false
75
+ col(:tax_rate, visible: false) { |order| rate_to_percentage(order.tax_rate) }
73
76
 
74
- col :tax_rate, visible: false do |order|
75
- tax_rate_to_percentage(order.tax_rate)
76
- end
77
+ col :surcharge, as: :price, visible: false
78
+ col(:surcharge_percent, visible: false) { |order| rate_to_percentage(order.surcharge_percent) }
77
79
 
78
80
  col :total, as: :price
79
81
 
80
- col :payment_provider, label: 'Provider', visible: false, search: { collection: EffectiveOrders.admin_payment_providers }
81
- col :payment_card, label: 'Card', visible: false
82
-
83
82
  if EffectiveOrders.collect_note
84
83
  col :note, visible: false
85
84
  end
@@ -42,18 +42,20 @@ class EffectiveOrdersDatatable < Effective::Datatable
42
42
  collection.where(id: Effective::OrderItem.where('name ILIKE ?', "%#{term}%").select('order_id'))
43
43
  end
44
44
 
45
+ col :payment_method, visible: false
46
+ col :payment_provider, label: 'Provider', visible: false, search: { collection: EffectiveOrders.payment_providers }
47
+ col :payment_card, label: 'Card', visible: false
48
+
45
49
  col :subtotal, as: :price, visible: false
50
+
46
51
  col :tax, as: :price, visible: false
52
+ col(:tax_rate, visible: false) { |order| rate_to_percentage(order.tax_rate) }
47
53
 
48
- col :tax_rate, visible: false do |order|
49
- tax_rate_to_percentage(order.tax_rate)
50
- end
54
+ col :surcharge, as: :price, visible: false
55
+ col(:surcharge_percent, visible: false) { |order| rate_to_percentage(order.surcharge_percent) }
51
56
 
52
57
  col :total, as: :price
53
58
 
54
- col :payment_provider, label: 'Provider', visible: false, search: { collection: EffectiveOrders.payment_providers }
55
- col :payment_card, label: 'Card', visible: false
56
-
57
59
  if EffectiveOrders.collect_note
58
60
  col :note
59
61
  end
@@ -103,11 +103,12 @@ module EffectiveCartsHelper
103
103
 
104
104
  def render_cart(cart = nil)
105
105
  cart ||= current_cart
106
- render(partial: 'effective/carts/cart', locals: { cart: cart })
106
+ render('effective/carts/cart', cart: cart)
107
107
  end
108
108
 
109
109
  def render_purchasables(*purchasables)
110
- render(partial: 'effective/orders/order_items', locals: { order: Effective::Order.new(purchasables) })
110
+ order = Effective::Order.new(purchasables)
111
+ render('effective/orders/purchasables', order: order)
111
112
  end
112
113
 
113
114
  end
@@ -10,9 +10,8 @@ module EffectiveMonerisCheckoutHelper
10
10
  api_token: EffectiveOrders.moneris_checkout.fetch(:api_token),
11
11
  store_id: EffectiveOrders.moneris_checkout.fetch(:store_id),
12
12
  checkout_id: EffectiveOrders.moneris_checkout.fetch(:checkout_id),
13
-
14
13
  action: :preload,
15
- txn_total: price_to_currency(order.total).gsub(',', '').gsub('$', ''),
14
+ txn_total: ('%.2f' % (order.total_with_surcharge / 100.0)),
16
15
 
17
16
  # Optional
18
17
  order_no: order.transaction_id, # Has to be unique. This is order number, billing name and Time.now
@@ -5,6 +5,12 @@ module EffectiveOrdersHelper
5
5
  number_to_currency(price / 100.0)
6
6
  end
7
7
 
8
+ def rate_to_percentage(rate)
9
+ rate = rate || 0.0
10
+ number_to_percentage(rate, strip_insignificant_zeros: true)
11
+ end
12
+
13
+ # Deprecated.
8
14
  def tax_rate_to_percentage(tax_rate, options = {})
9
15
  options[:strip_insignificant_zeros] = true if options[:strip_insignificant_zeros].nil?
10
16
  number_to_percentage(tax_rate, strip_insignificant_zeros: true)
@@ -119,4 +125,21 @@ module EffectiveOrdersHelper
119
125
  icon_to('shopping-cart', path, { title: 'Checkout' }.merge(options))
120
126
  end
121
127
 
128
+ def admin_mark_as_paid_payment_providers
129
+ providers = EffectiveOrders.admin_payment_providers
130
+
131
+ percentage = EffectiveOrders.credit_card_surcharge_percent.to_f
132
+ return providers unless percentage > 0.0
133
+
134
+ surcharge_providers = EffectiveOrders.credit_card_payment_providers
135
+
136
+ with_surcharge = providers.select { |provider| surcharge_providers.include?(provider) }
137
+ without_surcharge = providers.reject { |provider| surcharge_providers.include?(provider) }
138
+
139
+ {
140
+ "With #{rate_to_percentage(percentage)} credit card surcharge": with_surcharge.map { |provider| [provider, provider] },
141
+ 'Without credit card surcharge': without_surcharge.map { |provider| [provider, provider] }
142
+ }
143
+ end
144
+
122
145
  end
@@ -31,16 +31,31 @@ module EffectivePaypalHelper
31
31
  cert_id: EffectiveOrders.paypal[:cert_id],
32
32
  currency_code: EffectiveOrders.paypal[:currency],
33
33
  invoice: order.id,
34
- amount: (order.subtotal / 100.0).round(2),
35
- tax_cart: (order.tax / 100.0).round(2)
34
+ amount: '%.2f' % (order.amount_owing / 100.0),
35
+ tax_cart: '%.2f' % ((order.tax + order.surcharge_tax) / 100.0)
36
36
  }
37
37
 
38
- order.order_items.each_with_index do |item, x|
39
- values["item_number_#{x+1}"] = x+1
40
- values["item_name_#{x+1}"] = item.name
41
- values["quantity_#{x+1}"] = item.quantity
42
- values["amount_#{x+1}"] = '%.2f' % (item.price / 100.0)
43
- values["tax_#{x+1}"] = '%.2f' % ((item.tax / 100.0) / item.quantity) # Tax for 1 of these items
38
+ number = 0
39
+
40
+ order.order_items.each do |item|
41
+ number += 1
42
+
43
+ values["item_number_#{number}"] = number
44
+ values["item_name_#{number}"] = item.name
45
+ values["quantity_#{number}"] = item.quantity
46
+ values["amount_#{number}"] = '%.2f' % (item.price / 100.0)
47
+ values["tax_#{number}"] = '%.2f' % ((item.tax / 100.0) / item.quantity) # Tax for 1 of these items
48
+ end
49
+
50
+ # Credit Card Surcharge
51
+ if order.surcharge != 0
52
+ number += 1
53
+
54
+ values["item_number_#{number}"] = number
55
+ values["item_name_#{number}"] = 'Credit Card Surcharge'
56
+ values["quantity_#{number}"] = 1
57
+ values["amount_#{number}"] = '%.2f' % (order.surcharge / 100.0)
58
+ values["tax_#{number}"] = '%.2f' % (order.surcharge_tax / 100.0)
44
59
  end
45
60
 
46
61
  signed = OpenSSL::PKCS7::sign(OpenSSL::X509::Certificate.new(APP_CERT_PEM), OpenSSL::PKey::RSA.new(APP_KEY_PEM, ''), values.map { |k, v| "#{k}=#{v}" }.join("\n"), [], OpenSSL::PKCS7::BINARY)
@@ -60,12 +60,12 @@ module EffectiveStripeHelper
60
60
  customer.create_stripe_customer! # Only creates if customer not already present
61
61
 
62
62
  payment = {
63
- amount: order.total,
63
+ amount: order.total_with_surcharge,
64
64
  currency: EffectiveOrders.stripe[:currency],
65
65
  customer: customer.stripe_customer_id,
66
66
  payment_method: customer.payment_method_id.presence,
67
67
  description: stripe_order_description(order),
68
- metadata: { order_id: order.id },
68
+ metadata: { order_id: order.id }
69
69
  }
70
70
 
71
71
  token_required = customer.token_required?
@@ -52,11 +52,17 @@ module Effective
52
52
  payment_provider :string
53
53
  payment_card :string
54
54
 
55
- tax_rate :decimal, precision: 6, scale: 3
55
+ tax_rate :decimal, precision: 6, scale: 3
56
+ surcharge_percent :decimal, precision: 6, scale: 3
56
57
 
57
- subtotal :integer
58
- tax :integer
59
- total :integer
58
+ subtotal :integer # Sum of items subtotal
59
+ tax :integer # Tax on subtotal
60
+ amount_owing :integer # Subtotal + Tax
61
+
62
+ surcharge :integer # Credit Card Surcharge
63
+ surcharge_tax :integer # Tax on surcharge
64
+
65
+ total :integer # Subtotal + Tax + Surcharge + Surcharge Tax
60
66
 
61
67
  timestamps
62
68
  end
@@ -88,7 +94,8 @@ module Effective
88
94
  before_validation { assign_email }
89
95
  before_validation { assign_user_address }
90
96
  before_validation { assign_billing_name }
91
- before_validation { assign_order_totals }
97
+ before_validation { assign_order_values }
98
+ before_validation { assign_order_charges }
92
99
  end
93
100
 
94
101
  # Order validations
@@ -119,7 +126,7 @@ module Effective
119
126
  end
120
127
 
121
128
  # User validations -- An admin skips these when working in the admin/ namespace
122
- with_options unless: -> { pending? || skip_buyer_validations? || purchased? } do
129
+ with_options(unless: -> { pending? || skip_buyer_validations? || purchased? }) do
123
130
  validates :tax_rate, presence: { message: "can't be determined based on billing address" }
124
131
  validates :tax, presence: true
125
132
 
@@ -129,7 +136,7 @@ module Effective
129
136
  end
130
137
 
131
138
  # When Purchased
132
- with_options if: -> { purchased? } do
139
+ with_options(if: -> { purchased? }) do
133
140
  validates :purchased_at, presence: true
134
141
  validates :payment, presence: true
135
142
 
@@ -137,7 +144,7 @@ module Effective
137
144
  validates :payment_card, presence: true
138
145
  end
139
146
 
140
- with_options if: -> { deferred? } do
147
+ with_options(if: -> { deferred? }) do
141
148
  validates :payment_provider, presence: true
142
149
 
143
150
  validate do
@@ -145,11 +152,18 @@ module Effective
145
152
  end
146
153
  end
147
154
 
148
- before_save(if: -> { state_was == EffectiveOrders::PURCHASED }) do
149
- raise EffectiveOrders::AlreadyPurchasedException.new('cannot unpurchase an order') unless purchased?
150
- end
155
+ # Sanity check
156
+ before_save(if: -> { was_purchased? }) do
157
+ raise('cannot unpurchase an order') unless purchased?
158
+
159
+ raise('cannot change subtotal of a purchased order') if changes[:subtotal].present?
160
+
161
+ raise('cannot change tax of a purchased order') if changes[:tax].present?
162
+ raise('cannot change tax of a purchased order') if changes[:tax_rate].present?
163
+
164
+ raise('cannot change surcharge of a purchased order') if changes[:surcharge].present?
165
+ raise('cannot change surcharge percent of a purchased order') if changes[:surcharge_percent].present?
151
166
 
152
- before_save(if: -> { done? }) do
153
167
  raise('cannot change total of a purchased order') if changes[:total].present?
154
168
  end
155
169
 
@@ -213,9 +227,7 @@ module Effective
213
227
  removed.each { |order_item| order_item.mark_for_destruction }
214
228
 
215
229
  # Make sure to reset stored aggregates
216
- self.total = nil
217
- self.subtotal = nil
218
- self.tax = nil
230
+ assign_attributes(subtotal: nil, tax_rate: nil, tax: nil, surcharge_percent: nil, surcharge: nil, total: nil)
219
231
 
220
232
  removed.length == 1 ? removed.first : removed
221
233
  end
@@ -259,9 +271,7 @@ module Effective
259
271
  end.compact
260
272
 
261
273
  # Make sure to reset stored aggregates
262
- self.total = nil
263
- self.subtotal = nil
264
- self.tax = nil
274
+ assign_attributes(subtotal: nil, tax_rate: nil, tax: nil, surcharge_percent: nil, surcharge: nil, total: nil)
265
275
 
266
276
  retval = cart_items.map do |item|
267
277
  order_items.build(
@@ -311,24 +321,14 @@ module Effective
311
321
  end
312
322
 
313
323
  def total_label
314
- if refund? && purchased?
315
- 'Total Paid'
316
- elsif purchased?
317
- 'Total Paid'
318
- elsif refund? && (pending? || confirmed?)
319
- 'Total Due'
320
- elsif (pending? || confirmed?)
321
- 'Total Due'
322
- else
323
- 'Total'
324
- end
324
+ purchased? ? 'Total Paid' : 'Total Due'
325
325
  end
326
326
 
327
327
  # Visa - 1234
328
328
  def payment_method
329
329
  return nil unless purchased?
330
330
 
331
- provider = payment_provider if ['cheque', 'etransfer', 'phone'].include?(payment_provider)
331
+ provider = payment_provider if ['cheque', 'etransfer', 'phone', 'credit card'].include?(payment_provider)
332
332
 
333
333
  # Normalize payment card
334
334
  card = case payment_card.to_s.downcase.gsub(' ', '').strip
@@ -411,6 +411,18 @@ module Effective
411
411
  false
412
412
  end
413
413
 
414
+ def was_purchased?
415
+ state_was == EffectiveOrders::PURCHASED
416
+ end
417
+
418
+ def purchased_with_credit_card?
419
+ purchased? && EffectiveOrders.credit_card_payment_providers.include?(payment_provider)
420
+ end
421
+
422
+ def purchased_without_credit_card?
423
+ purchased? && EffectiveOrders.credit_card_payment_providers.exclude?(payment_provider)
424
+ end
425
+
414
426
  def declined?
415
427
  state == EffectiveOrders::DECLINED
416
428
  end
@@ -424,7 +436,7 @@ module Effective
424
436
  end
425
437
 
426
438
  def subtotal
427
- self[:subtotal] || present_order_items.map { |oi| oi.subtotal }.sum
439
+ self[:subtotal] || get_subtotal()
428
440
  end
429
441
 
430
442
  def tax_rate
@@ -435,8 +447,32 @@ module Effective
435
447
  self[:tax] || get_tax()
436
448
  end
437
449
 
450
+ def amount_owing
451
+ self[:amount_owing] || get_amount_owing()
452
+ end
453
+
454
+ def surcharge_percent
455
+ self[:surcharge_percent] || get_surcharge_percent()
456
+ end
457
+
458
+ def surcharge
459
+ self[:surcharge] || get_surcharge()
460
+ end
461
+
462
+ def surcharge_tax
463
+ self[:surcharge_tax] || get_surcharge_tax()
464
+ end
465
+
438
466
  def total
439
- (self[:total] || (subtotal + tax.to_i)).to_i
467
+ self[:total] || get_total()
468
+ end
469
+
470
+ def total_with_surcharge
471
+ get_total_with_surcharge()
472
+ end
473
+
474
+ def total_without_surcharge
475
+ get_total_without_surcharge()
440
476
  end
441
477
 
442
478
  def free?
@@ -526,12 +562,13 @@ module Effective
526
562
 
527
563
  # Call this as a way to skip over non consequential orders
528
564
  # And mark some purchasables purchased
565
+ # This is different than the Mark as Paid payment processor
529
566
  def mark_as_purchased!
530
567
  purchase!(skip_buyer_validations: true, email: false, skip_quickbooks: true)
531
568
  end
532
569
 
533
570
  # Effective::Order.new(items: Product.first, user: User.first).purchase!(email: false)
534
- def purchase!(payment: 'none', provider: 'none', card: 'none', email: true, skip_buyer_validations: false, skip_quickbooks: false)
571
+ def purchase!(payment: nil, provider: nil, card: nil, email: true, skip_buyer_validations: false, skip_quickbooks: false)
535
572
  return true if purchased?
536
573
 
537
574
  # Assign attributes
@@ -539,12 +576,16 @@ module Effective
539
576
  state: EffectiveOrders::PURCHASED,
540
577
  skip_buyer_validations: skip_buyer_validations,
541
578
 
542
- payment_provider: provider,
543
- payment_card: (card.presence || 'none'),
579
+ payment: payment_to_h(payment.presence || 'none'),
544
580
  purchased_at: (purchased_at.presence || Time.zone.now),
545
- payment: payment_to_h(payment)
581
+
582
+ payment_provider: (provider.presence || 'none'),
583
+ payment_card: (card.presence || 'none')
546
584
  )
547
585
 
586
+ # Updates surcharge and total based on payment_provider
587
+ assign_order_charges()
588
+
548
589
  begin
549
590
  Effective::Order.transaction do
550
591
  run_purchasable_callbacks(:before_purchase)
@@ -600,7 +641,7 @@ module Effective
600
641
  def decline!(payment: 'none', provider: 'none', card: 'none', validate: true)
601
642
  return false if declined?
602
643
 
603
- raise EffectiveOrders::AlreadyPurchasedException.new('order already purchased') if purchased?
644
+ raise('order already purchased') if purchased?
604
645
 
605
646
  error = nil
606
647
 
@@ -664,6 +705,10 @@ module Effective
664
705
 
665
706
  protected
666
707
 
708
+ def get_subtotal
709
+ present_order_items.map { |oi| oi.subtotal }.sum
710
+ end
711
+
667
712
  def get_tax_rate
668
713
  rate = instance_exec(self, &EffectiveOrders.order_tax_rate_method).to_f
669
714
 
@@ -675,10 +720,49 @@ module Effective
675
720
  end
676
721
 
677
722
  def get_tax
678
- return nil unless tax_rate.present?
723
+ return 0 unless tax_rate.present?
679
724
  present_order_items.reject { |oi| oi.tax_exempt? }.map { |oi| (oi.subtotal * (tax_rate / 100.0)).round(0).to_i }.sum
680
725
  end
681
726
 
727
+ def get_amount_owing
728
+ subtotal + tax
729
+ end
730
+
731
+ def get_surcharge_percent
732
+ percent = EffectiveOrders.credit_card_surcharge_percent.to_f
733
+ return nil unless percent > 0.0
734
+
735
+ return 0.0 if purchased_without_credit_card?
736
+
737
+ if (percent > 10.0 || percent < 0.5)
738
+ raise "expected EffectiveOrders.credit_card_surcharge to return a value between 10.0 (10%) and 0.5 (0.5%) or nil. Received #{percent}. Please return 2.5 for 2.5% surcharge."
739
+ end
740
+
741
+ percent
742
+ end
743
+
744
+ def get_surcharge
745
+ return 0 unless surcharge_percent.present?
746
+ ((subtotal + tax) * (surcharge_percent / 100.0)).round(0).to_i
747
+ end
748
+
749
+ def get_surcharge_tax
750
+ return 0 unless tax_rate.present?
751
+ (surcharge * (tax_rate / 100.0)).round(0).to_i
752
+ end
753
+
754
+ def get_total
755
+ subtotal + tax + surcharge + surcharge_tax
756
+ end
757
+
758
+ def get_total_with_surcharge
759
+ subtotal + tax + surcharge + surcharge_tax
760
+ end
761
+
762
+ def get_total_without_surcharge
763
+ subtotal + tax
764
+ end
765
+
682
766
  private
683
767
 
684
768
  def present_order_items
@@ -707,18 +791,31 @@ module Effective
707
791
  end
708
792
  end
709
793
 
710
- # This overwrites the prices, taxes, etc on every save.
711
- def assign_order_totals
794
+ # This overwrites the prices, taxes, surcharge, etc on every save.
795
+ # Does not get run from the before_validate on purchase.
796
+ def assign_order_values
712
797
  # Copies prices from purchasable into order items
713
798
  present_order_items.each { |oi| oi.assign_purchasable_attributes }
714
799
 
715
- # Sum of order item subtotals
716
- subtotal = present_order_items.map { |oi| oi.subtotal }.sum
800
+ # Calculated from each item
801
+ self.subtotal = get_subtotal()
717
802
 
718
- self.subtotal = subtotal
803
+ # We only know tax if there is a billing address
719
804
  self.tax_rate = get_tax_rate()
720
805
  self.tax = get_tax()
721
- self.total = subtotal + (tax || 0)
806
+
807
+ # Subtotal + Tax
808
+ self.amount_owing = get_amount_owing()
809
+ end
810
+
811
+ def assign_order_charges
812
+ # We only apply surcharge for credit card orders. But we have to display and calculate for non purchased orders
813
+ self.surcharge_percent = get_surcharge_percent()
814
+ self.surcharge = get_surcharge()
815
+ self.surcharge_tax = get_surcharge_tax()
816
+
817
+ # Subtotal + Tax + Surcharge + Surcharge Tax
818
+ self.total = get_total()
722
819
  end
723
820
 
724
821
  def update_purchasables_purchased_order!
@@ -32,7 +32,7 @@ module Effective
32
32
  ((quantity || 0) > 1 ? "#{quantity}x #{name}" : name) || 'order item'
33
33
  end
34
34
 
35
- # This method is called in a before_validation in order.assign_order_totals()
35
+ # This method is called in a before_validation in order.assign_order_values()
36
36
  def assign_purchasable_attributes
37
37
  assign_attributes(name: purchasable.purchasable_name, price: purchasable.price, tax_exempt: purchasable.tax_exempt) if purchasable
38
38
  end
@@ -1,67 +1,72 @@
1
- - include_quantity_column = order.order_items.any? { |order_item| order_item.quantity > 1 }
2
- - include_download_column = order.purchased? && order.order_items.any? { |order_item| order_item.purchased_download_url.present? }
3
-
4
1
  .effective-order-items
5
2
  %table.table
6
3
  %thead
7
4
  %tr
8
- - if include_quantity_column
9
- %th.quantity Qty
10
-
11
- - if include_download_column
12
- %th.download Download
13
-
5
+ %th.quantity Qty
14
6
  %th.item= order.order_items.length > 1 ? 'Items' : 'Item'
15
7
  %th.price Price
16
8
 
17
9
  %tbody
18
10
  - order.order_items.each do |item|
19
11
  %tr
20
- - if include_quantity_column
21
- %td.quantity= item.quantity
12
+ %td.quantity= item.quantity
13
+
14
+ %td.item
15
+ = item.name.html_safe
22
16
 
23
- - if include_download_column
24
- %td.download
25
- - if item.purchased_download_url.present?
26
- = link_to 'download', item.purchased_download_url
27
- - else
28
- = '-'
17
+ - if order.purchased? && item.purchased_download_url.present?
18
+ = link_to 'Download', item.purchased_download_url
29
19
 
30
- %td.item= item.name.html_safe
31
20
  %td.price= price_to_currency(item.subtotal)
32
21
 
22
+ %table.table
33
23
  %tfoot
34
- - if order.tax.to_i != 0 || order.tax_rate == nil
35
- %tr
36
- - if include_quantity_column
37
- %th.quantity
38
-
39
- - if include_download_column
40
- %th.download
24
+ %tr
25
+ %th
26
+ %td.subtotal Subtotal
27
+ %td.price.subtotal-price= price_to_currency(order.subtotal)
41
28
 
42
- %th.subtotal Subtotal
43
- %td.price.subtotal-price= price_to_currency(order.subtotal)
29
+ - if order.tax_rate.blank?
30
+ -# Nothing to do. We can't display Tax, Total or Credit Card Surcharge (which is taxed) yet.
44
31
 
45
- - if order.tax.to_i != 0
32
+ - elsif order.tax_rate.present? && order.surcharge_percent.to_f > 0.0
46
33
  %tr
47
- - if include_quantity_column
48
- %th.quantity
34
+ %th
35
+ %td.tax Tax (#{rate_to_percentage(order.tax_rate)})
36
+ %td.price.tax-price= price_to_currency(order.tax)
49
37
 
50
- - if include_download_column
51
- %th.download
38
+ %tr.single-line
39
+ %th
40
+ %td.amount-owing Amount owing before Credit Card Processing Fee
41
+ %td.price.amount-owing-price= price_to_currency(order.amount_owing)
52
42
 
53
- %th.tax Tax (#{tax_rate_to_percentage(order.tax_rate)})
54
- %td.price.tax-price= price_to_currency(order.tax)
43
+ %tr
44
+ %th
45
+ %td
46
+ %td
47
+
48
+ %tr
49
+ %th
50
+ %td.surcharge Credit Card Processing Fee (#{rate_to_percentage(order.surcharge_percent)}) on #{price_to_currency(order.amount_owing)}
51
+ %td.price.surcharge-price= price_to_currency(order.surcharge)
55
52
 
56
- - if order.tax_rate.present?
57
53
  %tr
58
- - if include_quantity_column
59
- %th.quantity
54
+ %th
55
+ %td.surcharge-tax Tax (#{rate_to_percentage(order.tax_rate)}) on Credit Card Processing Fee
56
+ %td.price.surcharge-tax-price= price_to_currency(order.surcharge_tax)
60
57
 
61
- - if include_download_column
62
- %th.download
58
+ %tr.double-line
59
+ %th
60
+ %td.total Total amount charged to credit card
61
+ %td.price.total-price= price_to_currency(order.total)
63
62
 
64
- %th.total
65
- = order.total_label
63
+ - elsif order.tax_rate.present? && !(order.surcharge_percent.to_f > 0.0)
64
+ %tr
65
+ %th
66
+ %td.tax Tax (#{rate_to_percentage(order.tax_rate)})
67
+ %td.price.tax-price= price_to_currency(order.tax)
66
68
 
69
+ %tr.single-line
70
+ %th
71
+ %td.total= order.total_label
67
72
  %td.price.total-price= price_to_currency(order.total)
@@ -0,0 +1,20 @@
1
+ .effective-order-items
2
+ %table.table
3
+ %thead
4
+ %tr
5
+ %th.quantity Qty
6
+ %th.item= order.order_items.length > 1 ? 'Items' : 'Item'
7
+ %th.price Price
8
+
9
+ %tbody
10
+ - order.order_items.each do |item|
11
+ %tr
12
+ %td.quantity= item.quantity
13
+
14
+ %td.item
15
+ = item.name.html_safe
16
+
17
+ - if order.purchased? && item.purchased_download_url.present?
18
+ = link_to 'Download', item.purchased_download_url
19
+
20
+ %td.price= price_to_currency(item.subtotal)
@@ -7,7 +7,8 @@
7
7
  = effective_form_with(model: order, url: effective_orders.mark_as_paid_order_path(order), method: :post) do |f|
8
8
  .row
9
9
  .col-6
10
- = f.select :payment_provider, EffectiveOrders.admin_payment_providers, required: true
10
+ - collection = admin_mark_as_paid_payment_providers()
11
+ = f.select :payment_provider, collection, required: true, grouped: collection.kind_of?(Hash)
11
12
 
12
13
  = f.text_field :payment_card,
13
14
  label: 'Payment card type, cheque, e-transfer or transaction number',
@@ -4,15 +4,24 @@
4
4
  %meta{:content => 'text/html; charset=UTF-8', 'http-equiv' => 'Content-Type'}
5
5
 
6
6
  :css
7
+ .effective-order-header h1 { margin: 0; }
8
+ .effective-order-shipping { padding-top: 12px; padding-bottom: 12px; }
9
+
7
10
  .effective-order table.table { min-width: 650px; vertical-align: top; border: 0; }
8
- .effective-order table.table td { border: 0; vertical-align: top; }
9
11
  .effective-order { text-align: left; }
10
- .effective-order .price { text-align: right; }
11
- .effective-order tfoot th { text-align: right; }
12
- .effective-order tfoot tr:first-child td { padding-top: 24px; }
13
- .effective-order tfoot tr:first-child th { padding-top: 24px; }
14
- .effective-order-shipping { padding-top: 12px; padding-bottom: 12px; }
15
- .effective-order-header h1 { margin: 0; }
12
+ .effective-order .price { text-align: right; padding-left: 24px; }
13
+
14
+ .effective-order tfoot th { text-align: right; white-space: nowrap; }
15
+ .effective-order tfoot td { text-align: right; white-space: nowrap; }
16
+
17
+ .effective-order tfoot th { width: 100%; }
18
+
19
+ .effective-order tfoot tr.single-line td { border-top: solid 1px; }
20
+ .effective-order tfoot tr.double-line td { border-top: double 4px; }
21
+
22
+ .effective-order tfoot .amount-owing { font-style: italic; }
23
+ .effective-order tfoot .total { font-style: italic; }
24
+
16
25
  @media print { .effective-page-break { page-break-inside: avoid; page-break-after: always; min-height: 1px; } }
17
26
 
18
27
  %body{style: 'background: #fff;'}
@@ -47,6 +47,12 @@ EffectiveOrders.setup do |config|
47
47
  # An order must have a tax rate (even if the value is 0) to be purchased
48
48
  config.order_tax_rate_method = Proc.new { |order| Effective::TaxRateCalculator.new(order: order).tax_rate }
49
49
 
50
+ # Credit Card Surcharge
51
+ # Will be applied to all orders based off the after-tax total.
52
+ # Use 2.4 for 2.4% or nil for none
53
+ config.credit_card_surcharge_percent = nil
54
+ config.credit_card_surcharge_qb_item_name = 'Credit Card Surcharge'
55
+
50
56
  # Minimum Charge
51
57
  # Prevent orders less than this value from being purchased
52
58
  # Stripe doesn't allow orders less than $0.50
@@ -23,9 +23,13 @@ class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
23
23
  t.string :payment_card
24
24
 
25
25
  t.decimal :tax_rate, :precision => 6, :scale => 3
26
+ t.decimal :surcharge_percent, :precision => 6, :scale => 3
26
27
 
27
28
  t.integer :subtotal
28
29
  t.integer :tax
30
+ t.integer :amount_owing
31
+ t.integer :surcharge
32
+ t.integer :surcharge_tax
29
33
  t.integer :total
30
34
 
31
35
  t.timestamps
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrders
2
- VERSION = '5.9.4'.freeze
2
+ VERSION = '6.0.0'.freeze
3
3
  end
@@ -39,6 +39,7 @@ module EffectiveOrders
39
39
  :billing_address, :shipping_address,
40
40
  :collect_note, :collect_note_required, :collect_note_message,
41
41
  :terms_and_conditions, :terms_and_conditions_label, :minimum_charge,
42
+ :credit_card_surcharge_percent, :credit_card_surcharge_qb_item_name,
42
43
 
43
44
  # Mailer
44
45
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject,
@@ -166,7 +167,7 @@ module EffectiveOrders
166
167
  #('pretend' if pretend?),
167
168
  #('refund' if refund?),
168
169
  ('stripe' if stripe?),
169
- ('other' if mark_as_paid?),
170
+ ('other (non credit card)' if mark_as_paid?),
170
171
  'none'
171
172
  ].compact
172
173
  end
@@ -175,6 +176,10 @@ module EffectiveOrders
175
176
  [('cheque' if cheque?), ('etransfer' if etransfer?), ('phone' if phone?)].compact
176
177
  end
177
178
 
179
+ def self.credit_card_payment_providers
180
+ ['credit card', 'moneris', 'moneris_checkout', 'paypal', 'stripe']
181
+ end
182
+
178
183
  def self.qb_sync?
179
184
  use_effective_qb_sync && defined?(EffectiveQbSync)
180
185
  end
@@ -285,7 +290,6 @@ module EffectiveOrders
285
290
  end
286
291
 
287
292
  class SoldOutException < Exception; end
288
- class AlreadyPurchasedException < Exception; end
289
293
 
290
294
  def self.gem_path
291
295
  __dir__.chomp('/lib')
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: 5.9.4
4
+ version: 6.0.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: 2022-12-02 00:00:00.000000000 Z
11
+ date: 2022-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -269,6 +269,7 @@ files:
269
269
  - app/views/effective/orders/_order_payment.html.haml
270
270
  - app/views/effective/orders/_order_shipping.html.haml
271
271
  - app/views/effective/orders/_orders_table.html.haml
272
+ - app/views/effective/orders/_purchasables.html.haml
272
273
  - app/views/effective/orders/cheque/_form.html.haml
273
274
  - app/views/effective/orders/declined.html.haml
274
275
  - app/views/effective/orders/deferred.html.haml