effective_products 0.0.3 → 0.0.7

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/admin/stamps_controller.rb +11 -0
  3. data/app/controllers/effective/ring_wizards_controller.rb +0 -21
  4. data/app/controllers/effective/stamp_wizards_controller.rb +10 -0
  5. data/app/datatables/admin/effective_stamps_datatable.rb +52 -0
  6. data/app/datatables/effective_stamp_wizards_datatable.rb +36 -0
  7. data/app/helpers/effective_products_helper.rb +0 -1
  8. data/app/models/concerns/effective_products_ring_wizard.rb +20 -29
  9. data/app/models/concerns/effective_products_stamp_wizard.rb +139 -0
  10. data/app/models/effective/ring.rb +0 -12
  11. data/app/models/effective/stamp.rb +114 -0
  12. data/app/models/effective/stamp_wizard.rb +7 -0
  13. data/app/views/admin/stamps/_form.html.haml +12 -0
  14. data/app/views/admin/stamps/_stamp.html.haml +53 -0
  15. data/app/views/effective/ring_wizards/_dashboard.html.haml +1 -1
  16. data/app/views/effective/ring_wizards/_ring.html.haml +34 -27
  17. data/app/views/effective/ring_wizards/_ring_wizard.html.haml +1 -6
  18. data/app/views/effective/ring_wizards/submitted.html.haml +1 -0
  19. data/app/views/effective/stamp_wizards/_content.html.haml +10 -0
  20. data/app/views/effective/stamp_wizards/_dashboard.html.haml +27 -0
  21. data/app/views/effective/stamp_wizards/_layout.html.haml +3 -0
  22. data/app/views/effective/stamp_wizards/_orders.html.haml +4 -0
  23. data/app/views/effective/stamp_wizards/_stamp.html.haml +45 -0
  24. data/app/views/effective/stamp_wizards/_stamp_fields.html.haml +45 -0
  25. data/app/views/effective/stamp_wizards/_stamp_wizard.html.haml +3 -0
  26. data/app/views/effective/stamp_wizards/_summary.html.haml +31 -0
  27. data/app/views/effective/stamp_wizards/billing.html.haml +15 -0
  28. data/app/views/effective/stamp_wizards/checkout.html.haml +6 -0
  29. data/app/views/effective/stamp_wizards/stamp.html.haml +18 -0
  30. data/app/views/effective/stamp_wizards/start.html.haml +16 -0
  31. data/app/views/effective/stamp_wizards/submitted.html.haml +16 -0
  32. data/app/views/effective/stamp_wizards/summary.html.haml +8 -0
  33. data/app/views/effective/stamps/_fields.html.haml +11 -0
  34. data/config/routes.rb +8 -0
  35. data/db/migrate/01_create_effective_products.rb.erb +55 -0
  36. data/lib/effective_products/engine.rb +1 -0
  37. data/lib/effective_products/version.rb +1 -1
  38. metadata +26 -3
  39. data/app/views/effective/rings/_fields.html.haml +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd6de56034ed84b15b02ab52785db58b37b0839e67a0db8cf31b77da8f4db148
4
- data.tar.gz: e7a59c34d1c681a582c7c7c510ad9cc8c8f911e7bfbe339864678bca3f4db4d7
3
+ metadata.gz: 36f1b24a9da60c9e39f6d27fd085283bd0f5b061f80c14a53f7a4a59edb1d31a
4
+ data.tar.gz: 713caaaaa536356ede62d6d207166a8861190bb3d8ea41c16296637f49033c84
5
5
  SHA512:
6
- metadata.gz: 4383a40c636b788b989b22a8dedbc8d7afac6be72313ec737d3fe3ea1457365054194f99739651e3d61cacfa5a412e3aaa0d7068c39bfa3d41819446a226119f
7
- data.tar.gz: b33a258e854dfdd4211edfb7143105d1c6af606cd8274886c548e65e414919a0d41e651cbd07e8399e497e2b06e9137f695cc053e43acf4509b663b01149f1de
6
+ metadata.gz: 8bc5e5606f1fe01fde2bc06429ba9f4813a0f6115cfafaa7fa657aaee71c4440f61a00bf523446a4b82af4e2513bf5593c19801030f50e1d7f82aafd87bddead
7
+ data.tar.gz: aa6f08d926456c04c97f34b7ad4d53b26e021339a98c3e54781ce3475056771b22ec46063d6daf0a47af990362c7e1d84213bc5392c07725673e71f3cf44db7c
@@ -0,0 +1,11 @@
1
+ module Admin
2
+ class StampsController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+ before_action { EffectiveResources.authorize!(self, :admin, :effective_products) }
5
+
6
+ include Effective::CrudController
7
+
8
+ submit :mark_paid, 'Save and Mark Paid'
9
+
10
+ end
11
+ end
@@ -6,26 +6,5 @@ module Effective
6
6
 
7
7
  resource_scope -> { EffectiveProducts.RingWizard.deep.where(owner: current_user) }
8
8
 
9
- # Allow only 1 in-progress application at a time
10
- before_action(only: [:new, :show], unless: -> { resource&.done? }) do
11
- existing = resource_scope.in_progress.where.not(id: resource).first
12
-
13
- if existing.present?
14
- flash[:success] = "You have been redirected to your existing in progress payment"
15
- redirect_to effective_products.ring_wizard_build_path(existing, existing.next_step)
16
- end
17
- end
18
-
19
- after_save do
20
- flash.now[:success] = ''
21
- end
22
-
23
- private
24
-
25
- def permitted_params
26
- model = (params.key?(:effective_ring_wizard) ? :effective_ring_wizard : :ring_wizard)
27
- params.require(model).permit!.except(:status, :status_steps, :wizard_steps, :submitted_at)
28
- end
29
-
30
9
  end
