effective_cpd 1.3.7 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/admin/cpd_targets_controller.rb +15 -0
  3. data/app/controllers/effective/cpd_statement_activities_controller.rb +6 -1
  4. data/app/datatables/admin/effective_cpd_cycles_datatable.rb +1 -1
  5. data/app/datatables/admin/effective_cpd_special_rules_datatable.rb +2 -3
  6. data/app/datatables/admin/effective_cpd_statements_datatable.rb +2 -4
  7. data/app/datatables/admin/effective_cpd_targets_datatable.rb +23 -0
  8. data/app/datatables/effective_cpd_available_cycles_datatable.rb +3 -4
  9. data/app/datatables/effective_cpd_completed_statements_datatable.rb +6 -5
  10. data/app/helpers/effective_cpd_helper.rb +13 -2
  11. data/app/models/concerns/effective_cpd_audit_review.rb +4 -0
  12. data/app/models/concerns/effective_cpd_statement.rb +8 -14
  13. data/app/models/concerns/effective_cpd_user.rb +38 -7
  14. data/app/models/effective/cpd_cycle.rb +1 -7
  15. data/app/models/effective/cpd_target.rb +31 -0
  16. data/app/views/admin/cpd_cycles/_form.html.haml +4 -1
  17. data/app/views/admin/cpd_cycles/_form_cpd_cycle.html.haml +0 -3
  18. data/app/views/admin/cpd_cycles/_form_cpd_special_rules.html.haml +1 -1
  19. data/app/views/admin/cpd_cycles/_form_cpd_targets.html.haml +18 -0
  20. data/app/views/admin/cpd_targets/_form.html.haml +18 -0
  21. data/app/views/admin/users/_form_cpd.html.haml +5 -1
  22. data/app/views/admin/users/_form_cpd_targets.html.haml +34 -0
  23. data/app/views/effective/cpd_statement_activities/_form.html.haml +2 -1
  24. data/app/views/effective/cpd_statements/_activities_table.html.haml +3 -0
  25. data/app/views/effective/cpd_statements/_layout.html.haml +6 -4
  26. data/app/views/effective/cpd_statements/_summary.html.haml +5 -4
  27. data/app/views/effective/cpd_statements/activities.html.haml +4 -2
  28. data/config/effective_cpd.rb +1 -0
  29. data/config/locales/effective_cpd.en.yml +1 -0
  30. data/config/routes.rb +1 -0
  31. data/db/migrate/01_create_effective_cpd.rb.erb +13 -1
  32. data/db/seeds.rb +0 -1
  33. data/lib/effective_cpd/version.rb +1 -1
  34. data/lib/effective_cpd.rb +2 -0
  35. data/lib/generators/effective_cpd/install_generator.rb +1 -0
  36. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: baf69685d3c7825c972b471700fbd6101891fbd0c5ea4c3d45864f56d6c4f5b4
4
- data.tar.gz: f8b52a21ec9077c29a5167d0b1fc482905fd35a6a1dd5188ee94d9dc442bbc06
3
+ metadata.gz: 15a9526456ab27ed3cc2dca6c6c368afe97e478282d66083cfb45e10250071c8
4
+ data.tar.gz: 4394265758150e1a979fa5cb000f22f5153c7c7a5be772e4b90d2795376697f4
5
5
  SHA512:
6
- metadata.gz: eb2211dbb1cc889c105a0040b3bdc5132cf2efe7c9f1566b4d107c3b4802c19fb0be169c2e3792d6c6f7987fdbed7938facf82b7326ed69efdda31ac86c8098b
7
- data.tar.gz: 26e17fa4c968667414ff73f6a5b203c4e9e2cecf35d8f716abe958cb6c8acd5551ef3298d6a8b20f8667ae335d80e934f98a36dfb4b7a88893a63080300fe84e
6
+ metadata.gz: bffcf39a42c4481b6e51425e0ff373b9a6670c2e9c01027099d4f3abe299fdf428ba601123e38f17f136abdd5f95cec8a35560839524dcd29c69bf3cdb653d9b
7
+ data.tar.gz: e427677d3c6ec195b01b0b22c9022ce4eac3c40fa04eeeb873da3a7573e2b8a68e076cc8151f684f9a0b0c11fe1804cc63ce77c9554d50823dfb54b9ed9e1614
@@ -0,0 +1,15 @@
1
+ module Admin
2
+ class CpdTargetsController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+ before_action { EffectiveResources.authorize!(self, :admin, :effective_cpd) }
5
+
6
+ include Effective::CrudController
7
+
8
+ private
9
+
10
+ def permitted_params
11
+ params.require(:effective_cpd_target).permit!
12
+ end
13
+
14
+ end
15
+ end
@@ -14,7 +14,12 @@ module Effective
14
14
  # Redirect the remote form back to the activities page
