#!/usr/bin/env python # -*- coding: utf-8 -*- # 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 # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # 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 _, pgettext from ishtar_common.forms import reverse_lazy from ishtar_common.wizards import Wizard, DeletionWizard, SearchWizard from archaeological_operations.wizards import OperationAdministrativeActWizard from archaeological_operations.models import AdministrativeAct from archaeological_context_records.models import ContextRecord from . import models class FindSearch(SearchWizard): model = models.Find class FindWizard(Wizard): model = models.Find wizard_done_window = reverse_lazy('show-find') def get_current_contextrecord(self): step = self.steps.current if not step: return if step.endswith('_creation'): # a context record has been selected main_form_key = 'selecrecord-' + self.url_name try: idx = int(self.session_get_value(main_form_key, 'pk')) current_cr = ContextRecord.objects.get(pk=idx) return current_cr except(TypeError, ValueError, ObjectDoesNotExist): pass current_item = self.get_current_object() if current_item: base_finds = current_item.base_finds.all() if base_finds: return base_finds[0].context_record def get_current_basefinds(self): find = self.get_current_object() if not find: return [] return find.base_finds.all() def get_form_kwargs(self, step=None): kwargs = super(FindWizard, self).get_form_kwargs(step) if step not in ( 'find-find_creation', 'find-find_modification', 'simplefind-find_modification',): return kwargs kwargs['context_record'] = self.get_current_contextrecord() if step == 'simplefind-find_modification': kwargs['base_finds'] = self.get_current_basefinds() return kwargs def get_context_data(self, form, **kwargs): """ Get the operation and context record "reminder" on top of wizard forms """ context = super(FindWizard, self).get_context_data(form, **kwargs) current_cr = self.get_current_contextrecord() if not current_cr or self.steps.current.startswith('select-'): return context context['reminders'] = ( (_(u"Operation"), str(current_cr.operation)), (_(u"Context record"), str(current_cr))) return context def get_extra_model(self, dct, m2m, form_list): dct = super(FindWizard, self).get_extra_model(dct, m2m, form_list) dct['order'] = 1 if 'pk' in dct and type(dct['pk']) == ContextRecord: dct['base_finds__context_record'] = dct.pop('pk') return dct class FindModificationWizard(FindWizard): modification = True main_item_select_keys = ('selec-', 'selecw-') filter_owns = { 'selec-find_modification': ['pk'], 'selecw-find_modification': ['pk'], } wizard_templates = { 'simplefind-find_modification': 'ishtar/wizard/wizard_simplefind.html', } class FindDeletionWizard(DeletionWizard): model = models.Find main_item_select_keys = ('selec-', 'selecw-') fields = ['label', 'material_types', 'datings', 'find_number', 'object_types', 'description', 'conservatory_state', 'mark', 'preservation_to_considers', 'integrities', 'remarkabilities', 'volume', 'weight', 'length', 'width', 'height', 'diameter', 'comment'] class TreatmentSearch(SearchWizard): model = models.Treatment class TreatmentBase(Wizard): model = models.Treatment wizard_done_window = reverse_lazy('show-treatment') base_url = "" saved_args = {"treatment_type_list": []} def get_current_finds(self): step = self.steps.current if not step: return find_form_key = 'selecfind-' + self.base_url find_ids = self.session_get_value(find_form_key, "resulting_pk") try: return [ models.Find.objects.get(pk=int(find_id.strip())) for find_id in find_ids.split(u',') ] except(TypeError, ValueError, AttributeError, ObjectDoesNotExist): pass def get_form_initial(self, step, data=None): initial = super(TreatmentBase, self).get_form_initial(step) base_step = 'basetreatment-' + self.base_url if step != base_step: return initial finds = self.get_current_finds() if not finds: return initial locations = [find.container.location.pk for find in finds if find.container] # no location or multiple locations if not locations or len(set(locations)) != 1: return initial if not initial: initial = {} initial['location'] = locations[0] return initial def get_extra_model(self, dct, m2m, form_list): dct = super(TreatmentBase, self).get_extra_model(dct, m2m, form_list) dct['treatment_type_list'] = [] for k, v in m2m: if k == 'treatment_type': if type(v) not in (list, tuple): v = [v] dct['treatment_type_list'] += v return dct class TreatmentWizard(TreatmentBase): basket_step = 'basetreatment-treatment_creation' saved_args = {"items": [], "treatment_type_list": []} base_url = 'treatment_creation' def get_form_kwargs(self, step, **kwargs): kwargs = super(TreatmentWizard, self).get_form_kwargs(step, **kwargs) if self.basket_step not in step: return kwargs kwargs['user'] = self.request.user return kwargs def get_extra_model(self, dct, m2m, form_list): """ Get items concerned by the treatment """ dct = super(TreatmentWizard, self).get_extra_model(dct, m2m, form_list) if 'resulting_pk' in dct: dct['items'] = [] pks = dct.pop('resulting_pk').split(u',') for pk in pks: try: find = models.Find.objects.get(pk=pk) dct['items'].append(find) except models.Find.DoesNotExist: raise PermissionDenied if 'basket' in dct: basket = dct.pop('basket') if basket.user.pk != dct['history_modifier'].pk: raise PermissionDenied dct['items'] = list(basket.items.all()) if 'items' in dct: for find in dct['items']: if 'own' in self.current_right \ and not find.is_own(dct['history_modifier']): raise PermissionDenied return dct class TreatmentModificationWizard(TreatmentWizard): modification = True class TreatmentN1Wizard(TreatmentBase): saved_args = {"upstream_items": [], "resulting_find": None, "treatment_type_list": []} base_url = 'treatment_creation_n1' def _update_simple_initial_from_finds(self, initial, find, k): r_k = "resulting_" + k if getattr(find, k) and r_k in initial: # pop k when value is inconsistent between finds if initial[r_k] and initial[r_k] != getattr(find, k).pk: initial.pop(r_k) else: initial[r_k] = getattr(find, k).pk return initial def _update_multi_initial_from_finds(self, initial, find, k): r_k = "resulting_" + k for value in getattr(find, k + 's').all(): if value.pk not in initial[r_k]: initial[r_k].append(value.pk) return initial def _update_num_initial_from_finds(self, initial, find, k): r_k = "resulting_" + k if not getattr(find, k): return initial if initial[r_k] is None: initial[r_k] = 0 initial[r_k] += getattr(find, k) return initial def _update_char_initial_from_finds(self, initial, find, k, sep=' ; '): r_k = "resulting_" + k value = getattr(find, k) if not value: return initial value = value.strip() if not initial[r_k]: initial[r_k] = value else: # new value is entirely inside the current value if value == initial[r_k] or (value + sep) in initial[r_k] or \ (sep + value) in initial[r_k]: return initial initial[r_k] += sep + value return initial def get_form_initial(self, step, data=None): initial = super(TreatmentN1Wizard, self).get_form_initial(step) if step != 'resultingfind-treatment_creation_n1': return initial finds = self.get_current_finds() if not finds: return initial simple_key = ['material_type_quality'] multi_key = ['material_type', 'object_type', 'communicabilitie'] numeric_key = ['find_number', 'min_number_of_individuals'] desc_key = ['decoration', 'inscription', 'comment', 'dating_comment'] char_key = ['manufacturing_place'] for k in simple_key + numeric_key + desc_key + char_key: initial["resulting_" + k] = None for k in multi_key: initial["resulting_" + k] = [] for find in finds: for k in simple_key: initial = self._update_simple_initial_from_finds( initial, find, k) for k in multi_key: initial = self._update_multi_initial_from_finds( initial, find, k) for k in numeric_key: initial = self._update_num_initial_from_finds( initial, find, k) for k in char_key: initial = self._update_char_initial_from_finds( initial, find, k, sep=' ; ') for k in desc_key: initial = self._update_char_initial_from_finds( initial, find, k, sep='\n') for k in initial.keys(): if initial[k] is None: initial.pop(k) return initial def get_extra_model(self, dct, m2m, form_list): """ Get items concerned by the treatment """ dct = super(TreatmentN1Wizard, self).get_extra_model( dct, m2m, form_list) if 'resulting_pk' not in dct: return dct dct['upstream_items'] = [] # manage upstream items pks = dct.pop('resulting_pk') if hasattr(pks, 'split'): pks = pks.split(',') # string for pk in pks: try: find = models.Find.objects.get(pk=pk) dct['upstream_items'].append(find) except models.Find.DoesNotExist: raise PermissionDenied for find in dct['upstream_items']: if 'own' in self.current_right \ and not find.is_own(dct['history_modifier']): raise PermissionDenied # extract data of the new find dct['resulting_find'] = {} for k in dct.keys(): if k.startswith('resulting_') and k != "resulting_find": dct['resulting_find'][ k[len('resulting_'):] ] = dct.pop(k) return dct class Treatment1NWizard(TreatmentBase): saved_args = {"upstream_item": None, "resulting_finds": None, "treatment_type_list": []} 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'] = str(_(u"Basket")) + u" - " + lbl initial['resultings_label'] = lbl + u"-" return initial def get_extra_model(self, dct, m2m, form_list): """ Get items concerned by the treatment """ dct = super(Treatment1NWizard, self).get_extra_model( dct, m2m, 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, str(_(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( str(pgettext("key for text search", u"basket")), dct["resulting_finds"]["basket_name"]) self.request.session['find'] = '' return dct class TreatmentDeletionWizard(DeletionWizard): wizard_confirm = 'ishtar/wizard/wizard_treatement_deletion.html' model = models.Treatment fields = ['label', 'other_reference', 'year', 'index', 'treatment_types', 'location', 'person', 'organization', 'external_id', 'comment', 'description', 'goal', 'start_date', 'end_date', 'container'] class TreatmentAdministrativeActWizard(OperationAdministrativeActWizard): model = models.Treatment current_obj_slug = 'administrativeacttreatment' ref_object_key = 'treatment' def get_reminder(self): return class TreatmentEditAdministrativeActWizard(TreatmentAdministrativeActWizard): model = AdministrativeAct edit = True def get_associated_item(self, dct): return self.get_current_object().treatment class TreatmentFileSearch(SearchWizard): model = models.TreatmentFile class TreatmentFileWizard(Wizard): model = models.TreatmentFile wizard_done_window = reverse_lazy('show-treatmentfile') class TreatmentFileModificationWizard(TreatmentFileWizard): modification = True class TreatmentFileDeletionWizard(DeletionWizard): model = models.TreatmentFile fields = ['name', 'internal_reference', 'external_id', 'year', 'index', 'type', 'in_charge', 'reception_date', 'creation_date', 'end_date', 'comment'] class TreatmentFileAdministrativeActWizard( OperationAdministrativeActWizard): model = models.TreatmentFile current_obj_slug = 'administrativeacttreatmentfile' ref_object_key = 'treatment_file' def get_reminder(self): form_key = 'selec-' + self.url_name if self.url_name.endswith('_administrativeactop'): # modification and deletion are suffixed with '_modification' # and '_deletion' so it is creation pk = self.session_get_value(form_key, "pk") try: return ( (_(u"Treatment request"), str(models.TreatmentFile.objects.get(pk=pk))), ) except models.TreatmentFile.DoesNotExist: return else: admin_id = self.session_get_value(form_key, "pk") try: admin = AdministrativeAct.objects.get(pk=admin_id) if not admin.operation: return return ( (_(u"Operation"), str(admin.operation)), ) except AdministrativeAct.DoesNotExist: return class TreatmentFileEditAdministrativeActWizard( TreatmentFileAdministrativeActWizard): model = AdministrativeAct edit = True def get_associated_item(self, dct): return self.get_current_object().treatment_file class FindBasketSearch(SearchWizard): model = models.FindBasket class FindBasketWizard(Wizard): model = models.FindBasket wizard_done_window = reverse_lazy('show-findbasket') class FindBasketEditWizard(FindBasketWizard): edit = True alt_is_own_method = 'get_write_query_owns' class FindBasketDeletionWizard(DeletionWizard): wizard_confirm = 'ishtar/wizard/wizard_findbasket_deletion.html' model = models.FindBasket