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

Allow future discontinued date #2204

Closed
wants to merge 44 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c6e136b
add custom filter to check whether the date is in the past, use it in…
amdomanska Jan 30, 2023
8e200be
add background job
amdomanska Jan 31, 2023
d5e1608
copy-paste mistakes fixed
amdomanska Jan 31, 2023
8c173c3
change delay to seconds
amdomanska Jan 31, 2023
7edc4c2
wrong file edited!
amdomanska Jan 31, 2023
c88549b
add UT and fix code
amdomanska Feb 1, 2023
1c7e0e1
refactoring
amdomanska Feb 1, 2023
1c27047
Merge branch 'develop' into feature/1529_future_discontinued_date
amdomanska Feb 1, 2023
6357e7f
add FeatureMap annotations
amdomanska Feb 1, 2023
91ad6eb
add functional test
amdomanska Feb 1, 2023
a037fd5
implement notification
amdomanska Feb 7, 2023
b2557c1
implement notification
amdomanska Feb 7, 2023
255bce2
add notif action and remove test code
amdomanska Feb 7, 2023
e8edabb
change notification classification
amdomanska Feb 8, 2023
f23b55b
revert accidental deletion
amdomanska Feb 8, 2023
8cbc146
new even notif unit tests
amdomanska Feb 8, 2023
f72e721
make sure only journals in doaj are found and fix unit tests
amdomanska Feb 8, 2023
b394331
add link to notification
amdomanska Feb 8, 2023
555e1a6
send separate notifications to appropriate managing editors
amdomanska Feb 15, 2023
b9e984f
check for current application
amdomanska Feb 15, 2023
ae807e8
remove unnecessary setting
amdomanska Feb 15, 2023
24214f7
fix imports and tests
amdomanska Feb 17, 2023
f54af1c
fix task test
amdomanska Feb 17, 2023
82b206a
fix the filter
amdomanska Mar 7, 2023
b5684a6
Merge branch 'develop' into feature/1529_future_discontinued_date
amdomanska Mar 13, 2023
ffd151d
remove unused method
amdomanska Mar 20, 2023
b354751
default discontinued date delta to 0
amdomanska Mar 20, 2023
ccf94f1
add functionality to dates lib
amdomanska Mar 20, 2023
d30fbd2
refactor DiscontinuedSoonQuery
amdomanska Mar 20, 2023
ef0510a
use dates lib in jinja filter
amdomanska Mar 20, 2023
a3d8694
fix errors
amdomanska Mar 20, 2023
368df56
Merge branch 'develop' into feature/1529_future_discontinued_date
amdomanska Mar 27, 2023
427ad2b
new full new notification type - alert
amdomanska Mar 27, 2023
34382bd
Merge branch 'develop' into feature/1529_future_discontinued_date
Steven-Eardley Apr 10, 2023
890f226
fix is_before usage
amdomanska Apr 14, 2023
7ae9295
Merge branch 'develop' into feature/1529_future_discontinued_date
Steven-Eardley Apr 14, 2023
bf63c0f
Merge branch 'develop' into feature/1529_future_discontinued_date
Steven-Eardley Apr 14, 2023
6139624
clean up
amdomanska Apr 17, 2023
4a73fde
Merge branch 'feature/1529_future_discontinued_date' of github.com:DO…
amdomanska Apr 17, 2023
4b37398
Merge branch 'develop' into feature/1529_future_discontinued_date
Steven-Eardley Apr 18, 2023
7341677
Update the cron schedule for discontinued task
Steven-Eardley Apr 18, 2023
edb84fe
Merge branch 'develop' into feature/1529_future_discontinued_date
Steven-Eardley May 2, 2023
ea294dc
Add missing import for new background job
Steven-Eardley May 2, 2023
7259212
Merge branch 'develop' into feature/1529_future_discontinued_date
amdomanska May 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doajtest/testbook/public_site/ToC.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
suite: Public Site
testset: ToC
tests:
- title: Test Correctly Displayed Discontinued Date
context:
role: anonymous
steps:
- step: To prepare to do this test make sure there are 3 journals publically available in DOAJ
one with discontinued date in the past
one with discontinued date in the future
one with discontinued date today
- step: Search for every journal from the list above
results:
- On the ToC of the journal with discontinued date in the past or today - the discontinued date is displayed
- On the ToC of the journal with discontinued date in the future - the discontinued date is not displayed
66 changes: 66 additions & 0 deletions doajtest/unit/test_task_discontinued_soon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import unittest
import datetime

from doajtest.helpers import DoajTestCase

from portality.core import app
from portality import models
from portality.tasks import find_discontinued_soon
from portality.ui.messages import Messages
from doajtest.fixtures import JournalFixtureFactory

class TestDiscontinuedSoon(DoajTestCase):

def _date_tomorrow(self):
return (datetime.datetime.today() + datetime.timedelta(days=1)).strftime('%Y-%m-%d')

def _date_in_2_days(self):
return (datetime.datetime.today() + datetime.timedelta(days=2)).strftime('%Y-%m-%d')

def test_discontinued_soon_found(self):

