effective_orders 6.4.4 → 6.5.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: 39a490616d23d3fa6a77d50362f39001535889c1edf07eff99e591560d77a18c
4
- data.tar.gz: e190a899ff398fafce51372870854da6e80bcee2ca9d90d827822e1d44fdd82a
3
+ metadata.gz: 658dc93673ea1d94b4ef09a9ad65fc267a58d36c7560f8e70a12a8719ee1f917
4
+ data.tar.gz: 190fcc09c8cd4de5ff184c54bc5612a3ccba50f2c97ea6b579d9cf3ec6b32fd5
5
5
  SHA512:
6
- metadata.gz: b47f581cacd6d03ba0da55b5e73571a11216fe98386fa1b116cb677b2eb6166361847e1bf94bf45862876126e01f63a490db8102c866fa4e169ded15177b32b0
7
- data.tar.gz: 76c775e10083421002756e7226eafa10256dad7be33bb975b4cfd0c9f73914377a45f299a2d52529ab1c5ac3e052dd7f384d73b549b74feae01e595fa56308ec
6
+ metadata.gz: a75d33e8b848a0a64d1e73617cc45a57070b98bcdf93ebe872d63f2e3f1f1158d697b6fe8786195de74068479c1e7e999b47d0ef25fa1c1482b405c671b53c59
7
+ data.tar.gz: e13b5214ba7fe0da6e68c981c89a391aedf6e0fbfb0bf1365689f4cb885b9342cca7b32ab21a31d91d215f6ac81fb4b66fc7fe1337daedcf3ccfd38ac0bfc217
@@ -85,13 +85,7 @@ module Admin
85
85
  flash[:danger] = 'Unable to send payment request'
86
86
  end
87
87
 
88
- if respond_to?(:redirect_back)
89
- redirect_back(fallback_location: effective_orders.admin_order_path(@order))
90
- elsif request.referrer.present?
91
- redirect_to :back
92
- else
93
- redirect_to effective_orders.admin_order_path(@order)
94
- end
88
+ redirect_back(fallback_location: effective_orders.admin_order_path(@order))
95
89
  end
96
90
 
97
91
  def bulk_send_payment_request
@@ -5,10 +5,10 @@ module Effective
5
5
 
6
6
  protected
7
7
 
8
- def order_purchased(payment:, provider:, card: 'none', email: true, skip_buyer_validations: false, purchased_url: nil)
9
- @order.purchase!(payment: payment, provider: provider, card: card, email: email, skip_buyer_validations: skip_buyer_validations)
8
+ def order_purchased(payment:, provider:, card: 'none', email: true, skip_buyer_validations: false, purchased_url: nil, current_user: nil)
9
+ @order.purchase!(payment: payment, provider: provider, card: card, email: email, skip_buyer_validations: skip_buyer_validations, current_user: current_user)
10
10
 
11
- Effective::Cart.where(user: @order.user).destroy_all
11
+ Effective::Cart.where(user: current_user).destroy_all if current_user.present?
12
12
 
13
13
  if flash[:success].blank?
14
14
  if email && @order.send_order_receipt_to_buyer?
@@ -25,7 +25,7 @@ module Effective
25
25
  def order_deferred(provider:, email: true, deferred_url: nil)
26
26
  @order.defer!(provider: provider, email: email)
27
27
 
28
- Effective::Cart.where(user: @order.user).destroy_all
28
+ Effective::Cart.where(user: @order.user).destroy_all if @order.user.present?
29
29
 
30
30
  if flash[:success].blank?
31
31
  if email
@@ -20,7 +20,8 @@ module Effective
20
20
  payment: 'free order. no payment required.',
21
21
  provider: 'free',
22
22
  card: 'none',
23
- purchased_url: free_params[:purchased_url]
23
+ purchased_url: free_params[:purchased_url],
24
+ current_user: current_user
24
25
  )
25
26
  end
26
27
 
@@ -19,7 +19,8 @@ module Effective
19
19
  card: mark_as_paid_params[:payment_card],
20
20
  email: @order.send_mark_as_paid_email_to_buyer?,
21
21
  skip_buyer_validations: true,
22
- purchased_url: effective_orders.admin_order_path(@order)
22
+ purchased_url: effective_orders.admin_order_path(@order),
23
+ current_user: nil # Admin action, we don't want to assign current_user to the order
23
24
  )
24
25
  end
25
26
 
@@ -14,7 +14,8 @@ module Effective
14
14
 
15
15
  @order ||= Effective::Order.find(params[:response_order_id])
