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()