openproject-service_packs 1.0.1

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +19 -0
  3. data/README.md +4 -0
  4. data/app/assets/javascripts/assigns.js +20 -0
  5. data/app/assets/javascripts/service_packs.js +17 -0
  6. data/app/assets/stylesheets/assigns.css +9 -0
  7. data/app/assets/stylesheets/service_packs.css +132 -0
  8. data/app/controllers/assigns_controller.rb +157 -0
  9. data/app/controllers/service_packs_controller.rb +219 -0
  10. data/app/helpers/service_pack_presenter.rb +39 -0
  11. data/app/helpers/service_pack_report.rb +65 -0
  12. data/app/helpers/service_packs_notification.rb +13 -0
  13. data/app/helpers/sp_assignment_manager.rb +25 -0
  14. data/app/mailers/application_mailer.rb +5 -0
  15. data/app/mailers/service_packs_mailer.rb +43 -0
  16. data/app/models/application_record.rb +3 -0
  17. data/app/models/assign.rb +13 -0
  18. data/app/models/mapping_rate.rb +14 -0
  19. data/app/models/service_pack.rb +180 -0
  20. data/app/models/service_pack_entry.rb +6 -0
  21. data/app/views/assigns/already_assigned.html.erb +14 -0
  22. data/app/views/assigns/not_assigned_yet.html.erb +19 -0
  23. data/app/views/assigns/unassignable.html.erb +4 -0
  24. data/app/views/layouts/mailer.html.erb +13 -0
  25. data/app/views/layouts/mailer.text.erb +1 -0
  26. data/app/views/service_packs/_active_assignments.html.erb +14 -0
  27. data/app/views/service_packs/_form.html.erb +80 -0
  28. data/app/views/service_packs/_rates_input.html.erb +15 -0
  29. data/app/views/service_packs/edit.html.erb +75 -0
  30. data/app/views/service_packs/index.html.erb +33 -0
  31. data/app/views/service_packs/new.html.erb +6 -0
  32. data/app/views/service_packs/show.html.erb +48 -0
  33. data/app/views/service_packs_mailer/expired_email.html.erb +1 -0
  34. data/app/views/service_packs_mailer/expired_email.text.erb +1 -0
  35. data/app/views/service_packs_mailer/notify_under_threshold1.html.erb +2 -0
  36. data/app/views/service_packs_mailer/notify_under_threshold1.text.erb +1 -0
  37. data/app/views/service_packs_mailer/notify_under_threshold2.html.erb +2 -0
  38. data/app/views/service_packs_mailer/notify_under_threshold2.text.erb +1 -0
  39. data/app/views/service_packs_mailer/used_up_email.html.erb +14 -0
  40. data/app/views/service_packs_mailer/used_up_email.text.erb +1 -0
  41. data/app/workers/expired_sp_worker.rb +11 -0
  42. data/app/workers/used_up_service_pack_job.rb +13 -0
  43. data/config/application.rb +4 -0
  44. data/config/routes.rb +13 -0
  45. data/config/schedule.example.rb +27 -0
  46. data/config/schedule.rb +28 -0
  47. data/config/sidekiq.yml +4 -0
  48. data/db/migrate/20190108031704_create_assigns.rb +11 -0
  49. data/db/migrate/20190108031712_create_service_packs.rb +14 -0
  50. data/db/migrate/20190108111243_create_mapping_rates.rb +11 -0
  51. data/db/migrate/20190113111300_rename_assign.rb +6 -0
  52. data/db/migrate/20190116085528_create_service_pack_entries.rb +9 -0
  53. data/db/migrate/20190121072000_final_assigns_table.rb +5 -0
  54. data/db/migrate/20190123150023_add_service_pack_ref_to_service_pack_entries.rb +5 -0
  55. data/db/migrate/20190123205130_feature_a_done.rb +16 -0
  56. data/db/migrate/20190301070654_change_units_of_service_pack_entries.rb +5 -0
  57. data/db/migrate/20190301071911_change_total_and_remained_units_of_service_pack.rb +6 -0
  58. data/lib/open_project/service_packs.rb +5 -0
  59. data/lib/open_project/service_packs/engine.rb +50 -0
  60. data/lib/open_project/service_packs/patches.rb +4 -0
  61. data/lib/open_project/service_packs/patches/enumeration_patch.rb +37 -0
  62. data/lib/open_project/service_packs/patches/project_patch.rb +14 -0
  63. data/lib/open_project/service_packs/patches/time_entry_activity_patch.rb +16 -0
  64. data/lib/open_project/service_packs/patches/time_entry_patch.rb +89 -0
  65. data/lib/open_project/service_packs/version.rb +5 -0
  66. data/lib/openproject-service_packs.rb +1 -0
  67. metadata +121 -0