16
16
 
17
- (EffectiveResources.authorize!(self, :update, @order) rescue false)
17
+ # We do this even if we're not authorized
18
+ EffectiveResources.authorized?(self, :update, @order)
18
19
 
19
20
  # Delete the Purchased and Declined Redirect URLs
20
21
  purchased_url = params.delete(:rvar_purchased_url)
@@ -37,7 +38,7 @@ module Effective
37
38
  return order_declined(payment: payment, provider: 'moneris', card: params[:card], declined_url: declined_url)
38
39
  end
39
40
 
40
- order_purchased(payment: payment, provider: 'moneris', card: params[:card], purchased_url: purchased_url)
41
+ order_purchased(payment: payment, provider: 'moneris', card: params[:card], purchased_url: purchased_url, current_user: current_user)
41
42
  end
42
43
 
43
44
  private
@@ -7,7 +7,9 @@ module Effective
7
7
  raise('moneris_checkout provider is not available') unless EffectiveOrders.moneris_checkout?
8
8
 
9
9
  @order = Order.find(params[:id])
10
- (EffectiveResources.authorize!(self, :update, @order) rescue false)
10
+
11
+ # We do this even if we're not authorized.
12
+ EffectiveResources.authorized?(self, :update, @order)
11
13
 
12
14
  payment = moneris_checkout_receipt_request(moneris_checkout_params[:ticket])
13
15
  purchased = (1..49).include?(payment['response_code'].to_i) # Must be > 0 and < 50 to be valid. Sometimes we get the string 'null'
@@ -24,7 +26,8 @@ module Effective
24
26
  payment: payment,
25
27
  provider: 'moneris_checkout',
26
28
  card: payment['card_type'],
27
- purchased_url: moneris_checkout_params[:purchased_url]
29
+ purchased_url: moneris_checkout_params[:purchased_url],
30
+ current_user: current_user
28
31
  )
29
32
  end
30
33
 
@@ -14,13 +14,14 @@ module Effective
14
14
 
15
15
  @order ||= Effective::Order.where(id: (params[:invoice].to_i rescue 0)).first
16
16
 
17
- (EffectiveResources.authorize!(self, :update, @order) rescue false)
17
+ # We do this even if we're not authorized
18
+ EffectiveResources.authorized?(self, :update, @order)
18
19
 
19
20
  if @order.present?
20
21
  if @order.purchased?
21
22
  order_purchased(payment: params, provider: 'paypal', card: params[:payment_type])
22
23
  elsif (params[:payment_status] == 'Completed' && params[:custom] == EffectiveOrders.paypal[:secret])
23
- order_purchased(payment: params, provider: 'paypal', card: params[:payment_type])
24
+ order_purchased(payment: params, provider: 'paypal', card: params[:payment_type], current_user: current_user)
24
25
  else
25
26
  order_declined(payment: params, provider: 'paypal', card: params[:payment_type])
26
27
  end
@@ -14,7 +14,8 @@ module Effective
14
14
  payment: 'for pretend',
15
15
  provider: 'pretend',
16
16
  card: 'none',
17
- purchased_url: pretend_params[:purchased_url]
17
+ purchased_url: pretend_params[:purchased_url],
18
+ current_user: current_user
18
19
  )
19
20
  end
20
21
 
@@ -7,7 +7,7 @@ module Effective
7
7
  raise('stripe provider is not available') unless EffectiveOrders.stripe?
8
8
 
9
9
  @order = Order.find(params[:id])
10
- @customer = Effective::Customer.for_user(@order.user)
10
+ @customer = Effective::Customer.for_user(current_user)
11
11
 
12
12
  EffectiveResources.authorize!(self, :update, @order)
13
13
 
@@ -33,7 +33,8 @@ module Effective
33
33
  payment: payment,
34
34
  provider: 'stripe',
35
35
  card: payment[:card],
36
- purchased_url: stripe_params[:purchased_url]
36
+ purchased_url: stripe_params[:purchased_url],
37
+ current_user: current_user
37
38
  )
38
39
  end
39
40
 
@@ -83,7 +83,8 @@ module EffectiveOrdersHelper
83
83
  end
84
84
 
85
85
  def render_checkout(order, namespace: nil, purchased_url: nil, declined_url: nil, deferred_url: nil)
86
- raise 'unable to checkout an order without a user' unless order && order.user
86
+ raise 'expected an order' unless order.kind_of?(Effective::Order)
87
+ raise 'unable to checkout an order without a user or organization' if order && (order.user.blank? && order.organization.blank?)
87
88
 
