summaryrefslogtreecommitdiff
path: root/ishtar_common/management/commands/ishtar_maintenance.py
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common/management/commands/ishtar_maintenance.py')
-rw-r--r--ishtar_common/management/commands/ishtar_maintenance.py135
1 files changed, 117 insertions, 18 deletions
diff --git a/ishtar_common/management/commands/ishtar_maintenance.py b/ishtar_common/management/commands/ishtar_maintenance.py
index 4f050088e..d57fb575e 100644
--- a/ishtar_common/management/commands/ishtar_maintenance.py
+++ b/ishtar_common/management/commands/ishtar_maintenance.py
@@ -1,14 +1,18 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from argparse import RawTextHelpFormatter
import csv
import datetime
import os
+import tempfile
+import shutil
import sys
from django.apps import apps
from django.conf import settings
+from django.contrib.auth.management import create_permissions
+from django.core.exceptions import FieldDoesNotExist
from django.core.management.base import BaseCommand, CommandError
from django.template.defaultfilters import slugify
@@ -28,8 +32,12 @@ if not os.path.exists(log_path):
os.mkdir(log_path, mode=0o770)
-def task_update_search_vectors(quiet=False, log=False):
+def task_update_search_vectors(options):
+ quiet = options.get("quiet", False)
+ log = options.get("log", False)
for model in apps.get_models():
+ if options.get('model', None) and model.__name__ != options['model']:
+ continue
if not hasattr(model, "update_search_vector") or \
not (getattr(model, "BASE_SEARCH_VECTORS", None) or
getattr(model, "INT_SEARCH_VECTORS", None) or
@@ -64,8 +72,12 @@ def task_update_search_vectors(quiet=False, log=False):
_end_task(changed_nb, msg, quiet, store_results, log, log_name, csv_cols)
-def task_check_cached_label(quiet=False, log=False):
+def task_check_cached_label(options):
+ quiet = options.get("quiet", False)
+ log = options.get("log", False)
for model in apps.get_models():
+ if options.get('model', None) and model.__name__ != options['model']:
+ continue
if model.__name__.startswith("Historical"):
continue
if hasattr(model, "CACHED_LABELS") and model.CACHED_LABELS:
@@ -116,6 +128,32 @@ def task_check_cached_label(quiet=False, log=False):
_end_task(changed_nb, msg, quiet, store_results, log, log_name, csv_cols)
+def task_update_external_id(options):
+ quiet = options.get("quiet", False)
+ for model in apps.get_models():
+ if options.get('model', None) and model.__name__ != options['model']:
+ continue
+ if model.__name__.startswith("Historical"):
+ continue
+ if not bool(
+ [k for k in dir(model) if k == "external_id"]):
+ continue
+ msg = "-> processing {}: ".format(model._meta.verbose_name)
+ ln = model.objects.count()
+ for idx, item in enumerate(model.objects.all()):
+ item.skip_history_when_saving = True
+ item.external_id = ""
+ item.complete_identifier = ""
+ item._no_move = True
+ if not quiet:
+ cmsg = "\r{} {}/{}".format(msg, idx + 1, ln)
+ sys.stdout.write(cmsg)
+ sys.stdout.flush()
+ item.save()
+ if not quiet:
+ sys.stdout.write("\n")
+
+
def _end_task(changed_nb, msg, quiet, store_results, log, log_name, csv_cols):
if not quiet:
if changed_nb:
@@ -134,7 +172,8 @@ def _end_task(changed_nb, msg, quiet, store_results, log, log_name, csv_cols):
sys.stdout.write(f"log: {path} written.\n")
-def task_main_image(quiet=False, log=False):
+def task_main_image(options):
+ quiet = options.get("quiet", False)
for model in apps.get_models():
if not issubclass(model, models_common.DocumentItem):
continue
@@ -155,14 +194,44 @@ def task_main_image(quiet=False, log=False):
sys.stdout.write(f"{nb} main image fixed for {model.__name__}\n")
-def task_missing_parcels(quiet=False, log=False):
+def task_regenerate_qrcodes(options):
+ quiet = options.get("quiet", False)
+ secure = not options['no-https']
+ for model in apps.get_models():
+ if options.get('model', None) and model.__name__ != options['model']:
+ continue
+ try:
+ model._meta.get_field('qrcode')
+ except FieldDoesNotExist:
+ continue
+ msg = "-> processing {}: ".format(model._meta.verbose_name)
+ ln = model.objects.count()
+ tmpdir = tempfile.mkdtemp("-qrcode")
+ for idx, obj in enumerate(model.objects.all()):
+ obj.skip_history_when_saving = True
+ obj._no_move = True
+ if not quiet:
+ cmsg = "\r{} {}/{}".format(msg, idx + 1, ln)
+ sys.stdout.write(cmsg)
+ sys.stdout.flush()
+ obj.generate_qrcode(secure=secure, tmpdir=tmpdir)
+ shutil.rmtree(tmpdir)
+ if not quiet:
+ sys.stdout.write("\n")
+
+
+def task_regenerate_permissions(options):
+ for app in ['ishtar_common', 'archaeological_operations',
+ 'archaeological_context_records',
+ 'archaeological_finds', 'archaeological_warehouse']:
+ create_permissions(apps.get_app_config(app))
+
+
+def task_missing_parcels(options):
+ quiet = options.get("quiet", False)
Parcel = apps.get_model("archaeological_operations", "Parcel")
q = Parcel.objects.filter(context_record__isnull=False, operation=None)
nb = q.count()
- if not nb:
- if not quiet:
- sys.stdout.write("No parcel to fix.\n")
- return
for idx, parcel in enumerate(q.all()):
if not quiet:
sys.stdout.write(f"\r[{percent(idx, nb)}] {idx + 1}/{nb}")
@@ -175,6 +244,13 @@ def task_missing_parcels(quiet=False, log=False):
parcel.save()
if not quiet:
sys.stdout.write("\n")
+ if not options.get("clean", False):
+ return
+ q = Parcel.objects.filter(associated_file=None, operation=None)
+ nb = q.count()
+ q.delete()
+ if not quiet:
+ sys.stdout.write(f"{nb} orphan parcel deleted.\n")
def percent(current, total):
@@ -186,21 +262,34 @@ def get_time():
TASKS = {
- "main_image": {
+ "fix_main_image": {
"help": "for items with images and no main image, put the first one created as a main image",
"action": task_main_image,
},
- "cached_label": {
- "help": "regenerate cached label on all tables",
+ "fix_missing_parcels": {
+ "help": "fix lost parcel association on operation from context records. "
+ "With --clean option delete orphan parcels.",
+ "action": task_missing_parcels,
+ },
+ "update_cached_label": {
+ "help": "regenerate cached label",
"action": task_check_cached_label,
},
+ "update_permissions": {
+ "help": "regenerate basic model permissions",
+ "action": task_regenerate_permissions,
+ },
+ "update_qrcodes": {
+ "help": "regenerate qrcodes",
+ "action": task_regenerate_qrcodes,
+ },
"update_search_vector": {
- "help": "regenerate search vectors on all tables",
+ "help": "regenerate search vectors",
"action": task_update_search_vectors,
},
- "operation_missing_parcels": {
- "help": "fix lost parcel association on operation from context records.",
- "action": task_missing_parcels,
+ "update_external_ids": {
+ "help": "regenerate external and complete ID",
+ "action": task_update_external_id,
},
}
@@ -226,22 +315,32 @@ class Command(BaseCommand):
)
parser.add_argument("task", help=task_help)
parser.add_argument(
+ '--model', type=str, default='', dest='model',
+ help='Specific model to update')
+ parser.add_argument(
"--quiet", dest="quiet", action="store_true", help="Quiet output"
)
parser.add_argument(
"--log", dest="log", action="store_true", help="Log into a file"
)
+ parser.add_argument(
+ '--no-https', dest='no-https', action='store_true',
+ default=False,
+ help="[update_qrcodes] Use this parameter if https is not available")
+ parser.add_argument(
+ '--clean', dest='clean', action='store_true',
+ default=False,
+ help="[operation_missing_parcels] Delete orphan parcel after fix")
def handle(self, *args, **options):
if options["task"] not in TASKS.keys():
msg = f"{options['task']} is not a valid task. Available tasks are:\n"
msg += "\n".join(TASKS.keys())
raise CommandError(msg)
- log = options["log"]
quiet = options["quiet"]
if not quiet:
sys.stdout.write(f"[{get_time()}] Processing task {options['task']}\n")
- errors = TASKS[options["task"]]["action"](quiet=quiet, log=log)
+ errors = TASKS[options["task"]]["action"](options)
if not errors:
if not quiet:
sys.stdout.write(f"[{get_time()}] Task {options['task']} finished\n")