summaryrefslogtreecommitdiff
path: root/archaeological_warehouse/management/commands/migrate_to_new_container_management.py
blob: 24ec078bf4bd1f7b14bc796f47cd4cbe408166fe (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
120
121
122
123
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2020 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# See the file COPYING for details.

import csv
import sys

from django.core.management.base import BaseCommand
from django.template.defaultfilters import slugify
from archaeological_warehouse import models


class Command(BaseCommand):
    help = 'Migrate to new container management (v3.0.6)'

    def handle(self, *args, **options):
        to_update = models.Container.objects.filter(
            division__pk__isnull=False, parent__isnull=True)
        container_types = {}
        created_nb = 0
        for div_type in models.WarehouseDivision.objects.all():
            container_type, c = models.ContainerType.objects.get_or_create(
                txt_idx=slugify(div_type.label),
                defaults={"label": div_type.label,
                          "stationary": True})
            if c:
                created_nb += 1
                sys.stdout.write("-> {} created\n".format(
                    div_type.label))
            container_types[div_type.pk] = container_type
        for wdl in models.WarehouseDivisionLink.objects.all():
            wdl.container_type = container_types[wdl.division_id]
            wdl.save()

        if created_nb:
            sys.stdout.write("* {} container types created\n".format(
                created_nb))
        to_be_done = to_update.count()
        created_nb = 0
        potential_duplicate = {}
        data = [("id", "warehouse", "reference",
                 "old cached division", "new cached division")]
        for idx, container in enumerate(to_update.values("id").all()):
            sys.stdout.write("* Updating: {}/{}\r".format(idx + 1, to_be_done))
            sys.stdout.flush()
            try:
                container = models.Container.objects.get(pk=container["id"])
            except models.Container.DoesNotExist:
                continue  # already merged
            if container.responsible_id not in potential_duplicate:
                potential_duplicate[container.responsible_id] = {}
            parent = None
            cached_division = container.cached_division
            for division in container.division.order_by(
                    "division__order").all():
                ref = division.reference.strip()
                if not ref or ref == "-":
                    continue
                new_container, created = models.Container.objects.get_or_create(
                    reference=division.reference.strip(),
                    parent=parent,
                    container_type=container_types[
                        division.division.division_id],
                    location=container.responsible,
                    responsible=container.responsible)
                if created:
                    created_nb += 1
                    ref = "{} || {}".format(str(new_container.container_type),
                                            slugify(division.reference.strip()))
                    if ref not in potential_duplicate[container.responsible_id]:
                        potential_duplicate[container.responsible_id][ref] = []
                    if division.reference.strip() not in \
                            potential_duplicate[container.responsible_id][ref]:
                        potential_duplicate[container.responsible_id][
                            ref].append(division.reference.strip())
                parent = new_container
            if parent:
                q = models.Container.objects.filter(
                    location=container.location,
                    container_type=container.container_type,
                    parent=parent,
                    reference=container.reference).exclude(pk=container.pk)
                if q.count():
                    other = q.all()[0]
                    other.merge(container)
                else:
                    container.parent = parent
                    container.save()
                data.append((container.id, str(container.responsible),
                             container.reference, cached_division,
                             container._generate_cached_division()))
        sys.stdout.write("\n* Potential duplicate:")
        for warehouse_id in potential_duplicate.keys():
            warehouse = models.Warehouse.objects.get(pk=warehouse_id)
            for ref in potential_duplicate[warehouse_id]:
                items = potential_duplicate[warehouse_id][ref]
                if len(items) > 1:
                    sys.stdout.write(
                        "\n-> {}: {}".format(warehouse, " ; ".join(items)))
        print("")
        sys.stdout.write("* {} container created\n".format(created_nb))
        if not data:
            return
        with open("new_containers.csv", 'w+') as f:
            w = csv.writer(f)
            w.writerows(data)
        sys.stdout.write("-> check new containers in \"new_containers.csv\"\n")