31
10
  end
@@ -0,0 +1,10 @@
1
+ module Effective
2
+ class StampWizardsController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+
5
+ include Effective::WizardController
6
+
7
+ resource_scope -> { EffectiveProducts.StampWizard.deep.where(owner: current_user) }
8
+
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ module Admin
2
+ class EffectiveStampsDatatable < Effective::Datatable
3
+ filters do
4
+ scope :ready_to_issue
5
+ scope :issued
6
+ scope :all
7
+ end
8
+
9
+ datatable do
10
+ order :updated_at
11
+
12
+ col :updated_at, visible: false
13
+ col :created_at, visible: false
14
+ col :id, visible: false
15
+
16
+ col :created_at, as: :date
17
+ col :owner, search: :string
18
+
19
+ col :applicant, visible: false
20
+ col :stamp_wizard, visible: false
21
+
22
+ col(:email) { |stamp| stamp.owner.email }
23
+ col(:phone) { |stamp| stamp.owner.phone }
24
+
25
+ col :member_number, label: 'Member #' do |stamp|
26
+ stamp.owner.try(:membership).try(:number)
27
+ end
28
+
29
+ col :name
30
+ col :name_confirmation, visible: false
31
+
32
+ col :category, visible: false
33
+
34
+ col :shipping_address, label: 'Address'
35
+
36
+ col :purchased_order, visible: false
37
+ col :price, visible: false
38
+ col :tax_exempt, visible: false
39
+ col :qb_item_name, visible: false
40
+
41
+ col :status, visible: false
42
+
43
+ col :issued_at
44
+
45
+ actions_col
46
+ end
47
+
48
+ collection do
49
+ Effective::Stamp.deep.all
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,36 @@
1
+ # Dashboard Stamp Payments
2
+ class EffectiveStampWizardsDatatable < Effective::Datatable
3
+ datatable do
4
+ order :created_at
5
+
6
+ col :token, visible: false
7
+ col :created_at, visible: false
8
+
9
+ col(:submitted_at, label: 'Submitted on') do |resource|
10
+ resource.submitted_at&.strftime('%F') || 'Incomplete'
11
+ end
12
+
13
+ col :owner, visible: false, search: :ststamp
14
+ col :status, visible: false
15
+ col :orders, action: :show
16
+
17
+ col(:issued_at, label: 'Issued on') do |resource|
18
+ resource.stamp.issued_at&.strftime('%F') || '-'
19
+ end
20
+
21
+ actions_col(actions: []) do |resource|
22
+ if resource.draft?
23
+ dropdown_link_to('Continue', effective_products.stamp_wizard_build_path(resource, reource.next_step), 'data-turbolinks' => false)
24
+ dropdown_link_to('Delete', effective_products.stamp_wizard_path(resource), 'data-confirm': "Really delete #{resource}?", 'data-method': :delete)
25
+ else
26
+ dropdown_link_to('Show', effective_products.stamp_wizard_path(resource))
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ collection do
33
+ EffectiveProducts.StampWizard.deep.done.where(owner: current_user)
34
+ end
35
+
36
+ end
@@ -1,3 +1,2 @@
1
1
  module EffectiveProductsHelper
2
-
3
2
  end
@@ -15,14 +15,6 @@ module EffectiveProductsRingWizard
15
15
 
16
16
  module ClassMethods
17
17
  def effective_products_ring_wizard?; true; end
18
-
19
- def all_wizard_steps
20
- const_get(:WIZARD_STEPS).keys
21
- end
22
-
23
- def required_wizard_steps
24
- [:start, :billing, :checkout, :submitted]
25
- end
26
18
  end
27
19
 
28
20
  included do
@@ -83,7 +75,7 @@ module EffectiveProductsRingWizard
83
75
  # All Steps validations
84
76
  validates :owner, presence: true
85
77
 
86
- # Tickets Step
78
+ # Ring Step
87
79
  validate(if: -> { current_step == :ring }) do
88
80
  self.errors.add(:rings, "can't be blank") unless present_rings.present?
89
81
  end
@@ -117,14 +109,7 @@ module EffectiveProductsRingWizard
117
109
  end
118
110
 
119
111
  def build_ring
120
- ring = rings.build(
121
- owner: owner,
122
- first_name: owner.try(:first_name),
123
- last_name: owner.try(:last_name),
124
- email: owner.try(:email),
125
- phone: owner.try(:phone)
126
- )
127
-
112
+ ring = rings.build(owner: owner)
128
113
  address = owner.try(:shipping_address) || owner.try(:billing_address)
129
114
 
130
115
  if address.present?
@@ -135,23 +120,29 @@ module EffectiveProductsRingWizard
135
120
  end
136
121
 
137
122
  def assign_pricing
138
- price = case ring.metal
139
- when '14k Yellow Gold' then 450_00
140
- when 'Sterling Silver' then 175_00
141
- when 'Titanium' then 50_00
142
- else
143
- raise "unexpected ring metal: #{ring.metal || 'none'}"
144
- end
145
-
146
- qb_item_name = "Chemist's Ring"
147
- tax_exempt = false
148
-
149
- ring.assign_attributes(price: price, qb_item_name: qb_item_name, tax_exempt: tax_exempt)
123
+ raise('to be implemented by including class')
124
+
125
+ # raise('expected a persisted ring') unless ring&.persisted?
126
+
127
+ # price = case ring.metal
128
+ # when '14k Yellow Gold' then 450_00
129
+ # when 'Sterling Silver' then 175_00
130
+ # when 'Titanium' then 50_00
131
+ # else
132
+ # raise "unexpected ring metal: #{ring.metal || 'none'}"
133
+ # end
134
+
135
+ # qb_item_name = "Professional Ring"
136
+ # tax_exempt = false
137
+
138
+ # ring.assign_attributes(price: price, qb_item_name: qb_item_name, tax_exempt: tax_exempt)
150
139
  end