15
15
  on :save, redirect: -> {
16
16
  statement = resource.cpd_statement
17
- effective_cpd.cpd_cycle_cpd_statement_build_path(statement.cpd_cycle, statement, :activities)
17
+
18
+ if params[:commit] == 'Save and Add Another'
19
+ effective_cpd.cpd_cycle_cpd_statement_build_path(statement.cpd_cycle, statement, :activities, activities: :new)
20
+ else
21
+ effective_cpd.cpd_cycle_cpd_statement_build_path(statement.cpd_cycle, statement, :activities)
22
+ end
18
23
  }
19
24
 
20
25
  def permitted_params
@@ -10,7 +10,7 @@ module Admin
10
10
  col :title
11
11
  col :start_at
12
12
  col :end_at
13
- col :required_score, label: 'Required'
13
+ col :required_to_submit, label: "Minimum score required to submit"
14
14
 
15
15
  actions_col
16
16
  end
@@ -5,9 +5,8 @@ module Admin
5
5
  col :created_at, visible: false
6
6
  col :updated_at, visible: false
7
7
 
8
- col :cpd_cycle
9
-
10
- col :cpd_rules
8
+ col :cpd_cycle, label: cpd_cycle_label
9
+ col :cpd_rules, label: 'Rules'
11
10
 
12
11
  col :category
13
12
  col :max_credits_per_cycle, label: 'Max ' + cpd_credits_label
@@ -22,10 +22,8 @@ module Admin
22
22
  cpd_score(cpd_statement.score)
23
23
  end
24
24
 
25
- if attributes[:user_id].present?
26
- col :required_score, label: 'Required' do |cpd_statement|
27
- cpd_score(cpd_statement.required_score || cpd_statement.targeted_score)
28
- end
25
+ col :target_score, label: "Required " + cpd_credits_label.capitalize, as: :decimal do |cpd_statement|
26
+ cpd_score(cpd_statement.target_score)
29
27
  end
30
28
 
31
29
  col :carry_forward do |cpd_statement|
@@ -0,0 +1,23 @@
1
+ module Admin
2
+ class EffectiveCpdTargetsDatatable < Effective::Datatable
3
+ datatable do
4
+ order :updated_at
5
+
6
+ col :updated_at, visible: false
7
+ col :created_at, visible: false
8
+ col :id, visible: false
9
+
10
+ col :user
11
+ col :cpd_cycle, search: Effective::CpdCycle.sorted, label: cpd_cycle_label
12
+
13
+ col :score, label: "Target or Required " + cpd_credits_label
14
+ col :required_to_submit
15
+
16
+ actions_col
17
+ end
18
+
19
+ collection do
20
+ Effective::CpdTarget.deep.all
21
+ end
22
+ end
23
+ end
@@ -7,11 +7,10 @@ class EffectiveCpdAvailableCyclesDatatable < Effective::Datatable
7
7
  col :start_at, visible: false
8
8
 
9
9
  col(:title, label: cpd_cycle_label)
10
- col :available_date, label: 'Available'
10
+ col :available_date
11
11
 
12
- col :required_score, label: 'Required' do |cpd_cycle|
13
- cpd_statement = EffectiveCpd.CpdStatement.new(cpd_cycle: cpd_cycle, user: current_user)
14
- cpd_score(cpd_statement.required_score || cpd_statement.targeted_score)
12
+ col :target_score, label: "Required #{cpd_credits_label}" do |cpd_cycle|
13
+ cpd_score(current_user.cpd_target_score(cpd_cycle: cpd_cycle))
15
14
  end
16
15
 
17
16
  actions_col(actions: []) do |cpd_cycle|
@@ -8,14 +8,15 @@ class EffectiveCpdCompletedStatementsDatatable < Effective::Datatable
8
8
  statement.cpd_cycle.to_s
9
9
  end
10
10
 
11
- col :submitted_at
12
- col :score, label: cpd_credits_label
11
+ col :submitted_at, as: :date, label: 'Submitted'
13
12
 
14
- col :required_score, label: 'Required' do |cpd_statement|
15
- cpd_score(cpd_statement.required_score || cpd_statement.targeted_score)
13
+ col :score, label: cpd_credits_label do |cpd_statement|
14
+ cpd_score(cpd_statement.score, cpd_statement.target_score)
16
15
  end
