effective_classifieds 0.3.0 → 0.4.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: bb0cfd942db297b12029c3482f9640b4016070b23293a8920f09cf7308b9f511
4
- data.tar.gz: 5677c6e19346e790344bf5dfaca5d411a06ec089e660a6fb0c13f19481b3393e
3
+ metadata.gz: 0aea0ae02dabe99cdca9471c23c158cdf007f31d7ae2fee4522103c2c3d678d7
4
+ data.tar.gz: 0f4272176f66730441f1fa4b46e6858dd784ae3b5c95ccd23ef001415f206dfd
5
5
  SHA512:
6
- metadata.gz: 2af2f02865c7961f045b3f259e6ba238b5b8f1485a72645771f278806a929887256971e8ca71e5d220e1e5f41cd04abd0354325ac72b380956d6e9b4e755b10d
7
- data.tar.gz: 0c80ae59bf92b7777cc0924a08c950a8687aee561ebe4901d4fe7023d8023f10ad03897eb68e29edcafac462fbc405911e9eccd8055a86b4c0b08e31bbe54017
6
+ metadata.gz: f62c3c700c9701fe44c1a2fc9be24f458c2aff875c0f32509d26f367ed8ad30e78b52e7cfb735bb34c5a8fb22908f6c88e81b0858fd3c51c9cda5de8e2242305
7
+ data.tar.gz: 2eece6889e8473c8acbc3c23a74b924894e89db234845ba0574784da9f0b3f6748ffb6e51596ee877c4f0c44a0a624c6fbfc16c423d901c95e182d73a4ee75e3
@@ -12,6 +12,8 @@ class Admin::EffectiveClassifiedWizardsDatatable < Effective::Datatable
12
12
  col :classified, search: :string
13
13
  col :owner
14
14
 
15
+ col :orders
16
+
15
17
  actions_col
16
18
  end
17
19
 
@@ -45,6 +45,8 @@ module Admin
45
45
  col :status, search: ['submitted', 'approved']
46
46
  end
47
47
 
48
+ col :purchased_order, visible: false
49
+
48
50
  actions_col do |classified|
49
51
  dropdown_link_to('View Classified', effective_classifieds.classified_path(classified), target: '_blank')
50
52
  end
@@ -10,7 +10,7 @@ class EffectiveClassifiedWizardsDatatable < Effective::Datatable
10
10
  wizard.submitted_at&.strftime('%F') || 'Incomplete'
11
11
  end
12
12
 
13
- col :classified, search: :string, label: 'Title'
13
+ col :classifieds, search: :string, label: 'Title'
14
14
 
15
15
  col :owner, visible: false, search: :string
16
16
 
@@ -30,7 +30,7 @@ class EffectiveClassifiedWizardsDatatable < Effective::Datatable
30
30
  end
31
31
 
32
32
  collection do
33
- EffectiveClassifieds.ClassifiedWizard.deep.where(owner: current_user).left_joins(:classified)
33
+ EffectiveClassifieds.ClassifiedWizard.deep.where(owner: current_user)
34
34
  end
35
35
 
36
36
  end
@@ -19,6 +19,7 @@ module EffectiveClassifiedsClassifiedWizard
19
19
 
20
20
  included do
21
21
  acts_as_tokened
22
+ acts_as_purchasable_parent
22
23
 
23
24
  acts_as_statused(
24
25
  :draft, # Just Started
@@ -29,9 +30,13 @@ module EffectiveClassifiedsClassifiedWizard
29
30
  start: 'Start',
30
31
  classified: 'Classified',
31
32
  summary: 'Review',
33
+ billing: 'Billing Address',
34
+ checkout: 'Checkout',
32
35
  submitted: 'Submitted'
33
36
  )
34
37
 
38
+ acts_as_purchasable_wizard
39
+
35
40
  log_changes(except: :wizard_steps) if respond_to?(:log_changes)
36
41
 
37
42
  # Application Namespace
@@ -39,8 +44,8 @@ module EffectiveClassifiedsClassifiedWizard
39
44
  accepts_nested_attributes_for :owner
40
45
 
41
46
  # Effective Namespace
