Ejemplo n.º 1
0
    def handle(self, filename=None, **options):
        try:
            from pydot import Dot, Edge, Node
        except ImportError:
            raise CommandError("need pydot python module ( apt-get install python-pydot )")

        graph = Dot()

        for status, description in STATUS_CHOICES:
            graph.add_node(Node(
                'status-%s' % status,
                label='"%s (%s)"' %
                    (description.encode('utf-8'), status))
            )

        from sadiki.core.workflow import workflow
        for transition_index in workflow.available_transitions():
            transition = workflow.get_transition_by_index(transition_index)
            graph.add_edge(Edge(
                'status-%s'% transition.src,
                'status-%s' % transition.dst,
                label='"%s (%s)"' % (transition.comment.encode('utf-8'), transition.index),
                style='solid' if transition.required_permissions else 'dashed',
            ))

        if filename:
            graph.write_png(filename)
        else:
            print graph.to_string()
Ejemplo n.º 2
0
    def dispatch(self, request, requestion_id, dst_status):
        u"""
        Метод переопределен, чтобы сохранить в атрибутах ``transition``
        """
        requestion = get_object_or_404(Requestion, id=requestion_id)

        redirect_to = request.REQUEST.get('next', '')
        self.redirect_to = check_url(
            redirect_to, self.default_redirect_to(requestion))

        if not requestion.is_available_for_actions:
            messages.error(
                request,
                u"Изменения заявки в статусе '{}' запрещены.".format(
                    requestion.get_status_display()
                ))
            return HttpResponseRedirect(self.redirect_to)

        transition_indexes = workflow.available_transitions(
            src=requestion.status, dst=int(dst_status))
        if transition_indexes:
            self.transition = workflow.get_transition_by_index(
                transition_indexes[0])
        else:
            self.transition = None

        # копирование ролей из workflow в проверку прав
        if self.transition:
            # Если на перевод есть права
            if self.transition.required_permissions:
                temp_copy = self.transition.required_permissions[:]
                # Пропустить публичный доступ ``ANONYMOUS_PERMISSION``
                if Transition.ANONYMOUS_PERMISSION in temp_copy:
                    temp_copy.remove(Transition.ANONYMOUS_PERMISSION)
                self.required_permissions = temp_copy

            # Если переод только внутрисистемный, запретить его выполнение
            else:
                self.required_permissions = None

            # задаем шаблон в зависимости от типа изменения статуса
            self.template_name = self.get_custom_template_name() or self.template_name

        response = super(RequestionStatusChange, self).dispatch(
            request, requestion)
        # если проверка прав прошла успешно, переход предполагает проверку
        # документов и у заявки не указан документ, то перенаправляем на
        # страницу указания документа
        if (isinstance(response, TemplateResponse) and not
            isinstance(request, FakeWSGIRequest) and self.transition and
                self.transition.check_document and
                requestion.is_fake_identity_documents):
            return HttpResponseRedirect(
                u'%s?next=%s' %
                (reverse('operator_requestion_set_identity_document',
                         kwargs={'requestion_id': requestion_id}),
                 urlquote(request.get_full_path()))
                )
        return response
Ejemplo n.º 3
0
    def test_short_stay_requestion_operator(self):
        requestion = create_requestion(status=STATUS_REQUESTER)
        requestion.pref_sadiks.add(self.kg)
        requestion.set_ident_document_authentic()
        requestion.status = STATUS_SHORT_STAY
        requestion.save()
        self.assertEqual(requestion.status, STATUS_SHORT_STAY)

        # проверяем допустимые переводы для подтвержденной заявки
        transition_indexes = workflow.available_transitions(
            src=requestion.status)
        self.assertEqual(len(transition_indexes), 3)
        self.assertEqual(transition_indexes.sort(), [
            SHORT_STAY_DISTRIBUTION, SHORT_STAY_REQUESTER,
            SHORT_STAY_DECISION_BY_RESOLUTION
        ].sort())

        transitions = requestion.available_transitions()

        # отсутствуют транзакции, выполняемые оператором
        operator_allowed_transactions = [
            t for t in transitions if 'is_operator' in t.required_permissions]
        self.assertEqual(len(operator_allowed_transactions), 0)

        # одна транзакция, выполняемая администратором
        supervisor_allowed_transactions = [
            t for t in transitions if 'is_supervisor' in t.required_permissions]
        self.assertEqual(len(supervisor_allowed_transactions), 1)

        login = self.client.login(
            username=OPERATOR_USERNAME,
            password=OPERATOR_PASSWORD
        )
        self.assertTrue(login)
        op_response = self.client.get(
            reverse('operator_requestion_info', args=(requestion.id, )))
        self.assertEqual(op_response.status_code, 200)
        self.assertEqual(op_response.context['requestion'], requestion)

        for t in workflow.transitions:
            url = reverse(
                'operator_requestion_status_change',
                args=(requestion.id, t.dst)
            )
            t_response = self.client.get(url)
            self.assertEqual(t_response.status_code, 403)
            # проверяем, что кнопка выполнения транзакций отсутствует
            html_button = '<a class="btn" href="{}">'.format(url)
            self.assertNotIn(html_button, op_response.content)