17
16
 
18
- col :carry_forward
17
+ col :carry_forward do |cpd_statement|
18
+ cpd_score(cpd_statement.carry_forward)
19
+ end
19
20
 
20
21
  unless attributes[:actions] == false
21
22
  actions_col(actions: []) do |cpd_statement|
@@ -68,6 +68,14 @@ module EffectiveCpdHelper
68
68
  ets(EffectiveCpd.CpdAuditLevel)
69
69
  end
70
70
 
71
+ def cpd_target_label
72
+ et(Effective::CpdTarget)
73
+ end
74
+
75
+ def cpd_targets_label
76
+ ets(Effective::CpdTarget)
77
+ end
78
+
71
79
  def cpd_rule_formula_hint(cpd_activity)
72
80
  raise('expected a CPDActivity') unless cpd_activity.kind_of?(Effective::CpdActivity)
73
81
 
@@ -96,8 +104,11 @@ module EffectiveCpdHelper
96
104
  @effective_cpd_categories ||= Effective::CpdCategory.deep.sorted
97
105
  end
98
106
 
99
- def cpd_score(value)
100
- ("%.#{2}f" % value.to_d)
107
+ def cpd_score(value, value2 = nil)
108
+ score1 = ("%.#{2}f" % value.to_d)
109
+ score2 = ("%.#{2}f" % value2.to_d)
110
+
111
+ (value.present? && value2.present?) ? "#{score1} / #{score2}" : score1
101
112
  end
102
113
 
103
114
  end
@@ -118,6 +118,10 @@ module EffectiveCpdAuditReview
118
118
  end
119
119
  end
120
120
 
121
+ with_options(if: -> { current_step == :recommendation }) do
122
+ validates :recommendation, presence: true
123
+ end
124
+
121
125
  with_options(if: -> { cpd_audit_level&.anonymous? }) do
122
126
  before_validation { assign_anonymous_name_and_number }
123
127
 
@@ -46,7 +46,7 @@ module EffectiveCpdStatement
46
46
  accepts_nested_attributes_for :cpd_statement_activities
47
47
 
48
48
  effective_resource do
49
- score :integer
49
+ score :decimal
50
50
 
51
51
  confirm_read :boolean
52
52
  confirm_factual :boolean
@@ -63,7 +63,7 @@ module EffectiveCpdStatement
63
63
  timestamps
64
64
  end
65
65
 
66
- scope :deep, -> { includes(:cpd_cycle, :user, cpd_statement_activities: [:files_attachments, :cpd_category, :original, cpd_activity: [:rich_text_body]]) }
66
+ scope :deep, -> { includes(:cpd_cycle, user: [:cpd_targets], cpd_statement_activities: [:files_attachments, :cpd_category, :original, cpd_activity: [:rich_text_body]]) }
67
67
  scope :sorted, -> { order(:cpd_cycle_id) }
68
68
 
69
69
  scope :draft, -> { where(submitted_at: nil) }
@@ -80,8 +80,8 @@ module EffectiveCpdStatement
80
80
  self.score ||= 0
81
81
  end
82
82
 
83
- validate(if: -> { completed? }) do
84
- min = required_score() || 0.0
83
+ validate(if: -> { completed? && target_score_required_to_submit? }) do
84
+ min = target_score() || 0.0
85
85
  self.errors.add(:score, "must be #{min} or greater to submit a statement") if score < min
86
86
  end
87
87
 
@@ -130,18 +130,12 @@ module EffectiveCpdStatement
130
130
  end
131
131
  alias_method :submitted?, :completed?
132
132
 
133
- def required_score
134
- required_by_cycle = cpd_cycle&.required_score
135
- required_by_user = user.cpd_statement_required_score(self) if user.respond_to?(:cpd_statement_required_score)
136
-
137
- [required_by_cycle, required_by_user].compact.max
133
+ def target_score
134
+ user.cpd_target_score(cpd_cycle: cpd_cycle)
138
135
  end
139
136
 
140
- def targeted_score
141
- targeted_by_cycle = cpd_cycle&.targeted_score
142
- targeted_by_user = user.cpd_statement_targeted_score(self) if user.respond_to?(:cpd_statement_targeted_score)
143
-
144
- [targeted_by_cycle, targeted_by_user].compact.max
137
+ def target_score_required_to_submit?
138
+ user.cpd_target_score_required_to_submit?(cpd_cycle: cpd_cycle)
145
139
  end