42
- has_one :classified, class_name: 'Effective::Classified', inverse_of: :classified_wizard, dependent: :destroy
43
- accepts_nested_attributes_for :classified, reject_if: :all_blank, allow_destroy: true
47
+ has_many :classifieds, class_name: 'Effective::Classified', inverse_of: :classified_wizard, dependent: :destroy
48
+ accepts_nested_attributes_for :classifieds, reject_if: :all_blank, allow_destroy: true
44
49
 
45
50
  effective_resource do
46
51
  # Acts as Statused
@@ -50,13 +55,16 @@ module EffectiveClassifiedsClassifiedWizard
50
55
  # Dates
51
56
  submitted_at :datetime
52
57
 
58
+ # Pricing
59
+ price_category :string
60
+
53
61
  # Acts as Wizard
54
62
  wizard_steps :text, permitted: false
55
63
 
56
64
  timestamps
57
65
  end
58
66
 
59
- scope :deep, -> { includes(:classified) }
67
+ scope :deep, -> { includes(:classifieds) }
60
68
  scope :sorted, -> { order(:id) }
61
69
 
62
70
  scope :in_progress, -> { where.not(status: [:submitted]) }
@@ -71,6 +79,30 @@ module EffectiveClassifiedsClassifiedWizard
71
79
  with_options(if: -> { current_step == :classified }) do
72
80
  validates :classified, presence: true
73
81
  end
82
+
83
+ # All Fees and Orders
84
+ def submit_fees
85
+ classifieds
86
+ end
87
+
88
+ def after_submit_purchased!
89
+ # Nothing to do
90
+ end
91
+
92
+ # Overrides the acts_as_purchasable_wizard submit!
93
+ def submit!
94
+ raise('already submitted') if was_submitted?
95
+
96
+ if checkout_required?
97
+ raise('expected a purchased order') unless submit_order&.purchased?
98
+ wizard_steps[:checkout] ||= Time.zone.now
99
+ end
100
+
101
+ wizard_steps[:submitted] = Time.zone.now
102
+ classified.submit! unless classified.was_submitted?
103
+
104
+ submitted!
105
+ end
74
106
  end
75
107
 
76
108
  # Instance Methods
@@ -86,19 +118,39 @@ module EffectiveClassifiedsClassifiedWizard
86
118
  submitted?
87
119
  end
88
120
 
89
- # Called on the Review / Summary Step
90
- # But we actually want to submit it
91
- def summary!
92
- submit!
121
+ def checkout_required?
122
+ required_steps.include?(:billing) && required_steps.include?(:checkout)
123
+ end
124
+
125
+ def no_checkout_required?
126
+ required_steps.exclude?(:billing) && required_steps.exclude?(:checkout)
93
127
  end
94
128
 
95
- def submit!
96
- raise('already submitted') if was_submitted?
129
+ def classified
130
+ classifieds.first
131
+ end
97
132
 
98
- classified.submit! unless classified.was_submitted?
133
+ def build_classified
134
+ classifieds.build(owner: owner)
135
+ end
99
136
 
100
- wizard_steps[:submitted] = Time.zone.now
101
- submitted!
137
+ def assign_pricing
138
+ raise('to be implemented by including class')
139
+ # classified.assign_attributes(price: price, qb_item_name: qb_item_name, tax_exempt: tax_exempt)
140
+ end
141
+
142
+ # After the configure Classified step
143
+ def classified!
144
+ assign_pricing() if classified.present?
145
+ raise('expected classified to have a price') if classified.price.blank?
146
+
147
+ save!
148
+ end
149
+
150
+ # This is the review/summary step. Last one if we're not doing checkout
151
+ def summary!
152
+ return submit! if no_checkout_required?
153
+ save!
102
154
  end
103
155
 
104
156
  end
@@ -7,6 +7,7 @@ module Effective
7
7
  attr_accessor :current_user
8
8
 
9
9
  acts_as_slugged
10
+ acts_as_purchasable
10
11
  log_changes if respond_to?(:log_changes)
11
12
  acts_as_role_restricted if respond_to?(:acts_as_role_restricted)
12
13
 
@@ -17,6 +18,7 @@ module Effective
17
18
  # When submitted through the wizard
18
19
  belongs_to :classified_wizard, polymorphic: true, optional: true
19
20
 
21
+ has_one_attached :file
20
22
  has_rich_text :body
21
23
 
