Exemplo n.º 1
0
    def form_valid(self, form, *args, **kwargs):
        """ Создаёт объект Корректировки, если есть поля с заполненными корректировками """
        # Деактивируем корректировку для нашего текущего шага
        corrections_qs = form.instance.get_correction_active(
            for_step=get_task_ref(self.linked_node))
        corrections_qs.update(is_active=False)

        # TODO MBPM-3: Вынести запрос к БД из цикла
        for corr_settings in self.can_create_corrections:
            correction_data = dict([
                (name.replace(corr_settings['action_btn_name'], ''), value)
                for name, value in form.cleaned_data.items()
                if name.endswith(corr_settings['action_btn_name']) and value
            ])
            if correction_data:
                Correction.objects.create(
                    task=self.activation.task,
                    proposal=self.activation.process,
                    for_step=get_task_ref(corr_settings['for_step']),
                    reviewed_version=form.cleaned_data['current_version'],
                    data=correction_data,
                    is_active=True,
                    owner=self.request.user)

        super().form_valid(form, *args, **kwargs)
        return HttpResponseRedirect(self.get_success_url())
Exemplo n.º 2
0
 def test_get_task_ref_succeed(self):
     self.assertEqual(
         fields.get_task_ref(
             TestFlow.start),
         'tests/test_fields.TestFlow.start')
     self.assertEqual(
         fields.get_task_ref(
             TestFlow.end),
         'tests/test_fields.TestFlow.end')
Exemplo n.º 3
0
 def task_loader(flow_task, **kwargs):
     proposal = kwargs['proposal']
     # Проверяем, есть ли у текущей заявки процесс по созданию BibServe-аккаунта
     if hasattr(proposal, 'bibserveprocess'):
         return flow_task.flow_class.task_class._default_manager.filter(
             flow_task=get_task_ref(flow_task),
             process_id=proposal.bibserveprocess.id).first()
Exemplo n.º 4
0
 def schedule(self, task_id):
     """
     Async task schedule
     """
     self.flow_task.job.apply_async(
         args=[get_task_ref(self.flow_task), self.task.process_id, self.task.pk],
         task_id=task_id,
         countdown=1)
Exemplo n.º 5
0
def is_already_has_task(activation, task):
    # TODO MBPM-3:
    # Кажется эта функция не используется
    if not hasattr(task, 'flow_class'):
        setattr(task, 'flow_class', ProposalConfirmationFlow)

    return activation.process.task_set.exclude(status='DONE').filter(
        flow_task=get_task_ref(task)).exists()
Exemplo n.º 6
0
    def __init__(self, *args, **kwargs):
        self.linked_node = kwargs.pop('linked_node')
        self.show_corrections = kwargs.pop('show_corrections', [])
        self.can_create_corrections = kwargs.pop('can_create_corrections')
        self.fields_corrections = kwargs.pop('fields_corrections')

        super().__init__(*args, **kwargs)

        # Делаем каждое поле неактивным
        for field in self.fields.values():
            if isinstance(field.widget, (CheckboxInput, Select, RadioSelect)):
                field.widget.attrs['disabled'] = 'disabled'
            else:
                field.widget.attrs['readonly'] = True

        # Добавляем поля для корректировки и комментариев согласно настройкам в self.can_create_corrections
        for corr_settings in self.can_create_corrections:
            # Если задана опция is_can_answer_only, то проверяем, есть ли корректировки,
            # на которые нужно отвечать. И если такие есть, то показываем поля для ответа.
            if 'is_can_answer_only' in corr_settings and corr_settings[
                    'is_can_answer_only']:
                has_correction = False
                if '__all__' in self.fields_corrections:
                    has_correction = bool([
                        corr for corr in self.fields_corrections['__all__']
                        if get_task_ref(corr_settings['for_step']) ==
                        get_task_ref(corr['from_step_obj'])
                    ])
                if not has_correction:
                    continue

            non_field_correction = forms.CharField(
                max_length=255,
                required=False,
                label=corr_settings['non_field_corr_label'],
                widget=forms.TextInput(
                    attrs={
                        'data-correction-field': 'true',
                        'action_btn_label': corr_settings['action_btn_label'],
                        'action_btn_name': corr_settings['action_btn_name'],
                        'action_btn_class': corr_settings['action_btn_class'],
                    }))
            self.fields[
                '__all__' +
                corr_settings['action_btn_name']] = non_field_correction