146
140
 
147
141
  def carry_forward
@@ -24,6 +24,10 @@ module EffectiveCpdUser
24
24
  has_many :cpd_audits, -> { order(:id) }, inverse_of: :user
25
25
  has_many :cpd_audit_reviews, -> { order(:id) }, inverse_of: :user
26
26
 
27
+ # Effective scoped
28
+ has_many :cpd_targets, -> { order(:cpd_cycle_id) }, inverse_of: :user, class_name: 'Effective::CpdTarget', dependent: :delete_all
29
+ accepts_nested_attributes_for :cpd_targets
30
+
27
31
  # These two should not be sorted
28
32
  scope :cpd_audit_auditees, -> { without_role(:cpd_audit_reviewer).without_role(:admin) }
29
33
  scope :cpd_audit_reviewers, -> { with_role(:cpd_audit_reviewer) }
@@ -39,15 +43,25 @@ module EffectiveCpdUser
39
43
  }
40
44
  end
41
45
 
42
- # This one will actually be enforced or displayed first
43
- def cpd_statement_required_score(cpd_statement)
44
- nil
46
+ def cpd_target_score(cpd_cycle:)
47
+ target = cpd_target(cpd_cycle: cpd_cycle)
48
+ return target.score if target&.score.present?
49
+
50
+ # Otherwise calculate default by membership category
51
+ if self.class.try(:effective_memberships_user?)
52
+ category = membership_categories_on(cpd_cycle.start_at)&.first if cpd_cycle.start_at.present?
53
+ category ||= membership_categories_on(cpd_cycle.end_at)&.first if cpd_cycle.end_at.present?
54
+ category ||= membership&.categories&.first
55
+
56
+ category&.cpd_target_score(cpd_cycle: cpd_cycle)
57
+ end
45
58
  end
46
59
 
47
- # This one will be displayed on the sidebar if first one is nil
48
- # Won't actually block the submission
49
- def cpd_statement_targeted_score(cpd_statement)
50
- nil
60
+ def cpd_target_score_required_to_submit?(cpd_cycle:)
61
+ target = cpd_target(cpd_cycle: cpd_cycle)
62
+ return target.required_to_submit? unless target&.required_to_submit.nil?
63
+
64
+ cpd_cycle.required_to_submit?
51
65
  end
52
66
 
53
67
  def cpd_audit_cpd_required?
@@ -69,4 +83,21 @@ module EffectiveCpdUser
69
83
  cpd_statement(cpd_cycle: cpd_cycle) || cpd_statements.build(cpd_cycle: cpd_cycle)
70
84
  end
71
85
 
86
+ def cpd_target(cpd_cycle:)
87
+ raise('expected an CpdCycle') unless cpd_cycle.class.respond_to?(:effective_cpd_cpd_cycle?)
88
+ cpd_targets.find { |cpd_target| cpd_target.cpd_cycle_id == cpd_cycle.id }
89
+ end
90
+
91
+ # Find or build
92
+ def build_cpd_target(cpd_cycle:)
93
+ raise('expected an CpdCycle') unless cpd_cycle.class.respond_to?(:effective_cpd_cpd_cycle?)
94
+ cpd_target(cpd_cycle: cpd_cycle) || cpd_targets.build(cpd_cycle: cpd_cycle)
95
+ end
96
+
97
+ # For the form
98
+ def build_cpd_targets
99
+ Effective::CpdCycle.sorted.all.each { |cpd_cycle| build_cpd_target(cpd_cycle: cpd_cycle) }
100
+ cpd_targets.sort_by(&:cpd_cycle_id).reverse
101
+ end
102
+
72
103
  end
@@ -26,7 +26,7 @@ module Effective
26
26
  start_at :datetime
27
27
  end_at :datetime
28
28
 
29
- required_score :integer # If set, a user must fill out this many activities to finish a statement
29
+ required_to_submit :boolean
30
30
 
31
31
  timestamps
32
32
  end
@@ -54,7 +54,6 @@ module Effective
54
54
 
55
55
  validates :title, presence: true
56
56
  validates :start_at, presence: true
57
- validates :required_score, numericality: { greater_than: 0, allow_nil: true }
58
57
 
59
58
  validate(if: -> { start_at.present? && end_at.present? }) do
60
59
  self.errors.add(:end_at, 'must be after the start date') unless end_at > start_at
@@ -78,11 +77,6 @@ module Effective
78
77
  title.presence || model_name.human
79
78
  end
80
79
 
