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 23 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
5 changes: 5 additions & 0 deletions cms/data/notifications.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,8 @@ update_request:publisher:rejected:notify:
short:
Your update request was rejected

journal:assed:discontinuing_soon:notify:
long: |
Journal "{title}" (id: {id}) will discontinue in {days} days.
short:
Journals discontinuing soon found
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from portality import models
from portality import constants
from portality.bll import exceptions
from doajtest.helpers import DoajTestCase
from doajtest.fixtures import JournalFixtureFactory, ApplicationFixtureFactory
from portality.events.consumers.journal_discontinuing_soon_notify import JournalDiscontinuingSoonNotify
from doajtest.fixtures import BackgroundFixtureFactory
import time

# Mock required to make application lookup work
@classmethod
def pull_application(cls, id):
app = models.Application(**ApplicationFixtureFactory.make_application_source())
return app

@classmethod
def pull_by_key(cls, key, value):
ed = models.EditorGroup()
acc = models.Account()
acc.set_id('testuser')
acc.set_email("[email protected]")
acc.save(blocking=True)
ed.set_maned(acc.id)
ed.save(blocking=True)

return ed

class TestJournalDiscontinuingSoonNotify(DoajTestCase):
def setUp(self):
super(TestJournalDiscontinuingSoonNotify, self).setUp()
self.pull_application = models.Application.pull
models.Application.pull = pull_application
self.pull_by_key = models.EditorGroup.pull_by_key
models.EditorGroup.pull_by_key = pull_by_key

def tearDown(self):
super(TestJournalDiscontinuingSoonNotify, self).tearDown()
models.Application.pull = self.pull_application
models.EditorGroup.pull_by_key = self.pull_by_key

def test_consumes(self):

event = models.Event("test:event", context={"data" : {"1234"}})
assert not JournalDiscontinuingSoonNotify.consumes(event)

event = models.Event("test:event", context={"data": {}})
assert not JournalDiscontinuingSoonNotify.consumes(event)

event = models.Event(constants.EVENT_JOURNAL_DISCONTINUING_SOON)
assert not JournalDiscontinuingSoonNotify.consumes(event)

event = models.Event(constants.EVENT_JOURNAL_DISCONTINUING_SOON, context = {"journal": {"1234"}, "discontinue_date": "2002-22-02"})
assert JournalDiscontinuingSoonNotify.consumes(event)

def test_consume_success(self):
self._make_and_push_test_context("/")

source = BackgroundFixtureFactory.example()
bj = models.BackgroundJob(**source)
# bj.save(blocking=True)

acc = models.Account()
acc.set_id('testuser')
acc.set_email("[email protected]")
acc.add_role('admin')
acc.save(blocking=True)

source = JournalFixtureFactory.make_journal_source()
journal = models.Journal(**source)
journal.save(blocking=True)

event = models.Event(constants.BACKGROUND_JOB_FINISHED, context={"job" : bj.data, "journal" : journal.id})
JournalDiscontinuingSoonNotify.consume(event)

time.sleep(2)
ns = models.Notification.all()
assert len(ns) == 1

n = ns[0]
assert n.who == acc.id
assert n.created_by == JournalDiscontinuingSoonNotify.ID
assert n.classification == constants.NOTIFICATION_CLASSIFICATION_STATUS
assert n.long is not None
assert n.short is not None
assert n.action is not None
assert not n.is_seen()
77 changes: 77 additions & 0 deletions doajtest/unit/test_task_discontinued_soon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
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

DELTA = app.config.get('DISCONTINUED_DATE_DELTA',1)

class TestDiscontinuedSoon(DoajTestCase):

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

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

def test_discontinued_soon_found(self):

# Both these should be found
journal_discontinued_to_found_1 = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_to_found_1.set_id("1")
jbib = journal_discontinued_to_found_1.bibjson()
jbib.title = "Discontinued Tomorrow 1"
jbib.discontinued_date = self._date_to_found()
journal_discontinued_to_found_1.save(blocking=True)

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

# that shouldn't be found
journal_discontinued_too_late = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_too_late.set_id("3")
jbib = journal_discontinued_too_late.bibjson()
jbib.title = "Discontinued In 2 days"
jbib.discontinued_date = self._date_too_late()
journal_discontinued_too_late.save(blocking=True)

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

assert len(job.audit) == 2
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")

def test_discontinued_soon_not_found(self):

# None of these should be found - this one discontinues in 2 days
journal_discontinued_too_late = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
journal_discontinued_too_late.set_id("1")
jbib = journal_discontinued_too_late.bibjson()
jbib.title = "Discontinued In 2 days"
jbib.discontinued_date = self._date_too_late()
journal_discontinued_too_late.save(blocking=True)

# this one is not in doaj
journal_not_in_doaj = models.Journal(**JournalFixtureFactory.make_journal_source(in_doaj=False))
journal_not_in_doaj.set_id("2")
jbib = journal_not_in_doaj.bibjson()
jbib.discontinued_date = self._date_to_found()
journal_not_in_doaj.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
5 changes: 5 additions & 0 deletions portality/app.py
Original file line number Diff line number Diff line change
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: 3 additions & 1 deletion portality/bll/services/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from portality.events.consumers.journal_editor_group_assigned_notify import JournalEditorGroupAssignedNotify
from portality.events.consumers.application_publisher_inprogress_notify import ApplicationPublisherInprogressNotify
from portality.events.consumers.update_request_publisher_rejected_notify import UpdateRequestPublisherRejectedNotify
from portality.events.consumers.journal_discontinuing_soon_notify import JournalDiscontinuingSoonNotify