151
140
 
152
141
  # After the configure Ring step
153
142
  def ring!
154
143
  assign_pricing() if ring.present?
144
+ raise('expected ring to have a price') if ring.price.blank?
145
+
155
146
  save!
156
147
  end
157
148
 
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ # EffectiveProductsStampWizard
4
+ #
5
+ # Mark your owner model with effective_products_stamp_wizard to get all the includes
6
+
7
+ module EffectiveProductsStampWizard
8
+ extend ActiveSupport::Concern
9
+
10
+ module Base
11
+ def effective_products_stamp_wizard
12
+ include ::EffectiveProductsStampWizard
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def effective_products_stamp_wizard?; true; end
18
+ end
19
+
20
+ included do
21
+ acts_as_purchasable_parent
22
+ acts_as_tokened
23
+
24
+ acts_as_statused(
25
+ :draft, # Just Started
26
+ :submitted # All done
27
+ )
28
+
29
+ acts_as_wizard(
30
+ start: 'Start',
31
+ stamp: 'Select Stamp',
32
+ summary: 'Review',
33
+ billing: 'Billing Address',
34
+ checkout: 'Checkout',
35
+ submitted: 'Submitted'
36
+ )
37
+
38
+ acts_as_purchasable_wizard
39
+
40
+ log_changes(except: :wizard_steps) if respond_to?(:log_changes)
41
+
42
+ # Application Namespace
43
+ belongs_to :owner, polymorphic: true
44
+ accepts_nested_attributes_for :owner
45
+
46
+ # Effective Namespace
47
+ has_many :stamps, -> { order(:id) }, class_name: 'Effective::Stamp', inverse_of: :stamp_wizard, dependent: :destroy
48
+ accepts_nested_attributes_for :stamps, reject_if: :all_blank, allow_destroy: true
49
+
50
+ has_many :orders, -> { order(:id) }, as: :parent, class_name: 'Effective::Order', dependent: :nullify
51
+ accepts_nested_attributes_for :orders
52
+
53
+ effective_resource do
54
+ # Acts as Statused
55
+ status :string, permitted: false
56
+ status_steps :text, permitted: false
57
+
58
+ # Dates
59
+ submitted_at :datetime
60
+
61
+ # Acts as Wizard
62
+ wizard_steps :text, permitted: false
63
+
64
+ timestamps
65
+ end
66
+
67
+ scope :deep, -> { includes(:owner, :orders, :stamps) }
68
+ scope :sorted, -> { order(:id) }
69
+
70
+ scope :in_progress, -> { where.not(status: [:submitted]) }
71
+ scope :done, -> { where(status: [:submitted]) }
72
+
73
+ scope :for, -> (user) { where(owner: user) }
74
+
75
+ # All Steps validations
76
+ validates :owner, presence: true
77
+
78
+ # Stamp Step
79
+ validate(if: -> { current_step == :stamp }) do
80
+ self.errors.add(:stamps, "can't be blank") unless present_stamps.present?
81
+ end
82
+
83
+ # All Fees and Orders
84
+ def submit_fees
85
+ stamps
86
+ end
87
+
88
+ def after_submit_purchased!
89
+ stamps.each { |stamp| stamp.submit! }
90
+ end
91
+
92
+ end
93
+
94
+ # Instance Methods
95
+ def to_s
96
+ 'stamp payment'
97
+ end
98
+
99
+ def in_progress?
100
+ draft?
101
+ end
102
+
103
+ def done?
104
+ submitted?
105
+ end
106
+
107
+ def stamp
108
+ stamps.first
109
+ end
110
+
111
+ def build_stamp
112
+ address = owner.try(:shipping_address) || owner.try(:billing_address)
113
+ stamps.build(owner: owner, shipping_address: address)
114
+ end
115
+
116
+ def assign_pricing
117
+ raise('to be implemented by including class')
118
+
119
+ # price = (stamp.physical? ? 100_00 : 50_00)
120
+ # qb_item_name = "Professional Stamp"
121
+ # tax_exempt = false
122
+
123
+ # stamp.assign_attributes(price: price, qb_item_name: qb_item_name, tax_exempt: tax_exempt)
124
+ end
125
+
126
+ # After the configure Stamp step
127
+ def stamp!
128
+ assign_pricing() if stamp.present?
129
+ raise('expected stamp to have a price') if stamp.price.blank?
130
+ save!
131
+ end
132
+
133
+ private
134
+
135
+ def present_stamps
136
+ stamps.reject(&:marked_for_destruction?)
137
+ end
138
+
139
+ end
@@ -53,17 +53,5 @@ module Effective
53
53
  issued_at.present?
54
54
  end
55
55
 
56
- # This is the Admin Save and Mark Paid action
57
- def mark_paid!
58
- raise('expected a blank ring payment') if ring_wizard.present?
59
-
60
- save!
61
-
62
- order = Effective::Order.new(items: self, user: owner)
63
- order.purchase!(skip_buyer_validations: true, email: false)
64
-
65
- true
66
- end
67
-
68
56
  end