journal_discontinued_tommorow_1 = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_tommorow_1.set_id("1")
jbib = journal_discontinued_tommorow_1.bibjson()
jbib.title = "Discontinued Tomorrow 1"
jbib.discontinued_date = self._date_tomorrow()
journal_discontinued_tommorow_1.save(blocking=True)

journal_discontinued_tommorow_2 = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_tommorow_2.set_id("2")
jbib = journal_discontinued_tommorow_2.bibjson()
jbib.title = "Discontinued Tomorrow 2"
jbib.discontinued_date = self._date_tomorrow()
journal_discontinued_tommorow_2.save(blocking=True)

journal_discontinued_in_2_days = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_in_2_days.set_id("3")
jbib = journal_discontinued_in_2_days.bibjson()
jbib.title = "Discontinued In 2 days"
jbib.discontinued_date = self._date_in_2_days()
journal_discontinued_in_2_days.save(blocking=True)

job = find_discontinued_soon.FindDiscontinuedSoonBackgroundTask.prepare("system")
task = find_discontinued_soon.FindDiscontinuedSoonBackgroundTask(job)
task.run()

assert len(job.audit) == 3
assert job.audit[0]["message"] == Messages.DISCONTINUED_JOURNAL_FOUND_LOG.format(id="1")
assert job.audit[1]["message"] == Messages.DISCONTINUED_JOURNAL_FOUND_LOG.format(id="2")
assert job.audit[2]["message"] == Messages.DISCONTINUED_JOURNALS_FOUND_EMAIL_SENT_LOG

def test_discontinued_soon_not_found(self):

journal_discontinued_in_2_days = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_in_2_days.set_id("3")
jbib = journal_discontinued_in_2_days.bibjson()
jbib.title = "Discontinued In 2 days"
jbib.discontinued_date = self._date_in_2_days()
journal_discontinued_in_2_days.save(blocking=True)

job = find_discontinued_soon.FindDiscontinuedSoonBackgroundTask.prepare("system")
task = find_discontinued_soon.FindDiscontinuedSoonBackgroundTask(job)
task.run()

assert len(job.audit) == 1
assert job.audit[0]["message"] == Messages.NO_DISCONTINUED_JOURNALS_FOUND_LOG
7 changes: 6 additions & 1 deletion portality/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from flask import request, abort, render_template, redirect, send_file, url_for, jsonify, send_from_directory
from flask_login import login_user, current_user

from datetime import datetime
from datetime import datetime, date
amdomanska marked this conversation as resolved.
Show resolved Hide resolved

import portality.models as models
from portality.core import app, es_connection, initialise_index
Expand Down Expand Up @@ -279,6 +279,11 @@ def form_diff_table_subject_expand(val):

return ", ".join(results)

@app.template_filter("is_in_the_past")
def is_in_the_past(dttm):
date = datetime.strptime(dttm, "%Y-%m-%d").date()
amdomanska marked this conversation as resolved.
Show resolved Hide resolved
return date <= date.today()


#######################################################

Expand Down
4 changes: 4 additions & 0 deletions portality/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@
MANAGING_EDITOR_EMAIL = "[email protected]"
CONTACT_FORM_ADDRESS = "[email protected]"
SCRIPT_TAG_DETECTED_EMAIL_RECIPIENTS = ["[email protected]"]
DISCONTINUED_JOURNALS_FOUND_RECEIPIENTS = ["[email protected]"]

SYSTEM_EMAIL_FROM = '[email protected]'
CC_ALL_EMAILS_TO = SYSTEM_EMAIL_FROM # DOAJ may get a dedicated inbox in the future
Expand Down Expand Up @@ -417,6 +418,7 @@
"anon_export": {"month": "*", "day": "10", "day_of_week": "*", "hour": "6", "minute": "30"},
"old_data_cleanup": {"month": "*", "day": "12", "day_of_week": "*", "hour": "6", "minute": "30"},
"monitor_bgjobs": {"month": "*", "day": "*/6", "day_of_week": "*", "hour": "10", "minute": "0"},
"find_discontinued_soon": {"month": "*", "day": "*", "day_of_week": "*", "hour": "7", "minute": "0"},
}

HUEY_TASKS = {
Expand Down Expand Up @@ -1354,3 +1356,5 @@
}
}

# report journals that discontinue in ... days (eg. 1 = tomorrow)
DISCONTINUED_DATE_DELTA = 1
133 changes: 133 additions & 0 deletions portality/tasks/find_discontinued_soon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import datetime
import csv
import json

from portality.core import app
from portality import models,app_email

from portality.tasks.redis_huey import main_queue

from portality.background import BackgroundTask, BackgroundSummary
from portality.tasks.helpers import background_helper
from portality.ui.messages import Messages


def _date():
return (datetime.datetime.today() + datetime.timedelta(days=app.config.get('DISCONTINUED_DATE_DELTA', 1))).strftime(
'%Y-%m-%d')
class DiscontinuedSoonQuery:
@classmethod
def query(cls):
return {
"query": {
"bool": {
"filter": {
"bool" : {
"must": [
{"term" : {"bibjson.discontinued_date": _date()}}
]
}
}
}
}
}
amdomanska marked this conversation as resolved.
Show resolved Hide resolved

