summaryrefslogtreecommitdiff
path: root/ishtar_common/management/commands/ishtar_operation_fix_merged_towns.py
blob: f7613b1b4c4de9c9cd4b7550b4f57fb22d5c771c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import csv
import datetime
import os
import sys

from django.conf import settings
from django.core.management.base import BaseCommand

from ishtar_common.models import Town
from archaeological_operations.models import Operation

log_path = os.sep.join([settings.ROOT_PATH, "logs"])
if not os.path.exists(log_path):
    os.mkdir(log_path, mode=0o770)


def percent(current, total):
    return f"{(current + 1) / total * 100:.1f}".rjust(4, "0") + "%"


def get_time():
    return datetime.datetime.now().isoformat().split(".")[0]


class Command(BaseCommand):
    help = "Verification of city attachment (old/new) of operations by year"

    def add_arguments(self, parser):
        parser.add_argument(
            "--log", dest="log", action="store_true", help="Log into a file"
        )

    def handle(self, *args, **options):
        q = Town.objects.filter(numero_insee__contains='-')
        checked = []
        ln = q.count()
        fixed = 0
        store_results = []
        for idx, result in enumerate(q.values_list("numero_insee", "id")):
            sys.stdout.write(f"\r* checking towns and associated operations {idx + 1}/{ln}" + " " * 20)
            sys.stdout.flush()
            num_insee, id_town = result
            base_insee, year = num_insee.split("-")
            if base_insee in checked:
                continue
            try:
                years = [(int(year), id_town)]
            except ValueError:
                continue
            checked.append(base_insee)
            q2 = Town.objects.filter(numero_insee__startswith=base_insee + "-").exclude(pk=id_town)
            for other_insee, other_id in q2.values_list("numero_insee", "id"):
                years.append((int(other_insee.split("-")[-1]), other_id))
            years = list(sorted(years))
            q3 = Town.objects.filter(numero_insee=base_insee)
            if not q3.count():
                continue
            base_town = q3.all()[0]
            previous_year = 0
            ids = [base_town.pk]
            years.append((base_town.year, base_town.pk))
            all_towns = [base_town] + [t for t in Town.objects.filter(numero_insee__startswith=base_insee + "-")]
            for idx_y, yt in enumerate(years):
                year, town_id = yt
                is_last = idx_y == len(years) - 1
                if is_last:  # last town do not take the current town
                    ids = ids[1:]
                q4 = Operation.objects.filter(towns__pk__in=ids)
                if is_last:
                    q4 = q4.filter(year__gt=year)
                else:
                    q4 = q4.filter(year__lte=years[idx_y + 1][0])
                if previous_year:
                    q4 = q4.filter(year__gt=previous_year)
                if not q4.count():
                    previous_year = year
                    ids.append(town_id)
                    continue
                town = Town.objects.get(pk=town_id)
                other_town = [t for t in all_towns if t.pk != town_id]
                for operation in q4.all():
                    sys.stdout.write(f"\r* {idx + 1}/{ln} - fixing {operation}" + " " * 20)
                    sys.stdout.flush()
                    fixed += 1
                    store_results.append((operation.pk, str(operation), f'{town.name} ({town.numero_insee})'))
                    operation.skip_history_when_saving = True
                    if town not in list(operation.towns.all()):
                        operation.towns.add(town)
                    if town.main_geodata:
                        if town.main_geodata_id not in operation.geodata.values_list("id", flat=True):
                            operation.geodata.add(town.main_geodata)
                        if not operation.main_geodata or operation.main_geodata in [t.main_geodata for t in other_town]:
                            operation.main_geodata = town.main_geodata
                            operation.save()
                    for t in other_town:
                        operation.towns.remove(t)
                previous_year = year
                ids.append(town_id)

        if fixed:
            cmsg = f"\r{fixed} operation(s) fixed" + 120 * " " + "\n"
        else:
            cmsg = "\r" + " " * 120 + "\n"
        sys.stdout.write(cmsg)
        log = options.get("log", False)
        if log and fixed:
            log_name = "operation-fix-merged-towns"
            csv_cols = ["id", "operation", "town"]
            filename = f"{get_time().replace(':', '')}-{log_name}.csv"
            path = os.sep.join([log_path, filename])
            with open(path, 'w+') as fle:
                writer = csv.writer(fle)
                writer.writerow(csv_cols)
                writer.writerows(store_results)
            sys.stdout.write(f"log: {path} written.\n")