diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-02-23 14:20:43 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-02-28 12:15:24 +0100 |
commit | 5e2331815b84e7f31f1b7cd02b3594e12811d66a (patch) | |
tree | e0e128bf80472f2947a5f69874b62c705f01b893 /archaeological_warehouse | |
parent | d713093cfabbfb8fe68caa4180de999ab70a3f71 (diff) | |
download | Ishtar-5e2331815b84e7f31f1b7cd02b3594e12811d66a.tar.bz2 Ishtar-5e2331815b84e7f31f1b7cd02b3594e12811d66a.zip |
Warehouse: localisations importer
Diffstat (limited to 'archaeological_warehouse')
-rw-r--r-- | archaeological_warehouse/models.py | 90 | ||||
-rw-r--r-- | archaeological_warehouse/tests.py | 70 |
2 files changed, 140 insertions, 20 deletions
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index e094436e1..71751fcbe 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -256,6 +256,10 @@ post_save.connect(post_save_cache, sender=WarehouseType) post_delete.connect(post_save_cache, sender=WarehouseType) +NO_DIVISION_ERROR = _( + "The division number {} has not been set for the warehouse {}.") + + class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, OwnPerms, MainItem, DivisionContainer, ValueGetter): SLUG = 'warehouse' @@ -361,6 +365,72 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, def __str__(self): return self.name + def get_container_type_by_place(self, place: int): + """ + Container type by place based on the default organisation of the + warehouse + + :param place: place number + :return: container type, other location or None, None + """ + q = WarehouseDivisionLink.objects.filter( + warehouse=self).order_by('order') + previous_container_types = [] + for idx, division_link in enumerate(q.all()): + if idx == place: + current_container_type = division_link.container_type + break + previous_container_types.append(division_link.container_type_id) + else: + return None, None + return current_container_type, previous_container_types + + @post_importer_action + def add_localisations(self, __, value): + self._add_localisations(value) + add_localisations.post_save = True + + def _add_localisations(self, value, return_errors=False): + """ + Add localisations for this warehouse. + Get the default localisation types and set each reference from the + value separated by ";" + + :param value: references of localisations separated by ; + :param return_errors: return error message default is False + :return: return an error message if return_errors set to True + """ + value = value.strip() + if not value: + if return_errors: + return None, _("No value") + return + + TMP_SEMI_COLON = "|#|#|" + value = value.replace("\\;", TMP_SEMI_COLON) # manage ";" used by a ref + + values = value.split(";") + + divisions = list(WarehouseDivisionLink.objects.filter( + warehouse=self).order_by('order')) + if len(values) > len(divisions): + if return_errors: + return str(_("{} values for only {} default divisions set for " + "warehouse {}")).format( + len(values), len(divisions), self.name) + return + + parent = None + for idx, value in enumerate(values): + value = value.replace(TMP_SEMI_COLON, ";").strip() + if not value or value == "-": + continue + parent, __ = Container.objects.get_or_create( + location=self, + reference=value, + container_type_id=divisions[idx].container_type_id, + parent=parent) + @property def short_label(self): return self.name @@ -1203,23 +1273,11 @@ class Container(DocumentItem, Merge, LightHistorizedItem, if return_errors: return None, _("No value") return - q = WarehouseDivisionLink.objects.filter( - warehouse=self.location).order_by('order') - current_container_type = None - error_msg = str( - _("The division number {} has not been set for the warehouse {}.") - ).format(place + 1, self.location) - previous_container_types = [] - for idx, division_link in enumerate(q.all()): - if idx == place: - current_container_type = division_link.container_type - break - previous_container_types.append(division_link.container_type_id) - else: - if return_errors: - return None, error_msg - return + error_msg = str(NO_DIVISION_ERROR).format(place + 1, self.location) + + current_container_type, previous_container_types = \ + self.location.get_container_type_by_place(place) if not current_container_type: # no division link set at this place if return_errors: diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py index 21833a08f..265a4a7ef 100644 --- a/archaeological_warehouse/tests.py +++ b/archaeological_warehouse/tests.py @@ -481,18 +481,80 @@ class ContainerWizardCreationTest(WizardTest, FindInit, TestCase): class WarehouseTest(TestCase): fixtures = WAREHOUSE_FIXTURES - def test_orga_from_warehouse(self): - w = models.Warehouse.objects.create( + def setUp(self): + self.warehouse = models.Warehouse.objects.create( name="Hophop", warehouse_type=models.WarehouseType.objects.all()[0], address="Adresse" ) - w.create_attached_organization() - w = models.Warehouse.objects.get(pk=w.pk) + self.container_types = models.ContainerType.objects.all()[:4] + + def test_orga_from_warehouse(self): + self.warehouse.create_attached_organization() + w = models.Warehouse.objects.get(pk=self.warehouse.pk) self.assertIsNotNone(w.organization) self.assertEqual(w.organization.name, "Hophop") self.assertEqual(w.organization.address, "Adresse") self.assertEqual(w.address, "") + def test_localisation_import(self): + container_nb = models.Container.objects.count() + base_value = "A;42;allée 3\;2" + error = self.warehouse._add_localisations( + base_value, return_errors=True) + self.assertTrue(error) # no division set + + for idx, ct in enumerate(self.container_types): + models.WarehouseDivisionLink.objects.create( + container_type=ct, order=idx * 10, warehouse=self.warehouse) + too_many_value = "A;42;allée 3\;2;5;42;3" + error = self.warehouse._add_localisations( + too_many_value, return_errors=True) + self.assertTrue(error) + + error = self.warehouse._add_localisations( + base_value, return_errors=True) + self.assertIsNone(error) + parent = None + for idx, reference in enumerate(("A", "42", "allée 3;2")): + q = models.Container.objects.filter( + parent=parent, + location=self.warehouse, + container_type=self.container_types[idx], + reference=reference) + self.assertEqual( + q.count(), 1, "Division {} {} - parent {} not created".format( + self.container_types[idx], reference, parent)) + parent = q.all()[0] + new_container_nb = models.Container.objects.count() + self.assertEqual(container_nb + 3, new_container_nb) + + value = "A;42;allée 4" + error = self.warehouse._add_localisations(value, return_errors=True) + self.assertIsNone(error) + # only create a new container + self.assertEqual(new_container_nb + 1, models.Container.objects.count()) + q = models.Container.objects.filter( + parent__reference="42", + parent__container_type=self.container_types[1], + parent__location=self.warehouse, + location=self.warehouse, + container_type=self.container_types[2], + reference="allée 4") + self.assertEqual(q.count(), 1) + + # test with an empty localisation + value = "A;42;;35" + error = self.warehouse._add_localisations(value, return_errors=True) + self.assertIsNone(error) + q = models.Container.objects.filter( + parent__reference="42", + parent__container_type=self.container_types[1], + parent__location=self.warehouse, + location=self.warehouse, + container_type=self.container_types[3], + reference="35") + self.assertEqual(q.count(), 1) + class ContainerTest(FindInit, TestCase): fixtures = WAREHOUSE_FIXTURES |