81
- # Todo, implement a cpd cycle targeted score entirely
82
- def targeted_score
83
- nil
84
- end
85
-
86
80
  def build_from_cycle(cycle:)
87
81
  raise('expected a CpdCycle') unless cycle.kind_of?(CpdCycle)
88
82
 
@@ -0,0 +1,31 @@
1
+ module Effective
2
+ class CpdTarget < ActiveRecord::Base
3
+ # App scoped
4
+ belongs_to :user, polymorphic: true
5
+
6
+ # Effective Namespace
7
+ belongs_to :cpd_cycle, class_name: 'Effective::CpdCycle'
8
+
9
+ log_changes(to: :user) if respond_to?(:log_changes)
10
+
11
+ REQUIRED_TO_SUBMIT = [["A minimum score is required to submit", true], ["Can submit with any score", false]]
12
+
13
+ effective_resource do
14
+ score :decimal
15
+ required_to_submit :boolean
16
+
17
+ timestamps
18
+ end
19
+
20
+ scope :deep, -> { includes(:user, :cpd_cycle) }
21
+ scope :sorted, -> { order(:cpd_cycle_id) }
22
+
23
+ validates :score, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
24
+ validates :score, presence: true, if: -> { required_to_submit? }
25
+
26
+ def to_s
27
+ score&.to_s || model_name.human
28
+ end
29
+
30
+ end
31
+ end
@@ -1,8 +1,11 @@
1
1
  = tabs do
2
- = tab 'Cycle' do
2
+ = tab(Effective::CpdCycle) do
3
3
  = render 'admin/cpd_cycles/form_cpd_cycle', cpd_cycle: cpd_cycle
4
4
 
5
5
  - if cpd_cycle.persisted?
6
+ = tab(ets(Effective::CpdTarget)) do
7
+ = render 'admin/cpd_cycles/form_cpd_targets', cpd_cycle: cpd_cycle
8
+
6
9
  = tab 'Special Rules' do
7
10
  = render 'admin/cpd_cycles/form_cpd_special_rules', cpd_cycle: cpd_cycle
8
11
 
@@ -8,9 +8,6 @@
8
8
  = f.date_field :end_at, date_linked: false,
9
9
  hint: "The last date a #{cpd_statement_label} may be created for this #{cpd_cycle_label}. leave blank for no end date."
10
10
 
11
- = f.number_field :required_score,
12
- hint: "The minimum required #{cpd_credits_label} to submit a #{cpd_statement_label} for this #{cpd_cycle_label}. leave blank to submit any amount."
13
-
14
11
  - if f.object.new_record?
15
12
  - latest_cycle = Effective::CpdCycle.latest_cycle
16
13
 
@@ -1,4 +1,4 @@
1
1
  %p Special rules operate on more than one category at a time.
2
2
 
3
- - datatable = Admin::EffectiveCpdSpecialRulesDatatable.new(cpd_cycle_id: cpd_cycle.id)
3
+ - datatable = Admin::EffectiveCpdSpecialRulesDatatable.new(cpd_cycle: cpd_cycle)
4
4
  = render_datatable(datatable, inline: true)
@@ -0,0 +1,18 @@
1
+ = effective_form_with(model: [:admin, cpd_cycle], engine: true) do |f|
2
+ %p The minimum number of #{cpd_credits_label} to submit a #{cpd_statement_label} in this #{cpd_cycle_label} is configured per user.
3
+ %p Visit a user page to better view their specific #{cpd_credits_label} requirements.
4
+
5
+ %p By default, the following behaviour will be applied to #{cpd_statements_label}:
6
+
7
+ .row
8
+ .col-lg-6
9
+ = f.select :required_to_submit, Effective::CpdTarget::REQUIRED_TO_SUBMIT
10
+
11
+ = f.save
12
+
13
+ %hr
14
+
15
+ .mt-4
16
+ %p The ability to submit a #{cpd_statement_label} in this #{cpd_cycle_label} has been individualized for the following:
17
+ - datatable = Admin::EffectiveCpdTargetsDatatable.new(cpd_cycle: cpd_cycle)
18
+ = render_datatable(datatable, inline: true)
@@ -0,0 +1,18 @@
1
+ = effective_form_with(model: [:admin, cpd_target], engine: true) do |f|
2
+ = f.hidden_field :user_type, value: current_user.class.name
3
+
4
+ - if inline_datatable? && inline_datatable.attributes[:user_id].present?
5
+ = f.hidden_field :user_id
6
+ - else
7
+ - ajax_url = (@select2_ajax_path || effective_resources.users_admin_select2_ajax_index_path) unless Rails.env.test?
8
+ = f.select :user_id, current_user.class.all, ajax_url: ajax_url
9
+
10
+ - if inline_datatable? && inline_datatable.attributes[:cpd_cycle_id].present?
11
+ = f.hidden_field :cpd_cycle_id
12
+ - else
13
+ = f.select :cpd_cycle_id, Effective::CpdCycle.sorted.all, label: cpd_cycle_label
14
+
15
+ = f.number_field :score
16
+ = f.check_box :required_to_submit, label: 'A minimum score is required to submit'
17
+
18
+ = effective_submit(f)
@@ -1,9 +1,13 @@
1
- %h2 Statements
1
+ %h2 #{cpd_statements_label}
2
2
  - datatable = Admin::EffectiveCpdStatementsDatatable.new(user: user)