Ejemplo n.º 4
0
def get_statuses_report_data(from_date, to_date):
    logs = Logger.objects.filter(
                Q(datetime__gt=from_date - one_day) &
                Q(datetime__lt=to_date + one_day))
    statuses_info = []
    for status in STATUS_CHOICES:
        transitions = workflow.available_transitions(dst=status[0])
        areas_info = []
        for area in Area.objects.all():
            to_status_number = logs.filter(action_flag__in=transitions).count()
            areas_info.append({'to_status_number': to_status_number})
        statuses_info.append(
            {'status': dict(STATUS_CHOICES)[status[0]], 'areas_info': areas_info})

    return {'statuses_info': statuses_info, 'areas': [unicode(area)
        for area in Area.objects.all()]}
Ejemplo n.º 5
0
    def dispatch(self, request, requestion_id, dst_status):
        u"""
        Метод переопределен, чтобы сохранить в атрибутах ``transition``
        """
        requestion = get_object_or_404(Requestion, id=requestion_id)

        redirect_to = request.REQUEST.get('next', '')
        self.redirect_to = check_url(redirect_to, self.default_redirect_to(requestion))

        transition_indexes = workflow.available_transitions(src=requestion.status, dst=int(dst_status))
        if transition_indexes:
            self.transition = workflow.get_transition_by_index(transition_indexes[0])
        else:
            self.transition = None

        # копирование ролей из workflow в проверку прав
        if self.transition:
            # Если на перевод есть права
            if self.transition.required_permissions:
                temp_copy = self.transition.required_permissions[:]
                # Пропустить публичный доступ ``ANONYMOUS_PERMISSION``
                if Transition.ANONYMOUS_PERMISSION in temp_copy:
                    temp_copy.remove(Transition.ANONYMOUS_PERMISSION)
                self.required_permissions = temp_copy

            # Если переод только внутрисистемный, запретить его выполнение
            else:
                self.required_permissions = None

        response = super(RequestionStatusChange, self).dispatch(request, requestion)
        # если проверка прав прошла, то проверяем есть ли у заявки документы
        if isinstance(response, TemplateResponse):
            if not requestion.evidience_documents().filter(
                    template__destination=REQUESTION_IDENTITY).exists():
                return HttpResponseRedirect(
                    u'%s?next=%s' %
                    (reverse('operator_requestion_set_identity_document',
                             kwargs={'requestion_id': requestion_id}),
                     urlquote(request.get_full_path()))
                )
        return response
Ejemplo n.º 6
0
 def check_permissions(self, request, current_requestion, *args, **kwags):
     from sadiki.core.workflow import workflow
     transitions_available = set(self.transitions) & set(workflow.available_transitions(
             current_requestion.status))
     return RequestionMixin.check_permissions(
         self, request, current_requestion) and transitions_available
Ejemplo n.º 7
0
    def test_operator_requestion_not_confirmed(self):
        requestion = create_requestion()
        requestion.pref_sadiks.add(self.kg)
        requestion.save()
        self.assertEqual(requestion.status, STATUS_REQUESTER_NOT_CONFIRMED)

        # проверяем допустимые переводы для неподтвержденной заявки
        transition_indexes = workflow.available_transitions(
            src=requestion.status)
        self.assertEqual(len(transition_indexes), 3)
        self.assertEqual(transition_indexes.sort(), [
            CONFIRM_REQUESTION,
            NOT_CONFIRMED_REMOVE_REGISTRATION,
            REQUESTION_REJECT
        ].sort())
        transitions = requestion.available_transitions()
        self.assertEqual(transition_indexes.sort(),
                         [t.index for t in transitions].sort())
        self.assertTrue(requestion.is_available_for_actions)

        # банальные проверки работы веб-интерфейса
        login = self.client.login(
            username=OPERATOR_USERNAME,
            password=OPERATOR_PASSWORD
        )
        self.assertTrue(login)
        op_response = self.client.get(
            reverse('operator_requestion_info', args=(requestion.id, )))
        self.assertEqual(op_response.status_code, 200)
        self.assertEqual(op_response.context['requestion'], requestion)

        # проверяем доступность разрешенных оператору транзакций
        user_allowed_transactions = [
            t for t in transitions if 'is_operator' in t.required_permissions]
        for t in user_allowed_transactions:
            url = reverse(
                'operator_requestion_status_change',
                args=(requestion.id, t.dst)
            )
            t_response = self.client.get(url)
            self.assertEqual(t_response.status_code, 200)
            # проверяем, что кнопка выполнения транзакций пристутствует
            html_button = '<a class="btn" href="{}">'.format(url)
            self.assertIn(html_button, op_response.content)

        # проверяем запрет для пользователя остальных транзакций
        # формируем список из запрещенных транзаций
        user_forbidden_transactions = [
            t for t in transitions if t not in user_allowed_transactions]
        allowed_dst = [t.dst for t in transitions]
        wrong_transitions = [
            t for t in workflow.transitions if (
                t.src != requestion.status and t.dst not in allowed_dst)
        ]
        for t in wrong_transitions + user_forbidden_transactions:
            url = reverse(
                'operator_requestion_status_change',
                args=(requestion.id, t.dst)
            )
            t_response = self.client.get(url)
            self.assertEqual(t_response.status_code, 403)
            # проверяем, что кнопка выполнения транзакций отсутствует
            html_button = '<a class="btn" href="{}">'.format(url)
            self.assertNotIn(html_button, op_response.content)