22
24
  acts_as_statused(
@@ -53,6 +55,10 @@ module Effective
53
55
 
54
56
  archived :boolean
55
57
 
58
+ price :integer
59
+ tax_exempt :boolean
60
+ qb_item_name :string
61
+
56
62
  timestamps
57
63
  end
58
64
 
@@ -103,7 +109,7 @@ module Effective
103
109
 
104
110
  # Automatically approve submissions created by admins outside the submissions wizard
105
111
  before_validation(if: -> { new_record? && classified_wizard.blank? }) do
106
- assign_attributes(status: :approved)
112
+ assign_attributes(status: :approved, price: 0)
107
113
  end
108
114
 
109
115
  validates :title, presence: true, length: { maximum: 200 }
@@ -133,6 +139,10 @@ module Effective
133
139
  self.errors.add(:category, 'is invalid') unless Array(EffectiveClassifieds.categories).include?(category)
134
140
  end
135
141
 
142
+ validate(if: -> { file.attached? && !Rails.env.test? }) do
143
+ self.errors.add(:file, 'expected a .pdf file') unless file.content_type == 'application/pdf'
144
+ end
145
+
136
146
  def to_s
137
147
  title.presence || 'New Classified'
138
148
  end
@@ -7,6 +7,12 @@
7
7
  = tab 'Access' do
8
8
  = render '/admin/classifieds/form_access', classified: classified
9
9
 
10
+ - if classified.classified_wizard.present?
11
+ = tab 'Orders' do
12
+ %h2 Orders
13
+ - datatable = Admin::EffectiveOrdersDatatable.new(parent: classified.classified_wizard, owner: classified.owner, user: classified.owner, total: false)
14
+ = render_datatable(datatable, simple: true)
15
+
10
16
  - if classified.respond_to?(:log_changes_datatable)
11
17
  = tab 'Logs' do
12
18
  = render_inline_datatable(classified.log_changes_datatable)
@@ -1,3 +1,4 @@
1
1
  = effective_form_with(model: [:admin, classified], engine: true) do |f|
2
2
  = render('effective/classifieds/fields', f: f, classified: f.object)
3
+
3
4
  = effective_submit(f)
@@ -0,0 +1 @@
1
+ - # Intentionally Blank
@@ -0,0 +1,4 @@
1
+ - if classified_wizard.submit_order&.purchased?
2
+ .card.mb-4
3
+ .card-body
4
+ = render(classified_wizard.submit_order)
@@ -0,0 +1,15 @@
1
+ = render 'layout' do
2
+ = render 'effective/classified_wizards/content', resource: resource
3
+
4
+ - raise('expected owner to respond to billing_address') unless resource.owner.respond_to?(:billing_address)
5
+
6
+ = card do
7
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
8
+ = f.hidden_field :id
9
+
10
+ = f.fields_for(:owner, f.object.owner) do |fo|
11
+ = effective_address_fields(fo, :billing)
12
+
13
+ %p.text-muted * Not all classifieds require a fee and we ask for a billing address for future use
14
+
15
+ = f.save 'Save and Continue'
@@ -0,0 +1,5 @@
1
+ = render 'layout' do
2
+ = render 'effective/classified_wizards/content', resource: resource
3
+
4
+ = card do
5
+ = render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:submitted), deferred_url: wizard_path(:checkout), declined_url: wizard_path(:checkout))
@@ -6,7 +6,7 @@
6
6
  = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
7
7
  = f.hidden_field :id
8
8
 
9
- = f.fields_for :classified, (f.object.classified || f.object.build_classified) do |fc|
9
+ = f.fields_for :classifieds, (f.object.classified || f.object.build_classified) do |fc|
10
10
  = fc.hidden_field :id
11
11
 
12
12
  = fc.hidden_field :owner_id, value: f.object.owner_id
@@ -14,4 +14,6 @@
14
14
 
15
15
  = render('effective/classifieds/fields', f: fc, classified: fc.object)
16
16
 
17
+ = render('effective/classified_wizards/additional_fields', f: f, classified_wizard: f.object)
18
+
17
19
  = f.save 'Save and Continue'
@@ -1,14 +1,29 @@
1
1
  = render 'layout' do
2
2
  = render 'effective/classified_wizards/content', resource: resource
3
3
 
4
+ - classified = resource.classified
5
+
4
6
  - raise('expected a submitted classified_wizard') unless resource.was_submitted?
