From d3572e18c34c20c661eb61c7f8c46358f7223d37 Mon Sep 17 00:00:00 2001
From: Philip Sargent <philip.sargent@klebos.com>
Date: Wed, 6 Jul 2022 17:35:08 +0300
Subject: [PATCH] QM reports all working

---
 core/models/caves.py |  2 +-
 core/views/caves.py  | 39 +++++++++++++++++---------------
 parsers/QMs.py       | 53 +++++++++++++++++++++++++-------------------
 parsers/survex.py    | 26 +++++++++-------------
 templates/qm.html    |  6 +++--
 5 files changed, 67 insertions(+), 59 deletions(-)

diff --git a/core/models/caves.py b/core/models/caves.py
index db86e66..5a09229 100644
--- a/core/models/caves.py
+++ b/core/models/caves.py
@@ -505,7 +505,7 @@ class QM(TroggleModel):
         return f'{self.code()}'
 
     def code(self):
-        return f'{str(self.found_by.cave_slug)[5:]}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' 
+        return f'{str(self.cave.slug())[5:]}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' 
              
     def newslug(self):
         qmslug = f'{str(self.cave)}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' 
diff --git a/core/views/caves.py b/core/views/caves.py
index 616e69f..2a2e5b8 100644
--- a/core/views/caves.py
+++ b/core/views/caves.py
@@ -485,43 +485,46 @@ def qm(request,cave_id,qm_id,year,grade=None, blockname=None):
     '''Reports on one specific QM
     Fixed and working July 2022, for both CSV imported QMs 
     needs refactoring though.
-    For survex-imported QMs we are not getting unique objects returned, so the query needs fixing.
+    
+    290 has several QMS with the same number, grade, year (2108) and first 8 chars of the survexblock. This crashes things.
     '''
     year=int(year)
     
-    if blockname == 'None':
+    if blockname == '':
         # CSV import QMs, use old technique
         try:
             c=getCave(cave_id)
             manyqms=c.get_QMs()
-            qm=manyqms.get(number=qm_id,found_by__date__year=year, found_by__cave_slug=c.slug()) 
+            qm=manyqms.get(number=qm_id,expoyear=year) 
             return render(request,'qm.html', {'qm': qm})
         except QM.DoesNotExist:
+            raise
             return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'})
 
     else:
-        # survex import QMs, need to disambiguate with blockname
-        # slug = f'{str(self.cave)}-{self.found_by.date.year}-{self.blockname}{self.number}{self.grade}' 
-
         try:
             qmslug = f'{cave_id}-{year}-{blockname=}{qm_id}{grade}'
             c=getCave(cave_id)
             manyqms=c.get_QMs()
-            qm=manyqms.get(found_by__date__year=year, blockname=blockname, number=qm_id, grade=grade) 
-            if qm:
-                print(qm, f'{qmslug=}:{cave_id=} {year=} {qm_id=} {blockname=} {qm.expoyear=}')
-                return render(request,'qm.html', {'qm': qm})
+            qmqs=manyqms.filter(expoyear=year, blockname=blockname, number=qm_id, grade=grade) 
+            if len(qmqs) > 1:           
+                for q in qmqs:
+                    print(qmqs)
+                message = f'Multiple QMs with the same cave, year, number, grade AND first 8 chars of the survexblock name. Fix this in the survex file(s). {cave_id=} {year=} {qm_id=} {blockname=}'
+                return render(request,'errors/generic.html', {'message': message})
             else:
-                return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'})
+                qm=qmqs.get(expoyear=year, blockname=blockname, number=qm_id, grade=grade) 
+                if qm:
+                    print(qm, f'{qmslug=}:{cave_id=} {year=} {qm_id=} {blockname=} {qm.expoyear=}')
+                    return render(request,'qm.html', {'qm': qm})
+                else:
+                    raise
+                    return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'})
         except MultipleObjectsReturned:
-            if len(qm) > 1:           
-                for q in qm:
-                    print(qm)
-                return render(request,'qm.html', {'qm': qm[0]})
-            else:
-                return render(request,'qm.html', {'qm': qm})
+           raise
         except QM.DoesNotExist:
-            return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'})
+           raise
+           return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'})
 
  
 def get_qms(request, caveslug):
diff --git a/parsers/QMs.py b/parsers/QMs.py
index ab9ec0f..2aa9bbf 100644
--- a/parsers/QMs.py
+++ b/parsers/QMs.py
@@ -27,7 +27,11 @@ def parseCaveQMs(cave,inputFile):
     have the passage name, e.g. in 204/qm.csv
     C2000-204-39	B	Tree	Pitch in Cave Tree		treeumphant.28	Gosser Streamway
     The CSV file does not have the exact date for the QM, only the year, so links to
