effective_cpd 1.3.6 → 1.4.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/admin/cpd_targets_controller.rb +15 -0
  3. data/app/datatables/admin/effective_cpd_cycles_datatable.rb +1 -1
  4. data/app/datatables/admin/effective_cpd_special_rules_datatable.rb +2 -3
  5. data/app/datatables/admin/effective_cpd_statements_datatable.rb +2 -4
  6. data/app/datatables/admin/effective_cpd_targets_datatable.rb +23 -0
  7. data/app/datatables/effective_cpd_available_cycles_datatable.rb +3 -4
  8. data/app/datatables/effective_cpd_completed_audits_datatable.rb +1 -1
  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_statements/_activities_table.html.haml +3 -0
  24. data/app/views/effective/cpd_statements/_layout.html.haml +6 -4
  25. data/app/views/effective/cpd_statements/_summary.html.haml +5 -4
  26. data/config/effective_cpd.rb +1 -0
  27. data/config/locales/effective_cpd.en.yml +1 -0
  28. data/config/routes.rb +1 -0
  29. data/db/migrate/01_create_effective_cpd.rb.erb +13 -1
  30. data/db/seeds.rb +0 -1
  31. data/lib/effective_cpd/version.rb +1 -1
  32. data/lib/effective_cpd.rb +2 -0
  33. data/lib/generators/effective_cpd/install_generator.rb +1 -0
  34. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d081774221fca2104ff32786f3f0728889ea43328e57ee9deb1f439097e55074
4
- data.tar.gz: db36231355f634444648f603c1072117037e33f2a12bd5389a219013d2315c23
3
+ metadata.gz: 10907aa7ee22755cd4b27d3e0fba90d6297dce95948e18c43b6e7a24f60d5f03
4
+ data.tar.gz: f2f2c72a7d1ea65c420583d7e2749dec93793b0395f4a2a4253f440c6f862f05
5
5
  SHA512:
6
- metadata.gz: ddc3a430c37807aec1207fe6aa1ee491391a75e8ba8bff7b122149ba45b723575c2f74c59ccf3553531995266a06abe41e98de6c27bce3c2b271f6ed872d9a08
7
- data.tar.gz: e0992fecce575014ee903c493ce47a3a7e91133c5a3ed9fab8e6c67c765716bbf47f43a5e5bd72402258bcef3576253efa8b8b362af31abcbfa5019095582a13
6
+ metadata.gz: 1114387c7ae09280a38b2f446456c1ae76d51647fd50b945dcf0d830f8e27b6aee44a6187f3f113b484939f5d89b59d78e1482416f9c9ba37b92e8be35b907da
7
+ data.tar.gz: 93c2ce6aa6b583bc33517291b44145a80542ac8545f6012a38ff5ed92a85fb7876a3f110d507034965b55942065113fb47fe0aa1c0994c44daf63613badd2e45
@@ -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
@@ -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|
@@ -18,7 +18,7 @@ class EffectiveCpdCompletedAuditsDatatable < Effective::Datatable
18
18
 
19
19
  collection do
20
20
  raise('expected a current_user') unless current_user.present?
21
- EffectiveCpd.CpdAudit.completed.where(user: current_user)
21
+ EffectiveCpd.CpdAudit.done.where(user: current_user)
22
22
  end
23
23
 
24
24
  end
@@ -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}?"
@@ -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)
@@ -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.6'
2
+ VERSION = '1.4.0'
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.6
4
+ version: 1.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: 2023-02-23 00:00:00.000000000 Z
11
+ date: 2023-03-02 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