7
+ - raise('expected a submitted classified') unless classified.was_submitted?
8
+
9
+ - if resource.checkout_required?
10
+ - raise('expected a purchased classified submit_order') unless resource.submit_order&.purchased?
5
11
 
6
12
  .alert.alert-warning.mb-4
7
- Successfully submitted on #{resource.submitted_at.strftime('%F')}.
13
+ This classified was submitted on #{classified.submitted_at.strftime('%F')}.
14
+
15
+ - unless classified.approved?
16
+ = card do
17
+ %p Your classified must still be approved before it will be displayed.
8
18
 
9
19
  = link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary mb-4'
10
20
 
11
21
  = render 'effective/classified_wizards/summary', classified_wizard: resource
12
22
  = render 'effective/classified_wizards/classified_wizard', classified_wizard: resource
13
23
 
24
+ - if resource.orders.present?
25
+ .mb-4
26
+ = collapse('Show orders...', card_class: 'my-2') do
27
+ = render 'effective/classified_wizards/orders', classified_wizard: resource
28
+
14
29
  = link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary'
@@ -17,14 +17,19 @@
17
17
  to
18
18
  #{classified.end_on&.strftime('%F')}
19
19
 
20
- - if classified.website.present?
20
+ - if classified.location.present?
21
21
  %tr
22
22
  %th Location
23
23
  %td= classified.location
24
24
 
25
25
  %tr
26
26
  %th Description
27
- %td= classified.body
27
+ %td= classified.body.to_s
28
+
29
+ - if classified.file.attached?
30
+ %tr
31
+ %th Attachment
32
+ %td= link_to(classified.file.filename, main_app.url_for(classified.file), target: '_blank')
28
33
 
29
34
  %tr
30
35
  %th Company
@@ -26,6 +26,8 @@
26
26
  - else
27
27
  = f.rich_text_area :body, label: 'Body content', hint: 'The main body content of your classified ad. Be sure to include all relevant information!'
28
28
 
29
+ = f.file_field :file, label: 'Attach PDF'
30
+
29
31
  %h2.mt-5.mb-0 Contact Information
30
32
  %p
31
33
  %small.text-muted Contact information will be displayed on the classified ad.
@@ -30,6 +30,12 @@ class CreateEffectiveClassifieds < ActiveRecord::Migration[6.1]
30
30
 
31
31
  t.boolean :archived, default: false
32
32
 
33
+ # Acts as purchasable
34
+ t.integer :purchased_order_id
35
+ t.integer :price
36
+ t.boolean :tax_exempt, default: false
37
+ t.string :qb_item_name
38
+
33
39
  t.timestamps
34
40
  end
35
41
 
@@ -52,6 +58,9 @@ class CreateEffectiveClassifieds < ActiveRecord::Migration[6.1]
52
58
  # Dates
53
59
  t.datetime :submitted_at
54
60
 
61
+ # Pricing
62
+ t.string :price_category
63
+
55
64
  t.datetime :updated_at
56
65
  t.datetime :created_at
57
66
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveClassifieds
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_classifieds
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.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-08-24 00:00:00.000000000 Z
11
+ date: 2022-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 4.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: effective_orders
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: effective_resources
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -195,12 +209,16 @@ files:
195
209
  - app/views/admin/classifieds/_form.html.haml
196
210
  - app/views/admin/classifieds/_form_access.html.haml
197
211
  - app/views/admin/classifieds/_form_classified.html.haml
212
+ - app/views/effective/classified_wizards/_additional_fields.html.haml
198
213
  - app/views/effective/classified_wizards/_classified.html.haml
199
214
  - app/views/effective/classified_wizards/_classified_wizard.html.haml
200
215
  - app/views/effective/classified_wizards/_content.html.haml
201
216
  - app/views/effective/classified_wizards/_dashboard.html.haml
202
217
  - app/views/effective/classified_wizards/_layout.html.haml
218
+ - app/views/effective/classified_wizards/_orders.html.haml
203
219
  - app/views/effective/classified_wizards/_summary.html.haml
220
+ - app/views/effective/classified_wizards/billing.html.haml
221
+ - app/views/effective/classified_wizards/checkout.html.haml
204
222
  - app/views/effective/classified_wizards/classified.html.haml
205
223
  - app/views/effective/classified_wizards/start.html.haml
206
224
  - app/views/effective/classified_wizards/submitted.html.haml