69
57
  end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Effective
4
+ class Stamp < ActiveRecord::Base
5
+ acts_as_purchasable
6
+ acts_as_addressable :shipping
7
+
8
+ acts_as_statused(
9
+ :draft, # Built in an application
10
+ :submitted, # Submitted by an applicant or stamp wizard
11
+ :issued # Issued by an admin
12
+ )
13
+
14
+ #CATEGORIES = ['Physical', 'Digital-only']
15
+ CATEGORIES = ['Physical']
16
+
17
+ log_changes if respond_to?(:log_changes)
18
+
19
+ # This stamp is charged to an owner
20
+ belongs_to :owner, polymorphic: true
21
+
22
+ # Sometimes a stamp is built through an applicant
23
+ belongs_to :applicant, polymorphic: true, optional: true
24
+
25
+ # Other times through the stamp_wizard
26
+ belongs_to :stamp_wizard, polymorphic: true, optional: true
27
+
28
+ effective_resource do
29
+ name :string
30
+ name_confirmation :string
31
+
32
+ category :string
33
+
34
+ # Admin issues stamps
35
+ issued_at :datetime # Present when issued by an admin
36
+
37
+ # Acts as Statused
38
+ status :string
39
+ status_steps :text
40
+
41
+ # Acts as Purchasable
42
+ price :integer
43
+ qb_item_name :string
44
+ tax_exempt :boolean
45
+
46
+ timestamps
47
+ end
48
+
49
+ scope :deep, -> { includes(:owner) }
50
+
51
+ scope :with_approved_applicants, -> { where(applicant_id: EffectiveMemberships.Applicant.approved) }
52
+ scope :with_stamp_wizards, -> { where(applicant_id: nil).where.not(stamp_wizard_id: nil) }
53
+
54
+ scope :ready_to_issue, -> {
55
+ with_approved_applicants.or(with_stamp_wizards).purchased.where.not(issued_at: nil)
56
+ }
57
+
58
+ validates :category, presence: true, inclusion: { in: CATEGORIES }
59
+ validates :name, presence: true
60
+ validates :name_confirmation, presence: true
61
+
62
+ validate(if: -> { name.present? && name_confirmation.present? }) do
63
+ self.errors.add(:name_confirmation, "doesn't match name") unless name == name_confirmation
64
+ end
65
+
66
+ validate(if: -> { physical? }) do
67
+ self.errors.add(:shipping_address, "can't be blank when physical stamp") unless shipping_address.present?
68
+ end
69
+
70
+ def to_s
71
+ ['Professional Stamp', *name.presence].join(' ')
72
+ end
73
+
74
+ def issued?
75
+ issued_at.present?
76
+ end
77
+
78
+ def mark_as_issued!
79
+ issued!
80
+ end
81
+
82
+ def physical?
83
+ category == 'Physical'
84
+ end
85
+
86
+ def created_by_admin?
87
+ stamp_wizard_id.blank? && applicant_id.blank?
88
+ end
89
+
90
+ # Called by an application when submitted
91
+ # Called by a stamp wizard when submitted
92
+ def submit!
93
+ raise('expected a purchased order') unless purchased?
94
+ submitted!
95
+ end
96
+
97
+ # This is the Admin Save and Mark Paid action
98
+ def mark_paid!
99
+ raise('expected an user with a membership category') unless owner && owner.try(:membership).present?
100
+
101
+ category = owner.membership.categories.first
102
+
103
+ assign_attributes(
104
+ price: category.stamp_fee,
105
+ tax_exempt: category.stamp_fee_tax_exempt,
106
+ qb_item_name: category.stamp_fee_qb_item_name
107
+ )
108
+
109
+ save!
110
+ Effective::Order.new(items: self, user: owner).mark_as_purchased!
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,7 @@
1
+ module Effective
2
+ class StampWizard < ActiveRecord::Base
3
+ self.table_name = EffectiveProducts.stamp_wizards_table_name.to_s
4
+
5
+ effective_products_stamp_wizard
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ = effective_form_with(model: [:admin, stamp], engine: true) do |f|
2
+ - if f.object.new_record?
3
+ = f.select :owner, { 'Users' => current_user.class.members.sorted }, polymorphic: true
4
+ - else
5
+ = f.static_field :owner
6
+
7
+ = render 'effective/stamps/fields', f: f, stamp: f.object
8
+
9
+ - if f.object.new_record?
10
+ = f.submit 'Save and Mark Paid'
11
+ - else
12
+ = f.submit 'Save'
@@ -0,0 +1,53 @@
1
+ %table.table
2
+ %tbody
3
+ %tr
4
+ %th Owner
5
+ %td
6
+ - url = (edit_polymorphic_path(stamp.owner) rescue "/admin/users/#{stamp.owner.to_param}/edit")
7
+ = link_to(stamp.owner, url)
8
+
9
+ %tr
10
+ %th Purchased Order
11
+ %td
12
+ - if stamp.purchased_order.present?
13
+ = link_to(stamp.purchased_order, effective_orders.admin_order_path(stamp.purchased_order))
14
+
15
+ %tr
16
+ %th Contact
17
+ %td
18
+ - owner = stamp.owner
19
+
20
+ = owner.to_s
21
+
22
+ - if owner.try(:email).present?
23
+ %br
24
+ = mail_to(owner.email)
25
+
26
+ - if owner.try(:phone).present?
27
+ %br
28
+ = owner.phone
29
+
30
+ - if owner.try(:membership).try(:number).present?
31
+ %br
32
+ Member Number #{owner.membership.number}
33
+
34
+ %tr
35
+ %th
36
+ %td= stamp.physical? ? 'Physical' : 'Digital Only'
37
+
38
+ - if stamp.shipping_address.present?
39
+ %tr
40
+ %th Address
41
+ %td= stamp.shipping_address.to_html
42
+
43
+ %tr
44
+ %th Name on Stamp
45
+ %td= stamp.name
46
+
47
+ %tr
48
+ %th Name Confirmation
49
+ %td= stamp.name_confirmation
50
+
51
+ %tr
52
+ %th Issued At
53
+ %td= stamp.issued_at&.strftime('%F') || 'Not Issued'
@@ -11,7 +11,7 @@
11
11
  Please