Exemplo n.º 7
0
 def schedule(self, task_id):
     """
     Async task schedule
     """
     self.flow_task.job.apply_async(args=[
         get_task_ref(self.flow_task), self.task.process_id, self.task.pk
     ],
                                    task_id=task_id,
                                    countdown=1)
Exemplo n.º 8
0
    def test_flow_job_decorator(self):
        act = JobTestFlow.start.run()

        with Context(throw_test_error=False):
            job_handler(
                get_task_ref(JobTestFlow.job), act.process.pk,
                act.process.get_task(JobTestFlow.job,
                                     status=[STATUS.SCHEDULED]).pk)

        tasks = act.process.task_set.all()
        self.assertEqual(3, tasks.count())
        self.assertTrue(all(task.finished is not None for task in tasks))
Exemplo n.º 9
0
    def test_flow_job_decorator(self):
        act = JobTestFlow.start.run()

        with Context(throw_test_error=False):
            job_handler(
                get_task_ref(JobTestFlow.job),
                act.process.pk,
                act.process.get_task(JobTestFlow.job, status=[STATUS.SCHEDULED]).pk)

        tasks = act.process.task_set.all()
        self.assertEqual(3, tasks.count())
        self.assertTrue(all(task.finished is not None for task in tasks))
Exemplo n.º 10
0
    def test_flow_job_decorator_error(self):
        act = JobTestFlow.start.run()

        with Context(throw_test_error=True):
            try:
                job_handler(
                    get_task_ref(JobTestFlow.job), act.process.pk,
                    act.process.get_task(JobTestFlow.job,
                                         status=[STATUS.SCHEDULED]).pk)
            except ValueError:
                """Expected test error."""

        tasks = act.process.task_set.all()
        self.assertEqual(2, tasks.count())

        job_task = act.process.get_task(JobTestFlow.job, status=[STATUS.ERROR])
        self.assertIn('Expected test error', job_task.comments)
Exemplo n.º 11
0
    def test_flow_job_decorator_error(self):
        act = JobTestFlow.start.run()

        with Context(throw_test_error=True):
            try:
                job_handler(
                    get_task_ref(JobTestFlow.job),
                    act.process.pk,
                    act.process.get_task(JobTestFlow.job, status=[STATUS.SCHEDULED]).pk)
            except ValueError:
                """Expected test error."""

        tasks = act.process.task_set.all()
        self.assertEqual(2, tasks.count())

        job_task = act.process.get_task(JobTestFlow.job, status=[STATUS.ERROR])
        self.assertIn('Expected test error', job_task.comments)
Exemplo n.º 12
0
def has_active_correction(activation, for_step=None):
    """
    Возвращает True, если у Заявки нет ни одной активной Корректировки.
    А это значит, что заявка на данном шаге подтверждена и можно переводить её на следующий шаг.

    :param activation: viewflow.activation.Activation
    :param for_step: viewflow.ThisObject
    :return: boolean
    """
    task_qs = activation.process.task_set.filter(correction__is_active=True)
    if for_step:
        if not hasattr(for_step, 'flow_class'):
            setattr(for_step, 'flow_class', ProposalConfirmationFlow)
        for_step = get_task_ref(for_step)
        task_qs = task_qs.filter(correction__for_step=for_step)

    if task_qs.exists():
        return True

    return False
Exemplo n.º 13
0
    def clean(self):
        self.cleaned_data = super().clean()

        # Проверяем, изменились ли те поля, к которым были указаны корректировки
        # correction_obj = self.instance.get_correction_active(for_step=get_task_ref(self.linked_node))
        # need_to_be_corrected = set(correction_obj.data.keys())
        corrections_qs = self.instance.get_correction_active(
            for_step=get_task_ref(self.linked_node))
        # Для Клиента всегда должна быть одна активная Корретировка, т.к. он общается через Аккаунта,
        # и только Аккаунт может создавать для него Корректировки
        # TODO MBPM-3: Закрепить это на уровне констрейта в БД?
        correction_obj = corrections_qs.first()
        need_to_be_corrected = set(correction_obj.data.keys())

        last_version = correction_obj.reviewed_version
        changed_fields = set(
            self.instance.get_diff_fields(self.cleaned_data, last_version,
                                          self.fields.keys()).keys())

        if '__all__' in need_to_be_corrected:
            if not changed_fields:
                msg = l_(
                    'Нужно изменить хотя бы одно поле в соответствие с корретировкой: '
                    + correction_obj.data['__all__'])
                self.add_error(None, msg)
            need_to_be_corrected.remove('__all__')

        not_corrected = need_to_be_corrected - changed_fields
        if not_corrected:
            for field_name in not_corrected:
                msg = l_(
                    'Нужно изменить это поле в соответствие с корректировкой: '
                    + correction_obj.data[field_name])
                self.add_error(field_name, msg)

        return self.cleaned_data
