Example #1
0
def patch_action_type(request, act_id):
    action_type = get_object_or_404(ActionType, id=int(act_id))

    name = request.data.get("name")
    entity_status = request.data.get("entity_status")
    description = request.data.get("description")
    label = request.data.get("label")
    format_data = request.data.get("format")

    action_controller = ActionController(action_type)

    result = {'id': action_type.id}

    if entity_status is not None and action_type.entity_status != entity_status:
        action_type.set_status(entity_status)
        result['entity_status'] = entity_status
        action_type.update_field('entity_status')

    if name is not None:
        action_type.name = name
        result['name'] = name
        action_type.update_field('name')

    if description is not None:
        action_type.description = description
        result['description'] = description
        action_type.update_field('description')

    if label is not None:
        lang = translation.get_language()
        action_type.set_label(lang, label)
        result['label'] = label
        action_type.update_field('label')

    if format_data is not None:
        if 'steps' not in format_data:
            raise SuspiciousOperation(_("Invalid format"))

        action_type.format['steps'] = []

        for step in format_data['steps']:
            # step format validation
            ActionStepFormatManager.check(action_controller, step)
            action_type.format['steps'].append(step)

        result['format'] = action_type.format
        action_type.update_field('format')

    action_type.save()

    return HttpResponseRest(request, result)
Example #2
0
    def get_step_data_format(self, step_index):
        """
        Get the columns format for the data of a particular step index.
        """
        action_steps = self.action.data.get('steps')
        if not action_steps:
            raise ActionError("Empty action steps")

        action_steps = self.action.data['steps']

        if step_index >= len(action_steps):
            raise ActionError("Action step index out of range")

        # # check step state
        # action_step_state = action_step.get('state', ActionController.STEP_INIT)
        # if action_step_state != ActionController.STEP_DONE:
        #     raise ActionError("Current action step state must be done")

        # step format
        action_type_steps = self.action_type.format['steps']

        step_format = action_type_steps[step_index]
        action_step_format = ActionStepFormatManager.get(step_format['type'])

        return action_step_format.data_format
Example #3
0
def get_format_type_list(request):
    """
    Return the list of format of action type
    """
    groups = {}
    items = {}

    for ft in ActionStepFormatManager.values():
        if ft.group:
            if ft.group.name not in groups:
                groups[ft.group.name] = {
                    'group': ft.group.name,
                    'label': str(ft.group.verbose_name)
                }

        if ft.name in items:
            raise SuspiciousOperation(
                "Already registered format of action type %s" % ft.name)

        items[ft.name] = {
            'id': ft.name,
            'group': ft.group.name,
            'value': ft.name,
            'label': str(ft.verbose_name)
        }

    groups_list = sorted(list(groups.values()), key=lambda x: x['group'])
    items_list = sorted(list(items.values()), key=lambda x: x['label'])

    results = {'groups': groups_list, 'items': items_list}

    return HttpResponseRest(request, results)
Example #4
0
def create_action_type(request):
    """
    Create a new action type
    """
    # check name uniqueness
    if ActionType.objects.filter(name=request.data['name']).exists():
        raise SuspiciousOperation(
            _('An action with a similar name already exists'))

    description = request.data.get("description")
    label = request.data.get("label")
    format_data = request.data.get("format", {'type': 'undefined'})
    lang = translation.get_language()

    # create the action type
    action_type = ActionType()
    action_type.name = request.data['name']
    action_type.set_label(lang, label)
    action_type.description = description
    action_type.format = format_data

    action_controller = ActionController(action_type, request.user)

    if format_data['type'] != 'undefined':
        # format validation
        ActionStepFormatManager.check(action_controller, format_data)

    action_type.save()

    result = {
        'id': action_type.id,
        'name': action_type.name,
        'label': action_type.get_label(),
        'format': action_type.format,
        'description': action_type.description
    }

    return HttpResponseRest(request, result)