12
12
  = link_to("Continue payment for #{existing}", effective_products.ring_wizard_build_path(existing, existing.next_step), 'data-turbolinks' => false, class: 'btn btn-primary')
13
13
  or you can
14
- = link_to('Abandon registration', effective_products.ring_wizard_path(existing), 'data-confirm': "Really delete #{existing}?", 'data-method': :delete, class: 'btn btn-danger')
14
+ = link_to('Abandon payment', effective_products.ring_wizard_path(existing), 'data-confirm': "Really delete #{existing}?", 'data-method': :delete, class: 'btn btn-danger')
15
15
  to start over.
16
16
 
17
17
  %hr
@@ -1,33 +1,40 @@
1
- = card('Ring') do
2
- - ring = ring_wizard.ring
3
- - owner = ring_wizard.owner
1
+ .card
2
+ .card-body
3
+ .row
4
+ .col-sm
5
+ %h5.card-title= ring_wizard.wizard_step_title(:ring)
6
+ .col-sm-auto.text-right
7
+ = link_to('Edit', wizard_path(:ring)) if edit_effective_wizard?
4
8
 
5
- %table.table.table-sm
6
- %tbody
7
- %tr
8
- %th Owner
9
- %td
10
- = owner.to_s
11
- - if owner.try(:email).present?
12
- %br
13
- = mail_to(owner.email)
9
+ - ring = ring_wizard.ring
10
+ - owner = ring_wizard.owner
14
11
 
15
- - if owner.try(:phone).present?
16
- %br
17
- = owner.phone
12
+ %table.table.table-sm
13
+ %tbody
14
+ %tr
15
+ %th Owner
16
+ %td
17
+ = owner.to_s
18
+ - if owner.try(:email).present?
19
+ %br
20
+ = mail_to(owner.email)
18
21
 
19
- - if owner.try(:membership).try(:number).present?
20
- %br
21
- Member Number #{owner.membership.number}
22
+ - if owner.try(:phone).present?
23
+ %br
24
+ = owner.phone
22
25
 
23
- %tr
24
- %th Address
25
- %td= ring.shipping_address.to_html
26
+ - if owner.try(:membership).try(:number).present?
27
+ %br
28
+ Member Number #{owner.membership.number}
26
29
 
27
- %tr
28
- %th Metal
29
- %td= ring.metal
30
+ %tr
31
+ %th Address
32
+ %td= ring.shipping_address.to_html
30
33
 
31
- %tr
32
- %th Size
33
- %td Size #{ring.size}
34
+ %tr
35
+ %th Metal
36
+ %td= ring.metal
37
+
38
+ %tr
39
+ %th Size
40
+ %td Size #{ring.size}
@@ -1,8 +1,3 @@
1
1
  .effective-ring-payment
2
- - blacklist = ring_wizard.class.required_wizard_steps + [:summary]
3
- - steps = ring_wizard.required_steps - blacklist
4
-
5
- = render "effective/ring_wizards/summary", ring_wizard: ring_wizard
6
-
7
- - steps.select { |step| ring_wizard.has_completed_step?(step) }.each do |partial|
2
+ - ring_wizard.render_steps.each do |partial|
8
3
  = render "effective/ring_wizards/#{partial}", ring_wizard: ring_wizard, step: partial
@@ -9,6 +9,7 @@
9
9
 
10
10
  = link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary mb-4'
11
11
 
12
+ = render 'effective/ring_wizards/summary', ring_wizard: resource
12
13
  = render 'effective/ring_wizards/ring_wizard', ring_wizard: resource
13
14
  = render 'effective/ring_wizards/orders', ring_wizard: resource
14
15
 