# ~~FindDiscontinuedSoonBackgroundTask:Task~~

class FindDiscontinuedSoonBackgroundTask(BackgroundTask):
__action__ = "find_discontinued_soon"

def find_journals_discontinuing_soon(self, job):
jdata = []

for journal in models.Journal.iterate(q=DiscontinuedSoonQuery.query(), keepalive='5m', wrap=True):
# ~~->Journal:Model~~
bibjson = journal.bibjson()
owner = journal.owner
account = models.Account.pull(owner)

jdata.append({"id": journal.id,
"title":bibjson.title,
"eissn": bibjson.get_one_identifier(bibjson.E_ISSN),
"pissn": bibjson.get_one_identifier(bibjson.P_ISSN),
"account_email": account.email if account else "Not Found",
"publisher": bibjson.publisher,
"discontinued date": bibjson.discontinued_date})
job.add_audit_message(Messages.DISCONTINUED_JOURNAL_FOUND_LOG.format(id=journal.id))

return jdata


def send_email(self, data, job):
# ~~->Email:ExternalService~~
try:
# send warning email about the service tag in article metadata detected
to = app.config.get('DISCONTINUED_JOURNALS_FOUND_RECEIPIENTS')
fro = app.config.get("SYSTEM_EMAIL_FROM", "[email protected]")
subject = app.config.get("SERVICE_NAME", "") + " - journals discontinuing soon found"
app_email.send_mail(to=to,
fro=fro,
subject=subject,
template_name="email/discontinue_soon.jinja2",
days=app.config.get('DISCONTINUED_DATE_DELTA',1),
data=json.dumps({"data": data}, indent=4, separators=(',', ': ')))
except app_email.EmailException:
app.logger.exception(Messages.DISCONTINUED_JOURNALS_FOUND_EMAIL_ERROR_LOG)

job.add_audit_message(Messages.DISCONTINUED_JOURNALS_FOUND_EMAIL_SENT_LOG)

def run(self):
job = self.background_job
journals = self.find_journals_discontinuing_soon(job=job)
if len(journals):
self.send_email(job=job, data=journals)
else:
job.add_audit_message(Messages.NO_DISCONTINUED_JOURNALS_FOUND_LOG)

def cleanup(self):
"""
Cleanup after a successful OR failed run of the task
:return:
"""
pass

@classmethod
def prepare(cls, username, **kwargs):
"""
Take an arbitrary set of keyword arguments and return an instance of a BackgroundJob,
or fail with a suitable exception

:param kwargs: arbitrary keyword arguments pertaining to this task type
:return: a BackgroundJob instance representing this task
"""

# first prepare a job record
job = background_helper.create_job(username, cls.__action__,
queue_id=huey_helper.queue_id, )
return job

@classmethod
def submit(cls, background_job):
"""
Submit the specified BackgroundJob to the background queue

:param background_job: the BackgroundJob instance
:return:
"""
background_job.save()
find_discontinued_soon.schedule(args=(background_job.id,), delay=10)

huey_helper = FindDiscontinuedSoonBackgroundTask.create_huey_helper(main_queue)

@huey_helper.register_schedule
def scheduled_find_discontinued_soon():
user = app.config.get("SYSTEM_USERNAME")
job = FindDiscontinuedSoonBackgroundTask.prepare(user)
FindDiscontinuedSoonBackgroundTask.submit(job)


@huey_helper.register_execute(is_load_config=False)
def find_discontinued_soon(job_id):
job = models.BackgroundJob.pull(job_id)
task = FindDiscontinuedSoonBackgroundTask(job)
BackgroundApi.execute(task)
2 changes: 1 addition & 1 deletion portality/templates/doaj/toc.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ <h1 class="row">
</span>
</p>

{% if bibjson.discontinued_date %}
{% if bibjson.discontinued_date | is_in_the_past %}
<p>Ceased publication on <strong>{{ bibjson.discontinued_datestamp.strftime("%d %B %Y") }}</strong></p>
{% endif %}

Expand Down
7 changes: 7 additions & 0 deletions portality/templates/email/discontinue_soon.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{#
~~FindDiscontinuedSoonBackgroundTask:Email~~
#}

Following journals will discontinue in {{ days }} days.

{{ data }}
6 changes: 6 additions & 0 deletions portality/ui/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ class Messages(object):

NOTIFY__DEFAULT_SHORT_NOTIFICATION = "You have a new notification"

DISCONTINUED_JOURNAL_FOUND_LOG = "Journal discontinuing soon found: {id}"
DISCONTINUED_JOURNALS_FOUND_EMAIL_SENT_LOG = "Email with journals discontinuing soon sent"
DISCONTINUED_JOURNALS_FOUND_EMAIL_ERROR_LOG = "Error sending email with journals discountinuing soon."
NO_DISCONTINUED_JOURNALS_FOUND_LOG = "No journals discontinuing soon found"


@classmethod
def flash(cls, tup):
if isinstance(tup, tuple):
Expand Down