diff options
| author | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-11-30 13:20:53 +0100 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-11-30 13:20:53 +0100 | 
| commit | 227885e4a6b2df9e4df1507d93c31dd30c5b458a (patch) | |
| tree | 7e216f7c036ae568407d46359dea361f2a641098 | |
| parent | d7d137c4b1689545abe9dc9af3ab936d0200a05f (diff) | |
| download | Ishtar-227885e4a6b2df9e4df1507d93c31dd30c5b458a.tar.bz2 Ishtar-227885e4a6b2df9e4df1507d93c31dd30c5b458a.zip | |
Simple treatment form. Treatment listing. (refs #3365)
| -rw-r--r-- | archaeological_finds/forms.py | 23 | ||||
| -rw-r--r-- | archaeological_finds/ishtar_menu.py | 36 | ||||
| -rw-r--r-- | archaeological_finds/models.py | 15 | ||||
| -rw-r--r-- | archaeological_finds/tests.py | 54 | ||||
| -rw-r--r-- | archaeological_finds/urls.py | 14 | ||||
| -rw-r--r-- | archaeological_finds/views.py | 15 | ||||
| -rw-r--r-- | archaeological_finds/wizards.py | 25 | ||||
| -rw-r--r-- | archaeological_operations/tests.py | 71 | ||||
| -rw-r--r-- | ishtar_common/tests.py | 31 | ||||
| -rw-r--r-- | ishtar_common/views.py | 2 | ||||
| -rw-r--r-- | ishtar_common/widgets.py | 2 | ||||
| -rw-r--r-- | ishtar_common/wizards.py | 9 | 
12 files changed, 243 insertions, 54 deletions
| diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 800fba34f..e25d52805 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -460,6 +460,8 @@ class UpstreamFindFormSelection(FindFormSelection):      def __init__(self, *args, **kwargs):          super(UpstreamFindFormSelection, self).__init__(*args, **kwargs)          self.fields['pk'].required = True +        self.fields['resulting_pk'] = self.fields.pop('pk') +  ##############################################  # Source management for archaeological finds # @@ -576,6 +578,18 @@ class FindBasketAddItemForm(forms.Form):          return basket +class TreatmentFormSelection(forms.Form): +    form_label = _("Treatment search") +    associated_models = {'pk': models.Treatment} +    currents = {'pk': models.Treatment} +    pk = forms.IntegerField( +        label="", required=False, +        widget=widgets.JQueryJqGrid( +            reverse_lazy('get-treatment'), +            FindSelect, models.Treatment), +        validators=[valid_id(models.Treatment)]) + +  class BaseTreatmentForm(ManageOldType, SelectFindBasketForm):      form_label = _(u"Base treatment")      associated_models = {'treatment_type': models.TreatmentType, @@ -606,12 +620,17 @@ class BaseTreatmentForm(ManageOldType, SelectFindBasketForm):          super(BaseTreatmentForm, self).__init__(*args, **kwargs)          self.fields['treatment_type'].choices = models.TreatmentType.get_types(              initial=self.init_data.get('treatment_type'), -            exclude=['packaging']) +            dct={'upstream_is_many': False, 'downstream_is_many': False} +        )          self.fields['treatment_type'].help_text = \ -            models.TreatmentType.get_help(exclude=['packaging']) +            models.TreatmentType.get_help( +               dct={'upstream_is_many': False, 'downstream_is_many': False})          self.fields['basket'].required = False          self.fields['basket'].help_text = \              _(u"Leave it blank if you want to select a single item") +        self.fields.keyOrder.pop(self.fields.keyOrder.index('basket')) +        self.fields.keyOrder.insert(self.fields.keyOrder.index('description'), +                                    'basket')      def clean(self, *args, **kwargs):          try: diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index f638a60b2..1ab0cb575 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -46,11 +46,6 @@ MENU_SECTIONS = [                   model=models.Find,                   access_controls=['change_find',                                    'change_own_find']), -             # MenuItem( -             #     'treatment_creation', _(u"Add a treatment"), -             #     model=models.Treatment, -             #     access_controls=['change_find', -             #                      'change_own_find']),               MenuItem(                   'find_deletion', _(u"Deletion"),                   model=models.Find, @@ -99,6 +94,35 @@ MENU_SECTIONS = [                                model=models.FindSource,                                access_controls=['change_find',                                                 'change_own_find']), -                 ]) +                 ]), +             # MenuItem( +             #     'treatment_creation', _(u"Add a treatment"), +             #     model=models.Treatment, +             #     access_controls=['change_find', +             #                      'change_own_find']), +             SectionItem( +                 'find_treatments', _(u"Treatments"), +                 childs=[ +                     MenuItem('treatment_search', +                              _(u"Search"), +                              model=models.Treatment, +                              access_controls=['view_find', +                                               'view_own_find']), +                     MenuItem('treatment_creation', +                              _(u"Creation"), +                              model=models.Treatment, +                              access_controls=['change_find', +                                               'change_own_find']), +                     MenuItem('treatment_modification', +                              _(u"Modification"), +                              model=models.Treatment, +                              access_controls=['change_find', +                                               'change_own_find']), +                     MenuItem('treatment_deletion', +                              _(u"Deletion"), +                              model=models.Treatment, +                              access_controls=['change_find', +                                               'change_own_find']), +                 ]),           ]))  ] diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index b7637ba3b..a886485b5 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -793,6 +793,7 @@ post_delete.connect(post_save_cache, sender=TreatmentType)  class Treatment(BaseHistorizedItem, OwnPerms): +    SHOW_URL = 'show-treatment'      external_id = models.CharField(_(u"External ID"), blank=True, null=True,                                     max_length=120)      container = models.ForeignKey(Container, verbose_name=_(u"Container"), @@ -814,6 +815,16 @@ class Treatment(BaseHistorizedItem, OwnPerms):      start_date = models.DateField(_(u"Start date"), blank=True, null=True)      end_date = models.DateField(_(u"End date"), blank=True, null=True)      history = HistoricalRecords() +    TABLE_COLS = ('treatment_type__label', 'person', 'start_date', +                  'downstream_cached_label', 'upstream_cached_label') +    EXTRA_REQUEST_KEYS = { +        "downstream_cached_label": "downstream__cached_label", +        "upstream_cached_label": "upstream__cached_label", +    } +    TABLE_COLS_LBL = { +        "downstream_cached_label": _(u"Downstream find"), +        "upstream_cached_label": _(u"Upstream find"), +    }      class Meta:          verbose_name = _(u"Treatment") @@ -844,10 +855,8 @@ class Treatment(BaseHistorizedItem, OwnPerms):          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() +            items = items.items.all()          for item in items:              new = item.duplicate(user)              item.downstream_treatment = self diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index a0a9f0a8a..fdced4bd4 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -23,12 +23,14 @@ from django.test import TestCase  from ishtar_common.models import ImporterType, IshtarUser, ImporterColumn,\      FormaterType, ImportTarget -from archaeological_finds import models +from archaeological_finds import models, views +from archaeological_warehouse.models import Warehouse, WarehouseType  from archaeological_context_records.tests import ImportContextRecordTest, \      ContextRecordInit  from ishtar_common import forms_common +from ishtar_common.tests import WizardTest, WizardTestFormData as FormData  class ImportFindTest(ImportContextRecordTest): @@ -216,3 +218,53 @@ class PackagingTest(FindInit, TestCase):              self.assertNotIn(                  item, self.finds,                  msg="Other basket have not been upgraded after packaging") + + +class TreatmentWizardCreationTest(WizardTest, FindInit, TestCase): +    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', +                settings.ROOT_PATH + +                '../archaeological_warehouse/fixtures/initial_data-fr.json', +                ] +    url_name = 'treatment_creation' +    wizard_name = 'treatment_wizard' +    steps = views.treatment_wizard_steps +    form_datas = [ +        FormData( +            'Move treament', +            form_datas={ +                'basetreatment-treatment_creation': { +                    'treatment_type': 4,  # move +                    'person': 1,  # doer +                    'location': 1,  # associated warehouse +                }, +                'selecfind-treatment_creation': { +                    'pk': 1 +                } +            }, +            ignored=('resultfind-treatment_creation', +                     'resultfinds-treatment_creation')) +    ] + +    def pre_wizard(self): +        q = Warehouse.objects.filter(pk=1) +        if not q.count(): +            warehouse = Warehouse.objects.create( +                name="default", warehouse_type=WarehouseType.objects.all()[0]) +            warehouse.id = 1 +            warehouse.save() +        self.treatment_number = models.Treatment.objects.count() +        super(TreatmentWizardCreationTest, self).pre_wizard() + +    def post_wizard(self): +        self.assertEqual(models.Treatment.objects.count(), +                         self.treatment_number + 1) +        pass diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 17cc4028f..bbb123d09 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -17,7 +17,7 @@  # See the file COPYING for details. -from django.conf.urls.defaults import * +from django.conf.urls import *  from ishtar_common.wizards import check_rights  import views @@ -89,7 +89,11 @@ urlpatterns = patterns(          check_rights(['change_find', 'change_own_find'])(              views.DeleteFindBasketView.as_view()), name='delete_findbasket'),      url(r'treatment_creation/(?P<step>.+)?$', -        views.treatment_creation_wizard, name='treatment_creation'), +        check_rights(['change_find', 'change_own_find'])( +            views.treatment_creation_wizard), name='treatment_creation'), +    url(r'treatment_search/(?P<step>.+)?$', +        check_rights(['view_find', 'view_own_find'])( +            views.treatment_search_wizard), name='treatment_search'),      url(r'get-upstreamtreatment/(?P<type>.+)?$', views.get_upstreamtreatment,          name='get-upstreamtreatment'),      url(r'get-downstreamtreatment/(?P<type>.+)?$', @@ -137,4 +141,10 @@ urlpatterns += patterns(          'show_find', name='show-historized-find'),      url(r'revert-find/(?P<pk>.+)/(?P<date>.+)$',          'revert_find', name='revert-find'), +    url(r'get-treatment/(?P<type>.+)?$', +        'get_treatment', name='get-treatment'), +    url(r'show-treatment(?:/(?P<pk>.+))?/(?P<type>.+)?$', 'show_treatment', +        name=models.Treatment.SHOW_URL), +    # url(r'get-treatment/(?P<type>.+)?$', 'get_treatment', +    #     name='get-treatment'),  ) diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 89babe9b7..f0c67c231 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -45,6 +45,9 @@ get_find = get_item(models.Find, 'get_find', 'find')  get_find_for_ope = get_item(models.Find, 'get_find', 'find',                              own_table_cols=models.Find.TABLE_COLS_FOR_OPE) +show_treatment = show_item(models.Treatment, 'treatment') +get_treatment = get_item(models.Treatment, 'get_treatement', 'treatment') +  show_findsource = show_item(models.FindSource, 'findsource')  get_findsource = get_item(models.FindSource, 'get_findsource', 'findsource') @@ -282,12 +285,20 @@ get_downstreamtreatment = get_item(      models.FindDownstreamTreatments, 'get_downstreamtreatment',      'downtreatment') -treatment_creation_wizard = TreatmentWizard.as_view([ +treatment_wizard_steps = [      ('basetreatment-treatment_creation', BaseTreatmentForm),      ('selecfind-treatment_creation', UpstreamFindFormSelection),      ('resultfind-treatment_creation', ResultFindForm),      ('resultfinds-treatment_creation', ResultFindFormSet), -    ('final-treatment_creation', FinalForm)], +    ('final-treatment_creation', FinalForm)] + +treatment_search_wizard = SearchWizard.as_view([ +    ('general-treatment_search', TreatmentFormSelection)], +    label=_(u"Treatment search"), +    url_name='treatment_search',) + +treatment_creation_wizard = TreatmentWizard.as_view( +    treatment_wizard_steps,      condition_dict={      'selecfind-treatment_creation':          check_not_exist('basetreatment-treatment_creation', diff --git a/archaeological_finds/wizards.py b/archaeological_finds/wizards.py index f897969c4..e97c4518e 100644 --- a/archaeological_finds/wizards.py +++ b/archaeological_finds/wizards.py @@ -17,7 +17,7 @@  # See the file COPYING for details. -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied  from django.utils.translation import ugettext_lazy as _  from ishtar_common.forms import reverse_lazy @@ -85,14 +85,33 @@ class FindDeletionWizard(DeletionWizard):  class TreatmentWizard(Wizard):      model = models.Treatment      basket_step = 'basetreatment-treatment_creation' +    saved_args = {"items": []} -    def get_form_kwargs(self, step): -        kwargs = super(TreatmentWizard, self).get_form_kwargs(step) +    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, form_list): +        """ +        Remove basket ID to the result dict +        """ +        dct = super(TreatmentWizard, self).get_extra_model(dct, form_list) +        if 'resulting_pk' in dct: +            try: +                find = models.Find.objects.get(pk=dct.pop('resulting_pk')) +                if 'own' in self.current_right \ +                        and not find.is_own(dct['history_modifier']): +                    raise PermissionDenied +                dct['items'] = [find] +            except (models.Find.DoesNotExist): +                raise PermissionDenied +        if 'basket' in dct: +            dct.pop('basket') +        return dct +  class FindSourceWizard(SourceWizard):      wizard_done_window = reverse_lazy('show-findsource') diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index dd294550e..80569fb1b 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -38,7 +38,8 @@ from ishtar_common.models import OrganizationType, Organization, \      ImporterType, IshtarUser, TargetKey, IshtarSiteProfile  from ishtar_common import forms_common -from ishtar_common.tests import WizardTest, create_superuser, create_user +from ishtar_common.tests import WizardTest, WizardTestFormData as FormData, \ +    create_superuser, create_user  class ImportOperationTest(TestCase): @@ -668,20 +669,20 @@ class OperationWizardCreationTest(WizardTest, OperationInitTest, TestCase):      url_name = 'operation_creation'      wizard_name = 'operation_wizard'      steps = views.wizard_steps -    form_datas = [( -        # data -        { +    form_datas = [ +        FormData( +            "Create a preventive diag", +            form_datas={              'general-operation_creation': {                  'operation_type': 1,  # preventive diag                  'year': 2016} -        }, -        # ignored -        ('filechoice-operation_creation', -         'preventive-operation_creation', -         'towns-operation_creation', -         'parcels-operation_creation', -         ) -    )] +            }, +            ignored=('filechoice-operation_creation', +                     'preventive-operation_creation', +                     'towns-operation_creation', +                     'parcels-operation_creation', ) +        ) +    ]      def pre_wizard(self):          self.operation_number = models.Operation.objects.count() @@ -697,15 +698,20 @@ class OperationWizardClosingTest(OperationWizardCreationTest):      url_name = 'operation_closing'      wizard_name = 'operation_closing_wizard'      steps = views.operation_closing_steps -    form_datas = [[ -        { -            'selec-operation_closing': {'pk': None}, -            'date-operation_closing': {'end_date': '2016-01-01'}, -        }, []]] +    form_datas = [ +        FormData( +            "Wizard closing test", +            form_datas={ +                'selec-operation_closing': {'pk': None}, +                'date-operation_closing': {'end_date': '2016-01-01'}, +            } +        ) +    ]      def pre_wizard(self):          self.ope = self.get_default_operation() -        self.form_datas[0][0]['selec-operation_closing']['pk'] = self.ope.pk +        self.form_datas[0].form_datas['selec-operation_closing']['pk'] = \ +            self.ope.pk          self.assertTrue(self.ope.is_active())          super(OperationWizardClosingTest, self).pre_wizard() @@ -714,7 +720,7 @@ class OperationWizardClosingTest(OperationWizardCreationTest):          self.assertFalse(ope.is_active())          self.assertEqual(              ope.closing()['date'].strftime('%Y-%d-%m'), -            self.form_datas[0][0]['date-operation_closing']['end_date']) +            self.form_datas[0].form_datas['date-operation_closing']['end_date'])  class OperationAdminActWizardCreationTest(WizardTest, OperationInitTest, @@ -730,25 +736,24 @@ class OperationAdminActWizardCreationTest(WizardTest, OperationInitTest,      url_name = 'operation_administrativeactop'      wizard_name = 'operation_administrative_act_wizard'      steps = views.administrativeactop_steps -    form_datas = [[ -        # data -        { -            'selec-operation_administrativeactop': { -            }, -            'administrativeact-operation_administrativeactop': { -                'signature_date': str(datetime.date.today()) -            } -        }, -        # ignored -        [] -    ]] +    form_datas = [ +        FormData( +            "Admin act creation", +            form_datas={ +                    'selec-operation_administrativeactop': { +                    }, +                    'administrativeact-operation_administrativeactop': { +                        'signature_date': str(datetime.date.today()) +                    } +                }, +        ) +    ]      def pre_wizard(self):          ope = self.get_default_operation() -          self.number = models.AdministrativeAct.objects.count() -        data = self.form_datas[0][0] +        data = self.form_datas[0].form_datas          data['selec-operation_administrativeactop']['pk'] = ope.pk          act = models.ActType.objects.filter(intented_to='O').all()[0].pk diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index 0c4bbda08..dbe3df4a5 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -75,6 +75,32 @@ def create_user():      return username, password, user +class WizardTestFormData(object): +    """ +    Test set to simulate wizard steps +    """ +    def __init__(self, name, form_datas, ignored=[], extra_tests=[]): +        """ +        :param name: explicit name of the test +        :param form_datas: dict with data for each step - dict key are wizard +        step name +        :param ignored: steps to be ignored in wizard processing +        :param extra_tests: list of extra tests. Theses tests must be functions +        accepting two parameters: the current test object and the final step +        response +        """ +        self.form_datas = form_datas +        self.ignored = ignored[:] +        self.extra_tests = extra_tests + +    def tests(self, test_object, final_step_response): +        """ +        Specific tests for theses datas. Raise Exception if not OK. +        """ +        for test in self.extra_tests: +            test(test_object, final_step_response) + +  class WizardTest(object):      url_name = None      wizard_name = '' @@ -95,7 +121,9 @@ class WizardTest(object):      def test_wizard(self):          url = reverse(self.url_name)          self.pre_wizard() -        for form_data, ignored in self.form_datas: +        for test_form_data in self.form_datas: +            form_data = test_form_data.form_datas +            ignored = test_form_data.ignored              for idx, step in enumerate(self.steps):                  current_step, current_form = step                  if current_step in ignored: @@ -138,6 +166,7 @@ class WizardTest(object):                          '/{}/{}'.format(self.url_name, next_form))                  else:                      response = self.client.post(url, data, follow=True) +            test_form_data.tests(self, response)          self.post_wizard() diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 8634125cd..cb6afe8c4 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -910,6 +910,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[],                      keys = [keys]                  my_vals = []                  for k in keys: +                    if k in model.EXTRA_REQUEST_KEYS: +                        k = model.EXTRA_REQUEST_KEYS[k]                      vals = [item]                      # foreign key may be divided by "." or "__"                      splitted_k = [] diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 1183836bc..be22bd3cb 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -581,6 +581,8 @@ class JQueryJqGrid(forms.RadioSelect):                      field_name += "__"                  field_name += f_name                  field_verbose_names.append(unicode(field_verbose_name)) +            if not field_name: +                field_name = "__".join(col_names)              if field_name in col_labels:                  jq_col_names.append(unicode(col_labels[field_name]))              elif col_names and col_names[0] in col_labels: diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index c065459f6..b9fba83b4 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -126,6 +126,8 @@ class Wizard(NamedUrlWizardView):      current_obj_slug = ''      file_storage = default_storage +    saved_args = {}  # argument to pass on object save +      '''      # buggy and unecessary...      def __init__(self, *args, **kwargs): @@ -543,12 +545,16 @@ class Wizard(NamedUrlWizardView):                      dct[dependant_item] = c_item              if 'pk' in dct:                  dct.pop('pk') +            saved_args = self.saved_args.copy() +            for k in saved_args: +                if k in dct: +                    saved_args[k] = dct.pop(k)              obj = self.get_saved_model()(**dct)              try:                  obj.full_clean()              except ValidationError:                  return self.render(form_list[-1]) -            obj.save() +            obj.save(**saved_args)              for k in adds:                  getattr(obj, k).add(adds[k])              # necessary to manage interaction between models like @@ -626,6 +632,7 @@ class Wizard(NamedUrlWizardView):              self.request.session[self.current_obj_slug] = unicode(obj.pk)          self.request.session[self.get_object_name(obj)] = unicode(obj.pk)          dct = {'item': obj} +        self.current_object = obj          # force evaluation of lazy urls          wizard_done_window = unicode(self.wizard_done_window)          if wizard_done_window: | 