3
3
  = render_datatable(datatable, inline: true)
4
4
 
5
5
  %hr
6
6
 
7
+ %h2 #{cpd_targets_label}
8
+ = render 'admin/users/form_cpd_targets', user: user
9
+ %hr
10
+
7
11
  %h2 Activities
8
12
  - datatable = Admin::EffectiveCpdStatementActivitiesDatatable.new(user: user)
9
13
  = render_datatable(datatable, inline: true)
@@ -0,0 +1,34 @@
1
+ = effective_form_with model: [:admin, user] do |f|
2
+ = f.hidden_field :id
3
+
4
+ %p The default values are displayed as placeholders.
5
+
6
+ %table.table
7
+ %thead
8
+ %th= cpd_cycle_label
9
+ %th Target or Required #{cpd_credits_label}
10
+
11
+ %tbody
12
+ = f.fields_for :cpd_targets, f.object.build_cpd_targets do |ctf|
13
+ = ctf.hidden_field :id
14
+ = ctf.hidden_field :cpd_cycle_id
15
+ = ctf.hidden_field :user_type
16
+ = ctf.hidden_field :user_id
17
+
18
+ - collection = Effective::CpdTarget::REQUIRED_TO_SUBMIT
19
+ - cpd_cycle = ctf.object.cpd_cycle
20
+ - target = f.object.cpd_target_score(cpd_cycle: cpd_cycle)
21
+ - required_to_submit = f.object.cpd_target_score_required_to_submit?(cpd_cycle: cpd_cycle)
22
+ - required_to_submit_placeholder = collection.find { |label, value| value == required_to_submit }.first
23
+
24
+ %tr
25
+ %td= link_to(cpd_cycle, effective_cpd.edit_admin_cpd_cycle_path(cpd_cycle), target: '_blank')
26
+
27
+ %td
28
+ .row
29
+ .col
30
+ = ctf.number_field :score, label: false, required: false, placeholder: target.to_s
31
+ .col
32
+ = ctf.select :required_to_submit, Effective::CpdTarget::REQUIRED_TO_SUBMIT, label: false, placeholder: required_to_submit_placeholder.to_s
33
+
34
+ = f.save "Save #{cpd_targets_label}", 'data-confirm': "Really Save #{cpd_targets_label} for #{user}?"
@@ -62,7 +62,8 @@
62
62
 
63
63
  .mb-3
64
64
  = f.submit do
65
- = f.save 'Save Activity'
65
+ = f.save "Save"
66
+ = f.save "Save and Add Another"
66
67
 
67
68
  %div{style: 'position: absolute; left: 0;'}
68
69
  - if f.object.new_record?
@@ -35,6 +35,9 @@
35
35
  = link_to('#', 'data-cpd-edit-activity': true) do
36
36
  = icon('plus-circle', class: 'small-1')
37
37
  = statement_activity.cpd_activity
38
+ = '-'
39
+ = statement_activity.description
40
+
38
41
  - if statement_activity.is_carry_over?
39
42
  %br
40
43
  %small carried forward from #{statement_activity.original_cycle}
@@ -19,18 +19,20 @@
19
19
 
20
20
  %tr
21
21
  %td
22
- %h4= cpd_score(resource.score.to_d)
22
+ %h4= cpd_score(resource.score)
23
23
 
24
24
  %td
25
- #{cpd_credits_label} out of #{(resource.required_score || resource.targeted_score).to_d} required
25
+ #{cpd_credits_label} out of #{cpd_score(resource.target_score)}
26
+ - if resource.target_score_required_to_submit?
27
+ required
26
28
 
27
29
  %tr
28
30
  %td