88
89
  locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, deferred_url: deferred_url, namespace: namespace }
89
90
 
@@ -21,7 +21,7 @@ module Effective
21
21
  subject = subject_for(__method__, "Order Receipt: ##{@order.to_param}", resource, opts)
22
22
  headers = headers_for(resource, opts)
23
23
 
24
- mail(to: @order.email, cc: @order.cc.presence, subject: subject, **headers)
24
+ mail(to: @order.emails, cc: @order.cc.presence, subject: subject, **headers)
25
25
  end
26
26
 
27
27
  # This is sent when an admin creates a new order or /admin/orders/new
@@ -34,7 +34,7 @@ module Effective
34
34
  subject = subject_for(__method__, "Payment request - Order ##{@order.to_param}", resource, opts)
35
35
  headers = headers_for(resource, opts)
36
36
 
37
- mail(to: @order.email, cc: @order.cc.presence, subject: subject, **headers)
37
+ mail(to: @order.emails, cc: @order.cc.presence, subject: subject, **headers)
38
38
  end
39
39
 
40
40
  # This is sent when someone chooses to Pay by Cheque
@@ -45,7 +45,7 @@ module Effective
45
45
  subject = subject_for(__method__, "Pending Order: ##{@order.to_param}", resource, opts)
46
46
  headers = headers_for(resource, opts)
47
47
 
48
- mail(to: @order.email, cc: @order.cc.presence, subject: subject, **headers)
48
+ mail(to: @order.emails, cc: @order.cc.presence, subject: subject, **headers)
49
49
  end
50
50
 
51
51
  # This is sent to admin when someone Accepts Refund
@@ -158,8 +158,8 @@ module Effective
158
158
 
159
159
  to ||= EffectiveOrders.mailer_admin
160
160
  from ||= EffectiveOrders.mailer_sender
161
- subject ||= subject_for(__method__,"An error occurred with order: ##{@order.to_param}", resource, opts)
162
- headers = headers_for(resource, opts)
161
+ subject ||= subject_for(__method__,"An error occurred with order: ##{@order.to_param}", @order, opts)
162
+ headers = headers_for(@order, opts)
163
163
 
164
164
  mail(to: to, from: from, subject: subject, **headers) do |format|
165
165
  format.html { render(template) }
@@ -31,9 +31,13 @@ module Effective
31
31
  # If we want to use orders in a has_many way
32
32
  belongs_to :parent, polymorphic: true, optional: true
33
33
 
34
- belongs_to :user, polymorphic: true, validate: false # This is the buyer/user of the order. We validate it below.
34
+ belongs_to :user, polymorphic: true, optional: true, validate: false # This is the buyer of the order. We validate it below.
35
35
  accepts_nested_attributes_for :user, allow_destroy: false, update_only: true
36
36
 
37
+ # When an organization is present, any user with role :billing in that organization can purchase this order
38
+ belongs_to :organization, polymorphic: true, optional: true, validate: false
39
+ accepts_nested_attributes_for :organization, allow_destroy: false, update_only: true
40
+
37
41
  has_many :order_items, -> { order(:id) }, inverse_of: :order, dependent: :delete_all
38
42
  accepts_nested_attributes_for :order_items, allow_destroy: true, reject_if: :all_blank
39
43
 
@@ -71,7 +75,7 @@ module Effective
71
75
 
72
76
  serialize :payment, Hash
73
77
 
74
- scope :deep, -> { includes(:addresses, :user, order_items: :purchasable) }
78
+ scope :deep, -> { includes(:addresses, :user, :organization, order_items: :purchasable) }
75
79
  scope :sorted, -> { order(:id) }
76
80
 
77
81
  scope :purchased, -> { where(state: EffectiveOrders::PURCHASED) }
@@ -98,22 +102,35 @@ module Effective
98
102
  self.state = EffectiveOrders::CONFIRMED if pending? && confirmed_checkout
99
103
  end
100
104
 
105
+ before_validation do
106
+ assign_attributes(user_type: nil) if user_type.present? && user_id.blank?
107
+ assign_attributes(organization_type: nil) if organization_type.present? && organization_id.blank?
108
+ end
109
+
101
110
  with_options(unless: -> { done? }) do
102
- before_validation { assign_email }
111
+ before_validation { assign_organization_address }
103
112
  before_validation { assign_user_address }
104
113
  before_validation { assign_billing_name }
114
+ before_validation { assign_billing_email }
105
115
  before_validation { assign_order_values }
106
116
  before_validation { assign_order_charges }