@@ -0,0 +1,10 @@
1
+ - all_steps_content = resource.try(:rich_text_all_steps_content)
2
+ - step_content = resource.try("rich_text_#{step}_content")
3
+
4
+ - if all_steps_content.present?
5
+ .card.mb-4
6
+ .card-body= all_steps_content
7
+
8
+ - if step_content.present?
9
+ .card.mb-4
10
+ .card-body= step_content
@@ -0,0 +1,27 @@
1
+ -# In progress payments
2
+ - existing = EffectiveProducts.StampWizard.in_progress.for(current_user).first
3
+ - datatable = EffectiveResources.best('EffectiveStampWizardsDatatable').new(self, namespace: :effective)
4
+
5
+ - if existing.present?
6
+ %h2 In Progress Stamp Payments
7
+
8
+ %p Your payment for Professional Stamp is incomplete
9
+
10
+ %p
11
+ Please
12
+ = link_to("Continue payment for #{existing}", effective_products.stamp_wizard_build_path(existing, existing.next_step), 'data-turbolinks' => false, class: 'btn btn-primary')
13
+ or you can
14
+ = link_to('Abandon payment', effective_products.stamp_wizard_path(existing), 'data-confirm': "Really delete #{existing}?", 'data-method': :delete, class: 'btn btn-danger')
15
+ to start over.
16
+
17
+ %hr
18
+
19
+ %h2 Stamp Payments
20
+
21
+ - if datatable.present?
22
+ = render_simple_datatable(datatable)
23
+ - else
24
+ %p You have no past stamp payments. When you do, we'll show them here.
25
+
26
+ - if existing.blank?
27
+ %p= link_to 'Order a Professional Stamp', effective_products.new_stamp_wizard_path, class: 'btn btn-primary'
@@ -0,0 +1,3 @@
1
+ .row
2
+ .col-lg-3.mb-3= render_wizard_sidebar(resource)
3
+ .col-lg-9= yield
@@ -0,0 +1,4 @@
1
+ - if stamp_wizard.submit_order&.purchased?
2
+ .card.mb-4
3
+ .card-body
4
+ = render(stamp_wizard.submit_order)
@@ -0,0 +1,45 @@
1
+ .card
2
+ .card-body
3
+ .row
4
+ .col-sm
5
+ %h5.card-title= stamp_wizard.wizard_step_title(:stamp)
6
+ .col-sm-auto.text-right
7
+ = link_to('Edit', wizard_path(:stamp)) if edit_effective_wizard?
8
+
9
+ - stamp = stamp_wizard.stamp
10
+ - owner = stamp_wizard.owner
11
+
12
+ %table.table.table-sm
13
+ %tbody
14
+ %tr
15
+ %th Owner
16
+ %td
17
+ = owner.to_s
18
+ - if owner.try(:email).present?
19
+ %br
20
+ = mail_to(owner.email)
21
+
22
+ - if owner.try(:phone).present?
23
+ %br
24
+ = owner.phone
25
+
26
+ - if owner.try(:membership).try(:number).present?
27
+ %br
28
+ Member Number #{owner.membership.number}
29
+
30
+ %tr
31
+ %th Category
32
+ %td= stamp.category
33
+
34
+ - if stamp.shipping_address.present?
35
+ %tr
36
+ %th Address
37
+ %td= stamp.shipping_address.to_html
38
+
39
+ %tr
40
+ %th Name
41
+ %td= stamp.name
42
+
43
+ %tr
44
+ %th Name Confirmation
45
+ %td= stamp.name_confirmation
@@ -0,0 +1,45 @@
1
+ %h2 Contact Information
2
+
3
+ - owner = f.object.owner
4
+
5
+ %p
6
+ = owner.to_s
7
+
8
+ - if owner.try(:email).present?
9
+ %br
10
+ = mail_to(owner.email)
11
+
12
+ - if owner.try(:phone).present?
13
+ %br
14
+ = owner.phone
15
+
16
+ - if owner.try(:membership).try(:number).present?
17
+ %br
18
+ Member Number #{owner.membership.number}
19
+
20
+ %h2 Display Name
21
+ %p Please enter and confirm your name as it should appear on the Professional Stamp.
22
+
23
+ = f.text_field :name
24
+ = f.text_field :name_confirmation, hint: 'must match name'
25
+
26
+ %h2 Stamp Information
27
+
28
+ %table.table
29
+ %thead
30
+ %th Stamp
31
+ %th.order_price Cost
32
+ %tbody
33
+ %tr
34
+ %td Physical
35
+ %td.order_price $50.00 + GST
36
+ %tr
37
+ %td Digital-only
38
+ %td.order_price $25.00 + GST
39
+
40
+ %p Please select a stamp:
41
+
42
+ = f.select :category, Effective::Stamp::CATEGORIES
43
+
44
+ = f.show_if :category, 'Physical' do
45
+ = effective_address_fields(f, :shipping)
@@ -0,0 +1,3 @@
1
+ .effective-stamp-payment
2
+ - stamp_wizard.render_steps.each do |partial|
3
+ = render "effective/stamp_wizards/#{partial}", stamp_wizard: stamp_wizard, step: partial
@@ -0,0 +1,31 @@
1
+ = card('Stamp Payment') do
2
+ - stamp = stamp_wizard.stamp
3
+
4
+ %table.table.table-sm
5
+ %tbody
6
+ - if request.path.start_with?('/admin')
7
+ %tr
8
+ %th Owner
9
+ %td
10
+ - url = (polymorphic_admin_path(stamp_wizard.owner) rescue "/admin/users/#{stamp_wizard.owner.to_param}/edit")
11
+ = link_to(stamp_wizard.owner, url)
12
+ - else
13
+ %tr
14
+ %th Owner
15
+ %td= stamp_wizard.owner
16
+
17
+ - if stamp_wizard.orders.present?
18
+ %tr
19
+ %th Order
20
+ %td
21
+ - stamp_wizard.orders.each do |order|
22
+ = link_to(order, effective_orders.order_path(order))
23
+
24
+ - if stamp_wizard.was_submitted?
25
+ %tr
26
+ %th Submitted
27
+ %td= stamp_wizard.submitted_at.strftime('%F')
28
+
29
+ %tr
30
+ %th Issued
31
+ %td= stamp.issued_at&.strftime('%F') || 'Not Issued'
@@ -0,0 +1,15 @@
1
+ = render 'layout' do
2
+ = render 'effective/stamp_wizards/content', resource: resource
3
+
4
+ - raise('expected owner to respond to billing_address') unless resource.owner.respond_to?(:billing_address)
5
+
6
+ = card('Billing Address') do
7
+ %p Please enter your billing address
8
+
9
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
10
+ = f.hidden_field :id
11
+
12
+ = f.fields_for(:owner, f.object.owner) do |fu|
13
+ = effective_address_fields(fu, :billing)
14
+
15
+ = f.save 'Save and Continue'
@@ -0,0 +1,6 @@
1
+ = render 'layout' do
2
+ = render 'effective/stamp_wizards/content', resource: resource
3
+
4
+ .card
5
+ .card-body
6
+ = render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:submitted), deferred_url: wizard_path(:checkout), declined_url: wizard_path(:checkout))
@@ -0,0 +1,18 @@
1
+ = render 'layout' do
2
+ = render 'effective/stamp_wizards/content', resource: resource
3
+
4
+ .card
5
+ .card-body
6
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
7
+ = f.hidden_field :id
8
+
9
+ = f.fields_for :stamps, (f.object.stamp || f.object.build_stamp) do |fr|
10
+ = fr.hidden_field :stamp_wizard_id
11
+ = fr.hidden_field :stamp_wizard_type
12
+
13
+ = fr.hidden_field :owner_id
14
+ = fr.hidden_field :owner_type
15
+
16
+ = render('effective/stamp_wizards/stamp_fields', f: fr)
17
+
18
+ = f.save 'Save and Continue'
@@ -0,0 +1,16 @@
1
+ = render 'layout' do
2
+ = render 'effective/stamp_wizards/content', resource: resource
3
+
4
+ .card
5
+ .card-body
6
+ %p Welcome #{current_user}!
7
+
8
+ %p You are about to purchase a Professional Stamp.
9
+
10
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
11
+ = f.hidden_field :id
12
+
13
+ = f.hidden_field :owner_type
14
+ = f.hidden_field :owner_id
15
+
16
+ = f.save 'Save and Continue'
@@ -0,0 +1,16 @@
1
+ = render 'layout' do
2
+ = render 'effective/stamp_wizards/content', resource: resource
3
+
4
+ - raise('expected a submitted resource') unless resource.was_submitted?
5
+ - raise('expected a purchased resource submit_order') unless resource.submit_order&.purchased?
6
+
7
+ .alert.alert-warning.mb-4
8
+ Successfully paid on #{resource.submit_order.purchased_at.strftime('%F')}.
9
+
10
+ = link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary mb-4'
11
+
12
+ = render 'effective/stamp_wizards/summary', stamp_wizard: resource
13
+ = render 'effective/stamp_wizards/stamp_wizard', stamp_wizard: resource
14
+ = render 'effective/stamp_wizards/orders', stamp_wizard: resource
15
+
16
+ = link_to 'Return to Dashboard', root_path, class: 'btn btn-lg btn-primary'
@@ -0,0 +1,8 @@
1
+ = render 'layout' do
2
+ = render 'effective/stamp_wizards/content', resource: resource
3
+
4
+ = render 'effective/stamp_wizards/stamp_wizard', stamp_wizard: resource
5
+
6
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
7
+ = f.hidden_field :id
8
+ = f.submit 'Save and Continue', class: 'btn btn-primary'
@@ -0,0 +1,11 @@
1
+ = f.text_field :name
2
+ = f.text_field :name_confirmation, hint: 'must match name'
3
+
4
+ %h2 Stamp Information
5
+
6
+ %p Please select a stamp and enter a shipping address.
7
+
8
+ = f.select :category, Effective::Stamp::CATEGORIES
9
+
10
+ = f.show_if :category, 'Physical' do
11
+ = effective_address_fields(f, :shipping)
data/config/routes.rb CHANGED
@@ -10,6 +10,10 @@ EffectiveProducts::Engine.routes.draw do
10
10
  resources :ring_wizards, name: :ring_wizard, only: [:new, :show, :destroy] do
