hackathon_manager 0.5.11 → 0.6.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/hackathon_manager/manage/lib/setupDataTables.js +1 -0
- data/app/assets/stylesheets/hackathon_manager/general/_main.sass +3 -0
- data/app/controllers/manage/messages_controller.rb +1 -1
- data/app/datatables/message_datatable.rb +2 -0
- data/app/models/message.rb +55 -20
- data/app/models/message_recipient_query.rb +61 -0
- data/app/models/questionnaire.rb +10 -0
- data/app/views/application/_triggered_email_summary.html.haml +27 -0
- data/app/views/manage/bus_lists/_form.html.haml +13 -12
- data/app/views/manage/messages/_form.html.haml +15 -13
- data/app/views/manage/messages/edit.html.haml +2 -1
- data/app/views/manage/messages/index.html.haml +8 -3
- data/app/views/manage/messages/show.html.haml +29 -16
- data/app/views/manage/questionnaires/index.html.haml +16 -5
- data/app/views/manage/questionnaires/show.html.haml +1 -1
- data/app/workers/bulk_message_worker.rb +28 -34
- data/db/migrate/20180108231420_add_trigger_to_message.rb +5 -0
- data/db/migrate/20180118035548_convert_message_recipients_to_recipient_queries.rb +36 -0
- data/lib/hackathon_manager/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b2b4e0940990bd9d79779dc11df2261481e953a
|
4
|
+
data.tar.gz: 231e89a71e42dd25ed692d41c2bf285dbee54962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eeb9342f9cd545f46932c0330154888d8cc549f26199b19d5c96f31a47d4503ba801aadf4913d6e2908ff947841ddb39158306aa0eda9b3dca2bdb572774542a
|
7
|
+
data.tar.gz: c17ae7672d988fe083cce647d3c1e4e0edb4005961a433ab803d0d7f9af8f6adfdca2a260a7390a2b432e19a9f6b7d8d6243cc81666180c35425acd999f40bea
|
@@ -72,6 +72,7 @@ var setupDataTables = function() {
|
|
72
72
|
{ orderable: true, data: 'id'},
|
73
73
|
{ orderable: true, data: 'name'},
|
74
74
|
{ orderable: true, data: 'subject'},
|
75
|
+
{ orderable: true, data: 'trigger'},
|
75
76
|
{ orderable: false, data: 'status'},
|
76
77
|
{ orderable: true, data: 'delivered_at'}
|
77
78
|
]
|
@@ -6,6 +6,7 @@ class MessageDatatable < AjaxDatatablesRails::Base
|
|
6
6
|
id: { source: "Message.id" },
|
7
7
|
name: { source: "Message.name" },
|
8
8
|
subject: { source: "Message.subject" },
|
9
|
+
trigger: { source: "Message.trigger" },
|
9
10
|
delivered_at: { source: "Message.delivered_at", searchable: false }
|
10
11
|
}
|
11
12
|
end
|
@@ -19,6 +20,7 @@ class MessageDatatable < AjaxDatatablesRails::Base
|
|
19
20
|
id: record.id,
|
20
21
|
name: record.name,
|
21
22
|
subject: record.subject,
|
23
|
+
trigger: Message::POSSIBLE_TRIGGERS[record.trigger],
|
22
24
|
status: record.status.titleize,
|
23
25
|
delivered_at: record.delivered_at.present? ? record.delivered_at.strftime("%B %d, %Y at %I:%M %p") : ''
|
24
26
|
}
|
data/app/models/message.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
class Message < ApplicationRecord
|
2
|
-
validates_presence_of :name, :subject, :
|
2
|
+
validates_presence_of :name, :subject, :template
|
3
3
|
validates_presence_of :body, if: :using_default_template?
|
4
4
|
|
5
5
|
strip_attributes
|
6
6
|
|
7
7
|
POSSIBLE_TEMPLATES = ["default"].freeze
|
8
8
|
|
9
|
-
|
9
|
+
POSSIBLE_SIMPLE_RECIPIENTS = {
|
10
10
|
"all" => "Everyone",
|
11
11
|
"incomplete" => "Incomplete Applications",
|
12
12
|
"complete" => "Complete Applications",
|
@@ -19,23 +19,18 @@ class Message < ApplicationRecord
|
|
19
19
|
"checked-in" => "Checked-In Attendees",
|
20
20
|
"non-checked-in" => "Non-Checked-In, Accepted & RSVP'd Applications",
|
21
21
|
"non-checked-in-excluding" => "Non-Checked-In Applications, Excluding Accepted & RSVP'd",
|
22
|
-
"bus-list-cornell-bing" => "Bus List: Cornell + Binghamton (Confirmed)",
|
23
|
-
"bus-list-buffalo" => "Bus List: Buffalo (Confirmed)",
|
24
|
-
"bus-list-albany" => "Bus List: Albany (Confirmed)",
|
25
|
-
"bus-list-cornell-bing-eligible" => "Bus List: Cornell + Binghamton (eligible, not signed up)",
|
26
|
-
"bus-list-buffalo-eligible" => "Bus List: Buffalo (eligible, not signed up)",
|
27
|
-
"bus-list-albany-eligible" => "Bus List: Albany (eligible, not signed up)",
|
28
|
-
"bus-list-cornell-bing-applied" => "Bus List: Cornell + Binghamton (applied/not accepted)",
|
29
|
-
"bus-list-buffalo-applied" => "Bus List: Buffalo (applied/not accepted)",
|
30
|
-
"bus-list-albany-applied" => "Bus List: Albany (applied/not accepted)",
|
31
|
-
"school-rit" => "Confirmed or accepted: RIT",
|
32
|
-
"school-cornell" => "Confirmed or accepted: Cornell",
|
33
|
-
"school-binghamton" => "Confirmed or accepted: Binghamton",
|
34
|
-
"school-buffalo" => "Confirmed or accepted: Buffalo",
|
35
|
-
"school-waterloo" => "Confirmed or accepted: Waterloo",
|
36
|
-
"school-toronto" => "Confirmed or accepted: Toronto",
|
37
|
-
"school-umd-collegepark" => "Confirmed or accepted: UMD College Park"
|
38
22
|
}.freeze
|
23
|
+
|
24
|
+
POSSIBLE_TRIGGERS = {
|
25
|
+
"questionnaire.pending" => "Questionnaire Status: Pending Review (new application)",
|
26
|
+
"questionnaire.accepted" => "Questionnaire Status: Accepted",
|
27
|
+
"questionnaire.waitlist" => "Questionnaire Status: Waitlisted",
|
28
|
+
"questionnaire.denied" => "Questionnaire Status: Denied",
|
29
|
+
"questionnaire.late_waitlist" => "Questionnaire Status: Waitlisted, Late",
|
30
|
+
"questionnaire.rsvp_confirmed" => "Questionnaire Status: RSVP Confirmed",
|
31
|
+
"questionnaire.rsvp_denied" => "Questionnaire Status: RSVP Denied"
|
32
|
+
}.freeze
|
33
|
+
|
39
34
|
serialize :recipients, Array
|
40
35
|
|
41
36
|
validates_inclusion_of :template, in: POSSIBLE_TEMPLATES
|
@@ -45,7 +40,16 @@ class Message < ApplicationRecord
|
|
45
40
|
end
|
46
41
|
|
47
42
|
def recipients_list
|
48
|
-
recipients.map
|
43
|
+
labels = recipients.map do |r|
|
44
|
+
if POSSIBLE_SIMPLE_RECIPIENTS.include?(r)
|
45
|
+
POSSIBLE_SIMPLE_RECIPIENTS[r]
|
46
|
+
elsif r =~ /(.*)::(\d*)/
|
47
|
+
MessageRecipientQuery.friendly_name(r)
|
48
|
+
else
|
49
|
+
"(unknown)"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
labels.join(', ')
|
49
53
|
end
|
50
54
|
|
51
55
|
def delivered?
|
@@ -68,10 +72,41 @@ class Message < ApplicationRecord
|
|
68
72
|
end
|
69
73
|
|
70
74
|
def can_edit?
|
71
|
-
status == "drafted"
|
75
|
+
status == "drafted" || trigger.present?
|
72
76
|
end
|
73
77
|
|
74
78
|
def using_default_template?
|
75
79
|
template == "default"
|
76
80
|
end
|
81
|
+
|
82
|
+
def self.possible_recipients
|
83
|
+
# Produce an array like:
|
84
|
+
# ["School: My University", "school::123"]
|
85
|
+
option = ->(query, model) { [MessageRecipientQuery.friendly_name(query, model), query] }
|
86
|
+
bus_list_recipients = BusList.select(:id, :name).map do |bus_list|
|
87
|
+
[
|
88
|
+
option.call("bus-list::#{bus_list.id}", bus_list),
|
89
|
+
option.call("bus-list--eligible::#{bus_list.id}", bus_list),
|
90
|
+
option.call("bus-list--applied::#{bus_list.id}", bus_list)
|
91
|
+
]
|
92
|
+
end
|
93
|
+
bus_list_recipients.flatten!(1) # Required since we have multiple options for each bus list
|
94
|
+
|
95
|
+
school_recipients = School.select(:id, :name).map do |school|
|
96
|
+
option.call("school::#{school.id}", school)
|
97
|
+
end
|
98
|
+
# No flatten needed here since each map returns a single option
|
99
|
+
|
100
|
+
# Combine all recipients. push(*recipients) is the most efficient,
|
101
|
+
# as it doesn't create a new array each time (concat() does)
|
102
|
+
recipients = POSSIBLE_SIMPLE_RECIPIENTS.invert.to_a
|
103
|
+
recipients.push(*bus_list_recipients)
|
104
|
+
recipients.push(*school_recipients)
|
105
|
+
recipients
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.queue_for_trigger(trigger, user_id)
|
109
|
+
messages_to_queue = Message.where(trigger: trigger)
|
110
|
+
messages_to_queue.map { |message| Mailer.delay.bulk_message_email(message.id, user_id) }
|
111
|
+
end
|
77
112
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class MessageRecipientQuery
|
2
|
+
attr_accessor :query
|
3
|
+
attr_accessor :type
|
4
|
+
attr_accessor :id
|
5
|
+
attr_accessor :model
|
6
|
+
|
7
|
+
def initialize(query, type, id, model)
|
8
|
+
@query = query
|
9
|
+
@type = type
|
10
|
+
@id = id
|
11
|
+
@model = model
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse(query, model = nil)
|
15
|
+
# Format:
|
16
|
+
# model::ID
|
17
|
+
# model--modifier::ID
|
18
|
+
match = query.match(/(.*)::(\d*)/)
|
19
|
+
type = match[1]
|
20
|
+
id = match[2]
|
21
|
+
|
22
|
+
# Find the backing database model, ensuring the given ID exists for that model.
|
23
|
+
model_name = nil
|
24
|
+
case type
|
25
|
+
when "bus-list", "bus-list--applied", "bus-list--eligible"
|
26
|
+
model ||= BusList.find_by_id(id)
|
27
|
+
model_name = "Bus List"
|
28
|
+
when "school"
|
29
|
+
model ||= School.find_by_id(id)
|
30
|
+
model_name = "School"
|
31
|
+
else
|
32
|
+
raise "Unknown recipient query type: #{type.inspect} (in message recipient query: #{query.inspect}"
|
33
|
+
end
|
34
|
+
raise "Could not find #{model_name} with ID #{id.inspect} (in message recipient query: #{query.inspect}" if model.blank?
|
35
|
+
|
36
|
+
MessageRecipientQuery.new(
|
37
|
+
query,
|
38
|
+
type,
|
39
|
+
id,
|
40
|
+
model
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.friendly_name(query, model = nil)
|
45
|
+
recipient_query = parse(query, model)
|
46
|
+
model = recipient_query.model
|
47
|
+
|
48
|
+
case recipient_query.type
|
49
|
+
when "bus-list"
|
50
|
+
"Bus List: #{model.name} (signed up for bus)"
|
51
|
+
when "bus-list--eligible"
|
52
|
+
"Bus List: #{model.name} (eligible, not signed up for bus)"
|
53
|
+
when "bus-list--applied"
|
54
|
+
"Bus List: #{model.name} (applied/not accepted)"
|
55
|
+
when "school"
|
56
|
+
"Confirmed or Accepted: #{model.name}"
|
57
|
+
else
|
58
|
+
raise "Unknown recipient query type: #{recipient_query.type.inspect} (in message recipient query: #{r.inspect}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/app/models/questionnaire.rb
CHANGED
@@ -2,6 +2,8 @@ class Questionnaire < ApplicationRecord
|
|
2
2
|
include ActiveModel::Dirty
|
3
3
|
|
4
4
|
before_validation :consolidate_school_names
|
5
|
+
after_create :queue_triggered_email_create
|
6
|
+
after_update :queue_triggered_email_update
|
5
7
|
after_save :update_school_questionnaire_count
|
6
8
|
after_destroy :update_school_questionnaire_count
|
7
9
|
|
@@ -181,4 +183,12 @@ class Questionnaire < ApplicationRecord
|
|
181
183
|
School.increment_counter(:questionnaire_count, school_id)
|
182
184
|
end
|
183
185
|
end
|
186
|
+
|
187
|
+
def queue_triggered_email_update
|
188
|
+
Message.queue_for_trigger("questionnaire.#{acc_status}", id) if saved_change_to_acc_status?
|
189
|
+
end
|
190
|
+
|
191
|
+
def queue_triggered_email_create
|
192
|
+
Message.queue_for_trigger("questionnaire.#{acc_status}", id)
|
193
|
+
end
|
184
194
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
%h3.no-margin Triggered Email Overview
|
2
|
+
%p
|
3
|
+
Recipient updates that match a given event will be sent the corresponding email(s) automatically.
|
4
|
+
%br
|
5
|
+
For example, when a user moves from the "Accepted" to "RSVP Confirmed" state, the user will be sent an email for the "RSVP Confirmed" event.
|
6
|
+
%p Hard-coded emails are those managed in the source code repository, and cannot be disabled.
|
7
|
+
|
8
|
+
%table.table
|
9
|
+
%thead
|
10
|
+
%tr
|
11
|
+
%th Trigger Event
|
12
|
+
%th Hard-coded Email
|
13
|
+
%th Triggered Emails
|
14
|
+
%tbody
|
15
|
+
- Message::POSSIBLE_TRIGGERS.keys.each do |trigger|
|
16
|
+
%tr
|
17
|
+
%td= Message::POSSIBLE_TRIGGERS[trigger]
|
18
|
+
- messages = Message.where(trigger: trigger).all
|
19
|
+
%td
|
20
|
+
= ['questionnaire.pending', 'questionnaire.accepted', 'questionnaire.denied', 'questionnaire.rsvp_confirmed'].include?(trigger) ? '<strong>Yes</strong>'.html_safe : 'No'
|
21
|
+
%td
|
22
|
+
- if messages.present?
|
23
|
+
%ul.no-margin
|
24
|
+
- messages.each do |message|
|
25
|
+
%li= link_to(message.name, manage_message_path(message))
|
26
|
+
- else
|
27
|
+
None
|
@@ -1,14 +1,15 @@
|
|
1
|
-
|
2
|
-
= f
|
1
|
+
.form-container
|
2
|
+
= simple_form_for(@bus_list, url: url_for(action: @bus_list.new_record? ? "create" : "update", controller: "bus_lists")) do |f|
|
3
|
+
= f.error_notification
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
.form-inputs
|
6
|
+
= f.input :name
|
7
|
+
= f.input :capacity
|
8
|
+
= f.input :needs_bus_captain
|
9
|
+
= f.input :notes, input_html: { rows: 10 }
|
10
|
+
%p
|
11
|
+
%small
|
12
|
+
%em Notes support Markdown and HTML.
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
.form-actions
|
15
|
+
= f.button :submit
|
@@ -1,15 +1,17 @@
|
|
1
|
-
|
2
|
-
= f
|
1
|
+
.form-container
|
2
|
+
= simple_form_for @message, url: url_for(action: @message.new_record? ? "create" : "update", controller: "messages") do |f|
|
3
|
+
= f.error_notification
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
.form-inputs
|
6
|
+
= f.input :name
|
7
|
+
= f.input :subject, hint: "All emails are from <pre>#{html_escape(Rails.configuration.hackathon['email_from'])}</pre>".html_safe
|
8
|
+
= f.input :template, as: :select, collection: Message::POSSIBLE_TEMPLATES.map { |x| [x.titleize, x] }, include_blank: false
|
9
|
+
- if @message.status == "drafted"
|
10
|
+
= f.input :recipients, as: :select, collection: Message.possible_recipients, input_html: { class: "selectize", multiple: true, }, hint: "Sent manually, in bulk", placeholder: "Type to search by school or type..."
|
11
|
+
- else
|
12
|
+
= f.input :recipients, as: :select, collection: Message.possible_recipients, input_html: { class: "selectize", multiple: true }, hint: "Cannot be edited once a message has been delivered", disabled: true
|
13
|
+
= f.input :trigger, as: :select, collection: Message::POSSIBLE_TRIGGERS.invert, include_blank: "(no automatic trigger)", hint: "Sent automatically, to an individual applicant"
|
14
|
+
= f.input :body, input_html: { rows: 10 }, hint: "Supports markdown and HTML"
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
.form-actions
|
17
|
+
= f.button :submit
|
@@ -8,11 +8,16 @@
|
|
8
8
|
%th ID
|
9
9
|
%th Name
|
10
10
|
%th Subject
|
11
|
-
%th
|
12
|
-
%th
|
11
|
+
%th Trigger
|
12
|
+
%th Bulk Status
|
13
|
+
%th Bulk Delivered
|
13
14
|
%tbody
|
14
15
|
|
15
16
|
%br
|
16
17
|
|
17
18
|
- unless current_user.admin_limited_access
|
18
|
-
= btn_link_to 'New Message', new_manage_message_path
|
19
|
+
%p= btn_link_to 'New Message', new_manage_message_path
|
20
|
+
|
21
|
+
%br
|
22
|
+
|
23
|
+
= render 'triggered_email_summary'
|
@@ -14,34 +14,47 @@
|
|
14
14
|
= @message.template.titleize
|
15
15
|
%p
|
16
16
|
%b Recipients:
|
17
|
-
= @message.recipients_list
|
17
|
+
= @message.recipients_list.presence || "(none)"
|
18
18
|
%br
|
19
19
|
%small
|
20
|
-
%em
|
20
|
+
%em Sent manually, in bulk
|
21
|
+
- if @message.recipients.present?
|
22
|
+
%br
|
23
|
+
%small
|
24
|
+
%em #{recipient_count} currently match this query
|
25
|
+
%p
|
26
|
+
%b Trigger:
|
27
|
+
= Message::POSSIBLE_TRIGGERS[@message.trigger] || "(no automatic trigger)"
|
28
|
+
%br
|
29
|
+
%small
|
30
|
+
%em Sent automatically, to an individual applicant
|
21
31
|
%p
|
22
32
|
%b Preview:
|
23
33
|
= link_to "Open full preview »".html_safe, preview_manage_message_path
|
24
34
|
|
25
35
|
%iframe.email-preview{src: preview_manage_message_path(@message)}
|
26
36
|
|
27
|
-
|
28
|
-
%
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
- if @message.recipients_list.present?
|
38
|
+
%fieldset
|
39
|
+
%legend Bulk delivery details
|
40
|
+
%p
|
41
|
+
%b
|
42
|
+
Status:
|
43
|
+
= @message.status.titleize
|
44
|
+
%p
|
45
|
+
%b Queued At:
|
46
|
+
= @message.queued_at || "(n/a)"
|
47
|
+
%p
|
48
|
+
%b Started At:
|
49
|
+
= @message.started_at || "(n/a)"
|
50
|
+
%p
|
51
|
+
%b Delivered At:
|
52
|
+
= @message.delivered_at || "(n/a)"
|
40
53
|
|
41
54
|
%hr
|
42
55
|
|
43
56
|
- unless current_user.admin_limited_access
|
44
|
-
- if @message.status == "drafted"
|
57
|
+
- if @message.status == "drafted" && @message.recipients_list.present?
|
45
58
|
= btn_link_to 'Deliver', deliver_manage_message_path(@message), method: :patch, data: { confirm: "Are you sure? The message \"#{@message.name}\" will be sent to #{recipient_count}." }
|
46
59
|
\|
|
47
60
|
- if @message.can_edit?
|
@@ -25,9 +25,20 @@
|
|
25
25
|
|
26
26
|
- unless current_user.admin_limited_access?
|
27
27
|
%br
|
28
|
-
|
28
|
+
.container.container-half
|
29
|
+
= btn_link_to 'New Questionnaire', new_manage_questionnaire_path
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
.container.container-half
|
32
|
+
|
33
|
+
.container.container-half
|
34
|
+
%fieldset
|
35
|
+
%legend Bulk Action
|
36
|
+
= simple_form_for Questionnaire.new, url: bulk_apply_manage_questionnaires_path, html: { data: { bulk_row_edit: true } } do |f|
|
37
|
+
= f.input :acc_status, as: :select, collection: Questionnaire::POSSIBLE_ACC_STATUS.invert, include_blank: false, label: "Acceptance Status:", input_html: { data: { bulk_row_edit: true } }, hint: "Updating this status may trigger an automatic email to each applicant - see below for details."
|
38
|
+
= f.button :submit, value: "Update Status", data: { bulk_row_edit: true }
|
39
|
+
|
40
|
+
%br
|
41
|
+
%br
|
42
|
+
%br
|
43
|
+
|
44
|
+
= render 'triggered_email_summary'
|
@@ -51,7 +51,7 @@
|
|
51
51
|
- unless current_user.admin_limited_access?
|
52
52
|
%hr
|
53
53
|
= simple_form_for @questionnaire, url: url_for(action: "update_acc_status", controller: "questionnaires") do |f|
|
54
|
-
= f.input :acc_status, as: :select, collection: Questionnaire::POSSIBLE_ACC_STATUS.invert, include_blank: false, label: "Acceptance Status:"
|
54
|
+
= f.input :acc_status, as: :select, collection: Questionnaire::POSSIBLE_ACC_STATUS.invert, include_blank: false, label: "Acceptance Status:", hint: "Updating this status may trigger an automatic email to the applicant - see #{link_to('messages', manage_messages_path)} for details.".html_safe
|
55
55
|
= f.button :submit, value: "Update Status"
|
56
56
|
|
57
57
|
%hr
|
@@ -18,13 +18,13 @@ class BulkMessageWorker
|
|
18
18
|
def self.build_recipients(recipient_types)
|
19
19
|
recipients = Set.new
|
20
20
|
recipient_types.each do |type|
|
21
|
-
recipients +=
|
21
|
+
recipients += user_ids(type)
|
22
22
|
end
|
23
23
|
recipients
|
24
24
|
end
|
25
25
|
|
26
26
|
# rubocop:disable CyclomaticComplexity
|
27
|
-
def self.
|
27
|
+
def self.user_ids(type)
|
28
28
|
case type
|
29
29
|
when "all"
|
30
30
|
User.where(admin: false).pluck(:id)
|
@@ -50,38 +50,32 @@ class BulkMessageWorker
|
|
50
50
|
Questionnaire.where("(acc_status = 'accepted' OR acc_status = 'rsvp_confirmed' OR acc_status = 'rsvp_denied') AND checked_in_at IS NULL").pluck(:user_id)
|
51
51
|
when "non-checked-in-excluding"
|
52
52
|
Questionnaire.where("acc_status != 'accepted' AND acc_status != 'rsvp_confirmed' AND acc_status != 'rsvp_denied' AND checked_in_at IS NULL").pluck(:user_id)
|
53
|
-
when
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
when "bus-list
|
70
|
-
|
71
|
-
when "
|
72
|
-
Questionnaire.where("
|
73
|
-
when "
|
74
|
-
Questionnaire.where("
|
75
|
-
when "school
|
76
|
-
Questionnaire.where("school_id =
|
77
|
-
|
78
|
-
|
79
|
-
when "school-waterloo"
|
80
|
-
Questionnaire.where("school_id = 5580 AND (acc_status = \"rsvp_confirmed\" OR acc_status = \"accepted\")").pluck(:user_id)
|
81
|
-
when "school-toronto"
|
82
|
-
Questionnaire.where("school_id = 5539 AND (acc_status = \"rsvp_confirmed\" OR acc_status = \"accepted\")").pluck(:user_id)
|
83
|
-
when "school-umd-collegepark"
|
84
|
-
Questionnaire.where("school_id = 5543 AND (acc_status = \"rsvp_confirmed\" OR acc_status = \"accepted\")").pluck(:user_id)
|
53
|
+
when /(.*)::(\d*)/
|
54
|
+
user_ids_from_query(type)
|
55
|
+
else
|
56
|
+
raise "Unknown recipient type: #{type.inspect}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# rubocop:enable CyclomaticComplexity
|
60
|
+
|
61
|
+
def self.user_ids_from_query(type)
|
62
|
+
# Parse the query
|
63
|
+
# See app/models/message_recipient_query.rb for how this works
|
64
|
+
recipient_query = MessageRecipientQuery.parse(type)
|
65
|
+
model = recipient_query.model
|
66
|
+
|
67
|
+
# Build the recipients query
|
68
|
+
case recipient_query.type
|
69
|
+
when "bus-list"
|
70
|
+
model.passengers.pluck(:user_id)
|
71
|
+
when "bus-list--eligible"
|
72
|
+
Questionnaire.joins(:school).where("schools.bus_list_id = ? AND riding_bus != 1 AND (acc_status = 'accepted' OR acc_status = 'rsvp_confirmed')", model.id).pluck(:user_id)
|
73
|
+
when "bus-list--applied"
|
74
|
+
Questionnaire.joins(:school).where("schools.bus_list_id = ? AND (acc_status != 'accepted' AND acc_status != 'rsvp_confirmed' AND acc_status != 'rsvp_denied')", model.id).pluck(:user_id)
|
75
|
+
when "school"
|
76
|
+
Questionnaire.where("school_id = ? AND (acc_status = 'rsvp_confirmed' OR acc_status = 'accepted')", model.id).pluck(:user_id)
|
77
|
+
else
|
78
|
+
raise "Unknown recipient query type: #{recipient_query.type.inspect} (in message recipient query: #{type.inspect}"
|
85
79
|
end
|
86
80
|
end
|
87
81
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class ConvertMessageRecipientsToRecipientQueries < ActiveRecord::Migration[5.1]
|
2
|
+
CONVERSION_MAPPING = {
|
3
|
+
"bus-list-cornell-bing" => ["bus-list", 1],
|
4
|
+
"bus-list-buffalo" => ["bus-list", 2],
|
5
|
+
"bus-list-albany" => ["bus-list", 3],
|
6
|
+
"bus-list-cornell-bing-eligible" => ["bus-list--eligible", 1],
|
7
|
+
"bus-list-buffalo-eligible" => ["bus-list--eligible", 2],
|
8
|
+
"bus-list-albany-eligible" => ["bus-list--eligible", 3],
|
9
|
+
"bus-list-cornell-bing-applied" => ["bus-list--applied", 1],
|
10
|
+
"bus-list-buffalo-applied" => ["bus-list--applied", 2],
|
11
|
+
"bus-list-albany-applied" => ["bus-list--applied", 3],
|
12
|
+
"school-rit" => ["school", 2304],
|
13
|
+
"school-cornell" => ["school", 2164],
|
14
|
+
"school-binghamton" => ["school", 5526],
|
15
|
+
"school-buffalo" => ["school", 2345],
|
16
|
+
"school-waterloo" => ["school", 5580],
|
17
|
+
"school-toronto" => ["school", 5539],
|
18
|
+
"school-umd-collegepark" => ["school", 5543]
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
def up
|
22
|
+
Message.all.each do |message|
|
23
|
+
CONVERSION_MAPPING.to_a.each do |mapping|
|
24
|
+
old = mapping[0]
|
25
|
+
new_type = mapping[1][0]
|
26
|
+
new_id = mapping[1][1]
|
27
|
+
|
28
|
+
index = message.recipients.index(old)
|
29
|
+
next if index.nil?
|
30
|
+
|
31
|
+
message.recipients[index] = "#{new_type}::#{new_id}"
|
32
|
+
message.save!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hackathon_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stuart Olivera
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -517,6 +517,7 @@ files:
|
|
517
517
|
- app/models/deletable_attachment.rb
|
518
518
|
- app/models/fips.rb
|
519
519
|
- app/models/message.rb
|
520
|
+
- app/models/message_recipient_query.rb
|
520
521
|
- app/models/questionnaire.rb
|
521
522
|
- app/models/school.rb
|
522
523
|
- app/models/school_name_duplicate.rb
|
@@ -524,6 +525,7 @@ files:
|
|
524
525
|
- app/views/application/_bus_list_info.html.haml
|
525
526
|
- app/views/application/_bus_list_stats.html.haml
|
526
527
|
- app/views/application/_questionnaire_summary.html.haml
|
528
|
+
- app/views/application/_triggered_email_summary.html.haml
|
527
529
|
- app/views/bus_lists/show.html.haml
|
528
530
|
- app/views/devise/passwords/_form.html.haml
|
529
531
|
- app/views/devise/passwords/edit.html.haml
|
@@ -638,7 +640,9 @@ files:
|
|
638
640
|
- db/migrate/20170107210122_create_school_name_duplicates.rb
|
639
641
|
- db/migrate/20170128063020_install_blazer.rb
|
640
642
|
- db/migrate/20171220042158_add_why_attend_to_questionnaires.rb
|
643
|
+
- db/migrate/20180108231420_add_trigger_to_message.rb
|
641
644
|
- db/migrate/20180116022530_set_default_count_on_schools.rb
|
645
|
+
- db/migrate/20180118035548_convert_message_recipients_to_recipient_queries.rb
|
642
646
|
- db/schools.csv
|
643
647
|
- db/seeds.rb
|
644
648
|
- lib/hackathon_manager.rb
|