Example #5
0
    def setup_data(self, input_data, input_columns):
        if not self.is_current_step_valid:
            raise ActionError("Invalid current action step")

        if self.is_current_step_done:
            raise ActionError("Current action step is already done")

        # step format
        action_type_steps = self.action_type.format['steps']

        action_steps = self.action.data['steps']
        step_index = len(action_steps) - 1

        step_format = action_type_steps[step_index]
        action_step_format = ActionStepFormatManager.get(step_format['type'])

        if not action_step_format.accept_user_data and input_data is not None:
            raise ActionError("Current step does not accept data from user")

        action_step = action_steps[step_index]

        # check step state
        action_step_state = action_step.get('state',
                                            ActionController.STEP_INIT)
        if action_step_state != ActionController.STEP_INIT and action_step_state != ActionController.STEP_SETUP:
            raise ActionError(
                "Current action step state must be initial or setup")

        # validate data according to step format
        validated_data = action_step_format.validate(step_format, input_data,
                                                     input_columns)

        action_step['state'] = ActionController.STEP_SETUP

        action_data = ActionData()
        action_data.action = self.action
        action_data.data_type = ActionDataType.INPUT.value
        action_data.step_index = step_index
        action_data.data = validated_data or []  # never null

        try:
            # finally save
            with transaction.atomic():
                self.action.save()
                action_data.save()

        except IntegrityError as e:
            raise ActionError(e)
Example #6
0
    def has_iterative_processing(self):
        """
        Is the current step wait for iterative processing.
        """
        action_steps = self.action.data.get('steps')
        if not action_steps:
            raise ActionError("Empty action steps")

        step_index = len(action_steps) - 1

        # step format
        action_type_steps = self.action_type.format['steps']

        step_format = action_type_steps[step_index]
        action_step_format = ActionStepFormatManager.get(step_format['type'])

        return action_step_format.iterative_processing
Example #7
0
    def update_related_entities(self, step_index, data_array):
        """
        After processing a step, the related table of entities must be updated to easily lookup for which entities
        an action is related to.
        """
        if not data_array:
            return

        action_steps = self.action.data.get('steps')
        if not action_steps:
            raise ActionError("Empty action steps")

        action_steps = self.action.data['steps']

        if step_index >= len(action_steps):
            raise ActionError("Action step index out of range")

        action_step = action_steps[step_index]

        # check step state
        action_step_state = action_step.get('state',
                                            ActionController.STEP_INIT)
        if action_step_state != ActionController.STEP_DONE:
            raise ActionError("Current action step state must be done")

        # step format
        action_type_steps = self.action_type.format['steps']

        step_format = action_type_steps[step_index]
        action_step_format = ActionStepFormatManager.get(step_format['type'])

        missing = []

        self.get_missing_entities(data_array, action_step_format.data_format,
                                  missing)

        # now for missing entities bulk create them
        ActionToEntity.objects.bulk_create(missing)
