summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2025-12-12 08:30:22 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2025-12-12 08:30:22 +0100
commit10177fbddd94fd4ca098fb8319ba2e6baddabad5 (patch)
tree31b0a2fc07472631e9744c1013ca64ffe66fde38
parent948696a25ef56e32bc04b93fd8802f45090ee6ba (diff)
downloadIshtar-10177fbddd94fd4ca098fb8319ba2e6baddabad5.tar.bz2
Ishtar-10177fbddd94fd4ca098fb8319ba2e6baddabad5.zip
🐛 treatment container history: fix history on container move (refs #6532)
-rw-r--r--archaeological_finds/models_finds.py22
-rw-r--r--archaeological_finds/models_treatments.py17
-rw-r--r--archaeological_finds/tests.py2
-rw-r--r--archaeological_warehouse/forms.py58
-rw-r--r--archaeological_warehouse/models.py3
-rw-r--r--archaeological_warehouse/tests.py70
-rw-r--r--ishtar_common/management/commands/migrate_find_container_v4_2.py4
7 files changed, 146 insertions, 30 deletions
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 0d7ee8b71..4b7536735 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -2428,11 +2428,11 @@ class Find(
@property
def has_packaging_for_current_container(self):
- return FindTreatment.objects.filter(find=self, location_type__in=["B", "C"])
+ return FindTreatment.objects.filter(find=self, location_type__in=["B", "C"]).exists()
@property
def has_packaging_for_reference_container(self):
- return FindTreatment.objects.filter(find=self, location_type__in=["B", "R"])
+ return FindTreatment.objects.filter(find=self, location_type__in=["B", "R"]).exists()
def public_representation(self):
dct = super(Find, self).public_representation()
@@ -3404,8 +3404,10 @@ class Find(
:param full_location: provided if update is triggered from container
"""
if getattr(self, "_container_fisrt_full_location", False) \
+ or not self.pk \
or self.has_packaging_for_current_container:
return False
+
self._container_fisrt_full_location = True
if self.container:
if not full_location:
@@ -3421,6 +3423,9 @@ class Find(
if return_value:
return ""
self.container_fisrt_full_location = ""
+ Find.objects.filter(pk=self.pk).update(
+ container_fisrt_full_location=self.container_fisrt_full_location
+ )
return True
def update_ref_full_location(self, full_location=None, return_value=False):
@@ -3429,8 +3434,11 @@ class Find(
:param full_location: provided if update is triggered from container
"""
if getattr(self, "_container_ref_fisrt_full_location", False) \
+ or not self.pk \
+ or self.has_packaging_for_current_container \
or self.has_packaging_for_reference_container:
return False
+ # if current container has already changed - do not change first
self._container_ref_fisrt_full_location = True
if self.container_ref:
if not full_location:
@@ -3446,6 +3454,9 @@ class Find(
if return_value:
return ""
self.container_ref_fisrt_full_location = ""
+ Find.objects.filter(pk=self.pk).update(
+ container_ref_fisrt_full_location=self.container_ref_fisrt_full_location
+ )
return True
def update_full_location(self):
@@ -3514,9 +3525,7 @@ class Find(
except Container.DoesNotExist:
pass
- if self.update_full_location():
- self.save()
- return True
+ self.update_full_location()
updated = self.update_external_id(save=False)
if updated:
@@ -3694,7 +3703,8 @@ class FindTreatment(models.Model):
on_delete=models.CASCADE
)
full_location = models.TextField(_("Full location"), default="", blank=True)
- location_type = models.CharField(_("Location type"), max_length=1, choices=LOCATION_TYPE,
+ location_type = models.CharField(_("Location type"), max_length=1,
+ choices=LOCATION_TYPE,
default="C")
class Meta:
diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py
index 429c9c3f3..24010984f 100644
--- a/archaeological_finds/models_treatments.py
+++ b/archaeological_finds/models_treatments.py
@@ -819,6 +819,23 @@ class Treatment(
post_save.connect(cached_label_changed, sender=Treatment)
+def treatment_attached_changed(sender, **kwargs):
+ # force full location
+ instance = kwargs.get("instance", None)
+ find_pk_set = kwargs.get("pk_set", None)
+ if not find_pk_set or not instance:
+ return
+ for find_id in find_pk_set:
+ q = FindTreatment.objects.filter(find_id=find_id, treatment_id=instance.pk)
+ if not q.count():
+ continue
+ for ft in q.all():
+ ft.generate_full_location()
+
+
+m2m_changed.connect(treatment_attached_changed, sender=Treatment.finds.through)
+
+
def pre_delete_treatment(sender, **kwargs):
treatment = kwargs.get("instance")
for find in Find.objects.filter(upstream_treatment=treatment).all():
diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py
index e84d86836..889742ba2 100644
--- a/archaeological_finds/tests.py
+++ b/archaeological_finds/tests.py
@@ -2308,8 +2308,6 @@ class FindQATest(FindInit, TestCase):
value = check[k]
value2 = check[k]
if k == "container" and data["qa-packaging-container_to_change"] == "reference":
- # if current not set -> auto set container to container_ref
- value = check["container_ref"]
# current set for find_1 -> keep it
value2 = Container.objects.get(reference="Test2 base")
if k == "container_ref" and data["qa-packaging-container_to_change"] == "current":
diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py
index 1d3b9d1a0..533315fbe 100644
--- a/archaeological_warehouse/forms.py
+++ b/archaeological_warehouse/forms.py
@@ -45,6 +45,7 @@ from archaeological_finds.models import (
ConservatoryState,
Find,
FindBasket,
+ FindTreatment,
IntegrityType,
MaterialType,
ObjectType,
@@ -853,27 +854,40 @@ class QAContainerMoveForm(QABasePackagingForm):
def save(self, items, user):
location_id = self.cleaned_data.get("qalocation", None)
parent_id = self.cleaned_data.get("qaparent", None)
+
+ changed = []
for container in self.items:
- changed = False
+ # move the container
if parent_id and parent_id != container.parent_id:
container.parent_id = parent_id
- changed = True
+ models.Container.objects.filter(id=container.id).update(
+ parent_id=parent_id
+ )
+ changed.append(container)
if location_id and location_id != container.location_id:
container.location_id = location_id
- # remove parent if do not share the same location
- if not changed and container.parent \
- and container.parent.location != container.location:
- container.parent = None
- changed = True
- if changed:
- container.save()
+ models.Container.objects.filter(id=container.id).update(
+ location_id=location_id
+ )
+ if container not in changed:
+ # remove parent if do not share the same location
+ if container.parent \
+ and container.parent.location != container.location:
+ container.parent = None
+ models.Container.objects.filter(id=container.id).update(
+ parent=None
+ )
+ changed.append(container)
if not self.cleaned_data.get("create_treatment", False):
+ for container in changed:
+ container.save()
return
treat_type = TreatmentType.objects.get(pk=self.cleaned_data['treatment_type'])
treat_state = TreatmentState.get_completed_state()
try:
- location = models.Warehouse.objects.get(pk=self.cleaned_data.get("qalocation", None))
+ location = models.Warehouse.objects.get(
+ pk=self.cleaned_data.get("qalocation", None))
except models.Warehouse.DoesNotExist:
location = None
@@ -893,8 +907,30 @@ class QAContainerMoveForm(QABasePackagingForm):
q = Find.objects.filter(Q(container=container) | Q(container_ref=container))
if not q.count():
continue
+ loca = container.generate_full_location()
for find in q.all():
- t.finds.add(find)
+ if find.update_current_full_location():
+ Find.objects.filter(pk=find.id).update(
+ container_fisrt_full_location=find.container_fisrt_full_location
+ )
+ if find.update_ref_full_location():
+ Find.objects.filter(pk=find.id).update(
+ container_ref_fisrt_full_location=find.container_ref_fisrt_full_location
+ )
+ location_type = "C"
+ if find.container_ref == container:
+ if find.container == container:
+ location_type = "B"
+ else:
+ location_type = "R"
+ FindTreatment.objects.create(
+ find=find, treatment=t,
+ location_type=location_type,
+ full_location=loca
+ )
t.save() # force find container history
+ for container in changed: # container post treatment after save
+ container.save()
+
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index be6c69eec..d4ddca3d4 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -1346,7 +1346,8 @@ class Container(
if not self.pk:
return False
if self.calculated_weight != self._calculate_weight():
- Container.objects.filter(pk=self.pk).update(calculated_weight=self.calculated_weight)
+ Container.objects.filter(pk=self.pk).update(
+ calculated_weight=self.calculated_weight)
return True
return False
diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py
index 20e0e20f0..c8e16a50c 100644
--- a/archaeological_warehouse/tests.py
+++ b/archaeological_warehouse/tests.py
@@ -628,9 +628,12 @@ class ContainerQATest(FindInit, TestCase):
def test_move(self):
c = Client()
- find_0 = self.finds[0]
+ find_0 = Find.objects.get(pk=self.finds[0].pk)
find_0.container = self.container_3
+ find_0.container_ref = self.container_3
find_0.save()
+ find = Find.objects.get(pk=find_0.pk)
+ self.assertTrue(find.container_fisrt_full_location)
pks_1 = f"{self.container_3.pk}-{self.container_4.pk}"
pks_2 = str(self.container_1.pk)
@@ -653,18 +656,33 @@ class ContainerQATest(FindInit, TestCase):
packaging = TreatmentType.objects.get(txt_idx="packaging")
- def check_location_of_children():
+ def check_location_of_children(idx):
# check change location of children
container3 = models.Container.objects.get(pk=self.container_3.pk)
self.assertEqual(container3.location, self.alt_warehouse)
container4 = models.Container.objects.get(pk=self.container_4.pk)
self.assertEqual(container4.location, self.alt_warehouse)
- def check_reinit_parent():
+ def check_reinit_parent(idx):
# reinit parent when not provided and location changed
container = models.Container.objects.get(pk=self.container_3.pk)
self.assertEqual(container.parent, None)
+ def init_treatment(find_0):
+ # create a first packaging treatment
+ treat_state = TreatmentState.get_completed_state()
+ t = Treatment.objects.create(
+ container=self.container_3,
+ year=2024,
+ start_date=datetime.date(2024, 2, 29),
+ location=self.main_warehouse,
+ treatment_state=treat_state
+ )
+ treat_type = TreatmentType.objects.get(txt_idx="packaging")
+ t.treatment_types.add(treat_type)
+ t.save()
+ t.finds.add(find_0)
+ t.save() # force find container history
data_check_lst = [
(
@@ -674,6 +692,7 @@ class ContainerQATest(FindInit, TestCase):
{"parent": self.container_2},
0,
pks_1,
+ None,
None
),
(
@@ -683,6 +702,7 @@ class ContainerQATest(FindInit, TestCase):
{"location": self.alt_warehouse},
0,
pks_1,
+ None,
None
),
(
@@ -695,10 +715,24 @@ class ContainerQATest(FindInit, TestCase):
{"parent": self.container_2},
2,
pks_1,
+ None,
None
),
(
{
+ "qa-move-qaparent": self.container_2.pk,
+ "qa-move-create_treatment": True,
+ "qa-move-year": 2019,
+ "qa-move-treatment_type": packaging.pk,
+ },
+ {"parent": self.container_2},
+ 2,
+ pks_1,
+ None,
+ init_treatment
+ ),
+ (
+ {
"qa-move-qalocation": self.alt_warehouse.pk,
"qa-move-create_treatment": True,
"qa-move-year": 2019,
@@ -707,6 +741,7 @@ class ContainerQATest(FindInit, TestCase):
{"location": self.alt_warehouse},
2,
pks_1,
+ None,
None
),
(
@@ -716,7 +751,8 @@ class ContainerQATest(FindInit, TestCase):
{"location": self.alt_warehouse},
0,
pks_2,
- check_location_of_children
+ check_location_of_children,
+ None
),
(
{
@@ -725,12 +761,13 @@ class ContainerQATest(FindInit, TestCase):
{"location": self.alt_warehouse},
0,
pks_1,
- check_reinit_parent
+ check_reinit_parent,
+ None
),
]
for idx, lst in enumerate(data_check_lst):
- data, check, nb_treat, pks, extra_check = lst
+ data, check, nb_treat, pks, extra_check, pre_init = lst
# reinit
self.container_1.location = self.main_warehouse
self.container_1.parent = None
@@ -741,6 +778,12 @@ class ContainerQATest(FindInit, TestCase):
self.container_4.location = self.main_warehouse
self.container_4.parent = self.container_1
self.container_4.save()
+ find_0.save()
+ FindTreatment.objects.exclude(id__isnull=True).delete()
+ Treatment.objects.exclude(id__isnull=True).delete()
+
+ if pre_init:
+ pre_init(find_0)
init_nb_treat = Treatment.objects.count()
@@ -755,7 +798,7 @@ class ContainerQATest(FindInit, TestCase):
self.assertEqual(init_nb_treat + nb_treat, final_nb_treat)
if extra_check:
- extra_check()
+ extra_check(idx)
if not final_nb_treat:
self.assertEqual(FindTreatment.objects.filter(find=find_0).count(), 0)
@@ -771,6 +814,19 @@ class ContainerQATest(FindInit, TestCase):
self.assertTrue(ft.full_location)
self.assertTrue(ft.location_type)
+ find = Find.objects.get(pk=find_0.pk)
+ if pre_init:
+ # pre init add a packaging -> first full location is not changed
+ self.assertNotEqual(
+ find.container_fisrt_full_location,
+ find.container.generate_full_location()
+ )
+ else:
+ self.assertEqual(
+ find.container_fisrt_full_location,
+ find.container.generate_full_location()
+ )
+
class ContainerTest(FindInit, TestCase):
fixtures = WAREHOUSE_FIXTURES
diff --git a/ishtar_common/management/commands/migrate_find_container_v4_2.py b/ishtar_common/management/commands/migrate_find_container_v4_2.py
index ec0d8489e..35f5c256b 100644
--- a/ishtar_common/management/commands/migrate_find_container_v4_2.py
+++ b/ishtar_common/management/commands/migrate_find_container_v4_2.py
@@ -34,7 +34,7 @@ def migrate(log=True):
)
q = Find.objects.filter(Q(container__isnull=False) | Q(container_ref__isnull=False)).filter(
- container_fisrt_full_location=""
+ Q(container_fisrt_full_location="") | Q(container_ref_fisrt_full_location="")
)
total = q.count()
ref_time = datetime.datetime.now()
@@ -44,8 +44,6 @@ def migrate(log=True):
write_output(base_lbl, idx, total, ref_time)
if find.update_full_location():
changed.append(("Find", str(find), find.pk))
- find.no_post_process()
- find.save()
if not quiet:
sys.stdout.write(