From dc25cc2b69483d97666fb6a54717aea4a9322893 Mon Sep 17 00:00:00 2001 From: Manuel Reinhardt Date: Wed, 8 May 2024 17:11:00 +0200 Subject: [PATCH 1/2] Show training certificates from other users in my organisation. Ref syslabcom/scrum#2142 --- src/euphorie/client/browser/certificates.py | 48 ++++++++++++++++--- .../templates/training_certificate_inner.pt | 6 +-- .../templates/training_certificate_view.pt | 2 +- src/euphorie/client/browser/training.py | 17 ++++++- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/euphorie/client/browser/certificates.py b/src/euphorie/client/browser/certificates.py index df2ebf2c76..c400bb6e60 100644 --- a/src/euphorie/client/browser/certificates.py +++ b/src/euphorie/client/browser/certificates.py @@ -1,6 +1,9 @@ +from euphorie.client.model import SurveySession +from euphorie.client.model import Training from plone import api from plone.memoize.view import memoize from Products.Five import BrowserView +from z3c.saconfig import Session class View(BrowserView): @@ -8,18 +11,51 @@ class View(BrowserView): @property @memoize - def trainings_portlet(self): - return api.content.get_view( - name="portlet-my-trainings", context=self.context, request=self.request + def trainings(self): + """Get all trainings from all the current user's organisations.""" + organisation_view = api.content.get_view( + name="organisation", + context=self.context, + request=self.request, ) + account_ids = [ + organisation.owner_id for organisation in organisation_view.organisations + ] + return [ + training + for training in ( + Session.query(Training) + .filter( + Training.session_id == SurveySession.id, + SurveySession.account_id.in_(account_ids), + ) + .filter(Training.status == "correct") + .order_by(Training.time.desc()) + .all() + ) + if training.session.tool + ] + + def get_certificate(self, training): + traversed_session = training.session.traversed_session + certificate_view = api.content.get_view( + name="training-certificate-inner", + context=traversed_session, + request=self.request, + ) + return certificate_view.index(training_id=training.id) @property @memoize def my_certificates(self): + """Get all certificates that I am allowed to view, grouped by year.""" certificates = {} - for training in self.trainings_portlet.my_certificates: + for training in self.trainings: year = training.time.year - link = f"{training.session.absolute_url()}/@@training-certificate-view" - content = self.trainings_portlet.get_certificate(training.session) + link = ( + f"{training.session.absolute_url()}/@@training-certificate-view" + f"?training_id={training.id}" + ) + content = self.get_certificate(training) certificates.setdefault(year, []).append({"link": link, "content": content}) return certificates.items() diff --git a/src/euphorie/client/browser/templates/training_certificate_inner.pt b/src/euphorie/client/browser/templates/training_certificate_inner.pt index 09eedf41a7..7b3141a5fc 100644 --- a/src/euphorie/client/browser/templates/training_certificate_inner.pt +++ b/src/euphorie/client/browser/templates/training_certificate_inner.pt @@ -1,9 +1,9 @@
@@ -21,7 +21,7 @@ This certificate is presented to

- ${python: account.title} + ${python: certificate.account.title}

Print certificate diff --git a/src/euphorie/client/browser/training.py b/src/euphorie/client/browser/training.py index 49a1823046..05408ab28f 100644 --- a/src/euphorie/client/browser/training.py +++ b/src/euphorie/client/browser/training.py @@ -20,6 +20,7 @@ from random import shuffle from sqlalchemy.orm.exc import NoResultFound from z3c.saconfig import Session +from zExceptions import NotFound from zExceptions import Unauthorized from zope.interface import implementer from zope.publisher.interfaces import IPublishTraverse @@ -320,9 +321,23 @@ def get_initial_answers(self): questions = sample(all_questions, k=num_training_questions) return {q.getId(): None for q in questions} + def get_training_by_id(self, training_id): + """Return the training for this session with the given id.""" + # check the session id to make sure we are not displaying a training in the + # context of a different session + session_id = self.webhelpers.session_id + try: + return ( + Session.query(Training) + .filter(Training.session_id == session_id, Training.id == training_id) + .one() + ) + except NoResultFound as exc: + raise NotFound from exc + @memoize def get_or_create_training(self): - """Return the training for this session.""" + """Return the current user's training for this session.""" account_id = self.webhelpers.get_current_account().id session_id = self.webhelpers.session_id try: From fc394c9fda053a7e64f6afc78c924ef8b9407bba Mon Sep 17 00:00:00 2001 From: Manuel Reinhardt Date: Mon, 13 May 2024 12:42:41 +0200 Subject: [PATCH 2/2] Show certificates in reverse chronological order Ref syslabcom/scrum#2143 --- src/euphorie/client/browser/certificates.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/euphorie/client/browser/certificates.py b/src/euphorie/client/browser/certificates.py index c400bb6e60..decfbc8853 100644 --- a/src/euphorie/client/browser/certificates.py +++ b/src/euphorie/client/browser/certificates.py @@ -57,5 +57,11 @@ def my_certificates(self): f"?training_id={training.id}" ) content = self.get_certificate(training) - certificates.setdefault(year, []).append({"link": link, "content": content}) + certificates.setdefault(year, []).append( + {"link": link, "content": content, "date": training.time} + ) + for year, year_certificates in certificates.items(): + certificates[year] = sorted( + year_certificates, key=lambda c: c["date"], reverse=True + ) return certificates.items()