diff options
| -rw-r--r-- | archaeological_finds/forms.py | 66 | ||||
| -rw-r--r-- | archaeological_finds/forms_treatments.py | 16 | ||||
| -rw-r--r-- | archaeological_finds/ishtar_menu.py | 7 | ||||
| -rw-r--r-- | archaeological_finds/models_finds.py | 10 | ||||
| -rw-r--r-- | archaeological_finds/models_treatments.py | 48 | ||||
| -rw-r--r-- | archaeological_finds/urls.py | 3 | ||||
| -rw-r--r-- | archaeological_finds/views.py | 13 | ||||
| -rw-r--r-- | archaeological_finds/wizards.py | 67 | ||||
| -rw-r--r-- | ishtar_common/templates/base.html | 37 | 
9 files changed, 238 insertions, 29 deletions
| diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 970b35f92..b95ac90c6 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -44,7 +44,7 @@ from archaeological_finds.forms_treatments import TreatmentSelect, \      AdministrativeActTreatmentFileFormSelection, \      AdministrativeActTreatmentFileModifForm, \      DashboardForm as DashboardTreatmentForm, N1TreatmentForm,\ -    DashboardTreatmentFileForm, QAFindTreatmentForm +    DashboardTreatmentFileForm, QAFindTreatmentForm, OneNTreatmentForm  from archaeological_operations.models import Period, ArchaeologicalSite, \      RelationType as OpeRelationType  from archaeological_operations.widgets import OAWidget @@ -84,7 +84,8 @@ __all__ = [      'SelectFindBasketForm', 'DeleteFindBasketForm', 'FindBasketAddItemForm',      'QAFindFormSingle', 'QAFindFormMulti', 'QAFindBasketForm',      'QAFindTreatmentForm', -    'N1TreatmentForm', 'ResultingFindForm' +    'N1TreatmentForm', 'OneNTreatmentForm', 'ResultingFindForm', +    'ResultingFindsForm', 'SingleUpstreamFindFormSelection'  ]  logger = logging.getLogger(__name__) @@ -379,8 +380,8 @@ class SimpleFindForm(BaseFindForm):  class ResultingFindForm(CustomForm, ManageOldType):      file_upload = True      form_label = _("Resulting find") -    form_admin_name = _(u"Treatment n-1 - 030 - General") -    form_slug = "treatmentn1-030-general" +    form_admin_name = _(u"Treatment n-1 - 030 - Resulting find") +    form_slug = "treatmentn1-030-resulting-find"      associated_models = {          'resulting_material_type': models.MaterialType, @@ -472,6 +473,50 @@ class ResultingFindForm(CustomForm, ManageOldType):      ] +class ResultingFindsForm(CustomForm, ManageOldType): +    form_label = _("Resulting finds") +    form_admin_name = _(u"Treatment 1-n - 030 - Resulting finds") +    form_slug = "treatment1n-030-resulting-finds" +    associated_models = {} + +    resultings_number = forms.IntegerField( +        label=_(u"Number of resulting finds"), +        min_value=1 +    ) +    resultings_label = forms.CharField( +        label=_(u"Prefix label for resulting finds"), +        validators=[validators.MaxLengthValidator(200)], +        help_text=_( +            u'E.g.: with a prefix "item-", each resulting item will be named ' +            u'"item-1", "item-2", "item-3"') +    ) +    resultings_start_number = forms.IntegerField( +        label=_(u"Numbering starting from"), initial=1, min_value=0 +    ) +    resultings_basket_name = forms.CharField( +        label=_(u"Name of the new basket containing the resulting items"), +        max_length=200 +    ) + +    def __init__(self, *args, **kwargs): +        self.user = None +        if 'user' in kwargs: +            self.user = kwargs.pop('user') +            if hasattr(self.user, 'ishtaruser'): +                self.user = self.user.ishtaruser +        super(ResultingFindsForm, self).__init__(*args, **kwargs) +        if not self.user: +            return + +    def clean(self): +        q = models.FindBasket.objects.filter( +            user=self.user, label=self.cleaned_data['resultings_basket_name']) +        if q.count(): +            raise forms.ValidationError(_(u"A basket with this label already " +                                          u"exists.")) +        return self.cleaned_data + +  class QAFindFormMulti(QAForm):      form_admin_name = _(u"Find - Quick action - Modify")      form_slug = "find-quickaction-modify" @@ -1065,7 +1110,7 @@ class FindDeletionForm(FinalForm):  class UpstreamFindFormSelection(PkWizardSearch, FindFormSelection): -    form_label = _(u"Upstream find") +    form_label = _(u"Upstream finds")      current_model = models.Find      pk_key = 'resulting_pk' @@ -1084,6 +1129,17 @@ class UpstreamFindFormSelection(PkWizardSearch, FindFormSelection):          self.fields['resulting_pk'] = self.fields.pop('pk') +class SingleUpstreamFindFormSelection(UpstreamFindFormSelection): +    current_model = models.Find +    pk = forms.CharField( +        label="", required=False, +        widget=widgets.DataTable( +            reverse_lazy('get-find'), +            FindSelect, current_model, +            source_full=reverse_lazy('get-find-full')), +        validators=[valid_ids(current_model)]) + +  class FindBasketSelect(CustomForm, TableSelect):      _model = models.FindBasket diff --git a/archaeological_finds/forms_treatments.py b/archaeological_finds/forms_treatments.py index 99a685825..be53dd418 100644 --- a/archaeological_finds/forms_treatments.py +++ b/archaeological_finds/forms_treatments.py @@ -80,7 +80,7 @@ class TreatmentFormSelection(forms.Form):  class BaseTreatmentForm(CustomForm, ManageOldType): -    form_label = _(u"Base treatment") +    form_label = _(u"Treatment")      form_admin_name = _(u"Treatment - 020 - General")      form_slug = "treatment-020-general"      base_models = ['treatment_type'] @@ -231,7 +231,6 @@ class BaseTreatmentForm(CustomForm, ManageOldType):  class N1TreatmentForm(BaseTreatmentForm): -    form_label = _(u"Base treatment")      form_admin_name = _(u"Treatment n-1 - 020 - General")      form_slug = "treatmentn1-020-general" @@ -244,6 +243,19 @@ class N1TreatmentForm(BaseTreatmentForm):      ] +class OneNTreatmentForm(BaseTreatmentForm): +    form_admin_name = _(u"Treatment 1-n - 020 - General") +    form_slug = "treatment1n-020-general" + +    TYPES = [ +        FieldType('treatment_state', models.TreatmentState), +        FieldType( +            'treatment_type', models.TreatmentType, is_multiple=True, +            extra_args={'dct': {'upstream_is_many': False, +                                'downstream_is_many': True}}) +    ] + +  class TreatmentModifyForm(BaseTreatmentForm):      index = forms.IntegerField(_(u"Index"))      id = forms.IntegerField(' ', widget=forms.HiddenInput, required=False) diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index cd7ed19b7..2f37f4c4b 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -167,6 +167,13 @@ MENU_SECTIONS = [                     u"- creation"),                   model=models.Treatment,                   access_controls=['change_find', 'change_own_find']), +             MenuItem( +                 'treatment_creation_1n', +                 _(u"Treatment " +                   u"1 <i class='fa fa-arrows-h' aria-hidden='true'></i> n " +                   u"- creation"), +                 model=models.Treatment, +                 access_controls=['change_find', 'change_own_find']),               MenuItem('treatment_modification',                        _(u"Modification"),                        model=models.Treatment, diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 1fb4f6132..e856cb8ca 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -1348,7 +1348,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms,              q = q.filter(**fltr)          return q.filter(downstream_treatment__isnull=True).count() -    def duplicate(self, user): +    def duplicate(self, user, copy_datings=True):          model = self.__class__          new = model.objects.get(pk=self.pk) @@ -1366,9 +1366,11 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms,          m2m = [field.name for field in model._meta.many_to_many                 if field.name not in PRIVATE_FIELDS]          for field in m2m: -            if field == 'images': -                for doc in Document.objects.filter(finds__pk=self.pk).all(): -                    doc.finds.add(new.pk) +            if field == 'datings' and copy_datings: +                for dating in self.datings.all(): +                    dating.pk = None +                    dating.save() +                    new.datings.add(dating)              else:                  for val in getattr(self, field).all():                      getattr(new, field).add(val) diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py index d92c98235..68935f142 100644 --- a/archaeological_finds/models_treatments.py +++ b/archaeological_finds/models_treatments.py @@ -29,6 +29,7 @@ from django.utils.translation import ugettext_lazy as _, pgettext_lazy, \  from archaeological_finds.models_finds import Find, FindBasket, TreatmentType  from archaeological_operations.models import ClosedItem, Operation +from archaeological_context_records.models import Dating  from archaeological_warehouse.models import Warehouse, Container  from ishtar_common.models import Document, GeneralType, \      ImageModel, BaseHistorizedItem, OwnPerms, HistoricalRecords, Person, \ @@ -72,7 +73,8 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem,          "person__cached_label": _(u"Responsible"),      }      # extra keys than can be passed to save method -    EXTRA_SAVED_KEYS = ('items', 'user', 'resulting_find', 'upstream_items') +    EXTRA_SAVED_KEYS = ('items', 'user', 'resulting_find', 'upstream_items', +                        'resulting_finds', 'upstream_item')      # alternative names of fields for searches      ALT_NAMES = { @@ -293,7 +295,10 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem,          if q.count():              self.index = q.all().aggregate(Max('index'))['index__max'] + 1 -    def _create_resulting_find(self, resulting_find, upstream_items): +    def _create_n_1_resulting_find(self, resulting_find, upstream_items): +        """ +        Manage creation of n<->1 treatment +        """          m2m = {}          base_fields = [f.name for f in Find._meta.get_fields()]          for k in resulting_find.keys(): @@ -363,15 +368,45 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem,          new_find.skip_history_when_saving = True          new_find.save() +    def _create_1_n_resulting_find(self, resulting_finds, upstream_item, user): +        """ +        Manage creation of 1<->n treatment +        """ +        new_items = [] +        start_number = resulting_finds['start_number'] +        for idx in range(resulting_finds['number']): +            label = resulting_finds['label'] + unicode(start_number + idx) +            new_find = Find.objects.get( +                pk=upstream_item.pk).duplicate(user) +            new_find.upstream_treatment = self +            new_find.label = label +            new_find.skip_history_when_saving = True +            new_find.save() +            new_items.append(new_find) + +        upstream_item.downstream_treatment = self +        upstream_item.skip_history_when_saving = True +        upstream_item.save() + +        if getattr(user, 'ishtaruser', None): +            b = FindBasket.objects.create( +                label=resulting_finds['basket_name'], user=user.ishtaruser) +            for item in new_items: +                b.items.add(item) +      def save(self, *args, **kwargs):          items, user, extra_args_for_new, resulting_find = [], None, [], None -        upstream_items = [] +        upstream_items, upstream_item, resulting_finds = [], None, None          if "items" in kwargs:              items = kwargs.pop('items')          if "resulting_find" in kwargs:              resulting_find = kwargs.pop('resulting_find') +        if "resulting_finds" in kwargs: +            resulting_finds = kwargs.pop('resulting_finds')          if "upstream_items" in kwargs:              upstream_items = kwargs.pop('upstream_items') +        if "upstream_item" in kwargs: +            upstream_item = kwargs.pop('upstream_item')          if "user" in kwargs:              user = kwargs.pop('user')          if "extra_args_for_new" in kwargs: @@ -386,7 +421,12 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem,              upstream_items = upstream_items.items.all()          if upstream_items and resulting_find: -            self._create_resulting_find(resulting_find, upstream_items) +            self._create_n_1_resulting_find(resulting_find, upstream_items) +            return + +        if upstream_item and resulting_finds: +            self._create_1_n_resulting_find(resulting_finds, upstream_item, +                                            self.history_modifier)              return          tps = list(self.treatment_types.all()) diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index b9f4d8b6c..6e9f59b8c 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -106,6 +106,9 @@ urlpatterns = [      url(r'^treatment_creation_n1/(?P<step>.+)?$',          check_rights(['change_find', 'change_own_find'])(              views.treatment_creation_n1_wizard), name='treatment_creation_n1'), +    url(r'^treatment_creation_1n/(?P<step>.+)?$', +        check_rights(['change_find', 'change_own_find'])( +            views.treatment_creation_1n_wizard), name='treatment_creation_1n'),      url(r'^treatment_modification/(?P<step>.+)?$',          check_rights(['change_find', 'change_own_find'])( diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index ceb00d432..29f0f75af 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -476,6 +476,19 @@ treatment_creation_n1_wizard = TreatmentN1Wizard.as_view(      label=_(u"New treatment"),      url_name='treatment_creation_n1',) +treatment_1n_wizard_steps = [ +    ('selecfind-treatment_creation_1n', SingleUpstreamFindFormSelection), +    ('file-treatment_creation_1n', TreatmentFormFileChoice), +    ('basetreatment-treatment_creation_1n', OneNTreatmentForm), +    ('resultingfinds-treatment_creation_1n', ResultingFindsForm), +    ('final-treatment_creation_1n', FinalForm) +] + +treatment_creation_1n_wizard = Treatment1NWizard.as_view( +    treatment_1n_wizard_steps, +    label=_(u"New treatment"), +    url_name='treatment_creation_1n',) +  treatment_modification_wizard = TreatmentModificationWizard.as_view(      [('selec-treatment_modification', TreatmentFormSelection),       ('file-treatment_modification', TreatmentFormFileChoice), diff --git a/archaeological_finds/wizards.py b/archaeological_finds/wizards.py index 3c25258a6..bd16a55de 100644 --- a/archaeological_finds/wizards.py +++ b/archaeological_finds/wizards.py @@ -17,8 +17,9 @@  # See the file COPYING for details. +from django.contrib import messages  from django.core.exceptions import ObjectDoesNotExist, PermissionDenied -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext_lazy as _, pgettext  from ishtar_common.forms import reverse_lazy  from ishtar_common.wizards import Wizard, DeletionWizard, SearchWizard @@ -316,6 +317,70 @@ class TreatmentN1Wizard(TreatmentBase):          return dct +class Treatment1NWizard(TreatmentBase): +    saved_args = {"upstream_item": None, "resulting_finds": None} +    base_url = 'treatment_creation_1n' + +    def get_form_kwargs(self, step, **kwargs): +        kwargs = super(Treatment1NWizard, self).get_form_kwargs(step, **kwargs) +        if step != 'resultingfind-treatment_creation_1n': +            return kwargs +        kwargs['user'] = self.request.user +        return kwargs + +    def get_form_initial(self, step, data=None): +        initial = super(Treatment1NWizard, self).get_form_initial(step) +        if step != 'resultingfinds-treatment_creation_1n': +            return initial +        finds = self.get_current_finds() +        if not finds: +            return initial +        lbl = finds[0].label +        initial['resultings_basket_name'] = unicode(_(u"Basket")) + u" - " + lbl +        initial['resultings_label'] = lbl + u"-" +        return initial + +    def get_extra_model(self, dct, form_list): +        """ +        Get items concerned by the treatment +        """ +        dct = super(Treatment1NWizard, self).get_extra_model(dct, form_list) +        if 'resulting_pk' not in dct: +            return dct + +        # manage upstream item +        pk = dct.pop('resulting_pk') +        try: +            find = models.Find.objects.get(pk=pk) +            dct['upstream_item'] = find +        except models.Find.DoesNotExist: +            raise PermissionDenied + +        if 'own' in self.current_right \ +                and not find.is_own(dct['history_modifier']): +            raise PermissionDenied + +        # extract attributes to generate the new find +        dct['resulting_finds'] = {} +        for k in dct.keys(): +            if k.startswith('resultings_'): +                dct['resulting_finds'][ +                    k[len('resultings_'):] +                ] = dct.pop(k) +        messages.add_message( +            self.request, messages.INFO, +            unicode(_(u"The new basket: \"{}\" have been created with the " +                      u"resulting items. This search have been pinned.") +                    ).format(dct["resulting_finds"]["basket_name"]) +        ) + +        self.request.session["pin-search-find"] = u'{}="{}"'.format( +            unicode(pgettext("key for text search", u"basket")), +            dct["resulting_finds"]["basket_name"]) +        self.request.session['find'] = '' +        return dct + +  class TreatmentDeletionWizard(DeletionWizard):      model = models.Treatment      fields = ['label', 'other_reference', 'year', 'index', diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index add4f1d6c..ab2baf955 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -108,20 +108,28 @@              <ul class="nav nav-pills flex-column" id="window-fixed-menu-list">              </ul>          </nav> -        <div id="window_wrapper"> -            <div id="window" role="tablist"></div> -        </div>          <div id="message_list"> -        {% if MESSAGES %}{% for message, message_type in MESSAGES %} -        <div class="alert alert-{{message_type}} alert-dismissible fade show" -             role="alert"> -            {{message}} -            <button type="button" class="close" data-dismiss="alert" -                    aria-label="Close"> -                <span aria-hidden="true">×</span> -            </button> -        </div> -        {% endfor %}{% endif %} +            {% if messages %} +            {% for message in messages %} +            <div class="alert alert-{{ message.tags }} alert-dismissible fade show" +                 role="alert"> +                {{message|safe}} +                <button type="button" class="close" data-dismiss="alert" +                        aria-label="Close"> +                    <span aria-hidden="true">×</span> +                </button> +            </div>{% endfor %} +            {% endif %} +            {% if MESSAGES %}{% for message, message_type in MESSAGES %} +            <div class="alert alert-{{message_type}} alert-dismissible fade show" +                 role="alert"> +                {{message}} +                <button type="button" class="close" data-dismiss="alert" +                        aria-label="Close"> +                    <span aria-hidden="true">×</span> +                </button> +            </div> +            {% endfor %}{% endif %}          </div>          {% if warnings %}{% for warning in warnings %}          <div class="alert alert-warning alert-dismissible fade show" role="alert"> @@ -130,6 +138,9 @@              </button>          </div>          {% endfor %}{% endif %} +        <div id="window_wrapper"> +            <div id="window" role="tablist"></div> +        </div>          {% block content %}{% endblock %}      </div> | 