107
117
  end
108
118
 
109
119
  # Order validations
110
- validates :user_id, presence: true
111
- validates :email, presence: true, email: true # email and cc validators are from effective_resources
120
+ validates :email, presence: true, email: true, if: -> { user_id.present? } # email and cc validators are from effective_resources
112
121
  validates :cc, email_cc: true
113
122
 
114
123
  validates :order_items, presence: { message: 'No items are present. Please add additional items.' }
115
124
  validates :state, inclusion: { in: EffectiveOrders::STATES.keys }
116
125
 
126
+ validate do
127
+ if EffectiveOrders.organization_enabled?
128
+ errors.add(:base, "must have a User or #{EffectiveOrders.organization_class_name || 'Organization'}") if user_id.blank? && organization_id.blank?
129
+ else
130
+ errors.add(:base, "must have a User") if user_id.blank?
131
+ end
132
+ end
133
+
117
134
  # Price validations
118
135
  validates :subtotal, presence: true
119
136
  validates :total, presence: true, if: -> { EffectiveOrders.minimum_charge.to_i > 0 }
@@ -164,7 +181,7 @@ module Effective
164
181
  raise('cannot change subtotal of a purchased order') if changes[:subtotal].present?
165
182
 
166
183
  raise('cannot change tax of a purchased order') if changes[:tax].present?
167
- raise('cannot change tax of a purchased order') if changes[:tax_rate].present?
184
+ raise('cannot change tax rate of a purchased order') if changes[:tax_rate].present?
168
185
 
169
186
  raise('cannot change surcharge of a purchased order') if changes[:surcharge].present?
170
187
  raise('cannot change surcharge percent of a purchased order') if changes[:surcharge_percent].present?
@@ -573,7 +590,7 @@ module Effective
573
590
  end
574
591
 
575
592
  # Effective::Order.new(items: Product.first, user: User.first).purchase!(email: false)
576
- def purchase!(payment: nil, provider: nil, card: nil, email: true, skip_buyer_validations: false, skip_quickbooks: false)
593
+ def purchase!(payment: nil, provider: nil, card: nil, email: true, skip_buyer_validations: false, skip_quickbooks: false, current_user: nil)
577
594
  return true if purchased?
578
595
 
579
596
  # Assign attributes
@@ -588,6 +605,10 @@ module Effective
588
605
  payment_card: (card.presence || 'none')
589
606
  )
590
607
 
608
+ if current_user&.email.present?
609
+ assign_attributes(email: current_user.email)
610
+ end
611
+
591
612
  # Updates surcharge and total based on payment_provider
592
613
  assign_order_charges()
593
614
 
@@ -677,9 +698,14 @@ module Effective
677
698
  true
678
699
  end
679
700
 
701
+ # These are all the emails we send all notifications to
702
+ def emails
703
+ ([email] + [user.try(:email)] + Array(organization.try(:billing_emails))).map(&:presence).compact.uniq
704
+ end
705
+
680
706
  # Doesn't control anything. Purely for the flash messaging
681
707
  def emails_send_to
682
- [email, cc.presence].compact.to_sentence
708
+ (emails + [cc.presence]).compact.uniq.to_sentence
683
709
  end
684
710
 
685
711
  def send_order_receipts!
@@ -775,12 +801,29 @@ module Effective
775
801
  order_items.reject { |oi| oi.marked_for_destruction? }
776
802
  end
777
803
 
804
+ # Organization first
778
805
  def assign_billing_name
779
- self.billing_name = billing_address.try(:full_name).presence || user.to_s.presence
806
+ self.billing_name = billing_address.try(:full_name).presence || organization.to_s.presence || user.to_s.presence
807
+ end
808
+
809
+ # User first
810
+ def assign_billing_email
811
+ email = emails.first
812
+ assign_attributes(email: email) if email.present?
780
813
  end
781
814
 
782
- def assign_email
783
- self.email = user.email if user.try(:email).present?
815
+ def assign_organization_address
816
+ return unless organization.present?
817
+
818
+ if EffectiveOrders.billing_address && billing_address.blank? && organization.try(:billing_address).present?
819
+ self.billing_address = organization.billing_address
820
+ self.billing_address.full_name ||= organization.to_s.presence
821
+ end
822
+
823
+ if EffectiveOrders.shipping_address && shipping_address.blank? && organization.try(:shipping_address).present?
824
+ self.shipping_address = organization.shipping_address
825
+ self.shipping_address.full_name ||= organization.to_s.presence
826
+ end
784
827
  end
785
828
 
