Repository: ietf-tools/datatracker

Issue:
status change workflow has case sensitivity errors
Creating a new status-change document currently fails with errors like this:

![image](https://github.com/ietf-tools/datatracker/assets/10996692/784371fd-794a-48ed-b5c5-2febbbd3a46f)

This is due to the form confusing how it displays a document name with how it searches for a document name, and postgresql searches being case sensitive. (A search for a DocAlias of "RFC3261" fails).

The tests have not exposed this, so they need to be inspected across the entire status-change workflow.


Discussion:

Resolving patch:
diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py
--- a/ietf/doc/views_status_change.py
+++ b/ietf/doc/views_status_change.py
@@ -418,7 +418,7 @@ def clean_helper(form, formtype):
         rfc_fields = {}
         status_fields={}
         for k in sorted(form.data.keys()):
-            v = form.data[k]
+            v = form.data[k].lower()
             if k.startswith('new_relation_row'):
                 if re.match(r'\d{1,4}',v):
                     v = 'rfc'+v
@@ -685,7 +685,7 @@ def last_call(request, name):
     form = LastCallTextForm(initial=dict(last_call_text=escape(last_call_event.text)))
 
     if request.method == 'POST':
-        if "save_last_call_text" in request.POST or "send_last_call_request" in request.POST:
+        if "save_last_call_text" in request.POST or ("send_last_call_request" in request.POST and status_change.ad is not None):
             form = LastCallTextForm(request.POST)
             if form.is_valid():
                 events = []


Test patch:
diff --git a/ietf/doc/tests_status_change.py b/ietf/doc/tests_status_change.py
--- a/ietf/doc/tests_status_change.py
+++ b/ietf/doc/tests_status_change.py
@@ -14,7 +14,7 @@
 from django.conf import settings
 from django.urls import reverse as urlreverse
 
-from ietf.doc.factories import DocumentFactory, IndividualRfcFactory, WgRfcFactory
+from ietf.doc.factories import DocumentFactory, IndividualRfcFactory, WgRfcFactory, DocEventFactory
 from ietf.doc.models import ( Document, DocAlias, State, DocEvent,
     BallotPositionDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent )
 from ietf.doc.utils import create_ballot_if_not_open
@@ -86,6 +86,16 @@ def test_start_review(self):
         status_change = Document.objects.get(name='status-change-imaginary-new2')
         self.assertIsNone(status_change.ad)        
 
+        # Verify that the right thing happens if a control along the way uppercases RFC
+        r = self.client.post(url,dict(
+            document_name="imaginary-new3",title="A new imaginary status change",
+            create_in_state=state_strpk,notify='ipu@ietf.org',new_relation_row_blah="RFC9999",
+            statchg_relation_row_blah="tois")
+        )
+        self.assertEqual(r.status_code, 302)
+        status_change = Document.objects.get(name='status-change-imaginary-new3')
+        self.assertTrue(status_change.relateddocument_set.filter(relationship__slug='tois',target__name='rfc9999'))
+
 
     def test_change_state(self):
 
@@ -289,7 +299,19 @@ def test_edit_lc(self):
         self.assertEqual(r.status_code,200)
         self.assertContains(r,  'RFC9999 from Proposed Standard to Internet Standard')
         self.assertContains(r,  'RFC9998 from Informational to Historic')
-      
+        q = PyQuery(r.content)
+        self.assertEqual(len(q("button[name='send_last_call_request']")), 1)
+
+        # Make sure request LC isn't offered with no responsible AD.
+        doc.ad = None
+        doc.save_with_history([DocEventFactory(doc=doc)])
+        r = self.client.get(url)
+        self.assertEqual(r.status_code,200) 
+        q = PyQuery(r.content)
+        self.assertEqual(len(q("button[name='send_last_call_request']")), 0)
+        doc.ad = Person.objects.get(name='Ad No2')
+        doc.save_with_history([DocEventFactory(doc=doc)])
+
         # request last call
         messages_before = len(outbox)
         r = self.client.post(url,dict(last_call_text='stuff',send_last_call_request='Save+and+Request+Last+Call'))