Example #8
0
    def ready(self):
        super().ready()

        # register descriptor cache category
        from main.cache import cache_manager
        cache_manager.register('accession')

        from messenger.cache import client_cache_manager
        client_cache_manager.register('accession')

        from main.models import main_register_models
        main_register_models(CollGateAccession.name)

        from audit.models import audit_register_models
        audit_register_models(CollGateAccession.name)

        # create a module accession
        accession_module = Module('accession', base_url='coll-gate')
        accession_module.include_urls(
            ('base', 'accessionsynonym', 'actions.actiontype',
             'actions.action', 'accession', 'accessionbatch', 'batch',
             'accessionpanel', 'batchpanel', 'accessionclassificationentry',
             'storagelocation'))

        # add the describable entities models
        from .models import Accession, Batch, AccessionPanel, BatchPanel

        # descriptor_module
        from django.apps import apps
        descriptor_app = apps.get_app_config('descriptor')
        descriptor_app.describable_entities += [
            Accession, Batch, AccessionPanel, BatchPanel
        ]

        # add the classificationEntry entities models, classification_module
        classification_app = apps.get_app_config('classification')
        classification_app.children_entities += [Accession]

        # registers standard format type of descriptors layouts
        from accession import layouttype

        for element in dir(layouttype):
            attr = getattr(layouttype, element)
            if type(attr) is type and layouttype.LayoutType in attr.__bases__:
                self.layout_types.append(attr())

        # and register them
        LayoutTypeManager.register(self.layout_types)

        # and the action type formats
        from accession.actions import actionstepformat

        for element in dir(actionstepformat):
            attr = getattr(actionstepformat, element)
            if type(
                    attr
            ) is type and attr is not actionstepformat.ActionStepFormat and issubclass(
                    attr, actionstepformat.ActionStepFormat):
                self.action_step_formats.append(attr())

        from accession.actions.actionstepformat import ActionStepFormatManager
        ActionStepFormatManager.register(self.action_step_formats)

        # accession menu
        menu_accession = ModuleMenu('accession',
                                    _('Accession'),
                                    auth=AUTH_USER)

        menu_accession.add_entry(
            MenuEntry('create-accession',
                      _('Create accession'),
                      "~accession/accession/create",
                      icon=FaGlyph('plus'),
                      order=1))

        menu_accession.add_entry(MenuSeparator(100))
        menu_accession.add_entry(
            MenuEntry('list-accession',
                      _('List accessions'),
                      "#accession/accession/",
                      icon=FaGlyph('list'),
                      order=101))
        menu_accession.add_entry(
            MenuEntry('panel-accession',
                      _('Panel accessions'),
                      "#accession/accessionpanel/",
                      icon=FaGlyph('list-alt'),
                      order=102))

        menu_accession.add_entry(MenuSeparator(200))
        menu_accession.add_entry(
            MenuEntry('search-accession',
                      _('Search accessions'),
                      "~accession/accession/search",
                      icon=FaGlyph('search'),
                      order=201))

        accession_module.add_menu(menu_accession)

        # batch menu
        menu_batch = ModuleMenu('batch', _('Batch'), auth=AUTH_USER)

        menu_batch.add_entry(
            MenuEntry('create-batch',
                      _('Introduce a batch'),
                      "~accession/batch/create",
                      icon=FaGlyph('plus'),
                      order=1))

        menu_batch.add_entry(MenuSeparator(100))
        menu_batch.add_entry(
            MenuEntry('list-batches',
                      _('List batches'),
                      "#accession/batch/",
                      icon=FaGlyph('list'),
                      order=101))
        menu_batch.add_entry(
            MenuEntry('panel-batches',
                      _('Panel batches'),
                      "#accession/batchpanel/",
                      icon=FaGlyph('list-alt'),
                      order=102))

        menu_batch.add_entry(MenuSeparator(200))
        menu_batch.add_entry(
            MenuEntry('search-batch',
                      _('Search batches'),
                      "~accession/batch/search",
                      icon=FaGlyph('search'),
                      order=201))

        accession_module.add_menu(menu_batch)

        # action menu
        menu_action = ModuleMenu('action', _('Action'), auth=AUTH_USER)

        menu_action.add_entry(
            MenuEntry('create-action',
                      _('Create action'),
                      "~accession/action/create",
                      icon=FaGlyph('plus'),
                      order=1))

        menu_action.add_entry(MenuSeparator(100))
        menu_action.add_entry(
            MenuEntry('list-actions',
                      _('List actions'),
                      "#accession/action/",
                      icon=FaGlyph('list-alt'),
                      order=101))

        accession_module.add_menu(menu_action)

        # accession administration menu
        menu_administration = ModuleMenu('administration',
                                         _('Administration'),
                                         order=999,
                                         auth=AUTH_STAFF)

        # storage location menu
        menu_administration.add_entry(
            MenuEntry('list-location',
                      _('Storage locations'),
                      "#accession/storagelocation/",
                      icon=FaGlyph('archive'),
                      order=-196,
                      auth=AUTH_STAFF))

        # descriptor related menus
        menu_administration.add_entry(MenuSeparator(500))
        menu_administration.add_entry(
            MenuEntry('list-action-type',
                      _('Action types'),
                      "#accession/actiontype/",
                      icon=FaGlyph('cubes'),
                      order=501,
                      auth=AUTH_STAFF))
        accession_module.add_menu(menu_administration)

        module_manager.register_module(accession_module)

        if self.is_run_mode():
            self.post_ready()