786
829
  def assign_user_address
@@ -1,10 +1,18 @@
1
1
  = effective_form_with(model: [:admin, order], engine: true) do |f|
2
- = f.hidden_field :user_type, value: (f.object.user || current_user).class.name
2
+ -# User
3
+ - klass = (f.object.user || current_user).class
4
+ - ajax_url = (@select2_users_ajax_path || effective_resources.users_admin_select2_ajax_index_path) unless Rails.env.test?
3
5
 
4
- - ajax_url = (@select2_ajax_path || effective_resources.users_admin_select2_ajax_index_path) unless Rails.env.test?
6
+ = f.hidden_field :user_type, value: klass.name
7
+ = f.select :user_id, klass.all, ajax_url: ajax_url
5
8
 
6
- = f.select :user_id, current_user.class.all, label: 'Buyer', required: true,
7
- ajax_url: ajax_url, hint: 'The user that should purchase this order.'
9
+ -# Organization
10
+ - if EffectiveOrders.organization_enabled?
11
+ - klass = (f.object.organization || EffectiveOrders.Organization.new).class
12
+ - ajax_url = (@select2_organizations_ajax_path || effective_resources.organizations_admin_select2_ajax_index_path) unless Rails.env.test?
13
+
14
+ = f.hidden_field :organization_type, value: klass.name
15
+ = f.select :organization_id, klass.all, ajax_url: ajax_url
8
16
 
9
17
  = f.email_cc_field :cc, hint: "Cc the above on any emailed receipts or payment requests."
10
18
 
@@ -15,7 +15,7 @@
15
15
  = (order.purchased_at || order.created_at).strftime("%F %H:%M")
16
16
  %td= order_summary(order)
17
17
  %td
18
- - if order.pending?
18
+ - if order.pending? || order.confirmed?
19
19
  = link_to_checkout(order: order)
20
20
  - else
21
21
  = link_to 'View', effective_orders.order_path(order)
@@ -1,7 +1,7 @@
1
1
  = render 'layout' do
2
2
  %h1.effective-heading= @page_title
3
3
 
4
- - if !@order.purchased? && @order.user == current_user
4
+ - if !@order.purchased? && EffectiveResources.authorized?(self, :update, @order)
5
5
  = render_checkout(@order)
6
6
  - else
7
7
  = render(@order)
@@ -23,6 +23,11 @@ EffectiveOrders.setup do |config|
23
23
  # Use effective_obfuscation gem to change order.id into a seemingly random 10-digit number
24
24
  config.obfuscate_order_ids = false
25
25
 
26
+ # Allow orders to be purchased by organization members
27
+ # This will fallback to EffectiveMemberships.Organization if you have that gem installed
28
+ # config.organization_enabled = false
29
+ # config.organization_class_name = 'Example::Organization'
30
+
26
31
  # Synchronize with Quickbooks
27
32
  config.use_effective_qb_sync = false
28
33
  config.use_effective_qb_online = false
@@ -4,6 +4,9 @@ class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
4
4
  t.integer :user_id
5
5
  t.string :user_type
6
6
 
7
+ t.integer :organization_id
8
+ t.string :organization_type
9
+
7
10
  t.integer :parent_id
8
11
  t.string :parent_type
9
12
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrders
2
- VERSION = '6.4.4'.freeze
2
+ VERSION = '6.5.0'.freeze
3
3
  end
@@ -41,6 +41,9 @@ module EffectiveOrders
41
41
  :terms_and_conditions, :terms_and_conditions_label, :minimum_charge,
42
42
  :credit_card_surcharge_percent, :credit_card_surcharge_qb_item_name,
43
43
 
44
+ # Organization mode
45
+ :organization_enabled, :organization_class_name,
46
+
44
47
  # Mailer
45
48
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject,
46
49
 
@@ -70,6 +73,18 @@ module EffectiveOrders
70
73
  ]
71
74
  end
72
75
 
76
+ def self.organization_enabled?
77
+ organization_enabled == true
78
+ end
79
+
80
+ def self.Organization
81
+ klass = organization_class_name&.constantize
82
+ klass ||= (EffectiveMemberships.Organization if defined?(EffectiveMemberships))
83
+ raise('Please set the effective_orders config.organization_class_name') if klass.blank?
84
+
85
+ klass
86
+ end
87
+
73
88
  def self.cheque?
74
89
  cheque.kind_of?(Hash)
75
90
  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.4
4
+ version: 6.5.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: 2023-06-01 00:00:00.000000000 Z
11
+ date: 2023-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails