effective_resources 1.9.16 → 1.10.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: e2aae5d9ac90fa652dad2f7a60995282a9347dbfbbfdb0b497d1c46db42d7fe4
4
- data.tar.gz: 9d19f8cc152193da25ab30c7a4bc43187f9e52fb4eb309c0751df134f2a76dbc
3
+ metadata.gz: 0bc703e350cb8ca2e07dd5d9f0413f88bd15e98bab5d113e2696397e00af0732
4
+ data.tar.gz: d40aa7078d8ce692b7c5c7991b5c5ed2c06de95b0bf3602c5253b2b19affe6e6
5
5
  SHA512:
6
- metadata.gz: 2f33925a5ae6b5eda2076f6a27607af422e02412db62b55d0b6175a77cff200c18450611c314680b54c7843b59bdc498b508b760c03221e47da2a6e62f59efb1
7
- data.tar.gz: 71e9ab7dd0e61db615b043455459dad0de6b4e199f14ed39a0eb88ac16558d8b33d55bb9e0b95a2412dd4fa630ef277b198636078825ddb66d5c6db68c6b9fd3
6
+ metadata.gz: 1f5a322f0390678c9fc5834003621d73a42ab538cb3c904d942b68d44a57acb81cd5ad4601b722f8f8795e64930074ad4281a8f26baea4d798edc0b182eaa48b
7
+ data.tar.gz: efcd8d06e4889a5adce7a747eb207a0abfb920ae4f46981fd4de82ddeace22eb9ff2364fe1482c99ccff71d94d0d3393e986fd10fd2c6aa74059459ac583f06a
@@ -69,6 +69,13 @@ module Effective
69
69
  @page_title ||= resource_wizard_step_title(resource, step)
70
70
  end
71
71
 
72
+ def ready_checkout
73
+ return unless step == :checkout
74
+ return unless resource.class.try(:acts_as_purchasable_wizard?)
75
+
76
+ resource.ready!
77
+ end
78
+
72
79
  end
73
80
  end
74
81
  end
@@ -25,6 +25,8 @@ module Effective
25
25
 
26
26
  before_action :assign_current_step
27
27
  before_action :assign_page_title
28
+
29
+ before_action :ready_checkout
28
30
  end
29
31
 
30
32
  helper_method :resource
@@ -14,8 +14,8 @@ module EffectiveResourcesWizardHelper
14
14
  return sidebar unless block_given?
15
15
 
16
16
  content_tag(:div, class: 'row') do
17
- content_tag(:div, class: 'col-3') { sidebar } +
18
- content_tag(:div, class: 'col-9') { yield }
17
+ content_tag(:div, class: 'col-lg-3') { sidebar } +
18
+ content_tag(:div, class: 'col-lg-9') { yield }
19
19
  end
20
20
  end
21
21
 
@@ -28,10 +28,10 @@ module EffectiveResourcesWizardHelper
28
28
  disabled = !resource.can_visit_step?(nav_step)
29
29
 
30
30
  label = [index, title].compact.join('. ')
31
- klass = ['list-group-item', ('active' if current), ('disabled' if disabled && !current)].compact.join(' ')
31
+ klass = ['list-group-item', 'list-group-item-action', ('active' if current), ('disabled' if disabled && !current)].compact.join(' ')
32
32
 
33
33
  if (current || disabled)
34
- content_tag(:li, label, class: klass)
34
+ content_tag(:a, label, class: klass)
35
35
  else
36
36
  link_to(label, wizard_path(nav_step), class: klass)
37
37
  end
@@ -0,0 +1,129 @@
1
+ # ActsAsPurchasableWizard
2
+ #
3
+
4
+ module ActsAsPurchasableWizard
5
+ extend ActiveSupport::Concern
6
+
7
+ module Base
8
+ def acts_as_purchasable_wizard
9
+ raise('please declare acts_as_wizard first') unless respond_to?(:acts_as_wizard?)
10
+ raise('please declare acts_as_purchasable_parent first') unless respond_to?(:acts_as_purchasable_parent?)
11
+
12
+ unless (const_get(:WIZARD_STEPS).keys & [:billing, :checkout, :submitted]).length == 3
13
+ raise('please include a :billing, :checkout and :submitted step')
14
+ end
15
+
16
+ include ::ActsAsPurchasableWizard
17
+ end
18
+ end
19
+
20
+ included do
21
+ validates :owner, presence: true
22
+
23
+ # Billing Step
24
+ validate(if: -> { current_step == :billing && owner.present? }) do
25
+ self.errors.add(:base, "must have a billing address") unless owner.billing_address.present?
26
+ self.errors.add(:base, "must have an email") unless owner.email.present?
27
+ end
28
+
29
+ after_purchase do |_|
30
+ raise('expected submit_order to be purchased') unless submit_order&.purchased?
31
+ before_submit_purchased!
32
+ submit_purchased!
33
+ after_submit_purchased!
34
+ end
35
+ end
36
+
37
+ # All Fees and Orders
38
+ def submit_fees
39
+ raise('to be implemented by caller')
40
+ end
41
+
42
+ def submit_order
43
+ orders.first
44
+ end
45
+
46
+ def find_or_build_submit_fees
47
+ submit_fees
48
+ end
49
+
50
+ def find_or_build_submit_order
51
+ order = submit_order || orders.build(user: owner)
52
+ fees = submit_fees().reject { |fee| fee.marked_for_destruction? }
53
+
54
+ # Adds fees, but does not overwrite any existing price.
55
+ fees.each do |fee|
56
+ order.add(fee) unless order.purchasables.include?(fee)
57
+ end
58
+
59
+ order.order_items.each do |order_item|
60
+ fee = fees.find { |fee| fee == order_item.purchasable }
61
+ order.remove(order_item) unless fee.present?
62
+ end
63
+
64
+ # From Billing Step
65
+ order.billing_address = owner.billing_address if owner.billing_address.present?
66
+
67
+ # Important to add/remove anything
68
+ order.save!
69
+
70
+ order
71
+ end
72
+
73
+ # Should be indempotent.
74
+ def build_submit_fees_and_order
75
+ return false if was_submitted?
76
+
77
+ fees = find_or_build_submit_fees()
78
+ raise('already has purchased submit fees') if fees.any?(&:purchased?)
79
+
80
+ order = find_or_build_submit_order()
81
+ raise('already has purchased submit order') if order.purchased?
82
+
83
+ true
84
+ end
85
+
86
+ # Owner clicks on the Billing step. Next step is Checkout
87
+ def billing!
88
+ ready! && save!
89
+ end
90
+
91
+ # Ready to check out
92
+ # This is called by the "ready_checkout" before_action in wizard_controller/before_actions.rb
93
+ def ready!
94
+ without_current_step do
95
+ build_submit_fees_and_order
96
+ save!
97
+ end
98
+ end
99
+
100
+ # Called automatically via after_purchase hook above
101
+ def submit_purchased!
102
+ return false if was_submitted?
103
+
104
+ wizard_steps[:checkout] = Time.zone.now
105
+ submit!
106
+ end
107
+
108
+ # A hook to extend
109
+ def before_submit_purchased!
110
+ end
111
+
112
+ def after_submit_purchased!
113
+ end
114
+
115
+ # Draft -> Submitted requirements
116
+ def submit!
117
+ raise('already submitted') if was_submitted?
118
+ raise('expected a purchased order') unless submit_order&.purchased?
119
+
120
+ wizard_steps[:checkout] ||= Time.zone.now
121
+ wizard_steps[:submitted] = Time.zone.now
122
+ submitted!
123
+ end
124
+
125
+ module ClassMethods
126
+ def acts_as_purchasable_wizard?; true; end
127
+ end
128
+
129
+ end
@@ -50,9 +50,13 @@ module ActsAsWizard
50
50
  can_revisit_completed_steps(step)
51
51
  end
52
52
 
53
+ def wizard_step_keys
54
+ self.class.const_get(:WIZARD_STEPS).keys
55
+ end
56
+
53
57
  def required_steps
54
58
  return self.class.test_required_steps if Rails.env.test? && self.class.test_required_steps.present?
55
- self.class.const_get(:WIZARD_STEPS).keys
59
+ wizard_step_keys()
56
60
  end
57
61
 
58
62
  def wizard_step_title(step)
@@ -104,6 +108,16 @@ module ActsAsWizard
104
108
  has_completed_step?(required_steps.last)
105
109
  end
106
110
 
111
+ def without_current_step(&block)
112
+ existing = current_step
113
+
114
+ begin
115
+ self.current_step = nil; yield
116
+ ensure
117
+ self.current_step = existing
118
+ end
119
+ end
120
+
107
121
  private
108
122
 
109
123
  def can_revisit_completed_steps(step)
@@ -0,0 +1,7 @@
1
+ !!!
2
+ %html{style: 'background: #fff;'}
3
+ %head
4
+ %meta{:content => 'text/html; charset=UTF-8', 'http-equiv' => 'Content-Type'}
5
+
6
+ %body{style: 'background: #fff;'}
7
+ = yield
@@ -21,6 +21,8 @@ EffectiveResources.setup do |config|
21
21
  # end
22
22
  config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) }
23
23
 
24
+ # Default Submits
25
+ #
24
26
  # These default submit actions will be added to each controller
25
27
  # and rendered when calling effective_submit(f)
26
28
  # based on the controller, and its `submits` if any.
@@ -28,4 +30,22 @@ EffectiveResources.setup do |config|
28
30
  # Supported values: 'Save', 'Continue', and 'Add New'
29
31
  config.default_submits = ['Save', 'Continue', 'Add New']
30
32
 
33
+ # Email Settings
34
+ #
35
+ # The default mailer settings for all effective gems
36
+ #
37
+ # Configure the parent class responsible to send e-mails.
38
+ # config.parent_mailer = '::ApplicationMailer'
39
+
40
+ # Default deliver method
41
+ # config.deliver_method = :deliver_now
42
+
43
+ # Default layout
44
+ # config.mailer_layout = 'effective_mailer_layout'
45
+
46
+ # Default From
47
+ config.mailer_sender = "no-reply@example.com"
48
+
49
+ # Send Admin correspondence To
50
+ config.mailer_admin = "admin@example.com"
31
51
  end
@@ -38,6 +38,16 @@ module EffectiveGem
38
38
 
39
39
  true
40
40
  end
41
+
42
+ # This is included into every gem
43
+ # The gem may not have a mailer or use effective email templates
44
+ def send_email(email, *args)
45
+ raise('gem does not respond to mailer_class') unless respond_to?(:mailer_class)
46
+ raise('expected args to be an Array') unless args.kind_of?(Array)
47
+
48
+ mailer_class.send(email, *args).send(EffectiveResources.deliver_method)
49
+ end
50
+
41
51
  end
42
52
 
43
53
  end
@@ -28,6 +28,7 @@ module EffectiveResources
28
28
  ActiveRecord::Base.extend(ActsAsSlugged::Base)
29
29
  ActiveRecord::Base.extend(ActsAsStatused::Base)
30
30
  ActiveRecord::Base.extend(ActsAsWizard::Base)
31
+ ActiveRecord::Base.extend(ActsAsPurchasableWizard::Base)
31
32
  ActiveRecord::Base.extend(HasManyRichTexts::Base)
32
33
 
33
34
  ActiveRecord::Base.extend(EffectiveDeviseUser::Base)
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '1.9.16'.freeze
2
+ VERSION = '1.10.0'.freeze
3
3
  end
@@ -5,7 +5,10 @@ require 'effective_resources/effective_gem'
5
5
  module EffectiveResources
6
6
 
7
7
  def self.config_keys
8
- [:authorization_method, :default_submits]
8
+ [
9
+ :authorization_method, :default_submits,
10
+ :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :parent_mailer
11
+ ]
9
12
  end
10
13
 
11
14
  include EffectiveGem
@@ -31,6 +34,28 @@ module EffectiveResources
31
34
  (['Save', 'Continue', 'Add New'] & Array(config.default_submits)).inject({}) { |h, v| h[v] = true; h }
32
35
  end
33
36
 
37
+ # Email
38
+ def self.deliver_method
39
+ config[:deliver_method] || :deliver_now
40
+ end
41
+
42
+ def self.mailer_layout
43
+ config[:mailer_layout] || 'effective_mailer_layout'
44
+ end
45
+
46
+ def self.mailer_sender
47
+ config[:mailer_sender] || raise('effective resources mailer_sender missing. Add it to config/initializers/effective_resources.rb')
48
+ end
49
+
50
+ def self.mailer_admin
51
+ config[:mailer_admin] || raise('effective resources mailer_admin missing. Add it to config/initializers/effective_resources.rb')
52
+ end
53
+
54
+ def self.parent_mailer_class
55
+ return config[:parent_mailer].constantize if config[:parent_mailer].present?
56
+ '::ApplicationMailer'.safe_constantize || 'ActionMailer::Base'.constantize
57
+ end
58
+
34
59
  # Utilities
35
60
 
36
61
  # This looks up the best class give the name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.16
4
+ version: 1.10.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-01-11 00:00:00.000000000 Z
11
+ date: 2022-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -153,6 +153,7 @@ files:
153
153
  - app/helpers/effective_resources_wizard_helper.rb
154
154
  - app/models/concerns/acts_as_archived.rb
155
155
  - app/models/concerns/acts_as_email_form.rb
156
+ - app/models/concerns/acts_as_purchasable_wizard.rb
156
157
  - app/models/concerns/acts_as_slugged.rb
157
158
  - app/models/concerns/acts_as_statused.rb
158
159
  - app/models/concerns/acts_as_tokened.rb
@@ -201,6 +202,7 @@ files:
201
202
  - app/views/effective/resource/_actions.html.haml
202
203
  - app/views/effective/resource/_actions_dropleft.html.haml
203
204
  - app/views/effective/resource/_actions_glyphicons.html.haml
205
+ - app/views/layouts/effective_mailer_layout.html.haml
204
206
  - config/effective_resources.rb
205
207
  - lib/effective_resources.rb
206
208
  - lib/effective_resources/effective_gem.rb