Skip to content
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

🎁 Depositor notifications #2226

Merged
merged 11 commits into from
May 31, 2024
28 changes: 28 additions & 0 deletions app/jobs/depositor_email_notification_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

class DepositorEmailNotificationJob < ApplicationJob
non_tenant_job

after_perform do |job|
reenqueue(job.arguments.first)
end

def perform(account)
Apartment::Tenant.switch(account.tenant) do
users = User.all

users.each do |user|
statistics = user.statistics_for
next if statistics.nil?

HykuMailer.depositor_email(user, statistics, account).deliver_now
end
end
end

private

def reenqueue(account)
DepositorEmailNotificationJob.set(wait_until: (Time.zone.now + 1.month).beginning_of_month).perform_later(account)
end
end
18 changes: 18 additions & 0 deletions app/mailers/hyku_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ def summary_email(user, messages, account)
template_name: 'summary_email')
end

def depositor_email(user, statistics, account)
@user = user
@statistics = statistics
@account = account
@url = dashboard_url_for(@account)
@application_name = account.sites.application_name

mail(to: @user.email,
subject: "Monthly Downloads Summary for #{@application_name}",
from: @account.contact_email,
template_path: 'hyku_mailer',
template_name: 'depositor_email')
end

private

def host_for_tenant
Expand All @@ -29,4 +43,8 @@ def host_for_tenant
def notifications_url_for(account)
"https://#{account.cname}/notifications"
end

def dashboard_url_for(account)
"https://#{account.cname}/dashboard"
end
end
18 changes: 18 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

# rubocop:disable Metrics/ClassLength
class User < ApplicationRecord
# Includes lib/rolify from the rolify gem
rolify
Expand Down Expand Up @@ -172,4 +173,21 @@ def mark_all_undelivered_messages_as_delivered!
receipt.update(is_delivered: true)
end
end

# Returns hash summary of user statistics for a date range... uses the prior month by default
def statistics_for(start_date: (Time.zone.now - 1.month).beginning_of_month, end_date: (Time.zone.now - 1.month).end_of_month)
stats_period = start_date..end_date
last_month_stats = stats.where(date: stats_period)

return nil if last_month_stats.empty?

{
new_file_downloads: last_month_stats.sum(:file_downloads),
new_work_views: last_month_stats.sum(:work_views),
total_file_views:,
total_file_downloads:,
total_work_views:
}
end
end
# rubocop:enable Metrics/ClassLength
1 change: 1 addition & 0 deletions app/services/create_account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def schedule_recurring_jobs
EmbargoAutoExpiryJob.perform_later(account)
LeaseAutoExpiryJob.perform_later(account)
BatchEmailNotificationJob.perform_later(account)
DepositorEmailNotificationJob.perform_later(account)
end