class EventsService(object):
Expand All @@ -44,7 +45,8 @@ class EventsService(object):
JournalEditorGroupAssignedNotify,
UpdateRequestPublisherAcceptedNotify,
UpdateRequestPublisherAssignedNotify,
UpdateRequestPublisherRejectedNotify
UpdateRequestPublisherRejectedNotify,
JournalDiscontinuingSoonNotify
]

def __init__(self):
Expand Down
2 changes: 2 additions & 0 deletions portality/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@
EVENT_APPLICATION_EDITOR_GROUP_ASSIGNED = "application:editor_group:assigned"
EVENT_JOURNAL_ASSED_ASSIGNED = "journal:assed:assigned"
EVENT_JOURNAL_EDITOR_GROUP_ASSIGNED = "journal:editor_group:assigned"
EVENT_JOURNAL_DISCONTINUING_SOON = "journal:discontinuing_soon"

NOTIFICATION_CLASSIFICATION_STATUS = "status"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we invent a new classification status, we need to think about how this is displayed in the notifications search UI. It will need an icon, or at least to check the edges code that shows the notifications search that it falls back to the text gracefully

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you suggest using one of the existing ones?

NOTIFICATION_CLASSIFICATION_STATUS_CHANGE = "status_change"
NOTIFICATION_CLASSIFICATION_ASSIGN = "assign"
NOTIFICATION_CLASSIFICATION_CREATE = "create"
NOTIFICATION_CLASSIFICATION_FINISHED = "finished"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, I think a new one makes sense, though "status" is a bit of an overloaded term. Perhaps "alert"? Then the icon can be a bell or something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do this, set the status in the constants like you have done, for this new "alert", then in portality/static/js/edges/notifications.edge.js add a new SVG icon in the icons dictionary, and a new description in the classifications dictionary and this should then display as appropriate

NOTIFICATION_CLASSIFICATION_STATUS_CHANGE = "status_change"
NOTIFICATION_CLASSIFICATION_ASSIGN = "assign"
NOTIFICATION_CLASSIFICATION_CREATE = "create"
Expand Down
66 changes: 66 additions & 0 deletions portality/events/consumers/journal_discontinuing_soon_notify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# ~~JournalDiscontinuingSoonNotify:Consumer~~
import json
import urllib.parse

from portality.util import url_for
from portality.events.consumer import EventConsumer
from portality.core import app
from portality import constants
from portality import models
from portality.bll import DOAJ, exceptions
from portality.lib import edges
from portality import dao


from portality.models.v2.journal import JournalDiscontinuedDateQuery

class JournalDiscontinuingSoonNotify(EventConsumer):
ID = "journal:assed:discontinuing_soon:notify"

@classmethod
def consumes(cls, event):
return event.id == constants.EVENT_JOURNAL_DISCONTINUING_SOON and \
event.context.get("journal") is not None and \
event.context.get("discontinue_date") is not None

@classmethod
def consume(cls, event):
journal_id = event.context.get("journal")
discontinued_date = event.context.get("discontinue_date")

journal = models.Journal.pull(journal_id)
if journal is None:
return

app_id = journal.current_application
if app_id is None:
app_id = journal.latest_related_application_id()
if app_id is None:
return

application = models.Application.pull(app_id)

if not application.editor_group:
return

eg = models.EditorGroup.pull_by_key("name", application.editor_group)
managing_editor = eg.maned
if not managing_editor:
return

# ~~-> Notifications:Service ~~
svc = DOAJ.notificationsService()

notification = models.Notification()
notification.who = managing_editor
notification.created_by = cls.ID
notification.classification = constants.NOTIFICATION_CLASSIFICATION_STATUS
notification.long = svc.long_notification(cls.ID).format(
days=app.config.get('DISCONTINUED_DATE_DELTA',1),
amdomanska marked this conversation as resolved.
Show resolved Hide resolved
title=journal.bibjson().title,
id=journal.id
)
notification.short = svc.short_notification(cls.ID)
notification.action = url_for("admin.journal_page", journal_id=journal.id)

svc.notify(notification)
23 changes: 22 additions & 1 deletion portality/models/v2/journal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1121,4 +1121,25 @@ def query(self):
"sort" : [
{"created_date" : {"order" : "desc"}}
]
}
}

class JournalDiscontinuedDateQuery(object):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented but then appeared not to be needed. Is it worth leaving or should be scrapped? Not currently used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to scrap if not used

base_query = {
"track_total_hits": True,
"query": {
"bool": {
"must": [
{"terms": {"bibjson.discontinued_date": "<date here>"}}
]
}
},
"size": 10000
}

def __init__(self, discontinued_date):
self.discontinued_date = discontinued_date

def query(self):
q = deepcopy(self.base_query)
q["query"]["bool"]["must"][0]["terms"]["bibjson.discontinued_date"] = [self.discontinued_date]
return q
3 changes: 3 additions & 0 deletions portality/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,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 +1355,5 @@
}
}

# report journals that discontinue in ... days (eg. 1 = tomorrow)
DISCONTINUED_DATE_DELTA = 0
richard-jones marked this conversation as resolved.
Show resolved Hide resolved
Loading