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 | 8b666443667f92e014d70a4247c7885375bba610 (patch) | |
tree | 7e216f7c036ae568407d46359dea361f2a641098 | |
parent | 62cac0ec03a96d5f358148cf6dff2a21ccf20854 (diff) | |
download | Ishtar-8b666443667f92e014d70a4247c7885375bba610.tar.bz2 Ishtar-8b666443667f92e014d70a4247c7885375bba610.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: |