#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2020-2025 Étienne Loks # 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 . # 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.location, responsible=container.location) 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 container.responsibility_id != container.responsible_id: container.responsibility_id = container.responsible_id container.save() 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")