11
11
  resources :build, controller: :ring_wizards, only: [:show, :update]
12
12
  end
13
+
14
+ resources :stamp_wizards, name: :stamp_wizard, only: [:new, :show, :destroy] do
15
+ resources :build, controller: :stamp_wizards, only: [:show, :update]
16
+ end
13
17
  end
14
18
 
15
19
  namespace :admin do
@@ -18,6 +22,10 @@ EffectiveProducts::Engine.routes.draw do
18
22
  resources :rings, only: [:index, :show] do
19
23
  post :mark_as_issued, on: :member
20
24
  end
25
+
26
+ resources :stamps do
27
+ post :mark_as_issued, on: :member
28
+ end
21
29
  end
22
30
 
23
31
  end
@@ -48,5 +48,60 @@ class CreateEffectiveProducts < ActiveRecord::Migration[6.1]
48
48
  add_index :ring_wizards, :status
49
49
  add_index :ring_wizards, :token
50
50
 
51
+ create_table :stamps do |t|
52
+ t.integer :owner_id
53
+ t.string :owner_type
54
+
55
+ t.integer :stamp_wizard_id
56
+ t.string :stamp_wizard_type
57
+
58
+ t.integer :applicant_id
59
+ t.string :applicant_type
60
+
61
+ t.string :status
62
+ t.text :status_steps
63
+
64
+ t.string :category
65
+ t.string :name
66
+ t.string :name_confirmation
67
+
68
+ t.datetime :issued_at
69
+
70
+ # Acts as purchasable
71
+ t.integer :purchased_order_id
72
+ t.integer :price
73
+ t.boolean :tax_exempt, default: false
74
+ t.string :qb_item_name
75
+
76
+ t.timestamps
77
+ end
78
+
79
+ create_table :stamp_wizards do |t|
80
+ t.string :token
81
+
82
+ t.integer :owner_id
83
+ t.string :owner_type
84
+
85
+ t.integer :user_id
86
+ t.string :user_type
87
+
88
+ # Acts as Statused
89
+ t.string :status
90
+ t.text :status_steps
91
+
92
+ # Acts as Wizard
93
+ t.text :wizard_steps
94
+
95
+ # Dates
96
+ t.datetime :submitted_at
97
+
98
+ t.datetime :updated_at
99
+ t.datetime :created_at
100
+ end
101
+
102
+ add_index :stamp_wizards, [:owner_id, :owner_type]
103
+ add_index :stamp_wizards, :status
104
+ add_index :stamp_wizards, :token
105
+
51
106
  end