@@ -0,0 +1,4 @@
1
+ <div id='sp-assign'>
2
+ <h2>No Service Pack is assigned to this project.</h2><br/>
3
+ <h3>No Service Pack can be assigned.</h3>
4
+ </div>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
+ <style>
6
+ /* Email styles need to be inline */
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <%= yield %>
12
+ </body>
13
+ </html>
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,14 @@
1
+ <% unless @assignments.empty? %>
2
+ <p id='assignments-box'>
3
+ This Service Pack has been assigned for <%= @assignments.count>1? -'these projects:' : -'this project:' %>
4
+ </p>
5
+ <ul>
6
+ <% @assignments.each do |assignment| %>
7
+ <li><%= link_to assignment.project.name, project_path(assignment.project) %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% else %>
11
+ <p>
12
+ This Service Pack is not being assigned to any projects.
13
+ </p>
14
+ <% end %>
@@ -0,0 +1,80 @@
1
+ <%= form_for @service_pack, url: service_packs_path, local: true do |form| %>
2
+
3
+ <% if @service_pack.errors.any? %>
4
+ <div id="error-explanation">
5
+ <h2>
6
+ <%= pluralize(@service_pack.errors.count, -'error') %> prohibited
7
+ this service pack from being saved:
8
+ </h2>
9
+ <ul>
10
+ <% @service_pack.errors.full_messages.each do |msg| %>
11
+ <li><%= msg %></li>
12
+ <% end %>
13
+ </ul>
14
+ </div>
15
+ <% end %>
16
+
17
+ <div class="form--field">
18
+ <%= form.label :name, class: 'form--label', title: -'The name of this service pack' %>
19
+ <span class="form--field-container">
20
+ <span class="form--text-field-container -slim">
21
+ <%= form.text_field :name, required: true, container_class: -'-slim' %>
22
+ </span>
23
+ </span>
24
+ </div>
25
+
26
+ <div class="form--field">
27
+ <%= form.label :total_units, class: 'form--label', title: 'The total units of this service pack' %>
28
+ <span class="form--field-container">
29
+ <span class="form--text-field-container -slim">
30
+ <%= form.number_field :total_units, step: 'any', required: true %>
31
+ </span>
32
+ </span>
33
+ </div>
34
+
35
+ <div class="form--field">
36
+ <%= form.label :started_date, class: 'form--label', title: 'The date this service pack activate' %>
37
+ <span class="form--field-container">
38
+ <span class="form--text-field-container -slim">
39
+ <%= form.date_field :started_date, required: true %>
40
+ </span>
41
+ </span>
42
+ </div>
43
+
44
+ <div class="form--field">
45
+ <%= form.label :expired_date, class: 'form--label', title: 'The date this service pack expires' %>
46
+ <span class="form--field-container">
47
+ <span class="form--text-field-container -slim">
48
+ <%= form.date_field :expired_date, required: true %>
49
+ </span>
50
+ </span>
51
+ </div>
52
+
53
+ <div class="form--field">
54
+ <%= form.label :threshold_1, class: 'form--label', title: 'Notification will be sent when the available units below' %>
55
+ <span class="form--field-container">
56
+ <span class="form--text-field-container -slim">
57
+ <%= form.number_field :threshold1, required: true, placeholder: 'In units' %>
58
+ </span>
59
+ </span>
60
+ </div>
61
+
62
+ <div class="form--field">
63
+ <%= form.label :threshold_2, class: 'form--label', title: 'Notification will be sent when the available units below' %>
64
+ <span class="form--field-container">
65
+ <span class="form--text-field-container -slim">
66
+ <%= form.number_field :threshold2, required: true, placeholder: 'In units' %>
67
+ </span>
68
+ </span>
69
+ </div>
70
+
71
+ <hr>
72
+
73
+ <%= render partial: -'rates_input' %>
74
+
75
+ <div class="button-container">
76
+ <%= form.submit class: -'-highlight -with-icon icon-checkmark button' %>
77
+ <%#= link_to "Back", service_packs_path, class: "button -alt-highlight" %>
78
+ </div>
79
+
80
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <div id="rates-input">
2
+ <table id="table-rates-input">
3
+ <tr>
4
+ <th>Activity</td>
5
+ <th>Rate</td>
6
+ </tr>
7
+ <% (1..@c).each do |i| %>
8
+ <tr>
9
+ <td><label><%= @sh[i - 1].name %>: </label></td>
10
+ <td><input type='number' name="service_pack[mapping_rates_attributes][<%= i %>][units_per_hour]" min='0' class='rates' placeholder='Units per hour' required></td>
11
+ <span><input type='hidden' name="service_pack[mapping_rates_attributes][<%= i %>][activity_id]" value="<%= @sh[i - 1].id %>"/></span>
12
+ </tr>
13
+ <% end %>
14
+ </table>
15
+ </div>
@@ -0,0 +1,75 @@
1
+ <%= stylesheet_link_tag -'service_packs', plugin: :openproject_service_packs %>
2
+
3
+ <% local_assigns[:additional_breadcrumb] = @sp.name %>
4
+ <% html_title l(:label_administration), -'Edit Service Pack' %>
5
+
6
+ <h2> <%= @sp.name %> </h2>
7
+
8
+ <%= form_for @sp, local: true do |form| %>
9
+
10
+ <% if @sp.errors.any? %>
11
+ <div id="error-explanation">
12
+ <h2>
13
+ <%= pluralize(@sp.errors.count, -"error") %> prohibited this service pack from being saved:
14
+ </h2>
15
+ <ul>
16
+ <% @sp.errors.full_messages.each do |e| %>
17
+ <li><%= e %></li>
18
+ <% end %>
19
+ </ul>
20
+ </div>
21
+ <% end %>
22
+
23
+ <div class="form--field">
24
+ <%= form.label :total_units, class: "form--label" %>
25
+ <span class="form--field-container">
26
+ <span class="form--text-field-container -slim">
27
+ <%= form.number_field :total_units, placeholder: 'must not below zero' %>
28
+ </span>
29
+ </span>
30
+ </div>
31
+ <div class="form--field">
32
+ <%= form.label :threshold1, class: "form--label" %>
33
+ <span class="form--field-container">
34
+ <span class="form--text-field-container -slim">
35
+ <%= form.number_field :threshold1, placeholder: 'Threshold 1' %>
36
+ </span>
37
+ </span>
38
+ </div>
39
+
40
+ <div class="form--field">
41
+ <%= form.label :threshold2, class: "form--label" %>
42
+ <span class="form--field-container">
43
+ <span class="form--text-field-container -slim">
44
+ <%= form.number_field :threshold2, placeholder: 'Threshold 2' %>
45
+ </span>
46
+ </span>
47
+ </div>
48
+
49
+ <hr>
50
+
51
+ <div id="rates-input">
52
+ <table id="table-rates-input">
53
+ <tr>
54
+ <th>Activity</th>
55
+ <th>Rate</th>
56
+ </tr>
57
+ <%= form.fields_for :mapping_rates do |rates_form| %>
58
+ <tr>
59
+ <td><%= rates_form.label "#{rates_form.object.activity.name}:" %></td>
60
+ <td><%= rates_form.number_field :units_per_hour, placeholder: -'Units per hour', class: -'rates', min: -'0', step: -'any', required: true %></td>
61
+ <span><%= rates_form.hidden_field :activity_id %></span>
62
+ </tr>
63
+ <% end %>
64
+ </table>
65
+ </div>
66
+
67
+ <div class="button-container">
68
+ <%= form.submit '&#x2714 Update'.html_safe, class: 'button -highlight' %>
69
+ </div>
70
+
71
+ <% end %>
72
+
73
+ </body>
74
+ </html>
75
+
@@ -0,0 +1,33 @@
1
+ <%= stylesheet_link_tag -'service_packs', plugin: :openproject_service_packs %>
2
+
3
+ <% html_title l(:label_administration), -'Service Packs' %>
4
+
5
+ <%= link_to -'New', new_service_pack_path, class: -"button -alt-highlight float-right" %>
6
+
7
+ <table>
8
+
9
+ <tr>
10
+ <th>Name</th>
11
+ <th>Total Units</th>
12
+ <th>Remained Units</th>
13
+ <th>Started Date</th>
14
+ <th>Expired Date</th>
15
+ <th>Threshold 1</th>
16
+ <th>Threshold 2</th>
17
+ <th>Assigned</th>
18
+ </tr>
19
+
20
+ <% @service_packs.each do |sp| %>
21
+ <tr>
22
+ <td><%= link_to sp.name, service_pack_path(sp) %></td>
23
+ <td><%= sp.total_units %></td>
24
+ <td><%= sp.remained_units %></td>
25
+ <td><%= sp.started_date %></td>
26
+ <td><%= sp.expired_date %></td>
27
+ <td><%= sp.threshold1 %></td>
28
+ <td><%= sp.threshold2 %></td>
29
+ <td><%= (sp.assigned? ? -'&#x2714' : -'').html_safe %></td>
30
+ </tr>
31
+ <% end %>
32
+
33
+ </table>
@@ -0,0 +1,6 @@
1
+ <%= stylesheet_link_tag -'service_packs', plugin: :openproject_service_packs %>
2
+
3
+ <% html_title l(:label_administration), -'Create Service Pack' %>
4
+ <% local_assigns[:additional_breadcrumb] = -'Create Service Pack' %>
5
+
6
+ <%= render -'form' %>
@@ -0,0 +1,48 @@
1
+ <%= javascript_include_tag 'service_packs.js', plugin: :openproject_service_packs %>
2
+ <%= stylesheet_link_tag 'service_packs', plugin: :openproject_service_packs %>
3
+
4
+ <% local_assigns[:additional_breadcrumb] = @service_pack.name %>
5
+ <% html_title l(:label_administration), @service_pack.name %>
6
+
7
+ <section id="detailed-sp">
8
+ <div id="block-left">
9
+ <div class="sp description">
10
+ <h2>Description</h2>
11
+ Name: <%= @service_pack.name %><br/>
12
+ Total units: <%= @service_pack.total_units %><br/>
13
+ Remain units: <%= @service_pack.remained_units %><br/>
14
+ Started date: <%= @service_pack.started_date %><br/>
15
+ Expired date: <%= @service_pack.expired_date %><br/>
16
+ Threshold 1: <%= pluralize(@service_pack.threshold1, 'unit', 'units') %> <br/>
17
+ Threshold 2: <%= pluralize(@service_pack.threshold2, 'unit', 'units') %><br/>
18
+ </div>
19
+ <div class="sp assigned">
20
+ <%= render partial: -'active_assignments' %>
21
+ </div>
22
+ </div>
23
+
24
+ <div id="block-right">
25
+ <div class="sp rates">
26
+ <h2>Rates</h2>
27
+ <ul>
28
+ <% @rates.each do |rate| %>
29
+ <li> <%= rate.activity.name %>: <%= pluralize(rate.units_per_hour, -'unit') %>/hour</li>
30
+ <% end %>
31
+ </ul>
32
+ </div>
33
+ </div>
34
+ </section>
35
+
36
+ <div class='button-container clearfix'>
37
+ <%#= link_to -'Back to Service Pack home page', service_packs_path, class: -'button float-left' %>
38
+
39
+ <% if @service_pack.assigned? %>
40
+ <%= link_to -'Delete', -'#', class: -'button destroy blocked float-right', disabled: true, :title => "Please unassign this service pack from all projects before deleting!" %>
41
+ <% else %>
42
+ <%= link_to 'Delete', service_pack_path(@service_pack), class: -'button destroy float-right', method: :delete, data: {confirm: -'Are you sure?', disable_with: -'Deleting...'} %>
43
+ <% end %>
44
+ <%= link_to -'Edit', edit_service_pack_path(@service_pack), class: -'button -alt-highlight float-right' %>
45
+ </div>
46
+
47
+ <hr/>
48
+ <p class='other-formats'>Report available in: <%= link_to -'CSV', {action: :show, format: :csv} %></p>
@@ -0,0 +1 @@
1
+ <h1>Service pack <%= @sp.name %> expired.</h1>
@@ -0,0 +1 @@
1
+ the service pack <%= @sp.name %> expired!
@@ -0,0 +1,2 @@
1
+ <h3>Hi <%= @user.firstname %> <%= @user.lastname %></h3>
2
+ <p>The service pack <%= @sp.name %> applied on your projects now only has <%= @sp.remained_units %> units left</p>
@@ -0,0 +1 @@
1
+ Hi <%= @user.firstname %> <%= @user.lastname %>,the service pack <%= @sp.name %> applied on your projects now only has <%= @sp.remained_units %> units left.
@@ -0,0 +1,2 @@
1
+ <h3>Hi <%= @user.firstname %> <%= @user.lastname %></h3>
2
+ <p>The service pack <%= @sp.name %> applied on your projects now only has <%= @sp.remained_units %> units left</p>
@@ -0,0 +1 @@
1
+ Hi <%= @user.firstname %> <%= @user.lastname %>,the service pack <%= @sp.name %> applied on your projects now only has <%= @sp.remained_units %> units left.
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
+ <title>service pack units ran out</title>
8
+ </head>
9
+ <body>
10
+
11
+ <p>The service pack <%= @sp.name %> has no units left!</p>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1 @@
1
+ The service pack <%= @sp.name %> has no units left!
@@ -0,0 +1,11 @@
1
+ require 'sidekiq-scheduler'
2
+
3
+ class ExpiredSpWorker
4
+ include Sidekiq::Worker
5
+
6
+ def perform
7
+ expired_sp_s = ServicePack.expired
8
+ return if expired_sp_s.count.zero?
9
+ ServicePacksMailer.expired_email(ServicePack.expired)
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class UsedUpServicePackJob < ApplicationJob
2
+ attr_reader :sp
3
+
4
+ def initialize(sp)
5
+ @sp = sp
6
+ end
7
+
8
+ def perform
9
+ User.where(admin: true).each do |user|
10
+ ServicePacksMailer.used_up_email(user, @sp).deliver_now
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ class Application < Rails::Application
2
+ # ...
3
+ config.active_job.queue_adapter = :sidekiq
4
+ end
@@ -0,0 +1,13 @@
1
+ OpenProject::Application.routes.draw do
2
+ resources :service_packs do
3
+ get '/statistics', to: 'service_packs#statistics', constraints: lambda { |req| req.format == :json }
4
+ end
5
+ scope "/projects/:project_id" do
6
+ get '/assigns', to: 'assigns#show'
7
+ get '/assigns/report', to: 'assigns#report'
8
+ post '/assigns/assign', to: 'assigns#assign'
9
+ post '/assigns/unassign', to: 'assigns#unassign'
10
+ get '/assigns/statistics', to: 'assigns#statistics', constraints: lambda { |req| req.format == :json }
11
+ get '/assigns/:assignment_id/transfer', to: 'assigns#select_to_transfer', as: 'sp_transfer'
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # Use this file to easily define all of your cron jobs.
2
+ #
3
+ # It's helpful, but not entirely necessary to understand cron before proceeding.
4
+ # http://en.wikipedia.org/wiki/Cron
5
+
6
+ # Example:
7
+ #
8
+ # set :output, "/path/to/my/cron_log.log"
9
+ #
10
+ # every 2.hours do
11
+ # command "/usr/bin/some_great_command"
12
+ # runner "MyModel.some_method"
13
+ # rake "some:great:rake:task"
14
+ # end
15
+ #
16
+ # every 4.days do
17
+ # runner "AnotherModel.prune_old_records"
18
+ # end
19
+
20
+ # Learn more: http://github.com/javan/whenever
21
+
22
+
23
+ job_type :runner, "cd :openproject_path && export OPENPROJECT_ROOT=:openproject_path && rails runner -e :environment ':task'"
24
+
25
+ every 5.minutes do
26
+ runner 'ServicePack.cron_send_default', environment: 'development', openproject_path: PUT_OPENPROJECT_ROOT_DIR_HERE
27
+ end
@@ -0,0 +1,28 @@
1
+ # Use this file to easily define all of your cron jobs.
2
+ #
3
+ # It's helpful, but not entirely necessary to understand cron before proceeding.
4
+ # http://en.wikipedia.org/wiki/Cron
5
+
6
+ # Example:
7
+ #
8
+ # set :output, "/path/to/my/cron_log.log"
9
+ #
10
+ # every 2.hours do
11
+ # command "/usr/bin/some_great_command"
12
+ # runner "MyModel.some_method"
13
+ # rake "some:great:rake:task"
14
+ # end
15
+ #
16
+ # every 4.days do
17
+ # runner "AnotherModel.prune_old_records"
18
+ # end
19
+
20
+ # Learn more: http://github.com/javan/whenever
21
+
22
+
23
+ job_type :runner, "cd :openproject_path && export OPENPROJECT_ROOT=:openproject_path && rails runner -e :environment ':task'"
24
+
25
+ every 10.seconds do
26
+ #runner 'ServicePack.check_expired_sp', environment: 'development', openproject_path: '~/Desktop/openproject'
27
+ runner 'ServicePack.check_used_up', environment: 'development', openproject_path: '~/Desktop/openproject'
28
+ end