예제 #1
0
    def used_columns(self) -> List[Column]:
        """Extend the used columns with those in the attachments.

        :return: List of column objects
        """
        # Columns from base case
        column_list = super().used_columns()

        # Columns from {{ colname }} in text content
        for match in VAR_USE_RES[0].finditer(self.text_content):
            var_name = match.group('vname')
            column = self.workflow.columns.filter(name=var_name).first()
            if column:
                column_list.append(column)
        # Columns from {% ot_insert_report "c1" "c2" %}
        for match in VAR_USE_RES[2].finditer(self.text_content):
            column_list.extend([
                col for col in self.workflow.columns.filter(
                    name__in=shlex.split(match.group('args')))
            ])

        # Columns from the attachment
        for attachment in self.attachments.all():
            column_list.extend([col for col in attachment.columns.all()])
            attachment_formula = attachment.formula
            if attachment_formula:
                column_list.extend([
                    col for col in self.workflow.columns.filter(
                        name__in=formula.get_variables(attachment_formula))
                ])

        return list(set(column_list))
예제 #2
0
def do_clone_condition(
    user,
    condition: models.Condition,
    new_action: models.Action = None,
    new_name: str = None,
) -> models.Condition:
    """Clone a condition.

    Function to clone a condition and change action and/or name

    :param user: User executing the operation
    :param condition: Condition to clone
    :param new_action: New action to point
    :param new_name: New name
    :return: New condition
    """
    old_id = condition.id
    old_name = condition.name

    if new_name is None:
        new_name = condition.name
    if new_action is None:
        new_action = condition.action

    new_condition = models.Condition(
        name=new_name,
        description_text=condition.description_text,
        action=new_action,
        formula=copy.deepcopy(condition.formula),
        n_rows_selected=condition.n_rows_selected,
        is_filter=condition.is_filter)
    new_condition.save()

    try:
        # Update the many to many field.
        new_condition.columns.set(
            new_condition.action.workflow.columns.filter(
                name__in=formula.get_variables(new_condition.formula), ))
    except Exception as exc:
        new_condition.delete()
        raise exc

    condition.log(user,
                  models.Log.CONDITION_CLONE,
                  id_old=old_id,
                  name_old=old_name)

    return new_condition
예제 #3
0
    def create(self, validated_data, **kwargs) -> Optional[Condition]:
        """Create a new condition object based on the validated_data.

        :param validated_data: Validated data obtained by the parser
        :param kwargs: Additional arguments
        :return: Condition object
        """
        condition_obj = None
        try:
            condition_obj = _create_condition(
                validated_data,
                self.context['action'])

            # Process columns
            if validated_data.get('columns'):
                # Load the columns pointing to the action (if any)
                columns = ColumnNameSerializer(
                    data=validated_data.get('columns'),
                    many=True,
                    required=False,
                )
                if columns.is_valid():
                    cnames = [cdata['name'] for cdata in columns.data]
                else:
                    raise Exception(_('Incorrect column data'))
            else:
                cnames = get_variables(condition_obj.formula)

            # Set the condition values
            condition_obj.columns.set(
                self.context['action'].workflow.columns.filter(
                    name__in=cnames),
            )

            # If n_rows_selected is -1, reevaluate
            if condition_obj.n_rows_selected == -1:
                condition_obj.update_n_rows_selected()

            # Save condition object
            condition_obj.save()
        except Exception:
            if condition_obj and condition_obj.id:
                condition_obj.delete()
            raise

        return condition_obj
예제 #4
0
def save_condition_form(
    request: HttpRequest,
    form,
    action: models.Action,
    is_filter: Optional[bool] = False,
) -> JsonResponse:
    """Process the AJAX form POST to create and update conditions and filters.

    :param request: HTTP request
    :param form: Form being used to ask for the fields
    :param action: The action to which the condition is attached to
    :param is_filter: The condition is a filter
    :return: JSON response
    """
    if is_filter and form.instance.id is None and action.get_filter():
        # Should not happen. Go back to editing the action
        return JsonResponse({'html_redirect': ''})

    is_new = form.instance.id is None

    # Update fields and save the condition
    condition = form.save(commit=False)
    condition.formula_text = None
    condition.action = action
    condition.is_filter = is_filter
    condition.save()
    condition.columns.set(
        action.workflow.columns.filter(name__in=formula.get_variables(
            condition.formula), ))

    # If the request has the 'action_content' field, update the action
    action_content = request.POST.get('action_content')
    if action_content:
        action.set_text_content(action_content)

    _propagate_changes(condition, form.changed_data, form.old_name, is_new)

    # Store the type of event to log
    if is_new:
        log_type = models.Log.CONDITION_CREATE
    else:
        log_type = models.Log.CONDITION_UPDATE
    condition.log(request.user, log_type)
    return JsonResponse({'html_redirect': ''})
예제 #5
0
def do_clone_condition(
    condition: Condition,
    new_action: Action = None,
    new_name: str = None,
) -> Condition:
    """Clone a condition.

    Function to clone a condition and change action and/or name

    :param condition: Condition to clone

    :param new_action: New action to point

    :param new_name: New name

    :return: New condition
    """
    if new_name is None:
        new_name = condition.name
    if new_action is None:
        new_action = condition.action

    new_condition = Condition(
        name=new_name,
        description_text=condition.description_text,
        action=new_action,
        formula=copy.deepcopy(condition.formula),
        n_rows_selected=condition.n_rows_selected,
        is_filter=condition.is_filter
    )
    new_condition.save()

    try:
        # Update the many to many field.
        new_condition.columns.set(new_condition.action.workflow.columns.filter(
            name__in=get_variables(new_condition.formula),
        ))
    except Exception as exc:
        new_condition.delete()
        raise exc

    return new_condition
예제 #6
0
def save_condition_form(
    request: HttpRequest,
    form,
    template_name: str,
    action: Action,
    is_filter: Optional[bool] = False,
) -> JsonResponse:
    """
    Process the AJAX form to create and update conditions and filters.

    :param request: HTTP request

    :param form: Form being used to ask for the fields

    :param template_name: Template being used to render the form

    :param action: The action to which the condition is attached to

    :param is_filter: The condition is a filter

    :return: JSON response
    """
    if request.method == 'POST' and form.is_valid():

        if not form.has_changed():
            return JsonResponse({'html_redirect': None})

        if is_filter and form.instance.id is None and action.get_filter():
            # Should not happen. Go back to editing the action
            return JsonResponse({'html_redirect': ''})

        is_new = form.instance.id is None

        # Update fields and save the condition
        condition = form.save(commit=False)
        condition.formula_text = None
        condition.action = action
        condition.is_filter = is_filter
        condition.save()
        condition.columns.set(action.workflow.columns.filter(
            name__in=get_variables(condition.formula),
        ))

        # If the request has the 'action_content' field, update the action
        action_content = request.POST.get('action_content')
        if action_content:
            action.set_text_content(action_content)

        propagate_changes(condition, form.changed_data, form.old_name, is_new)

        # Store the type of event to log
        if is_new:
            log_type = Log.CONDITION_CREATE
        else:
            log_type = Log.CONDITION_UPDATE
        condition.log(request.user, log_type)
        return JsonResponse({'html_redirect': ''})

    # GET request or invalid form
    return JsonResponse({
        'html_form': render_to_string(
            template_name,
            {
                'form': form,
                'action_id': action.id,
                'condition': form.instance},
            request=request),
    })