private
Expand Down
34 changes: 34 additions & 0 deletions app/views/hyku_mailer/depositor_email.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; }
.email-container { max-width: 600px; margin: auto; padding: 20px; border: 1px solid #ccc; }
.footer { font-size: 12px; color: #666; margin-top: 20px; }
.highlight { color: #0056b3; }
.button {
display: inline-block;
padding: 10px 20px;
margin: 10px 0;
background-color: #0056b3;
color: white;
text-decoration: none;
border-radius: 5px;
}
</style>
</head>
<body>
ShanaLMoore marked this conversation as resolved.
Show resolved Hide resolved
<div class="email-container">
<p>Dear Author,</p>
<p>You had <%= pluralize(@statistics[:new_file_downloads], 'download') %> in <%= Date.today.prev_month.strftime("%B %Y") %> across your <%= pluralize(@statistics[:new_work_views], 'work') %> in <%= @application_name %>. Your current readership:</p>
<ul>
<li><%= pluralize(@statistics[:total_file_downloads], 'Total File Download') %></li>
<li><%= pluralize(@statistics[:total_work_views], 'Total Work View') %></li>
</ul>
<a href="<%= @url %>" class="button">VISIT MY DASHBOARD</a>
<div class="footer">
<p>These monthly reports are provided to you on behalf of <%= @application_name %>. For questions, comments, or to add more content and increase your readership and visibility as an author, please contact your repository administrator.</p>
</div>
</div>
</body>
</html>
44 changes: 44 additions & 0 deletions spec/jobs/depositor_email_notification_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

RSpec.describe DepositorEmailNotificationJob do
let(:account) { FactoryBot.create(:account) }
let(:receipt) { FactoryBot.create(:mailboxer_receipt, receiver: user) }
let!(:message) { receipt.notification }
let!(:user) { FactoryBot.create(:user) }

before do
allow(Apartment::Tenant).to receive(:switch).and_yield
ActionMailer::Base.deliveries.clear
end

after do
clear_enqueued_jobs
end

describe '#perform' do
it 're-enqueues the job' do
expect { DepositorEmailNotificationJob.perform_now(account) }.to have_enqueued_job(DepositorEmailNotificationJob).with(account)
end

context 'when the user has new statistics' do
let(:statistics) { { new_file_downloads: 2, new_work_views: 3, total_file_downloads: 6, total_file_views: 7, total_work_views: 16 } }

before do
allow(User).to receive(:all).and_return([user])
allow(user).to receive(:statistics_for).and_return(statistics)
end

it 'sends email to users' do
expect { described_class.perform_now(account) }.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end

context 'when the user has no new statistics' do
let(:statistics) { nil }

it 'sends does not send email to user' do
expect { DepositorEmailNotificationJob.perform_now(account) }.to_not change { ActionMailer::Base.deliveries.count }
end
end
end
end
23 changes: 23 additions & 0 deletions spec/mailers/previews/hyku_mailer_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,27 @@ def summary_email

HykuMailer.new.summary_email(user, messages, account)
end

laritakr marked this conversation as resolved.
Show resolved Hide resolved
def depositor_email
# Creating mock statistics
statistics = {
new_file_downloads: 1,
new_work_views: 6,
total_file_views: 20,
total_file_downloads: 20,
total_work_views: 100
}

# Mock user
user = Struct.new(:email, :name).new('[email protected]', 'Depositor Name')

# Mock site and account setup
site = Struct.new(:application_name)
sites = site.new('MUShare')

account = Struct.new(:cname, :contact_email, :sites).new('acme.pals.test', '[email protected]', sites)

# Calling the depositor_email method of the HykuMailer with mock data
HykuMailer.new.depositor_email(user, statistics, account)
end
end
41 changes: 41 additions & 0 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,47 @@
is_expected.to validate_presence_of(:password)
end

context '#stistics_for' do
let(:account) { FactoryBot.create(:account) }

before do
allow(Apartment::Tenant).to receive(:switch).and_yield
end

describe 'no statistics' do
it 'returns nil' do
expect(subject.statistics_for).to be nil
end
end

describe 'with user statistics' do
let!(:stat_1_prior_month) { UserStat.create!(user_id: subject.id, date: 1.month.ago, file_views: 3, file_downloads: 2, work_views: 5) }
let!(:stat_2_prior_month) { UserStat.create!(user_id: subject.id, date: 1.month.ago, file_views: 2, file_downloads: 1, work_views: 7) }
let!(:stat_2_months_ago) { UserStat.create!(user_id: subject.id, date: 2.months.ago, file_views: 1, file_downloads: 1, work_views: 1) }
let!(:stat_yesterday) { UserStat.create!(user_id: subject.id, date: 1.day.ago, file_views: 1, file_downloads: 2, work_views: 3) }
let!(:someone_elses_user_id) { subject.id + 1 }
let!(:not_my_stat) { UserStat.create!(user_id: someone_elses_user_id, date: 1.month.ago, file_views: 10, file_downloads: 11) }
let(:user_stats) { { new_file_downloads: 3, new_work_views: 12, total_file_downloads: 6, total_file_views: 7, total_work_views: 16 } }
let(:yesterday_stats) { { new_file_downloads: 2, new_work_views: 3, total_file_downloads: 6, total_file_views: 7, total_work_views: 16 } }

it 'returns a summary hash of prior months stats' do
expect(subject.statistics_for).to eq(user_stats)
end

it 'summarizes stats for specified date range' do
expect(subject.statistics_for(start_date: Time.zone.now - 2.days, end_date: Time.zone.now)).to eq(yesterday_stats)
end

it 'returns nil if no statistics in specified date range' do
expect(subject.statistics_for(start_date: Time.zone.now - 4.months, end_date: Time.zone.now - 5.months)).to be nil
end

it 'returns nil if start and end dates the same' do
expect(subject.statistics_for(start_date: Time.zone.now - 5.months, end_date: Time.zone.now - 5.months)).to be nil
end
end
end

context 'the first created user in global tenant' do
before do
allow(Account).to receive(:global_tenant?).and_return true
Expand Down
3 changes: 2 additions & 1 deletion spec/services/create_account_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@
end

describe '#schedule_recurring_jobs' do
it "Enqueues Embargo and Lease Expiry jobs" do
it "Enqueues Recurring jobs" do
expect(EmbargoAutoExpiryJob).to receive(:perform_later).with(account)
expect(LeaseAutoExpiryJob).to receive(:perform_later).with(account)
expect(BatchEmailNotificationJob).to receive(:perform_later).with(account)
expect(DepositorEmailNotificationJob).to receive(:perform_later).with(account)
subject.schedule_recurring_jobs
end
end
Expand Down
Loading