Example #9
0
    def process_current_step(self):
        if not self.is_current_step_valid:
            raise ActionError("Invalid current action step")

        if self.is_current_step_done:
            raise ActionError("Current action step is already done")

        # step format
        action_type_steps = self.action_type.format['steps']

        action_steps = self.action.data['steps']
        step_index = len(action_steps) - 1

        step_format = action_type_steps[step_index]
        action_step_format = ActionStepFormatManager.get(step_format['type'])

        action_step = action_steps[step_index]

        # check step state
        action_step_state = action_step.get('state',
                                            ActionController.STEP_INIT)
        if action_step_state != ActionController.STEP_SETUP:
            raise ActionError("Current action step state must be setup")

        # current step data set
        try:
            data_array = ActionData.objects.get(
                action=self.action,
                step_index=step_index,
                data_type=ActionDataType.INPUT).data
        except ActionData.DoesNotExist:
            data_array = None

        if step_index > 0:
            # output of the previous state if not initial step
            prev_output_array = ActionData.objects.get(
                action=self.action,
                step_index=step_index - 1,
                data_type=ActionDataType.OUTPUT).data
        else:
            prev_output_array = None

        # for iterative step only set the flag to process and returns
        if action_step_format.iterative:
            # process, save and make associations
            try:
                with transaction.atomic():
                    action_step_format.prepare_iterative_process(
                        self, step_format, action_step, prev_output_array,
                        data_array)

                    action_data = ActionData()
                    action_data.action = self.action
                    action_data.data_type = ActionDataType.OUTPUT.value
                    action_data.step_index = step_index
                    action_data.data = []  # empty array initially

                    action_step['state'] = ActionController.STEP_PROCESS

                    self.action.save()
                    action_data.save()

            except IntegrityError as e:
                raise ActionError(e)

            return

        # process, save and make associations
        try:
            with transaction.atomic():
                output_data = action_step_format.process(
                    self, step_format, action_step, prev_output_array,
                    data_array)

                action_data = ActionData()
                action_data.action = self.action
                action_data.data_type = ActionDataType.OUTPUT.value
                action_data.step_index = step_index
                action_data.data = output_data

                action_step['state'] = ActionController.STEP_DONE

                # and init the next one
                if self.has_more_steps:
                    self.add_step_data()
                else:
                    self.action.completed = True

                self.action.save()
                action_data.save()

                # and add the related refs
                self.update_related_entities(step_index, output_data)

        except IntegrityError as e:
            raise ActionError(e)
Example #10
0
    def process_current_step_once(self, data):
        """
        Process one more element of the current step in case of progressive step.

        :param data:
        :return:
        """
        if not self.is_current_step_valid:
            raise ActionError("Invalid current action step")

        if self.is_current_step_done:
            raise ActionError("Current action step is already done")

        # step format
        action_type_steps = self.action_type.format['steps']

        action_steps = self.action.data['steps']
        step_index = len(action_steps) - 1

        step_format = action_type_steps[step_index]
        action_step_format = ActionStepFormatManager.get(step_format['type'])

        action_step = action_steps[step_index]

        # check step state
        action_step_state = action_step.get('state',
                                            ActionController.STEP_INIT)
        if action_step_state != ActionController.STEP_SETUP or action_step_state != ActionController.STEP_PROCESS:
            raise ActionError(
                "Current action step state must be setup or process")

        # current step data set
        try:
            data_array = ActionData.objects.get(
                action=self.action,
                step_index=step_index,
                data_type=ActionDataType.INPUT).data
        except ActionData.DoesNotExist:
            data_array = None

        if step_index > 0:
            # output of the previous state if not initial step
            try:
                prev_output_array = ActionData.objects.get(
                    action=self.action,
                    step_index=step_index - 1,
                    data_type=ActionDataType.OUTPUT).data
            except ActionData.DoesNotExist:
                prev_output_array = None
        else:
            prev_output_array = None

        # process, save and make associations
        try:
            with transaction.atomic():
                output_data = action_step_format.process_iteration(
                    self, self.action, step_format, action_step,
                    prev_output_array, data_array)

                # first time create the action data
                try:
                    action_data = ActionData.objects.get(
                        action=self.action,
                        step_index=step_index,
                        data_type=ActionDataType.OUTPUT)
                except ActionData.DoesNotExist:
                    action_data = ActionData()
                    action_data.action = self.action
                    action_data.data_type = ActionDataType.OUTPUT.value
                    action_data.step_index = step_index

                # @todo to be finished and tested

                # aggregate the results
                action_data.data += output_data
                action_step['progression'][0] += 1  # and one more iteration

                # done once process reach end
                if action_step['progression'][1] == action_step['progression'][
                        2]:
                    action_step['state'] = ActionController.STEP_DONE

                    # and init the next one
                    if self.has_more_steps:
                        self.add_step_data()
                    else:
                        self.action.completed = True

                self.action.save()
                action_data.save()

                # and add the related refs
                self.update_related_entities(step_index, output_data)

        except IntegrityError as e:
            raise ActionError(e)