def get_template_context(self, *args, **kwargs):
        ctxt = super().get_template_context(*args, **kwargs)

        activities = ctxt['page'].object_list
        CremeEntity.populate_relations(activities, self._RTYPES_2_POP)  # Optimisation

        entity = ctxt.get('object')
        if entity is not None:
            for activity in activities:
                activity.enable_unlink_button = True

            if isinstance(entity, Organisation):
                # We display the 'unlink' button only for Activities that have
                # at least a Relation with the Organisation (if a direct Relation
                # does not exist the button is useless).
                for activity in activities:
                    activity.enable_unlink_button = \
                        any(entity.id == rel.object_entity_id
                                for rel in chain(activity.get_subject_relations(),
                                                 activity.get_linkedto_relations(),
                                                )
                           )

        ctxt['display_review'] = SettingValue.objects.get_4_key(review_key).value

        return ctxt
Exemple #2
0
    def detailview_display(self, context):
        graph = context['object']
        btc = self.get_template_context(context,
                                        graph.roots.select_related('entity'))
        CremeEntity.populate_real_entities(
            [node.entity for node in btc['page'].object_list])

        return self._render(btc)
Exemple #3
0
    def detailview_display(self, context):
        btc = self.get_template_context(
                    context, SemiFixedRelationType.objects.all(),
        )

        CremeEntity.populate_real_entities([sfrt.object_entity for sfrt in btc['page'].object_list])

        return self._render(btc)
Exemple #4
0
    def restore(self):
        CremeEntity.restore(self)

        # TODO: in a signal handler instead ?
        #       (we need a restore signal, or an official "backup" feature -- see HistoryLine)
        if self.status in (constants.MAIL_STATUS_NOTSENT, constants.MAIL_STATUS_SENDINGERROR):
            # TODO: regroup the 'refresh' message, to avoid flooding the job manager
            from ..creme_jobs import entity_emails_send_type

            entity_emails_send_type.refresh_job()
Exemple #5
0
    def detailview_display(self, context):
        btc = self.get_template_context(
            context,
            InstanceBrickConfigItem.objects.prefetch_related('entity'),
        )

        CremeEntity.populate_real_entities(
            [ibci.entity for ibci in btc['page'].object_list])

        return self._render(btc)
Exemple #6
0
    def detailview_display(self, context):
        btc = self.get_template_context(
            context,
            context['object'].get_mails().select_related('recipient_entity'),
        )

        CremeEntity.populate_real_entities(
            [*filter(None, (lw_mail.recipient_entity for lw_mail in btc['page'].object_list))]
        )

        return self._render(btc)
Exemple #7
0
    def restore(self):
        CremeEntity.restore(self)

        # TODO: in a signal handler instead ?
        #       (we need a restore signal, or an official "backup" feature -- see HistoryLine)
        from .sending import EmailSending, SENDING_STATE_DONE

        if EmailSending.objects.filter(campaign=self).exclude(
                state=SENDING_STATE_DONE).exists():
            # TODO: regroup the 'refresh' message, to avoid flooding the job manager
            from ..creme_jobs import campaign_emails_send_type

            campaign_emails_send_type.refresh_job()
    def populate_entities(histories):
        #        entities_pks = histories.values_list('entity_pk', flat=True)
        entities_pks = [history.entity_pk for history in histories]
        #        entities = CremeEntity.objects.filter(pk__in=entities_pks)
        entities = CremeEntity.objects.filter(
            pk__in=set(entities_pks)
        )  #Forcing the retrieve for MySQL <= v5.1.49 which "doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery"
        CremeEntity.populate_real_entities(entities)
        entities_map = {
            entity.pk: entity.get_real_entity()
            for entity in entities
        }

        for hist in histories:
            hist._entity = entities_map.get(hist.entity_pk)