52
107
  end
@@ -11,6 +11,7 @@ module EffectiveProducts
11
11
  initializer 'effective_products.active_record' do |app|
12
12
  ActiveSupport.on_load :active_record do
13
13
  ActiveRecord::Base.extend(EffectiveProductsRingWizard::Base)
14
+ ActiveRecord::Base.extend(EffectiveProductsStampWizard::Base)
14
15
  end
15
16
  end
16
17
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveProducts
2
- VERSION = '0.0.3'.freeze
2
+ VERSION = '0.0.7'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_products
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.7
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-28 00:00:00.000000000 Z
11
+ date: 2022-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -222,14 +222,23 @@ files:
222
222
  - app/assets/stylesheets/effective_products.scss
223
223
  - app/assets/stylesheets/effective_products/base.scss
224
224
  - app/controllers/admin/rings_controller.rb
225
+ - app/controllers/admin/stamps_controller.rb
225
226
  - app/controllers/effective/ring_wizards_controller.rb
227
+ - app/controllers/effective/stamp_wizards_controller.rb
226
228
  - app/datatables/admin/effective_rings_datatable.rb
229
+ - app/datatables/admin/effective_stamps_datatable.rb
227
230
  - app/datatables/effective_ring_wizards_datatable.rb
231
+ - app/datatables/effective_stamp_wizards_datatable.rb
228
232
  - app/helpers/effective_products_helper.rb
229
233
  - app/models/concerns/effective_products_ring_wizard.rb
234
+ - app/models/concerns/effective_products_stamp_wizard.rb
230
235
  - app/models/effective/ring.rb
231
236
  - app/models/effective/ring_wizard.rb
237
+ - app/models/effective/stamp.rb
238
+ - app/models/effective/stamp_wizard.rb
232
239
  - app/views/admin/rings/_ring.html.haml
240
+ - app/views/admin/stamps/_form.html.haml
241
+ - app/views/admin/stamps/_stamp.html.haml
233
242
  - app/views/effective/ring_wizards/_content.html.haml
234
243
  - app/views/effective/ring_wizards/_dashboard.html.haml
235
244
  - app/views/effective/ring_wizards/_layout.html.haml
@@ -244,7 +253,21 @@ files:
244
253
  - app/views/effective/ring_wizards/start.html.haml
245
254
  - app/views/effective/ring_wizards/submitted.html.haml
246
255
  - app/views/effective/ring_wizards/summary.html.haml
247
- - app/views/effective/rings/_fields.html.haml
256
+ - app/views/effective/stamp_wizards/_content.html.haml
257
+ - app/views/effective/stamp_wizards/_dashboard.html.haml
258
+ - app/views/effective/stamp_wizards/_layout.html.haml
259
+ - app/views/effective/stamp_wizards/_orders.html.haml
260
+ - app/views/effective/stamp_wizards/_stamp.html.haml
261
+ - app/views/effective/stamp_wizards/_stamp_fields.html.haml
262
+ - app/views/effective/stamp_wizards/_stamp_wizard.html.haml
263
+ - app/views/effective/stamp_wizards/_summary.html.haml
264
+ - app/views/effective/stamp_wizards/billing.html.haml
265
+ - app/views/effective/stamp_wizards/checkout.html.haml
266
+ - app/views/effective/stamp_wizards/stamp.html.haml
267
+ - app/views/effective/stamp_wizards/start.html.haml
268
+ - app/views/effective/stamp_wizards/submitted.html.haml
269
+ - app/views/effective/stamp_wizards/summary.html.haml
270
+ - app/views/effective/stamps/_fields.html.haml
248
271
  - config/effective_products.rb
249
272
  - config/routes.rb
250
273
  - db/migrate/01_create_effective_products.rb.erb
@@ -1,39 +0,0 @@
1
- %h2 Contact Information
2
-
3
- = f.text_field :first_name
4
- = f.text_field :last_name
5
- = f.email_field :email
6
- = f.phone_field :phone
7
- = f.static_field :member_number, value: f.object.owner&.membership&.number || 'None'
8
-
9
- = effective_address_fields(f, :shipping)
10
-
11
- %h2 Ring Information
12
-
13
- %table.table
14
- %thead
15
- %th Ring Size
16
- %th Composition
17
- %th.order_price Cost
18
- %tbody
19
- %tr
20
- %td 3-8
21
- %td 14k Yellow Gold
22
- %td.order_price $425.00 + GST
23
- %tr
24
- %td 3-8
25
- %td Sterling Silver
26
- %td.order_price $175.00 + GST
27
- %tr
28
- %td 3-13
29
- %td Titanium
30
- %td.order_price $50.00 + GST
31
-
32
- %ul
33
- %li 14k Yellow Gold and Sterling Silver rings are available in sizes 3 - 8.
34
- %li Titanium rings are available in sizes 3 - 13.
35
-
36
- %p Please select a ring metal and size:
37
-
38
- = f.select :metal, Effective::Ring::METALS
39
- = f.select :size, Effective::Ring::TITANIUM_SIZES