-    survex files might be ambiguous. But potentially useful?"""
+    survex files might be ambiguous. But potentially useful?
+    
+    Much of this code assumes that QMs are edited using troggle. This is not done so this code can be deleted.
+    All QMs are created afresh and this is all only run once on import on a fresh database.
+    """
 
     if cave=='204-steinBH':
         try:
@@ -59,7 +63,7 @@ def parseCaveQMs(cave,inputFile):
         return nqms
 
     #qmPath = settings.EXPOWEB+inputFile
-    qmPath = os.path.join(settings.EXPOWEB, inputFile)
+    qmPath = os.path.join(settings.EXPOWEB, inputFile) # why not use the pathlib stuff ?
 
     qmCSVContents = open(qmPath,'rU')
     dialect=csv.Sniffer().sniff(qmCSVContents.read())
@@ -73,20 +77,22 @@ def parseCaveQMs(cave,inputFile):
             n += 1
             year=int(line[0][1:5])
             logslug = f'PH_{int(year)}_{int(n):02d}'
+            # logbook placeholder code was previously here. No longer needed.
             #check if placeholder exists for given year, create it if not
-            message = " ! - "+ str(year) + " logbook: placeholder entry for '" + cave + "' created. DUMMY EXPEDITION ID. Should be re-attached to the actual trip."
-            if cave=='204-steinBH':
-                placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="204", title="placeholder for QMs in 204", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date(year, 1, 1),"cave_slug":str(steinBr), "slug": logslug})
-            elif cave=='234-Hauch':
-                placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="234", title="placeholder for QMs in 234", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date(year, 1, 1),"cave_slug":str(hauchHl)})
-            # if hadToCreate:
-                # print(message)
-                # DataIssue.objects.create(parser='QMs', message=message)
+            # message = " ! - "+ str(year) + " logbook: placeholder entry for '" + cave + "' created. DUMMY EXPEDITION ID. Should be re-attached to the actual trip."
+            # if cave=='204-steinBH':
+                # placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="204", title="placeholder for QMs in 204", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date(year, 1, 1),"cave_slug":str(steinBr), "slug": logslug})
+            # elif cave=='234-Hauch':
+                # placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="234", title="placeholder for QMs in 234", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date(year, 1, 1),"cave_slug":str(hauchHl)})
+            # # if hadToCreate:
+                # # print(message)
+                # # DataIssue.objects.create(parser='QMs', message=message)
             QMnum=re.match(r".*?-\d*?-X?(?P<numb>\d*)",line[0]).group("numb")
             newQM = QM()
-            newQM.found_by=placeholder
+            # newQM.found_by=placeholder
             newQM.number=QMnum
             newQM.cave = caveid
+            newQM.blockname = ""
             if line[1]=="Dig":
                 newQM.grade="D"
             else:
@@ -94,12 +100,12 @@ def parseCaveQMs(cave,inputFile):
             newQM.area=line[2]
             newQM.location_description=line[3]
             
-            # Troggle checks if QMs are completed by checking if they have a ticked_off_by trip. 
+            # Troggle will in future (?! - written in 2006) check if QMs are completed by checking if they have a ticked_off_by trip. 
             # In the table, completion is indicated by the presence of a completion discription.
             newQM.completion_description=line[4]
             newQM.nearest_station_description=line[5]
-            if newQM.completion_description:  
-                newQM.ticked_off_by=placeholder
+            # if newQM.completion_description:  
+                # newQM.ticked_off_by=placeholder
 
             newQM.comment=line[6]
             try:
@@ -139,15 +145,16 @@ def parse_KH_QMs(kh, inputFile):
         if res:
             res=res.groupdict()
             year=int(res['year'])
+            # logbook placeholder code was previously here. No longer needed.
             #check if placeholder exists for given year, create it if not
-            message = " ! - "+ str(year) + " logbook: placeholder entry for '161 KH' created. DUMMY EXPEDITION ID. Should be re-attached to the actual trip."
-            placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="161", title="placeholder for QMs in 161", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date((year), 1, 1),"cave_slug":str(kh)})
-            # if hadToCreate:
+            # message = " ! - "+ str(year) + " logbook: placeholder entry for '161 KH' created. DUMMY EXPEDITION ID. Should be re-attached to the actual trip."
+            # placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="161", title="placeholder for QMs in 161", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date((year), 1, 1),"cave_slug":str(kh)})
+            # # if hadToCreate:
                 # print(message)
                 # DataIssue.objects.create(parser='QMs', message=message)
             lookupArgs={
-                # inadequate now that the sequence numbers are not unique for survex-parsed QMs
-                'found_by':placeholder,
+                #'found_by':placeholder,
+                'blockname': "",
                 'expoyear':year,
                 'number':res['number'],
                 'cave': kh,
@@ -158,10 +165,10 @@ def parse_KH_QMs(kh, inputFile):
                 'location_description':res['description']
                 }
             instance, created = save_carefully(QM,lookupArgs,nonLookupArgs) 
