From 810505f6071739d265d967f618dc001f9d8049e4 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 2 Jun 2016 20:52:56 +0200 Subject: Fix container creation --- archaeological_warehouse/forms.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archaeological_warehouse') diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index f045fac1e..fb36d6c18 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -99,6 +99,8 @@ class ContainerForm(forms.Form): widget=forms.Textarea, required=False) def __init__(self, *args, **kwargs): + if 'limits' in kwargs: + kwargs.pop('limits') super(ContainerForm, self).__init__(*args, **kwargs) self.fields['container_type'].choices = \ models.ContainerType.get_types() -- cgit v1.2.3 From 8fb73687373a3a876f2ce790047c9972e616dc34 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 3 Jun 2016 00:42:55 +0200 Subject: Warehouse: work on packaging --- archaeological_finds/forms.py | 6 +++++- archaeological_finds/models.py | 22 ++++++++++++++-------- archaeological_warehouse/forms.py | 12 +++++++----- archaeological_warehouse/views.py | 2 +- archaeological_warehouse/wizards.py | 17 ++++++++++++----- ishtar_common/models.py | 2 ++ ishtar_common/views.py | 3 +-- 7 files changed, 42 insertions(+), 22 deletions(-) (limited to 'archaeological_warehouse') diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 99907781b..f5387febe 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -432,8 +432,12 @@ class SelectFindBasketForm(forms.Form): basket = forms.ChoiceField(label=_(u"Basket"), required=True, choices=[]) def __init__(self, *args, **kwargs): - self.user = kwargs.pop('user') + self.user = None + if 'user' in kwargs: + self.user = kwargs.pop('user') super(SelectFindBasketForm, self).__init__(*args, **kwargs) + if not self.user: + return self.fields['basket'].choices = [('', '--')] + [ (b.pk, unicode(b)) for b in models.FindBasket.objects.filter(user=self.user)] diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index 417dd3929..c8b392310 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -32,6 +32,7 @@ from ishtar_common.models import GeneralType, ImageModel, BaseHistorizedItem, \ from archaeological_operations.models import AdministrativeAct from archaeological_context_records.models import ContextRecord, Dating +from ishtar_common.models import PRIVATE_FIELDS from archaeological_warehouse.models import Warehouse, Container @@ -478,19 +479,24 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): return q.filter(downstream_treatment__isnull=True).count() def duplicate(self, user): - # TODO - raise + model = self.__class__ + # base fields + table_cols = [field.name for field in model._meta.fields + if field.name not in PRIVATE_FIELDS or + field.name == 'order'] dct = dict([(attr, getattr(self, attr)) for attr in - ('order', 'label', 'description', - 'volume', 'weight', 'find_number', 'dating', - 'conservatory_state', 'preservation_to_consider', - 'weight_unit', )]) + table_cols]) dct['order'] += 1 dct['history_modifier'] = user new = self.__class__(**dct) new.save() - for base_find in self.base_finds.all(): - new.base_finds.add(base_find) + + # m2m fields + m2m = [field.name for field in model._meta.many_to_many + if field.name not in PRIVATE_FIELDS] + for field in m2m: + for val in getattr(self, field).all(): + getattr(new, field).add(val) return new @classmethod diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index fb36d6c18..080467e55 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2013 Étienne Loks +# Copyright (C) 2010-2016 É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 @@ -22,12 +22,13 @@ from django.conf import settings from django.utils.translation import ugettext_lazy as _ from ishtar_common.models import Person, valid_id -from archaeological_finds.models import TreatmentType +from archaeological_finds.models import TreatmentType, FindBasket import models from ishtar_common import widgets from ishtar_common.forms import name_validator, reverse_lazy, \ get_form_selection, TableSelect -from archaeological_finds.forms import FindMultipleFormSelection +from archaeological_finds.forms import FindMultipleFormSelection, \ + SelectFindBasketForm def get_warehouse_field(label=_(u"Warehouse"), required=True): @@ -137,11 +138,12 @@ ContainerFormSelection = get_form_selection( new_message=_(u"Add a new container")) -class BasePackagingForm(forms.Form): +class BasePackagingForm(SelectFindBasketForm): form_label = _(u"Packaging") associated_models = {'treatment_type': TreatmentType, 'person': Person, - 'location': models.Warehouse} + 'location': models.Warehouse, + 'basket': FindBasket} treatment_type = forms.IntegerField(label="", widget=forms.HiddenInput) person = forms.IntegerField( label=_(u"Packager"), diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py index aab18ed40..be5e6150c 100644 --- a/archaeological_warehouse/views.py +++ b/archaeological_warehouse/views.py @@ -89,7 +89,7 @@ def autocomplete_container(request): warehouse_packaging_wizard = PackagingWizard.as_view([ ('seleccontainer-packaging', ContainerFormSelection), ('base-packaging', BasePackagingForm), - ('multiselecitems-packaging', FindPackagingFormSelection), + # ('multiselecitems-packaging', FindPackagingFormSelection), ('final-packaging', FinalForm)], label=_(u"Packaging"), url_name='warehouse_packaging',) diff --git a/archaeological_warehouse/wizards.py b/archaeological_warehouse/wizards.py index 833c1c697..5f2b4346d 100644 --- a/archaeological_warehouse/wizards.py +++ b/archaeological_warehouse/wizards.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2012 Étienne Loks +# Copyright (C) 2012-2016 É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 @@ -25,17 +25,24 @@ from archaeological_finds.models import Treatment class PackagingWizard(TreatmentWizard): + + def get_form_kwargs(self, step): + kwargs = super(PackagingWizard, self).get_form_kwargs(step) + if 'base-packaging' not in step: + return kwargs + kwargs['user'] = self.request.user + return kwargs + + def save_model(self, dct, m2m, whole_associated_models, form_list, return_object): dct = self.get_extra_model(dct, form_list) obj = self.get_current_saved_object() dct['location'] = dct['container'].location - items = dct.pop('finds') + basket = dct.pop('basket') treatment = Treatment(**dct) treatment.save() - if not hasattr(items, '__iter__'): - items = [items] - for item in items: + for item in basket.items.all(): new = item.duplicate(self.request.user) item.downstream_treatment = treatment item.save() diff --git a/ishtar_common/models.py b/ishtar_common/models.py index f3974d04d..dcf141dde 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -581,6 +581,8 @@ class HistoryError(Exception): def __str__(self): return repr(self.value) +PRIVATE_FIELDS = ('id', 'history_modifier', 'order') + class BaseHistorizedItem(Imported): IS_BASKET = False diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 59cfe6321..2df1f4b44 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -61,7 +61,7 @@ from archaeological_files.forms import DashboardForm as DashboardFormFile from ishtar_common.forms import FinalForm, FinalDeleteForm from ishtar_common import forms_common as forms from ishtar_common import wizards -from ishtar_common.models import HistoryError +from ishtar_common.models import HistoryError, PRIVATE_FIELDS import models @@ -325,7 +325,6 @@ def format_val(val): HIERARCHIC_LEVELS = 5 HIERARCHIC_FIELDS = ['periods', 'period', 'unit', 'material_types', 'material_type', 'conservatory_state'] -PRIVATE_FIELDS = ('id', 'history_modifier', 'order') def get_item(model, func_name, default_name, extra_request_keys=[], -- cgit v1.2.3 From ef0f4113e70fee55e399f76229e0712caeed849c Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 4 Jun 2016 14:34:11 +0200 Subject: Treatment: workon on basket update after treatment --- archaeological_finds/models.py | 29 +++++++++++++ archaeological_finds/tests.py | 81 ++++++++++++++++++++++++++++++++++++- archaeological_warehouse/wizards.py | 14 ++----- 3 files changed, 112 insertions(+), 12 deletions(-) (limited to 'archaeological_warehouse') diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index c8b392310..0a1e59a68 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -612,6 +612,35 @@ class Treatment(BaseHistorizedItem, OwnPerms): lbl += u" %s %s" % (_(u"by"), unicode(self.person)) return lbl + def save(self, *args, **kwargs): + items, user, extra_args_for_new = [], None, [] + if "items" in kwargs: + items = kwargs.pop('items') + if "user" in kwargs: + user = kwargs.pop('user') + if "extra_args_for_new" in kwargs: + extra_args_for_new = kwargs.pop('extra_args_for_new') + is_new = self.pk is None + super(Treatment, self).save(*args, **kwargs) + if not is_new or not items: + return + basket = None + if hasattr(items, "items"): + basket = items + items = basket.items.all() + for item in items: + new = item.duplicate(user) + item.downstream_treatment = self + item.save() + new.upstream_treatment = self + for k in extra_args_for_new: + setattr(new, k, extra_args_for_new[k]) + new.save() + # update baskets + for basket in FindBasket.objects.filter(items__pk=item.pk).all(): + basket.items.remove(item) + basket.items.add(new) + class TreatmentSource(Source): class Meta: diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index ccf821757..f75e9cfa3 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -19,11 +19,13 @@ from django.conf import settings from django.core.files.uploadedfile import SimpleUploadedFile -from ishtar_common.models import ImporterType +from django.test import TestCase +from ishtar_common.models import ImporterType, IshtarUser from archaeological_finds import models -from archaeological_context_records.tests import ImportContextRecordTest +from archaeological_context_records.tests import ImportContextRecordTest, \ + ContextRecordInit from ishtar_common import forms_common @@ -67,3 +69,78 @@ class ImportFindTest(ImportContextRecordTest): self.assertTrue(current_nb == (old_nb + 4)) self.assertEqual( models.Find.objects.filter(material_types__pk=ceram).count(), 4) + + +class FindInit(ContextRecordInit): + test_context_records = False + + def create_finds(self, user=None, data_base={}, data={}): + if not getattr(self, 'finds', None): + self.finds = [] + if not getattr(self, 'base_finds', None): + self.base_finds = [] + + default = {'label': "Base find"} + if not data_base.get('history_modifier'): + data_base['history_modifier'] = self.get_default_user() + if not data_base.get('context_record'): + data_base['context_record'] = self.get_default_context_record() + + default.update(data_base) + base_find = models.BaseFind.objects.create(**default) + self.base_finds.append(base_find) + + data["history_modifier"] = data_base["history_modifier"] + find = models.Find.objects.create(**data) + find.base_finds.add(base_find) + self.finds.append(find) + return self.finds, self.base_finds + + def get_default_find(self): + return self.create_finds()[0] + + +class PackagingTest(TestCase, FindInit): + fixtures = [settings.ROOT_PATH + + '../fixtures/initial_data.json', + settings.ROOT_PATH + + '../ishtar_common/fixtures/initial_data.json', + settings.ROOT_PATH + + '../archaeological_files/fixtures/initial_data.json', + settings.ROOT_PATH + + '../archaeological_operations/fixtures/initial_data-fr.json', + settings.ROOT_PATH + + '../archaeological_finds/fixtures/initial_data-fr.json', + ] + model = models.Find + + def setUp(self): + self.create_finds({"label": u"Find 1"}) + self.create_finds({"label": u"Find 2"}) + self.basket = models.FindBasket.objects.create( + label="My basket", user=IshtarUser.objects.get( + pk=self.get_default_user().pk)) + self.other_basket = models.FindBasket.objects.create( + label="My other basket", user=IshtarUser.objects.get( + pk=self.get_default_user().pk)) + for find in self.finds: + self.basket.items.add(find) + self.other_basket.items.add(find) + + def testPackaging(self): + treatment_type = models.TreatmentType.objects.get(txt_idx='packaging') + treatment = models.Treatment(treatment_type=treatment_type) + items_nb = models.Find.objects.count() + treatment.save(user=self.get_default_user(), items=self.basket) + self.assertEqual(items_nb + self.basket.items.count(), + models.Find.objects.count(), + msg="Packaging doesn't generate enough new finds") + # new version of the find is in the basket + for item in self.basket.items.all(): + self.assertNotIn( + item, self.finds, + msg="Original basket have not been upgraded after packaging") + for item in self.other_basket.items.all(): + self.assertNotIn( + item, self.finds, + msg="Other basket have not been upgraded after packaging") diff --git a/archaeological_warehouse/wizards.py b/archaeological_warehouse/wizards.py index 5f2b4346d..409f7b28f 100644 --- a/archaeological_warehouse/wizards.py +++ b/archaeological_warehouse/wizards.py @@ -33,22 +33,16 @@ class PackagingWizard(TreatmentWizard): kwargs['user'] = self.request.user return kwargs - def save_model(self, dct, m2m, whole_associated_models, form_list, return_object): dct = self.get_extra_model(dct, form_list) obj = self.get_current_saved_object() dct['location'] = dct['container'].location - basket = dct.pop('basket') + items = dct.pop('basket') treatment = Treatment(**dct) - treatment.save() - for item in basket.items.all(): - new = item.duplicate(self.request.user) - item.downstream_treatment = treatment - item.save() - new.upstream_treatment = treatment - new.container = dct['container'] - new.save() + extra_args_for_new = {"container": dct['container']} + treatment.save(items=items, user=self.request.user, + extra_args_for_new=extra_args_for_new) res = render_to_response('ishtar/wizard/wizard_done.html', {}, context_instance=RequestContext(self.request)) return return_object and (obj, res) or res -- cgit v1.2.3 From 67499224d71e34c49bf4550cc81fd0fe3efc092c Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 5 Jun 2016 23:45:19 +0200 Subject: Fix warehouse creation --- archaeological_warehouse/forms.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archaeological_warehouse') diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index 080467e55..d56df8139 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -67,6 +67,8 @@ class WarehouseForm(forms.Form): required=False) def __init__(self, *args, **kwargs): + if 'limits' in kwargs: + kwargs.pop('limits') super(WarehouseForm, self).__init__(*args, **kwargs) self.fields['warehouse_type'].choices = \ models.WarehouseType.get_types() -- cgit v1.2.3