Ejemplo n.º 8
0
    def post(self, request, *args, **kwargs):
        # Начальные значения
        status_code = STATUS_DATA_ERROR
        err_msg = None
        data = kwargs['data']
        dst_status = int(data['dst_status'])
        requestion = Requestion.objects.get(pk=data['requestion_id'])
        # параноидальная проверка целостности данных
        if requestion.requestion_number != data['requestion_number']:
            err_msg = u"Ошибка проверки данных заявки: номер заявки отличается"\
                      u"от указанного в профиле"
            result = {'status_code': STATUS_DATA_ERROR, 'err_msg': {
                '__all__': err_msg,
            }}
            return self.render_to_response(result)

        if (requestion.status in
                [STATUS_DISTRIBUTED, STATUS_DISTRIBUTED_FROM_ES] and
                dst_status != STATUS_KG_LEAVE):
            err_msg = u"Заявка зачислена в Электроочереди, действие невозможно"
            if dst_status == STATUS_DISTRIBUTED_FROM_ES:
                err_msg = u"Заявка уже зачислена в Электроочереди"
            result = {'status_code': STATUS_ALREADY_DISTRIBUTED,
                      'err_msg': {'__all__': err_msg}}
            return self.render_to_response(result)

        transition_indexes = workflow.available_transitions(
            src=requestion.status, dst=dst_status)
        # TODO: Проверка на корректность ДОУ?
        # sadik = requestion.distributed_in_vacancy.sadik_group.sadik
        # Если в форме передается свидетельство о рождении и текущий
        # документ у заявки - временный, меняем
        if 'document_number' in data and requestion.evidience_documents()[0].fake:
            form_data = {
                'template': data['template'],
                'document_number': data['document_number'],
            }
            form = RequestionIdentityDocumentForm(
                instance=requestion, data=form_data)
            if form.is_valid():
                form.save()
                requestion.evidience_documents().filter(fake=True).delete()
            else:
                err_msg = {}
                for error in form.errors:
                    err_msg[error] = form.errors[error]
                result = {'status_code': status_code, 'err_msg': err_msg}
                return self.render_to_response(result)
        if transition_indexes:
            transition = workflow.get_transition_by_index(transition_indexes[0])
            if transition.index in INNER_TRANSITIONS:
                if Requestion.objects.filter(
                        id=requestion.id, status=transition.src).update(
                        status=transition.dst):
                    Logger.objects.create_for_action(
                        transition.index, context_dict=data,
                        extra={'obj': requestion})
                    status_code = STATUS_OK
                else:
                    status_code = STATUS_DATA_ERROR
                    err_msg = u"Проверьте статус заявки в Электроочереди"
            else:
                form = self.form(requestion=requestion,
                                 data={'reason': data.get('reason'),
                                       'transition': transition.index,
                                       'confirm': "yes"},
                                 initial={'transition': transition.index})
                if form.is_valid():
                    pre_status_change.send(
                        sender=Requestion, request=request,
                        requestion=requestion, transition=transition, form=form)
                    requestion.status = transition.dst
                    requestion.save()
                    post_status_change.send(
                        sender=Requestion, request=request,
                        requestion=requestion, transition=transition, form=form)
                    status_code = STATUS_OK
                else:
                    err_msg = {}
                    for error in form.errors:
                        err_msg[error] = form.errors[error]
        else:
            err_msg = {
                '__all__': u"Невозможно изменить статус заявки в электроочереди"
            }
        result = {'status_code': status_code, 'err_msg': err_msg}
        return self.render_to_response(result)