diff --git a/ietf/doc/tests_utils.py b/ietf/doc/tests_utils.py index 7db59819da..ef71f6ae6e 100644 --- a/ietf/doc/tests_utils.py +++ b/ietf/doc/tests_utils.py @@ -13,13 +13,15 @@ from ietf.group.factories import GroupFactory, RoleFactory from ietf.name.models import DocTagName from ietf.person.factories import PersonFactory +from ietf.doc.factories import BallotPositionDocEventFactory from ietf.utils.test_utils import TestCase, name_of_file_containing, reload_db_objects from ietf.person.models import Person from ietf.doc.factories import DocumentFactory, WgRfcFactory, WgDraftFactory from ietf.doc.models import State, DocumentActionHolder, DocumentAuthor from ietf.doc.utils import (update_action_holders, add_state_change_event, update_documentauthors, fuzzy_find_documents, rebuild_reference_relations, build_file_urls, - ensure_draft_bibxml_path_exists, update_or_create_draft_bibxml_file) + ensure_draft_bibxml_path_exists, update_or_create_draft_bibxml_file, + last_ballot_doc_revision) from ietf.utils.draft import Draft, PlaintextDraft from ietf.utils.xmldraft import XMLDraft @@ -533,3 +535,27 @@ def test_update_draft_bibxml_file(self, mock): self.assertEqual(mock.call_count, 1) self.assertEqual(mock.call_args, call(doc, "26")) self.assertEqual(ref_path.read_text(), "This\nis\nmy\nbibxml") + + +class LastBallotDocRevisionTests(TestCase): + def test_last_ballot_doc_revision(self): + now = timezone.now() + ad = Person.objects.get(user__username="ad") + bpde_with_null_send_email = BallotPositionDocEventFactory( + time=now - datetime.timedelta(minutes=30), + send_email=None, + ) + ballot = bpde_with_null_send_email.ballot + BallotPositionDocEventFactory( + ballot=ballot, + balloter=ad, + pos_id='noobj', + comment='Commentary', + comment_time=timezone.now(), + send_email=None, + ) + doc = bpde_with_null_send_email.doc + rev = bpde_with_null_send_email.rev + nobody = PersonFactory() + self.assertIsNone(last_ballot_doc_revision(doc, nobody)) + self.assertEqual(rev, last_ballot_doc_revision(doc, ad)) diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index 115b28b09b..2bd9a3d314 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -36,11 +36,12 @@ from ietf.doc.models import Document, DocHistory, State, DocumentAuthor, DocHistoryAuthor from ietf.doc.models import RelatedDocument, RelatedDocHistory, BallotType, DocReminder from ietf.doc.models import DocEvent, ConsensusDocEvent, BallotDocEvent, IRSGBallotDocEvent, NewRevisionDocEvent, StateDocEvent -from ietf.doc.models import TelechatDocEvent, DocumentActionHolder, EditedAuthorsDocEvent +from ietf.doc.models import TelechatDocEvent, DocumentActionHolder, EditedAuthorsDocEvent, BallotPositionDocEvent from ietf.name.models import DocReminderTypeName, DocRelationshipName from ietf.group.models import Role, Group, GroupFeatures from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, is_individual_draft_author, is_bofreq_editor from ietf.person.models import Email, Person +from ietf.person.utils import get_active_balloters from ietf.review.models import ReviewWish from ietf.utils import draft, log from ietf.utils.mail import parseaddr, send_mail @@ -687,6 +688,22 @@ def nice_consensus(consensus): } return mapping[consensus] +def last_ballot_doc_revision(doc, person): + """ Return the document revision for the most recent ballot position + by the provided user. """ + ballot = doc.active_ballot() + if ballot is None or person is None: + return None + balloters = get_active_balloters(ballot.ballot_type) + if person not in balloters: + return None + position_queryset = BallotPositionDocEvent.objects.filter(type="changed_ballot_position", balloter=person, ballot=ballot).order_by("-time") + if not position_queryset.exists(): + return None + ballot_time = position_queryset.first().time + doc_rev = NewRevisionDocEvent.objects.filter(doc=doc, time__lte=ballot_time).order_by('-time').first().rev + return doc_rev + def has_same_ballot(doc, date1, date2=None): """ Test if the most recent ballot created before the end of date1 is the same as the most recent ballot created before the diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index 4a20db3c89..50070734f9 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -79,6 +79,7 @@ from ietf.doc.views_ballot import parse_ballot_edit_return_point from ietf.doc.forms import InvestigateForm, TelechatForm, NotifyForm, ActionHoldersForm, DocAuthorForm, DocAuthorChangeBasisForm from ietf.doc.mails import email_comment, email_remind_action_holders +from ietf.doc.utils import last_ballot_doc_revision from ietf.mailtrigger.utils import gather_relevant_expansions from ietf.meeting.models import Session, SessionPresentation from ietf.meeting.utils import group_sessions, get_upcoming_manageable_sessions, sort_sessions, add_event_info_to_session_qs @@ -1225,6 +1226,10 @@ def document_history(request, name): request.user, ("Area Director", "Secretariat", "IRTF Chair") ) + # if the current user has balloted on this document, give them a revision hint + ballot_doc_rev = None + if request.user.is_authenticated: + ballot_doc_rev = last_ballot_doc_revision(doc, request.user.person) return render( request, @@ -1235,6 +1240,7 @@ def document_history(request, name): "diff_revisions": diff_revisions, "events": events, "can_add_comment": can_add_comment, + "ballot_doc_rev": ballot_doc_rev, }, ) diff --git a/ietf/templates/doc/document_history.html b/ietf/templates/doc/document_history.html index a9ee3e9a36..78471e08d6 100644 --- a/ietf/templates/doc/document_history.html +++ b/ietf/templates/doc/document_history.html @@ -20,6 +20,11 @@

Revision differences

{% include "doc/document_history_form.html" with doc=doc diff_revisions=diff_revisions action=rfcdiff_base_url snapshot=snapshot only %} {% endif %} + {% if ballot_doc_rev %} +

+ Your most recent ballot position was provided when the document was at version {{ ballot_doc_rev }}. +

+ {% endif %}

Document history

{% if doc.came_from_draft %}