Exemple #9
0
    def test_actions_void01(self):
        "Instance actions"
        user = self.user
        registry = self.registry

        class MockA(MockAction):
            id = 'test-a'

        class MockB(MockContactAction):
            id = 'test-b'

        class MockC(MockAction):
            id = 'test-c'

        registry.register_instance_actions(MockA, MockB, MockC)
        registry.void_instance_actions(FakeOrganisation, MockC)

        entity = CremeEntity(user=user)
        contact = FakeContact(user=user, last_name='Kawa')
        orga = FakeOrganisation(user=user, name='Kimengumi')

        self.assertSortedActions([MockA, MockC],
                                 registry.instance_actions(user=user,
                                                           instance=entity))
        self.assertSortedActions([MockA, MockB, MockC],
                                 registry.instance_actions(user=user,
                                                           instance=contact))
        self.assertSortedActions([MockA],
                                 registry.instance_actions(user=user,
                                                           instance=orga))
Exemple #10
0
    def test_override03(self):
        "Bulk action"
        user = self.user
        registry = self.registry

        registry.register_bulk_actions(MockBulkAction)
        registry.register_bulk_actions(MockContactBulkAction)

        self.assertFalse([
            *registry.instance_actions(user=user,
                                       instance=CremeEntity(user=user))
        ])
        self.assertFalse([
            *registry.instance_actions(user=user,
                                       instance=FakeContact(user=user))
        ])
        self.assertFalse([
            *registry.instance_actions(user=user,
                                       instance=FakeOrganisation(user=user))
        ])

        self.assertSortedActions([MockBulkAction],
                                 registry.bulk_actions(user=user,
                                                       model=CremeEntity))
        self.assertSortedActions([MockContactBulkAction],
                                 registry.bulk_actions(user=user,
                                                       model=FakeContact))
        self.assertSortedActions([MockBulkAction],
                                 registry.bulk_actions(user=user,
                                                       model=FakeOrganisation))
Exemple #11
0
    def test_action_is_registered_for_instance02(self):
        "One action registered"
        user = self.user
        registry = self.registry
        entity = CremeEntity(user=user)
        contact = FakeContact(user=user, first_name='Yui', last_name='Kawa')

        registry.register_instance_actions(MockAction)

        # Entity ---
        entity_actions = [
            *registry.instance_actions(user=user, instance=entity)
        ]
        self.assertEqual(1, len(entity_actions))

        entity_action = entity_actions[0]
        self.assertIsInstance(entity_action, MockAction)
        self.assertEqual(user, entity_action.user)
        self.assertEqual(CremeEntity, entity_action.model)
        self.assertEqual(entity, entity_action.instance)

        self.assertEqual([MockAction],
                         registry.instance_action_classes(model=CremeEntity))

        # Contact ---
        contact_actions = [
            *registry.instance_actions(user=user, instance=contact)
        ]
        self.assertEqual(1, len(contact_actions))

        contact_action = contact_actions[0]
        self.assertIsInstance(contact_action, MockAction)
        self.assertEqual(user, contact_action.user)
        self.assertEqual(FakeContact, contact_action.model)
        self.assertEqual(contact, contact_action.instance)

        self.assertEqual([MockAction],
                         registry.instance_action_classes(model=FakeContact))
Exemple #12
0
    def test_override_duplicate(self):
        user = self.user
        registry = self.registry

        registry.register_instance_actions(MockAction)
        registry.register_instance_actions(MockContactAction)

        entity = CremeEntity(user=user)
        contact = FakeContact(user=user)

        self.assertSortedActions([MockAction],
                                 registry.instance_actions(user=user,
                                                           instance=entity))
        self.assertSortedActions([MockContactAction],
                                 registry.instance_actions(user=user,
                                                           instance=contact))

        # Same action, no problem
        registry.register_instance_actions(MockContactAction)

        self.assertSortedActions([MockAction],
                                 registry.instance_actions(user=user,
                                                           instance=entity))
        self.assertSortedActions([MockContactAction],
                                 registry.instance_actions(user=user,
                                                           instance=contact))

        # Other action, raise error ---
        class MockA(MockContactAction):
            pass

        with self.assertRaises(ActionRegistrationError) as ctxt:
            registry.register_instance_actions(MockA)

        self.assertEqual(
            str(ctxt.exception), "Duplicated action '{}' for model {}".format(
                MockA.id, MockContactAction.model))
