diff --git a/core/TESTS/test_caves.py b/core/TESTS/test_caves.py
index 6704cd8..8390df5 100644
--- a/core/TESTS/test_caves.py
+++ b/core/TESTS/test_caves.py
@@ -182,8 +182,8 @@ class FixturePageTests(TestCase):
         content = response.content.decode()
         ph = r"284 <em>Seetrichter</em>"
         phmatch = re.search(ph, content)
-        with open('_cave_fix_caves.html', 'w') as f:
-            f.write(content)
+        # with open('_cave_fix_caves.html', 'w') as f:
+            # f.write(content)
         self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph + "'")
 
 # Although the Cave object exists, it looks like we get a bad slug error when trying to get a QM page.
diff --git a/core/models/logbooks.py b/core/models/logbooks.py
index 4f29bb3..1ffe55d 100644
--- a/core/models/logbooks.py
+++ b/core/models/logbooks.py
@@ -45,8 +45,8 @@ class LogbookEntry(TroggleModel):
 
     date = (
         models.DateField()
-    )  # MJG wants to turn this into a datetime such that multiple Logbook entries on the same day can be ordered.ld()
-    expedition = models.ForeignKey(Expedition, blank=True, null=True, on_delete=models.CASCADE)  # yes this is double-
+    ) 
+    expedition = models.ForeignKey(Expedition, blank=True, null=True, on_delete=models.CASCADE)  
     title = models.CharField(max_length=200)
     cave_slug = models.SlugField(max_length=50, blank=True, null=True)
     place = models.CharField(
@@ -146,7 +146,6 @@ def writelogbook(year, filename):
         logbookfile = re.sub(r"<body>", "<body>\n" + frontmatter + endmatter, logbookfile)
     else:
         logbookfile = re.sub(r"<body>", f"<body>\n<h1>Expo {year}</h1>\n" + endmatter, logbookfile)
-    # print("  - frontmatter opened")
 
     dir = Path(settings.EXPOWEB) / "years" / str(year)
     filepath = Path(dir, filename)
@@ -253,17 +252,6 @@ class QM(TroggleModel):
             blocknamestr = ""
         return f"{cavestr}-{expoyearstr}-{self.number}{self.grade}{blocknamestr}"
 
-    # def get_completion_url(self):
-        # """assumes html file named is in same folder as cave description file
-        # WRONG - needs rewriting!"""
-        # cd = None
-        # if self.completion_description:
-            # try:
-                # dir = Path(self.cave.url).parent
-                # cd = dir / self.completion_description
-            # except:
-                # cd = None
-        # return cd
 
     def newslug(self):
         qmslug = f"{str(self.cave)}-{self.expoyear}-{self.blockname}{self.number}{self.grade}"
diff --git a/core/views/scans.py b/core/views/scans.py
index 4d9f851..7cb0b94 100644
--- a/core/views/scans.py
+++ b/core/views/scans.py
@@ -128,7 +128,7 @@ def is_cave(wallet, id):
             print(f" - Wallet {wallet} Failed to find cave object from id <{id}>")
             if id.lower() != "unknown" and id != "":
                 print(f" - adding <{id}> to pendingcaves DataIssues")
-                add_cave_to_pending_list(id, wallet, f"Wallet {wallet} - Could not find id <{id}>")
+                add_cave_to_pending_list(id, wallet, f"Wallet {wallet} - Could not find cave id <{id}>")
             return False
 
 def fillblankothers(w):
@@ -260,11 +260,15 @@ def walletslistperson(request, slug):
    
     manywallets = personwallet(p)
     expeditions = Expedition.objects.all()
-    print("--")
+    length_ug = 0.0
+    for w in manywallets:
+        for sb in w.survexblock_set.all():
+            length_ug += sb.legslength
     return render(
         request,
         "personwallets.html",
-        {"manywallets": manywallets, "settings": settings, "person": p, "expeditions": expeditions},
+        {"manywallets": manywallets, "settings": settings, "person": p, "expeditions": expeditions,           
+        "length_ug": length_ug}
     )
 
 
@@ -309,7 +313,6 @@ def walletslistyear(request, year):
     for w in manywallets:
         for sb in w.survexblock_set.all():
             length_ug += sb.legslength
-    print("--")
     return render(
         request,
         "yearwallets.html",
@@ -336,50 +339,52 @@ def cavewallets(request, caveid):
 
     # remove duplication. Sorting is done in the template
     # But this only gets wallets which have survex files attached..
-    wallets = set(Wallet.objects.filter(survexblock__survexfile__cave=cave))
+    # wallets = set(Wallet.objects.filter(survexblock__survexfile__cave=cave))
 
     # all the ones without a survexblock attached via a *ref, search for match in JSON
-    zilchwallets = set(Wallet.objects.exclude(survexblock__survexfile__cave=cave))
-    for z in zilchwallets:
-        zcaveid = z.cave()
-        if zcaveid:
-            cleanid = str(zcaveid).strip("' []'")
+    # zilchwallets = set(Wallet.objects.exclude(survexblock__survexfile__cave=cave))
+    # for z in zilchwallets:
+        # zcaveid = z.cave() # read JSON
+        # if zcaveid:
+            # cleanid = str(zcaveid).strip("' []\"")
  
-            if cleanid.find(',') != -1:
-                # it's a list of cave ids
-                wurl = f"/walletedit/{z.walletname.replace('#',':')}"
-                message = f" ! In {z.walletname}  cavewallets, we do not handle lists of cave ids yet '{cleanid}'"
-                print(message)
-                DataIssue.objects.update_or_create(parser="scans", message=message, url=wurl)
-                
-                # it's a list of cave ids as a string. Identify any orphan caves hidden here
-                ids = cleanid.split(',')
-                for i in ids:
-                    i = i.strip("' []'")
-                    if is_cave(z,i):
-                        fcave = Gcavelookup[i.strip("' []'")]  # just sets it to the last one found. nasty. bug waiting to happen 
-                
-            elif cleanid in Gcavelookup:
-                fcave = Gcavelookup[cleanid]
-                if str(fcave.slug()) == caveid:
-                    # print(f' - Found one ! {z.walletname=} {zcaveid=}')
-                    wallets.add(z)
-            elif f"1623-{cleanid}" in Gcavelookup: # special hack for all the old wallets which are 1623
-                fcave = Gcavelookup[f"1623-{cleanid}"]
-                if str(fcave.slug()) == caveid:
-                    # print(f' - Found one ! {z.walletname=} {zcaveid=}')
-                    wallets.add(z)
-            elif cleanid in ['surface', 'unknown', '']:
-                # message = f" ! In {z.walletname} cavewallets, ignoring '{cleanid}' as not a cave"
+            # if cleanid.find(',') != -1:
+                # # it's a list of cave ids
+                # wurl = f"/walletedit/{z.walletname.replace('#',':')}"
+                # message = f" ! In {z.walletname}  cavewallets, we do not handle lists of cave ids yet '{cleanid}'"
                 # print(message)
-                pass
-            else:
-                wurl = f"/walletedit/{z.walletname.replace('#',':')}"
-                message = f" ! In {z.walletname} cavewallets, there is an unrecognised cave name '{cleanid}', adding to pending list."
-                print(message)
-                DataIssue.objects.update_or_create(parser="scans", message=message, url=wurl)
-                add_cave_to_pending_list(cleanid, z, f"an unrecognised cave name in {z.walletname}") 
+                # DataIssue.objects.update_or_create(parser="scans", message=message, url=wurl)
+                
+                # # it's a list of cave ids as a string. Identify any orphan caves hidden here
+                # ids = cleanid.split(',')
+                # for i in ids:
+                    # i = i.strip("' []'")
+                    # if is_cave(z,i):
+                        # fcave = Gcavelookup[i.strip("' []'")]  # just sets it to the last one found. nasty. bug waiting to happen 
+                
+            # elif cleanid in Gcavelookup:
+                # fcave = Gcavelookup[cleanid]
+                # if str(fcave.slug()) == caveid:
+                    # # print(f' - Found one ! {z.walletname=} {zcaveid=}')
+                    # wallets.add(z)
+            # elif f"1623-{cleanid}" in Gcavelookup: # special hack for all the old wallets which are 1623
+                # fcave = Gcavelookup[f"1623-{cleanid}"]
+                # if str(fcave.slug()) == caveid:
+                    # # print(f' - Found one ! {z.walletname=} {zcaveid=}')
+                    # wallets.add(z)
+            # elif cleanid in ['surface', 'unknown', '']:
+                # # message = f" ! In {z.walletname} cavewallets, ignoring '{cleanid}' as not a cave"
+                # # print(message)
+                # pass
+            # else:
+                # wurl = f"/walletedit/{z.walletname.replace('#',':')}"
+                # message = f" ! In {z.walletname} cavewallets, there is an unrecognised cave name '{cleanid}', adding to pending list."
+                # print(message)
+                # DataIssue.objects.update_or_create(parser="scans", message=message, url=wurl)
+                # add_cave_to_pending_list(cleanid, z, f"an unrecognised cave name in {z.walletname}") 
 
+     # or now:
+    wallets = cave.wallets.all()
     manywallets = list(set(wallets))
     for w in manywallets:
         fillblankpeople(w)
@@ -387,11 +392,15 @@ def cavewallets(request, caveid):
         w.ticks = w.get_ticks()  # the complaints in colour form, from the json file on disc
         fixsurvextick(w, w.ticks)
     expeditions = Expedition.objects.all()
-    print("--")
+    length_ug = 0.0
+    for w in manywallets:
+        for sb in w.survexblock_set.all():
+            length_ug += sb.legslength    
     return render(
         request,
         "cavewallets.html",
-        {"manywallets": manywallets, "settings": settings, "cave": cave, "expeditions": expeditions},
+        {"manywallets": manywallets, "settings": settings, "cave": cave, "expeditions": expeditions,
+        "length_ug": length_ug}
     )
 
 
diff --git a/core/views/wallets_edit.py b/core/views/wallets_edit.py
index a9022f3..c99201b 100644
--- a/core/views/wallets_edit.py
+++ b/core/views/wallets_edit.py
@@ -244,7 +244,7 @@ def get_complaints(complaints, waldata, svxfiles, files, wallet, wurl):
                     w.caves.add(caveobject) # new many-to-many field
                     #print(w.caves)
             else:
-                # either single cave or the square barckets have been removed
+                # either single cave or the square brackets have been removed
                 ids = caveid.split(",")
                 for i in ids:
                     j = i.replace("'","").strip('[] "')
@@ -254,7 +254,6 @@ def get_complaints(complaints, waldata, svxfiles, files, wallet, wurl):
                         w.caves.add(caveobject)
                     except: 
                         pass
-            print(f'get_cave_leniently from "{waldata["cave"]}" => {caveobject}')
             # if not caveobject.url == waldata["description url"]:
             # complaints.append(f'The URL of cave description \"{waldata["description url"]}\" does not match the one on record for this cave which is: "{caveobject.url}". If the wallet is not for a cave, put a useful URL here.')
         except Cave.MultipleObjectsReturned:
@@ -573,7 +572,9 @@ def walletedit(request, path=None):
                 svxf = svxf.with_suffix(".svx")
             f = Path(settings.SURVEX_DATA) / svxf
             if not f.is_file():
-                message = f"Specified survex file '{fpath}' in database not found on disc"
+                message = f"! {wallet} Specified survex file '{svxf}' in wallet not found on disc, probably renamed."
+                DataIssue.objects.update_or_create(parser="wallets", message=message, url=wurl)  # set URL to this wallet folder
+
                 print(message)
                 continue
                 
@@ -582,7 +583,7 @@ def walletedit(request, path=None):
             try:
                 svxfile = SurvexFile.objects.get(path=fpath)
             except:
-                message = f"Specified survex file '{fpath}'not found? database may be empty. Exception."
+                message = f"Specified and present survex file '{fpath}'not found in db. Database may be empty. Exception."
                 print(message)
                 # This failure will also get picked up by the "S" colour code red or orange
             try:
diff --git a/parsers/caves.py b/parsers/caves.py
index fe8c92c..b7b6c4c 100644
--- a/parsers/caves.py
+++ b/parsers/caves.py
@@ -107,7 +107,7 @@ def add_cave_to_pending_list(id, wallet, message):
     """(id, f"Wallet {wallet} - Could not find id <{id}>")
     """
     wurl = f"/walletedit/{wallet.walletname}".replace('#', ':')
-    DataIssue.objects.create(parser="wallets", message=message, url=wurl)
+    DataIssue.objects.update_or_create(parser="wallets", message=message, url=wurl)
 
 def create_new_cave(svxpath, svxid=None, msg=None):
     """This is called only when a new survex file is edited online which has a path on the
diff --git a/templates/cavewallets.html b/templates/cavewallets.html
index ffc4034..315164a 100644
--- a/templates/cavewallets.html
+++ b/templates/cavewallets.html
@@ -23,6 +23,8 @@ traced to produce Tunnel or Therion drawings and eventually the final complete c
 {% include 'wallet_table.html' %}
 <p>Note that names in italics are copied from the related survex file block name.
 <br />
+<p>Total underground survey length: {{length_ug|floatformat:"1g"}} m
+<br />
 <table width=95%>
 <tr><th>Wallet</th><th width=13%>Wallet Date</th><th>Wallet Name</th><th width=25%>People</th><th>Scans</th><th>Survex blocks</th><th>Drawings using these scans</th></tr>
 {% for wallet in manywallets|dictsort:"walletname" %}
diff --git a/templates/personwallets.html b/templates/personwallets.html
index 4f5a403..526e142 100644
--- a/templates/personwallets.html
+++ b/templates/personwallets.html
@@ -22,6 +22,8 @@ traced to produce Tunnel or Therion drawings and eventually the final complete c
 {% include 'wallet_table.html' %}
 <p>Note that names in italics are copied from the related survex file block name.
 <br />
+<p>Total underground survey length: {{length_ug|floatformat:"1g"}} m
+<br />
 <table width=95%>
 <tr><th>Wallet</th><th width=13%>Wallet Date</th><th>Wallet Name</th><th width=28%>Team</th><th width=8%>Cave(s)</th><th>Scans</th><th>Survex blocks</th><th>Drawings using these scans</th></tr>
 {% for wallet in manywallets|dictsort:"walletname" %}
diff --git a/templates/walletform.html b/templates/walletform.html
index ef07665..9b90ba8 100644
--- a/templates/walletform.html
+++ b/templates/walletform.html
@@ -184,7 +184,7 @@ and <em>also</em> the exported files in standard formats: svx, svg etc. See why
            <label for="cave">Cave ID (only needed if no survex file yet)</label>
            <input {% if not user.username %} disabled{% endif %} 
            label = "Cave" name = "cave" size="12"
-           title="Single cave id e.g. 2017-DM-01 or 1623-256. Not a list. "
+           title="Single cave id or comma-separated list e.g. 2017-DM-01, 1623-256. "
            placeholder="{{cave}}" value="{{cave}}"  /> 
     <br>        
            <label for="psg">Survey area (wallet name)</label>