Exemplo n.º 14
0
 def test_get_task_ref_succeed(self):
     self.assertEqual(fields.get_task_ref(TestFlow.start), "tests/test_fields.TestFlow.start")
     self.assertEqual(fields.get_task_ref(TestFlow.end), "tests/test_fields.TestFlow.end")
Exemplo n.º 15
0
    def get_fields_corrections(self, instance):
        """
        Возвращает dict с ключами с именем полей и значениями в виде Корректировок и историй изменений заявки.
        На основании show_corrections и полей формы.
        """
        for_steps = []
        # {'for_step': '', 'made_on_step': ''}
        # добавляем имя своего шага, чтобы видеть корректировки, созданные для этого шага
        for_steps.append({'for_step': get_task_ref(self.linked_node)})
        # добавляем возможность видеть корректировки для других шагов, если это настроенно в ноде
        for corr_setting in self.show_corrections:
            for_steps.append({
                'for_step':
                get_task_ref(corr_setting['for_step']),
                'made_on_step':
                get_task_ref(corr_setting['made_on_step']) if
                ('made_on_step' in corr_setting) else None
            })
        corrections_qs = instance.get_corrections_all(for_steps)

        # Поля, которые видит пользователь в рамках этого view
        fields = self.fields
        if not fields:
            fields = self.form_class.base_fields.keys()
            fields = [
                name for (name, field) in self.form_class.base_fields.items()
            ]

        fields_corrections = {}

        # Добавляем non_field поле
        for correction in corrections_qs:
            if '__all__' in correction.data:
                non_field_corr = {
                    'msg': correction.data['__all__'],
                    'from_step': str(correction.task.flow_task),
                    'from_step_obj': correction.task.flow_task,
                    'owner': str(correction.owner),
                    'created': correction.created,
                    'is_active': correction.is_active,
                    'changed_fieldschanged_fields': None,
                }
                if '__all__' in fields_corrections:
                    fields_corrections['__all__'].append(non_field_corr)
                else:
                    fields_corrections['__all__'] = [non_field_corr]

                if correction.fixed_in_version:
                    base_instace = json.loads(correction.fixed_in_version.
                                              serialized_data)[0]['fields']
                    diff = ProposalProcess.get_diff_fields(
                        base_instace, correction.reviewed_version, fields)
                    non_field_corr['changed_fields'] = diff
                    for (changed_field_name,
                         changed_field_old_value) in diff.items():
                        field_corr = {
                            'msg': correction.data['__all__'],
                            'from_step': str(correction.task.flow_task),
                            'from_step_obj': correction.task.flow_task,
                            'owner': str(correction.owner),
                            'created': correction.created,
                            'is_active': correction.is_active,
                            'version_value': None
                        }
                        if correction.fixed_in_version:
                            field_corr[
                                'version_value'] = changed_field_old_value[
                                    'old_value']
                        if changed_field_name in fields_corrections:
                            fields_corrections[changed_field_name].append(
                                field_corr)
                        else:
                            fields_corrections[changed_field_name] = [
                                field_corr
                            ]

        for field_name in fields:
            for correction in corrections_qs:
                if field_name in correction.data:
                    field_corr = {
                        'msg': correction.data[field_name],
                        'from_step': str(correction.task.flow_task),
                        'from_step_obj': correction.task.flow_task,
                        'owner': str(correction.owner),
                        'created': correction.created,
                        'is_active': correction.is_active,
                        'version_value': None,
                    }
                    if correction.fixed_in_version:
                        base_instace = json.loads(correction.fixed_in_version.
                                                  serialized_data)[0]['fields']

                        diff = ProposalProcess.get_diff_fields(
                            base_instace, correction.reviewed_version,
                            [field_name])
                        if diff:
                            field_corr['version_value'] = diff[field_name][
                                'old_value']

                    if field_name in fields_corrections:
                        fields_corrections[field_name].append(field_corr)
                    else:
                        fields_corrections[field_name] = [field_corr]

        return fields_corrections
Exemplo n.º 16
0
def is_already_done(activation, task):
    if not hasattr(task, 'flow_class'):
        setattr(task, 'flow_class', ProposalConfirmationFlow)

    return activation.process.task_set.filter(flow_task=get_task_ref(task),
                                              status='DONE').exists()