-            if created:
-               message = " ! - "+ instance.code() + " QM entry for '161 KH' created. "
-               print(message)
-               DataIssue.objects.create(parser='QMs', message=message)
+            # if created:
+               # message = " ! - "+ instance.code() + " QM entry for '161 KH' created. "
+               # print(message)
+               # DataIssue.objects.create(parser='QMs', message=message)
             nqms += 1
     return nqms
             
diff --git a/parsers/survex.py b/parsers/survex.py
index fa92924..e4ec8b3 100644
--- a/parsers/survex.py
+++ b/parsers/survex.py
@@ -532,11 +532,7 @@ class LoadingSurvex():
         # we would have to create one. But that is not obligatory and no QMs loaded from CSVs have one
         
         # Older troggle/CSV assumes a logbook entry 'found_by' for each QM, with a date. 
-        # We have a date from the survexfile. This is needed for the absolute_url resolution..
-        
-        # We don't know if the survexfile has an associated logbook entry as there is no direct link
-        # so we create a dummy one anyway. We should make logbook entry links optional in QMs in future and
-        # remove this hack.
+        # We don't need this anymore so we don't need to create a placeholder logbook entry.
         qmyear = str(survexblock.date)[:4]
         blockname = survexblock.name[:7]
         logslug = f'D{int(qmyear)}_{blockname}_{int(qm_no):03d}'
@@ -548,27 +544,27 @@ class LoadingSurvex():
             place = "oops"
        
         
-        message = f' ! - logbook dummy "{logslug}" {str(survexblock.date)[:11]} for cave "{caveslug}" created.'
+        # message = f' ! - logbook dummy "{logslug}" {str(survexblock.date)[:11]} for cave "{caveslug}" created.'
 
-        placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=qmyear, 
-                        place=place, 
-                        title="placeholder for survex QM", 
-                        text=message, 
-                        entry_type="DUMMY", 
-                        expedition_id=1, 
-                        defaults={"date": survexblock.date,"cave_slug":caveslug, "slug": logslug})
+        # placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=qmyear, 
+                        # place=place, 
+                        # title="placeholder for survex QM", 
+                        # text=message, 
+                        # entry_type="DUMMY", 
+                        # expedition_id=1, 
+                        # defaults={"date": survexblock.date,"cave_slug":caveslug, "slug": logslug})
         # print(insp+message)
         # DataIssue.objects.create(parser='survex', message=message)
   
         try:
             qm = QM.objects.create(number=qm_no,
-                                            # nearest_station=a_survex_station_object, # can be null
+                                              # nearest_station=a_survex_station_object, # can be null
                                               nearest_station_description=qm_resolve_station,
                                               nearest_station_name=qm_nearest,
                                               grade=qm_grade.upper(),
                                               location_description=qm_notes,
                                               blockname = blockname, # only set for survex-imported QMs
-                                              found_by = placeholder,
+                                              # found_by = placeholder,
                                               expoyear = str(survexblock.date.year),
                                               cave = survexblock.survexfile.cave)
             qm.save
diff --git a/templates/qm.html b/templates/qm.html
index 4bcc25d..a63b903 100644
--- a/templates/qm.html
+++ b/templates/qm.html
@@ -34,8 +34,8 @@
 {% if qm.cave %}
 <a href="{% url 'caveQMs' qm.cave|safe %}">{{ qm.cave|safe }} QMs</a> <br>
 {% else %}
-    {% if qm.found_by.cave %}
-    <a href="{% url 'caveQMs' qm.found_by.cave|safe %}">{{ qm.found_by.cave|safe }} QMs</a> <br>
+    {% if qm.cave %}
+    <a href="{% url 'caveQMs' qm.cave|safe %}">{{ qm.cave|safe }} QMs</a> <br>
     {% endif %}
 {% endif %}
 <a href="/{{ qm.cave.url }}">{{ qm.cave|safe }} cave description</a> 
@@ -49,8 +49,10 @@
 <h3>Grade</h3>
 {{qm.grade}}
 
+{% if qm.found_by %}
 <h3>Creation</h3>
 Found by <a href="{{qm.found_by.get_absolute_url}}">{{qm.found_by}}</a> on {{qm.found_by.date}}.
+{% endif %}
 
 <h3>Completion</h3>
 {% if ticked_off_by %}