-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Endpoints for Notifications #950
Closed
Santosh3007
wants to merge
77
commits into
source-academy:master
from
Santosh3007:add-notifications-endpoints
Closed
Changes from all commits
Commits
Show all changes
77 commits
Select commit
Hold shift + click to select a range
fcc4cf5
Create NotificationType Model
Santosh3007 b429644
Configure Oban and Bamboo for notifications system
Junyi00 d024a75
Create NotificationConfig Model
Santosh3007 cd20b4a
Create TimeOption Model
Santosh3007 a580719
Create NotificationPreference Model
Santosh3007 877220a
Create SentNotification Model
Santosh3007 c8ecd5d
Add Email Field to User Model
Junyi00 6a6cec7
fix: Fix Oban configuration
Junyi00 1b5ca22
chore: Add dependency on bamboo_phoenix for email template rendering
Junyi00 39367e4
feat: Implement Oban job for avenger backlog emails
Junyi00 e6cd06c
chore: Prevent browser from opening automatically when a local email …
Junyi00 4cc7b7f
Add migrations for notification triggers and avenger backlog
Junyi00 1802e49
Implement notification configuration checks
Junyi00 0f7b7e4
Fix formatting errors
Santosh3007 dd951e8
fix: Fix notifications schema typos
Junyi00 554054f
fix: Fix test configurations not being applied
Junyi00 960d75b
chore: remove unused controllers and views
Santosh3007 851a309
chore: Add tests for notifications
Junyi00 fa4ea44
chore: Add test for avenger backlog email
Junyi00 6602170
chore: Resolve style violations
Junyi00 669ac75
chore: Resolve style violations
Junyi00 e8bff4c
chore: Resolve style violations
Junyi00 45bbb34
style: fix formatting
Santosh3007 f6857b9
fix: Fix bad refactoring
Junyi00 f709625
fix: Fix testing environment with Oban and Bamboo
Junyi00 5b43002
test: add tests for notification types
Santosh3007 b37f4a5
test: add tests for time options
Santosh3007 b0000c6
chore: Update constraints and changesets for notification models
Junyi00 7003af5
chore: Update default behaviour for no time_option in user preference
Junyi00 1f25fc0
style: fix formatting
Santosh3007 d6d6869
test: add tests for sent notifications
Santosh3007 fdfd195
Add tests for notifications module
Junyi00 31c7b5c
Merge branch 'add-avenger-backlog-notification' of https://github.com…
Junyi00 498ca1b
fix: Fix testing with Oban
Junyi00 70823a6
Add more tests for notifications module
Junyi00 cf160f8
test: add tests for NotificationWorker
Santosh3007 83d4943
style: fix formatting
Santosh3007 bf362c7
style: fix formatting
Santosh3007 05aac5c
style: fix formatting
Santosh3007 3b571ff
Merge branch 'add-avenger-backlog-notification' of https://github.com…
Junyi00 8f0e982
fix: Fix tests under notification types name constraints
Junyi00 ba29201
feat: Implement job for assessment submission mail
Santosh3007 c07f88f
Merge branch 'add-avenger-backlog-notification' of https://github.com…
Junyi00 4f120ee
fix: Fix assessment submission worker
Junyi00 0b245a9
chore: Add test for assessment submission
Junyi00 9600d40
chore: Add migration to populate existing nus users' emails
Junyi00 22c1391
feat: implement sent_notifications
Santosh3007 8ef9a59
fix: fix tests
Santosh3007 a516463
style: fix formatting
Santosh3007 8994947
fix: fix guard clauses
Santosh3007 b93cdbd
fix: Fix db triggers not running for assessment submission notifications
Junyi00 deca215
feat: Add endpoints for notifications
Junyi00 5c321ca
fix: Duplicate records returned with multiple time options
Junyi00 1422153
chore: Update notifications endpoints
Junyi00 de920be
Add more endpoints for notifications UI
Junyi00 a0b8eef
update notifications query to return a single preference
Junyi00 059d969
Update endpoint to batch update notification configs instead
Junyi00 2cc2f35
Fix Notifications Endpoints
Santosh3007 2880a3a
Add upsert endpoint for notification preferences
Santosh3007 dc02296
Merge branch 'master' into add-notifications-endpoints
Santosh3007 e8a28d6
Fix linting
Santosh3007 5cc0439
Fix linting
Santosh3007 6206538
Fix linting
Santosh3007 45f3e1c
Fix Notification Type tests
Santosh3007 5b50c47
Fix spec issues for notifications
Junyi00 b620cd3
FIx linting
Santosh3007 1ff2fb1
Fix avenger backlog tests
Santosh3007 bb46771
Fix Type Checking
Santosh3007 95206d4
Add tests for notifications controller
Junyi00 eedaf8c
Fix credo errors
Junyi00 5949366
Fix formatting issues
Junyi00 9cc08b4
Fix module name definition
Junyi00 6c242a0
Add more tests and remove unused controller actions
Junyi00 df05af4
Add user level configuration for avenger backlog
Santosh3007 65a2a8a
Merge branch 'master' into add-notifications-endpoints
RichDom2185 c21e42f
Merge branch 'master' into add-notifications-endpoints
martin-henz 39fe3cb
Merge branch 'master' into add-notifications-endpoints
YaleChen299 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,7 +62,76 @@ defmodule Cadet.Notifications do | |
where(query, [c], c.assessment_config_id == ^assconfig_id) | ||
end | ||
|
||
Repo.one(query) | ||
config = Repo.one(query) | ||
|
||
if config != nil do | ||
config | ||
else | ||
IO.puts( | ||
"No NotificationConfig found for Course #{course_id} and NotificationType #{notification_type_id}" | ||
) | ||
|
||
nil | ||
end | ||
end | ||
|
||
def get_notification_config!(id), do: Repo.get!(NotificationConfig, id) | ||
|
||
@doc """ | ||
Gets all notification configs that belong to a course | ||
""" | ||
def get_notification_configs(course_id) do | ||
query = | ||
from(n in Cadet.Notifications.NotificationConfig, | ||
where: n.course_id == ^course_id | ||
) | ||
|
||
query | ||
|> Repo.all() | ||
|> Repo.preload([:notification_type, :course, :assessment_config, :time_options]) | ||
end | ||
|
||
@doc """ | ||
Gets all notification configs with preferences that | ||
1. belongs to the course of the course reg, | ||
2. only notifications that it can configure based on course reg's role | ||
""" | ||
def get_configurable_notification_configs(cr_id) do | ||
cr = Repo.get(Cadet.Accounts.CourseRegistration, cr_id) | ||
|
||
case cr do | ||
nil -> | ||
nil | ||
|
||
_ -> | ||
is_staff = cr.role == :staff | ||
|
||
query = | ||
from(n in Cadet.Notifications.NotificationConfig, | ||
join: ntype in Cadet.Notifications.NotificationType, | ||
on: n.notification_type_id == ntype.id, | ||
join: c in Cadet.Courses.Course, | ||
on: n.course_id == c.id, | ||
left_join: ac in Cadet.Courses.AssessmentConfig, | ||
on: n.assessment_config_id == ac.id, | ||
left_join: p in Cadet.Notifications.NotificationPreference, | ||
on: p.notification_config_id == n.id, | ||
where: | ||
ntype.for_staff == ^is_staff and | ||
n.course_id == ^cr.course_id and | ||
(p.course_reg_id == ^cr.id or is_nil(p.course_reg_id)) | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A different style of query. Please stick to piping. |
||
|
||
query | ||
|> Repo.all() | ||
|> Repo.preload([ | ||
:notification_type, | ||
:course, | ||
:assessment_config, | ||
:time_options, | ||
:notification_preferences | ||
]) | ||
end | ||
end | ||
|
||
@doc """ | ||
|
@@ -83,6 +152,17 @@ defmodule Cadet.Notifications do | |
|> Repo.update() | ||
end | ||
|
||
def update_many_noti_configs(noti_configs) when is_list(noti_configs) do | ||
Repo.transaction(fn -> | ||
for noti_config <- noti_configs do | ||
case Repo.update(noti_config) do | ||
{:ok, res} -> res | ||
{:error, error} -> Repo.rollback(error) | ||
end | ||
end | ||
end) | ||
end | ||
|
||
@doc """ | ||
Returns an `%Ecto.Changeset{}` for tracking notification_config changes. | ||
|
||
|
@@ -112,6 +192,23 @@ defmodule Cadet.Notifications do | |
""" | ||
def get_time_option!(id), do: Repo.get!(TimeOption, id) | ||
|
||
@doc """ | ||
Gets all time options for a notification config | ||
""" | ||
def get_time_options_for_config(notification_config_id) do | ||
query = | ||
from(to in Cadet.Notifications.TimeOption, | ||
join: nc in Cadet.Notifications.NotificationConfig, | ||
on: to.notification_config_id == nc.id, | ||
where: nc.id == ^notification_config_id | ||
) | ||
|
||
Repo.all(query) | ||
end | ||
|
||
@doc """ | ||
Gets all time options for an assessment config and notification type | ||
""" | ||
def get_time_options_for_assessment(assessment_config_id, notification_type_id) do | ||
query = | ||
from(ac in Cadet.Courses.AssessmentConfig, | ||
|
@@ -126,6 +223,9 @@ defmodule Cadet.Notifications do | |
Repo.all(query) | ||
end | ||
|
||
@doc """ | ||
Gets the default time options for an assessment config and notification type | ||
""" | ||
def get_default_time_option_for_assessment!(assessment_config_id, notification_type_id) do | ||
query = | ||
from(ac in Cadet.Courses.AssessmentConfig, | ||
|
@@ -160,6 +260,34 @@ defmodule Cadet.Notifications do | |
|> Repo.insert() | ||
end | ||
|
||
def upsert_many_time_options(time_options) when is_list(time_options) do | ||
Repo.transaction(fn -> | ||
for to <- time_options do | ||
case Repo.insert(to, | ||
on_conflict: {:replace, [:is_default]}, | ||
conflict_target: [:minutes, :notification_config_id] | ||
) do | ||
{:ok, time_option} -> time_option | ||
{:error, error} -> Repo.rollback(error) | ||
end | ||
end | ||
end) | ||
end | ||
|
||
def upsert_many_noti_preferences(noti_prefs) when is_list(noti_prefs) do | ||
Repo.transaction(fn -> | ||
for np <- noti_prefs do | ||
case Repo.insert(np, | ||
on_conflict: {:replace, [:is_enabled, :time_option_id]}, | ||
conflict_target: [:course_reg_id, :notification_config_id] | ||
) do | ||
{:ok, noti_pref} -> noti_pref | ||
{:error, error} -> Repo.rollback(error) | ||
end | ||
end | ||
end) | ||
end | ||
|
||
@doc """ | ||
Deletes a time_option. | ||
|
||
|
@@ -176,6 +304,41 @@ defmodule Cadet.Notifications do | |
Repo.delete(time_option) | ||
end | ||
|
||
def delete_many_time_options(to_ids) when is_list(to_ids) do | ||
Repo.transaction(fn -> | ||
for to_id <- to_ids do | ||
time_option = Repo.get(TimeOption, to_id) | ||
|
||
if is_nil(time_option) do | ||
Repo.rollback("Time option do not exist") | ||
else | ||
case Repo.delete(time_option) do | ||
{:ok, time_option} -> time_option | ||
{:delete_error, error} -> Repo.rollback(error) | ||
end | ||
end | ||
end | ||
end) | ||
end | ||
|
||
@doc """ | ||
Gets the notification preference based from its id | ||
""" | ||
def get_notification_preference!(notification_preference_id) do | ||
query = | ||
from(np in NotificationPreference, | ||
left_join: to in TimeOption, | ||
on: to.id == np.time_option_id, | ||
where: np.id == ^notification_preference_id, | ||
preload: :time_option | ||
) | ||
|
||
Repo.one!(query) | ||
end | ||
|
||
@doc """ | ||
Gets the notification preference based from notification type and course reg | ||
""" | ||
def get_notification_preference(notification_type_id, course_reg_id) do | ||
query = | ||
from(np in NotificationPreference, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,31 +73,35 @@ defmodule Cadet.Workers.NotificationWorker do | |
for avenger_cr <- avengers_crs do | ||
avenger = Cadet.Accounts.get_user(avenger_cr.user_id) | ||
|
||
ungraded_submissions = | ||
Jason.decode!( | ||
elem( | ||
Cadet.Assessments.all_submissions_by_grader_for_index(avenger_cr, true, true), | ||
1 | ||
if is_user_enabled(notification_type_id, avenger_cr.id) do | ||
ungraded_submissions = | ||
Jason.decode!( | ||
elem( | ||
Cadet.Assessments.all_submissions_by_grader_for_index(avenger_cr, true, true), | ||
1 | ||
) | ||
) | ||
) | ||
|
||
if length(ungraded_submissions) < ungraded_threshold do | ||
IO.puts("[AVENGER_BACKLOG] below threshold!") | ||
else | ||
IO.puts("[AVENGER_BACKLOG] SENDING_OUT") | ||
if length(ungraded_submissions) < ungraded_threshold do | ||
IO.puts("[AVENGER_BACKLOG] below threshold!") | ||
else | ||
IO.puts("[AVENGER_BACKLOG] SENDING_OUT") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is a logger better here? |
||
|
||
email = | ||
Email.avenger_backlog_email( | ||
ntype.template_file_name, | ||
avenger, | ||
ungraded_submissions | ||
) | ||
email = | ||
Email.avenger_backlog_email( | ||
ntype.template_file_name, | ||
avenger, | ||
ungraded_submissions | ||
) | ||
|
||
{status, email} = Mailer.deliver_now(email) | ||
{status, email} = Mailer.deliver_now(email) | ||
|
||
if status == :ok do | ||
Notifications.create_sent_notification(avenger_cr.id, email.html_body) | ||
if status == :ok do | ||
Notifications.create_sent_notification(avenger_cr.id, email.html_body) | ||
end | ||
end | ||
else | ||
IO.puts("[ASSESSMENT_SUBMISSION] user-level disabled") | ||
end | ||
end | ||
else | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the query here in a different style?