effective_orders 6.4.4 → 6.5.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: 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