diff options
| -rw-r--r-- | archaeological_finds/models_finds.py | 15 | ||||
| -rw-r--r-- | archaeological_warehouse/migrations/0112_auto_20210308_1628.py | 35 | ||||
| -rw-r--r-- | archaeological_warehouse/models.py | 46 | ||||
| -rw-r--r-- | archaeological_warehouse/templates/ishtar/sheet_container.html | 15 | ||||
| -rw-r--r-- | archaeological_warehouse/tests.py | 67 | ||||
| -rw-r--r-- | ishtar_common/migrations/0214_auto_20210308_1628.py | 25 | ||||
| -rw-r--r-- | ishtar_common/models.py | 3 | 
7 files changed, 204 insertions, 2 deletions
| diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index c3faf93d0..066bdb239 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -21,6 +21,7 @@ from collections import OrderedDict  import datetime  import uuid +from django.apps import apps  from django.conf import settings  from django.contrib.gis.db import models  from django.contrib.postgres.indexes import GinIndex @@ -2680,12 +2681,26 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,          return True      def save(self, *args, **kwargs): +        old_container = None +        # fetch in db +        if self.pk: +            old_container = self.__class__.objects.filter( +                pk=self.pk).values_list("container_id", flat=True)[0]          super(Find, self).save(*args, **kwargs)          self.skip_history_when_saving = True          if self.container_ref and not self.container:              self.container = self.container_ref +        if self.container and self.container._calculate_weight(): +            self.container.save() +        elif not self.container and old_container: +            # force recalculation of weight when a find is removed +            Container = apps.get_model("archaeological_warehouse.Container") +            old_container = Container.objects.get(pk=old_container) +            if old_container._calculate_weight(): +                old_container.save() +          updated = self.update_external_id(save=False)          if updated:              self._cached_label_checked = False diff --git a/archaeological_warehouse/migrations/0112_auto_20210308_1628.py b/archaeological_warehouse/migrations/0112_auto_20210308_1628.py new file mode 100644 index 000000000..b1241b076 --- /dev/null +++ b/archaeological_warehouse/migrations/0112_auto_20210308_1628.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2021-03-08 16:28 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('archaeological_warehouse', '0111_auto_20210225_1039'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='container', +            name='cached_weight', +            field=models.FloatField(blank=True, null=True, verbose_name='Cached weight (g)'), +        ), +        migrations.AddField( +            model_name='container', +            name='calculated_weight', +            field=models.FloatField(blank=True, null=True, verbose_name='Calculated weight (g)'), +        ), +        migrations.AddField( +            model_name='container', +            name='weight', +            field=models.FloatField(blank=True, null=True, verbose_name='Weight (g)'), +        ), +        migrations.AddField( +            model_name='containertype', +            name='tare_weight', +            field=models.FloatField(blank=True, null=True, verbose_name='Tare weight (g)'), +        ), +    ] diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index b2fa7853c..089a021af 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -36,7 +36,7 @@ from django.apps import apps  from ishtar_common.data_importer import post_importer_action, \      pre_importer_action  from ishtar_common.model_managers import ExternalIdManager, UUIDModelManager -from ishtar_common.models import ValueGetter +from ishtar_common.models import ValueGetter, get_current_profile  from ishtar_common.models_common import GeneralType, \      LightHistorizedItem, OwnPerms, Address, post_save_cache, \      DashboardFormItem, document_attached_changed, SearchAltName, \ @@ -590,6 +590,7 @@ class ContainerType(GeneralType):      width = models.IntegerField(_("Width (mm)"), blank=True, null=True)      height = models.IntegerField(_("Height (mm)"), blank=True, null=True)      volume = models.FloatField(_("Volume (l)"), blank=True, null=True) +    tare_weight = models.FloatField(_("Tare weight (g)"), blank=True, null=True)      reference = models.CharField(_("Ref."), max_length=300, blank=True,                                   null=True)      order = models.IntegerField(_("Order"), default=10) @@ -758,7 +759,8 @@ class Container(DocumentItem, Merge, LightHistorizedItem,          "location__name": _("Warehouse")      }      GEO_LABEL = "cached_label" -    CACHED_LABELS = ['cached_division', 'cached_label', 'cached_location', ] +    CACHED_LABELS = ['cached_division', 'cached_label', 'cached_location', +                     'cached_weight']      # alternative names of fields for searches      ALT_NAMES = { @@ -960,6 +962,13 @@ class Container(DocumentItem, Merge, LightHistorizedItem,                                 related_name="children", blank=True, null=True)      index = models.IntegerField(_("Container ID"), blank=True, null=True,                                  db_index=True) +    weight = models.FloatField(_("Weight (g)"), blank=True, null=True) +    calculated_weight = models.FloatField( +        _("Calculated weight (g)"), blank=True, null=True) +    cached_weight = models.FloatField( +        _("Cached weight (g)"), blank=True, null=True, +        help_text=_("Entered weight if available otherwise calculated weight.") +    )      old_reference = models.TextField(_("Old reference"), blank=True, default="")      external_id = models.TextField(_("External ID"), blank=True, default="")      auto_external_id = models.BooleanField( @@ -1066,6 +1075,37 @@ class Container(DocumentItem, Merge, LightHistorizedItem,          cached_label = " - ".join(items)          return cached_label +    def _generate_cached_weight(self): +        return self.weight if self.weight else self.calculated_weight + +    def _calculate_weight(self) -> bool: +        """ +        Calculate the weight of the contained finds + tare weight of the +        container +        :return: True if calculated weight is changed +        """ +        profile = get_current_profile() +        if profile.calculate_weight_on_full and self.finds.filter( +                weight__isnull=True).count(): +            weight = None +        else: +            weight = sum( +                w for w in self.finds.filter(weight__isnull=False).values_list( +                    "weight", flat=True).all()) +            weight += self.container_type.tare_weight \ +                if self.container_type.tare_weight else 0 +        if weight != self.calculated_weight: +            self.calculated_weight = weight +            return True +        return False + +    @property +    def get_calculated_weight_percent(self): +        if not self.calculated_weight or not self.weight: +            return (self.calculated_weight +                    - self.weight) / self.calculated_weight * 100 +        return 0 +      @property      def get_cached_division(self):          return self._generate_cached_division() @@ -1564,6 +1604,8 @@ class Container(DocumentItem, Merge, LightHistorizedItem,          self._update_warehouse_max_division()          updated = False +        updated += self._calculate_weight() +          if not self.index and not self.container_type.stationary:              self.skip_history_when_saving = True              q = Container.objects.filter( diff --git a/archaeological_warehouse/templates/ishtar/sheet_container.html b/archaeological_warehouse/templates/ishtar/sheet_container.html index 98b640936..686bd08ff 100644 --- a/archaeological_warehouse/templates/ishtar/sheet_container.html +++ b/archaeological_warehouse/templates/ishtar/sheet_container.html @@ -111,6 +111,20 @@                  {% endif %}                  {% include "ishtar/blocks/sheet_creation_section.html" %}                  {% field_flex "Old reference" item.old_reference %} +                {% if item.get_calculated_weight_percent > 5 %} +                <div class="alert alert-warning" role="alert"> +                    <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>   +                    {% trans "Calculated weight is bigger than entered weight (over 5%)." %} +                </div> +                {% field_flex "Weight (g)" item.weight %} +                {% field_flex "Calculated weight (g)" item.calculated_weight %} +                {% else %} +                    {% if item.weight %} +                    {% field_flex "Weight (g)" item.weight %} +                    {% elif item.calculated_weight %} +                    {% field_flex "Calculated weight (g)" item.calculated_weight %} +                    {% endif %} +                {% endif %}                  {% field_flex_full "Comment" item.comment "<pre>" "</pre>" %}                  {% include "ishtar/blocks/sheet_json.html" %}              </div> @@ -124,6 +138,7 @@              {% field_flex "Width (mm)" container_type.width %}              {% field_flex "Height (mm)" container_type.height %}              {% field_flex "Volume (l)" container_type.volume %} +            {% field_flex "Tare weight (g)" container_type.tare_weight %}              {% field_flex "Reference" container_type.reference %}          </div>          {% endif %} diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py index b65b68351..dc1744312 100644 --- a/archaeological_warehouse/tests.py +++ b/archaeological_warehouse/tests.py @@ -1144,3 +1144,70 @@ class ContainerTest(FindInit, TestCase):              container_1.get_material_types_code(),              "|".join(sorted([mat0.code, mat1.code, mat2.code]))) +    def test_calculated_weight(self): +        self.create_finds() +        self.create_finds() +        self.create_finds() +        find0 = self.finds[0] +        find1 = self.finds[1] +        find1.weight = 600 +        find1.save() +        find2 = self.finds[2] +        find2.weight = 700 +        find2.save() + +        ct = models.ContainerType.objects.all()[0] +        ct.tare_weight = 200 +        ct.save() +        container_1 = models.Container.objects.create( +            reference="Test 1", +            location=self.main_warehouse, +            container_type=ct) +        container_1.save() +        self.assertEqual(container_1.calculated_weight, 200) +        self.assertEqual(container_1.cached_weight, 200) +        find0.container = container_1 +        find0.save() +        container_1 = models.Container.objects.get(pk=container_1.pk) +        # no weight -> tare weight +        self.assertEqual(container_1.calculated_weight, 200) +        self.assertEqual(container_1.cached_weight, 200) + +        find1.container = container_1 +        find1.save() +        container_1 = models.Container.objects.get(pk=container_1.pk) +        # tare weight + find1 weight +        self.assertEqual(container_1.calculated_weight, 800) +        self.assertEqual(container_1.cached_weight, 800) + +        find2.container = container_1 +        find2.save() +        container_1 = models.Container.objects.get(pk=container_1.pk) +        # tare weight + find1 weight + find2 weight +        self.assertEqual(container_1.calculated_weight, 1500) +        self.assertEqual(container_1.cached_weight, 1500) + +        profile, created = IshtarSiteProfile.objects.get_or_create( +            slug='default', active=True) +        profile.calculate_weight_on_full = True +        profile.save() + +        container_1.save() +        container_1 = models.Container.objects.get(pk=container_1.pk) +        # a find with no weight is inside the container +        self.assertEqual(container_1.calculated_weight, None) +        self.assertEqual(container_1.cached_weight, None) + +        find0.container = None +        find0.save() +        # once the find with no weight is removed the weight is recalculated +        container_1 = models.Container.objects.get(pk=container_1.pk) +        self.assertEqual(container_1.calculated_weight, 1500) +        self.assertEqual(container_1.cached_weight, 1500) + +        find0.container = container_1 +        find0.save() +        container_1 = models.Container.objects.get(pk=container_1.pk) +        self.assertEqual(container_1.calculated_weight, None) +        self.assertEqual(container_1.cached_weight, None) + diff --git a/ishtar_common/migrations/0214_auto_20210308_1628.py b/ishtar_common/migrations/0214_auto_20210308_1628.py new file mode 100644 index 000000000..eb9f01740 --- /dev/null +++ b/ishtar_common/migrations/0214_auto_20210308_1628.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2021-03-08 16:28 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('ishtar_common', '0213_auto_20210302_0950'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='ishtarsiteprofile', +            name='calculate_weight_on_full', +            field=models.BooleanField(default=False, verbose_name='Container - calculate weight only when all find has a weight'), +        ), +        migrations.AlterField( +            model_name='customform', +            name='user_types', +            field=models.ManyToManyField(blank=True, help_text='Deprecated - use profile types', to='ishtar_common.PersonType'), +        ), +    ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 0e5a39c1f..180acd626 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -748,6 +748,9 @@ class IshtarSiteProfile(models.Model, Cached):                      "Only manage association of operations, context records "                      "and finds.")      ) +    calculate_weight_on_full = models.BooleanField( +        _("Container - calculate weight only when all find has a weight"), +        default=False)      config = models.CharField(          _("Alternate configuration"), max_length=200,          choices=ALTERNATE_CONFIGS_CHOICES, | 