29
- %h4= cpd_score(last_3_scores.to_d)
31
+ %h4= cpd_score(last_3_scores)
30
32
 
31
33
  %td #{cpd_credits_label} in last 3 #{cpd_cycles_label} (including this #{cpd_cycle_label})
32
34
 
33
35
  = cpd_cycle.sidebar_content.to_s
34
36
 
35
37
  .col-9
36
- = yield
38
+ .mb-3= yield
@@ -26,8 +26,9 @@
26
26
 
27
27
  %tr
28
28
  %th Total #{cpd_credits_label}
29
- %td= cpd_score(cpd_statement.score)
29
+ %td= cpd_score(cpd_statement.score, cpd_statement.target_score)
30
30
 
31
- %tr.carry-forward
32
- %th Carry Forward
33
- %td= cpd_score(cpd_statement.carry_forward)
31
+ - if cpd_statement.carry_forward.to_d > 0.0
32
+ %tr.carry-forward
33
+ %th Carry Forward
34
+ %td= cpd_score(cpd_statement.carry_forward)
@@ -4,7 +4,9 @@
4
4
  .col-9
5
5
  %h1= resource.cpd_cycle
6
6
 
7
- .activities-index
7
+ - activities = (params[:activities] == 'new' ? :new : :index)
8
+
9
+ .activities-index{style: ('display: none;' unless activities == :index)}
8
10
  = render('layout') do
9
11
  - if resource.cpd_cycle.all_steps_content.present?
10
12
  .mb-2= resource.cpd_cycle.all_steps_content.to_s
@@ -22,5 +24,5 @@
22
24
  = f.hidden_field :current_step
23
25
  = f.submit 'Save and Continue', center: true
24
26
 
25
- .activities-new{style: 'display: none;'}
27
+ .activities-new{style: ('display: none;' unless activities == :new)}
26
28
  = render('activities_new', cpd_statement: resource)
@@ -23,6 +23,7 @@ EffectiveCpd.setup do |config|
23
23
  config.cpd_audit_review_items_table_name = :cpd_audit_review_items
24
24
 
25
25
  config.cpd_bulk_audits_table_name = :cpd_bulk_audits
26
+ config.cpd_targets_table_name = :cpd_targets
26
27
 
27
28
  # Layout Settings
28
29
  # Configure the Layout per controller, or all at once
@@ -18,6 +18,7 @@ en:
18
18
  effective/cpd_cycle: 'CPD Period'
19
19
  effective/cpd_statement_activity: 'CPD Statement Activity'
20
20
  effective/cpd_category: 'CPD Category'
21
+ effective/cpd_target: 'CPD Target'
21
22
 
22
23
  attributes:
23
24
  # These ones might be app level
data/config/routes.rb CHANGED
@@ -36,6 +36,7 @@ EffectiveCpd::Engine.routes.draw do
36
36
  resources :cpd_cycles, except: [:show]
37
37
  resources :cpd_rules, only: [:index]
38
38
  resources :cpd_special_rules, except: [:show]
39
+ resources :cpd_targets, except: [:show]
39
40
 
40
41
  resources :cpd_statements, only: [:index, :show] do
41
42
  post :unsubmit, on: :member
@@ -6,7 +6,7 @@ class CreateEffectiveCpd < ActiveRecord::Migration[6.0]
6
6
  t.datetime :start_at
7
7
  t.datetime :end_at
8
8
 
9
- t.integer :required_score
9
+ t.boolean :required_to_submit, default: false
10
10
 
11
11
  t.datetime :updated_at
12
12
  t.datetime :created_at
@@ -324,5 +324,17 @@ class CreateEffectiveCpd < ActiveRecord::Migration[6.0]
324
324
  t.timestamps
325
325
  end
326
326
 
327
+ create_table <%= @cpd_targets_table_name %> do |t|
328
+ t.integer :user_id
329
+ t.string :user_type
330
+
331
+ t.integer :cpd_cycle_id
332
+
333
+ t.decimal :score
334
+ t.boolean :required_to_submit
335
+
336
+ t.timestamps
337
+ end
338
+
327
339
  end
328
340
  end
