Coverage for portality / tasks / journal_in_out_doaj.py: 82%
112 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-04 09:41 +0100
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-04 09:41 +0100
1from flask_login import current_user
2from portality import models, lock
3from portality.bll import DOAJ
4from portality.core import app
5from portality.lib import dates
7from portality.tasks.redis_huey import events_queue as queue
8from portality.decorators import write_required
10from portality.background import BackgroundTask, BackgroundApi, BackgroundSummary
12import json
14from portality.ui.messages import Messages
17def change_by_query(query, in_doaj_new_val, dry_run=True):
18 ids = []
19 sane = {}
20 sane["query"] = query["query"]
21 job = None
22 for j in models.Journal.iterate(sane, wrap=False):
23 ids.append(j.get("id"))
24 if not dry_run:
25 job = change_in_doaj(ids, in_doaj_new_val, selection_query=sane)
27 affected = len(ids)
28 job_id = None
29 if job is not None:
30 job_id = job.id
31 return BackgroundSummary(job_id, affected={"journals" : affected})
33 # return len(ids)
35def change_in_doaj(journal_ids, in_doaj_new_val, **kwargs):
36 job = SetInDOAJBackgroundTask.prepare(current_user.id, journal_ids=journal_ids, in_doaj=in_doaj_new_val, **kwargs)
37 SetInDOAJBackgroundTask.submit(job)
38 return job
40def find_matching_issns_in_doaj(journal_ids):
41 if not isinstance(journal_ids, list):
42 journal_ids = [journal_ids]
43 with_matches = []
44 for journal_id in journal_ids:
45 j = models.Journal.pull(journal_id)
46 other_with_the_same_issns = models.Journal.find_by_issn(j.bibjson().issns())
47 if len([j for j in other_with_the_same_issns if j.is_in_doaj()]) > 0:
48 with_matches.append(journal_id)
49 return with_matches
51class SetInDOAJBackgroundTask(BackgroundTask):
52 # ~~SetInDOAJBackgroundTask:Process->BackgroundTask:Process~~
53 __action__ = "set_in_doaj"
55 def run(self):
56 """
57 Execute the task as specified by the background_jon
58 :return:
59 """
60 job = self.background_job
61 params = job.params
63 journal_ids = self.get_param(params, "journal_ids")
64 in_doaj = self.get_param(params, "in_doaj")
66 if journal_ids is None or len(journal_ids) == 0 or in_doaj is None:
67 raise RuntimeError("SetInDOAJBackgroundTask.run run without sufficient parameters")
69 # preliminary check to see whether we can change the status of all requested journals
70 if in_doaj:
71 matching_issns = find_matching_issns_in_doaj(journal_ids)
72 if matching_issns:
73 job.add_audit_message(
74 Messages.CANNOT_CHANGE_THE_STATUS__OTHER_JOURNAL_IN_DOAJ_EXISTS)
75 job.outcome_fail()
76 return job
78 for journal_id in journal_ids:
79 job.add_audit_message("Setting in_doaj to {x} for journal {y}".format(x=str(in_doaj), y=journal_id))
80 # ~~->Journal:Model~~
81 j = models.Journal.pull(journal_id)
83 # ~~->Account:Model~~
84 account = models.Account.pull(job.user)
85 if j is None:
86 raise RuntimeError("Journal with id {} does not exist".format(journal_id))
88 current_in_doaj = j.is_in_doaj()
89 if in_doaj and not current_in_doaj:
90 j.last_reinstated = dates.now_str()
91 j.add_note(Messages.JOURNAL_REINSTATED_NOTE.format(username=job.user, date=dates.now_str()), author_id=job.user)
93 if not in_doaj:
94 if current_in_doaj:
95 j.last_withdrawn = dates.now_str()
96 j.add_note(Messages.JOURNAL_WITHDRAWN_NOTE.format(username=job.user, date=dates.now_str()), author_id=job.user)
98 # Rejecting associated update request
99 # ~~->Application:Service~~
100 svc = DOAJ.applicationService()
101 ur = svc.reject_update_request_of_journal(j.id, account)
102 if ur:
103 job.add_audit_message(Messages.AUTOMATICALLY_REJECTED_UPDATE_REQUEST_WITH_ID.format(urid=ur))
104 else:
105 job.add_audit_message(Messages.NO_UPDATE_REQUESTS)
108 j.bibjson().active = in_doaj
109 j.set_in_doaj(in_doaj)
110 j.save()
111 j.propagate_in_doaj_status_to_articles() # will save each article, could take a while
112 job.add_audit_message("Journal {x} set in_doaj to {y}, and all associated articles".format(x=journal_id, y=str(in_doaj)))
114 def cleanup(self):
115 """
116 Cleanup after a successful OR failed run of the task
117 :return:
118 """
119 # remove the lock on the journal
120 job = self.background_job
121 params = job.params
122 journal_ids = self.get_param(params, "journal_ids")
123 username = job.user
125 lock.batch_unlock("journal", journal_ids, username)
127 @classmethod
128 def prepare(cls, username, **kwargs):
129 """
130 Take an arbitrary set of keyword arguments and return an instance of a BackgroundJob,
131 or fail with a suitable exception
133 :param kwargs: arbitrary keyword arguments pertaining to this task type
134 :return: a BackgroundJob instance representing this task
135 """
137 # first prepare a job record
138 job = models.BackgroundJob()
139 job.user = username
140 job.action = cls.__action__
142 journal_ids = kwargs.get("journal_ids")
144 params = {}
145 cls.set_param(params, "journal_ids", journal_ids)
146 cls.set_param(params, "in_doaj", kwargs.get("in_doaj"))
148 if journal_ids is None or len(journal_ids) == 0 or kwargs.get("in_doaj") is None:
149 raise RuntimeError("SetInDOAJBackgroundTask.prepare run without sufficient parameters")
151 job.params = params
152 job.queue_id = huey_helper.queue_id
154 if "selection_query" in kwargs:
155 refs = {}
156 cls.set_reference(refs, "selection_query", json.dumps(kwargs.get('selection_query')))
157 job.reference = refs
159 # now ensure that we have the locks for this journal
160 # will raise an exception if this fails
161 lock.batch_lock("journal", journal_ids, username, timeout=app.config.get("BACKGROUND_TASK_LOCK_TIMEOUT", 3600))
163 return job
165 @classmethod
166 def submit(cls, background_job):
167 """
168 Submit the specified BackgroundJob to the background queue
170 :param background_job: the BackgroundJob instance
171 :return:
172 """
173 background_job.save()
174 set_in_doaj.schedule(args=(background_job.id,), delay=app.config.get('HUEY_ASYNC_DELAY', 10))
177huey_helper = SetInDOAJBackgroundTask.create_huey_helper(queue)
180@huey_helper.register_execute(is_load_config=False)
181def set_in_doaj(job_id):
182 job = models.BackgroundJob.pull(job_id)
183 task = SetInDOAJBackgroundTask(job)
184 BackgroundApi.execute(task)