Exemple #13
0
    def test_override01(self):
        "Empty."
        user = self.user
        registry = self.registry

        self.assertFalse([
            *registry.instance_actions(user=user,
                                       instance=CremeEntity(user=user))
        ])
        self.assertFalse([
            *registry.instance_actions(user=user,
                                       instance=FakeContact(user=user))
        ])
        self.assertFalse([
            *registry.instance_actions(user=user,
                                       instance=FakeOrganisation(user=user))
        ])

        self.assertFalse(
            [*registry.bulk_actions(user=user, model=CremeEntity)])
        self.assertFalse(
            [*registry.bulk_actions(user=user, model=FakeContact)])
        self.assertFalse(
            [*registry.bulk_actions(user=user, model=FakeOrganisation)])
Exemple #14
0
    def generate_png(self, user):
        from os.path import join

        import pygraphviz as pgv

        # NB: to work with utf8 label in node: all node must be added explicitly with
        #     unicode label, and when edges are a created, nodes identified by their
        #     labels encoded as string

        graph = pgv.AGraph(directed=True)

        # NB: "self.roots.all()" causes a strange additional query (retrieving of the base CremeEntity !)....
        has_perm_to_view = user.has_perm_to_view
        roots = [
            root for root in RootNode.objects.filter(
                graph=self.id).select_related('entity')
            if not root.entity.is_deleted and has_perm_to_view(root.entity)
        ]

        add_node = graph.add_node
        add_edge = graph.add_edge

        # TODO: entity cache ? regroups relations by type ? ...

        CremeEntity.populate_real_entities([root.entity for root in roots
                                            ])  #small optimisation

        for root in roots:
            add_node(str(root.entity), shape='box')
            # add_node('filled box',    shape='box', style='filled', color='#FF00FF')
            # add_node('filled box v2', shape='box', style='filled', fillcolor='#FF0000', color='#0000FF', penwidth='2.0') #default pensize="1.0"

        orbital_nodes = {}  #cache

        for root in roots:
            subject = root.entity
            str_subject = str(subject)
            relations   = subject.relations.filter(type__in=root.relation_types.all())\
                                           .select_related('object_entity', 'type')

            Relation.populate_real_object_entities(
                relations)  # Small optimisation

            for relation in relations:
                object_ = relation.object_entity
                if not user.has_perm_to_view(object_):
                    continue

                uni_object = str(object_)
                str_object = uni_object

                orbital_node = orbital_nodes.get(object_.id)
                if not orbital_node:
                    add_node(uni_object)
                    orbital_nodes[object_.id] = str_object

                add_edge(str_subject,
                         str_object,
                         label=str(relation.type.predicate))
                # add_edge('b', 'd', color='#FF0000', fontcolor='#00FF00', label='foobar', style='dashed')

        orbital_rtypes = self.orbital_relation_types.all()

        if orbital_rtypes:
            orbital_ids = orbital_nodes.keys()

            for relation in Relation.objects.filter(
                    subject_entity__in=orbital_ids,
                    object_entity__in=orbital_ids,
                    type__in=orbital_rtypes).select_related('type'):
                add_edge(orbital_nodes[relation.subject_entity_id],
                         orbital_nodes[relation.object_entity_id],
                         label=str(relation.type.predicate),
                         style='dashed')

        # print graph.string()

        graph.layout(prog='dot')  # Algo: neato dot twopi circo fdp nop

        img_format = 'png'  # Format: pdf svg
        img_basename = 'graph_{}.{}'.format(self.id, img_format)

        try:
            path = FileCreator(join(settings.MEDIA_ROOT, 'upload', 'graphs'),
                               img_basename).create()
        except FileCreator.Error as e:
            raise self.GraphException(e) from e

        try:
            # graph.draw(join(dir_path, filename), format='png')  # Format: pdf svg
            graph.draw(path, format=img_format)  # Format: pdf svg
        except IOError as e:
            delete_file(path)

            raise self.GraphException(str(e)) from e

        fileref = FileRef.objects.create(  # user=request.user, TODO
            filedata='upload/graphs/' + basename(path),
            basename=img_basename,
        )

        return HttpResponseRedirect(
            reverse('creme_core__dl_file', args=(fileref.filedata, )))
Exemple #15
0
 def test_is_date_field(self):
     entity = CremeEntity()
     get_field = entity._meta.get_field
     self.assertTrue(meta.is_date_field(get_field('created')))
     self.assertFalse(meta.is_date_field(get_field('user')))