data/db/seeds.rb CHANGED
@@ -18,7 +18,6 @@ cycle = Effective::CpdCycle.create!(
18
18
  title: "#{now.year} Continuing Professional Development",
19
19
  start_at: now.beginning_of_year,
20
20
  end_at: now.end_of_year,
21
- required_score: 100,
22
21
  all_steps_content: "All Steps Content",
23
22
  start_content: "Start Content",
24
23
  activities_content: "Activities Content",
@@ -1,3 +1,3 @@
1
1
  module EffectiveCpd
2
- VERSION = '1.3.7'
2
+ VERSION = '1.4.1'
3
3
  end
data/lib/effective_cpd.rb CHANGED
@@ -14,6 +14,8 @@ module EffectiveCpd
14
14
  :cpd_audit_level_questions_table_name, :cpd_audit_level_question_options_table_name,
15
15
  :cpd_audits_table_name, :cpd_audit_responses_table_name, :cpd_audit_response_options_table_name,
16
16
  :cpd_audit_reviews_table_name, :cpd_audit_review_items_table_name, :cpd_bulk_audits_table_name,
17
+ :cpd_targets_table_name,
18
+
17
19
  :layout, :auditee_user_scope, :audit_reviewer_user_scope,
18
20
  :use_effective_messaging,
19
21
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates,
@@ -48,6 +48,7 @@ module EffectiveCpd
48
48
  @cpd_audit_review_items_table_name = ':' + EffectiveCpd.cpd_audit_review_items_table_name.to_s
49
49
 
50
50
  @cpd_bulk_audits_table_name = ':' + EffectiveCpd.cpd_bulk_audits_table_name.to_s
51
+ @cpd_targets_table_name = ':' + EffectiveCpd.cpd_targets_table_name.to_s
51
52
 
52
53
  migration_template ('../' * 3) + 'db/migrate/01_create_effective_cpd.rb.erb', 'db/migrate/create_effective_cpd.rb'
53
54
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_cpd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.7
4
+ version: 1.4.1
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-02-23 00:00:00.000000000 Z
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -234,6 +234,7 @@ files:
234
234
  - app/controllers/admin/cpd_special_rules_controller.rb
235
235
  - app/controllers/admin/cpd_statement_activities_controller.rb
236
236
  - app/controllers/admin/cpd_statements_controller.rb
237
+ - app/controllers/admin/cpd_targets_controller.rb
237
238
  - app/controllers/effective/cpd_audit_reviews_controller.rb
238
239
  - app/controllers/effective/cpd_audits_controller.rb
239
240
  - app/controllers/effective/cpd_cycles_controller.rb
@@ -253,6 +254,7 @@ files:
253
254
  - app/datatables/admin/effective_cpd_special_rules_datatable.rb
254
255
  - app/datatables/admin/effective_cpd_statement_activities_datatable.rb
255
256
  - app/datatables/admin/effective_cpd_statements_datatable.rb
257
+ - app/datatables/admin/effective_cpd_targets_datatable.rb
256
258
  - app/datatables/effective_cpd_available_audit_reviews_datatable.rb
257
259
  - app/datatables/effective_cpd_available_audits_datatable.rb
258
260
  - app/datatables/effective_cpd_available_cycles_datatable.rb
@@ -288,6 +290,7 @@ files:
288
290
  - app/models/effective/cpd_special_rule_mate.rb
289
291
  - app/models/effective/cpd_statement.rb
290
292
  - app/models/effective/cpd_statement_activity.rb
293
+ - app/models/effective/cpd_target.rb
291
294
  - app/views/admin/cpd_activities/_form.html.haml
292
295
  - app/views/admin/cpd_audit_level_questions/_form.html.haml
293
296
  - app/views/admin/cpd_audit_levels/_form.html.haml
@@ -324,10 +327,13 @@ files:
324
327
  - app/views/admin/cpd_cycles/_form_cpd_cycle.html.haml
325
328
  - app/views/admin/cpd_cycles/_form_cpd_rules.html.haml
326
329
  - app/views/admin/cpd_cycles/_form_cpd_special_rules.html.haml
330
+ - app/views/admin/cpd_cycles/_form_cpd_targets.html.haml
327
331
  - app/views/admin/cpd_special_rules/_form.html.haml
328
332
  - app/views/admin/cpd_statements/_cpd_statement.html.haml
333
+ - app/views/admin/cpd_targets/_form.html.haml
329
334
  - app/views/admin/users/_form_cpd.html.haml
330
335
  - app/views/admin/users/_form_cpd_audits.html.haml
336
+ - app/views/admin/users/_form_cpd_targets.html.haml
331
337
  - app/views/effective/cpd/_dashboard.html.haml
332
338
  - app/views/effective/cpd_audit_level_questions/_cpd_audit_level_question.html.haml
333
339
  - app/views/effective/cpd_audit_responses/_cpd_audit_response.html.haml