示例#1
0
class Memo(creme_models.CremeModel):
    content       = models.TextField(_('Content'))
    on_homepage   = models.BooleanField(_('Displayed on homepage'), blank=True, default=False)
    creation_date = creme_fields.CreationDateTimeField(_('Creation date'), editable=False)
    user          = creme_fields.CremeUserForeignKey(verbose_name=_('Owner user'))

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+', editable=False)
    entity = models.ForeignKey(
        creme_models.CremeEntity,  related_name='assistants_memos',
        editable=False, on_delete=models.CASCADE,
    ).set_tags(viewable=False)
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type', fk_field='entity',
    )

    objects = MemoManager()

    creation_label = _('Create a memo')
    save_label     = _('Save the memo')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('Memo')
        verbose_name_plural = _('Memos')

    def __str__(self):
        # NB: translate for unicode can not take 2 arguments...
        return ellipsis(self.content.strip().replace('\n', ''), 25)

    def get_edit_absolute_url(self):
        return reverse('assistants__edit_memo', args=(self.id,))

    def get_related_entity(self):  # For generic views
        return self.creme_entity
class CommercialApproach(creme_models.CremeModel):
    title = models.CharField(_('Title'), max_length=200)
    # ok_or_in_futur = models.BooleanField(_('Done?'), editable=False, default=False)
    description = models.TextField(_('Description'), blank=True)
    creation_date = creme_fields.CreationDateTimeField(_('Creation date'),
                                                       editable=False)

    related_activity = models.ForeignKey(
        settings.ACTIVITIES_ACTIVITY_MODEL,
        null=True,
        editable=False,
        on_delete=models.CASCADE,
    )

    # entity_content_type = models.ForeignKey(ContentType, related_name="comapp_entity_set", editable=False, on_delete=models.CASCADE)
    # entity_id           = models.PositiveIntegerField(editable=False)  # .set_tags(viewable=False) uncomment if it becomes an auxiliary (get_related_entity())
    # creme_entity        = GenericForeignKey(ct_field="entity_content_type", fk_field="entity_id")
    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+',
                                                             editable=False)
    entity = models.ForeignKey(
        creme_models.CremeEntity,
        related_name='commercial_approaches',
        editable=False,
        on_delete=models.CASCADE,
    )  # .set_tags(viewable=False) uncomment if it becomes an auxiliary (get_related_entity())
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type', fk_field='entity')

    creation_label = _('Create a commercial approach')
    save_label = _('Save the commercial approach')

    class Meta:
        app_label = 'commercial'
        verbose_name = _('Commercial approach')
        verbose_name_plural = _('Commercial approaches')

    def __str__(self):
        return self.title

    @staticmethod
    def get_approaches(entity_pk=None):
        # queryset = CommercialApproach.objects.filter(ok_or_in_futur=False) \
        #                                      .select_related('related_activity')
        queryset = CommercialApproach.objects.select_related(
            'related_activity')

        return queryset.filter(entity_id=entity_pk) if entity_pk else \
               queryset.exclude(entity__is_deleted=True)

    @staticmethod
    def get_approaches_for_ctypes(ct_ids):
        warnings.warn(
            'CommercialApproach.get_approaches_for_ctypes() is deprecated.',
            DeprecationWarning)
        # return CommercialApproach.objects.filter(entity_content_type__in=ct_ids, ok_or_in_futur=False) \
        return CommercialApproach.objects.filter(entity_content_type__in=ct_ids) \
                                 .select_related('related_activity')
示例#3
0
class Alert(creme_models.CremeModel):
    title        = models.CharField(_('Title'), max_length=200)
    description  = models.TextField(_('Description'), blank=True)
    is_validated = models.BooleanField(_('Validated'), editable=False, default=False)
    reminded     = models.BooleanField(_('Notification sent'), editable=False, default=False)  # Need by creme_core.core.reminder
    trigger_date = models.DateTimeField(_('Trigger date'))
    user         = creme_fields.CremeUserForeignKey(verbose_name=_('Owner user'))

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+', editable=False)
    entity              = models.ForeignKey(creme_models.CremeEntity, related_name='assistants_alerts',
                                            editable=False, on_delete=models.CASCADE,
                                           ).set_tags(viewable=False)
    creme_entity        = creme_fields.RealEntityForeignKey(ct_field='entity_content_type', fk_field='entity')

    objects = AlertManager()

    creation_label = _('Create an alert')
    save_label     = _('Save the alert')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('Alert')
        verbose_name_plural = _('Alerts')

    def __str__(self):
        return self.title

    def get_edit_absolute_url(self):
        return reverse('assistants__edit_alert', args=(self.id,))

    # @staticmethod
    # def get_alerts(entity):
    #     warnings.warn('Alert.get_alerts() is deprecated.', DeprecationWarning)
    #     return Alert.objects.filter(is_validated=False, entity_id=entity.id).select_related('user')

    # @staticmethod
    # def get_alerts_for_home(user):
    #     warnings.warn('Alert.get_alerts_for_home() is deprecated.', DeprecationWarning)
    #     return Alert.objects.filter(is_validated=False,
    #                                 user__in=[user] + user.teams,
    #                                )\
    #                         .select_related('user')

    # @staticmethod
    # def get_alerts_for_ctypes(ct_ids, user):
    #     warnings.warn('Alert.get_alerts_for_ctypes() is deprecated.', DeprecationWarning)
    #     return Alert.objects.filter(entity_content_type__in=ct_ids, user__in=[user] + user.teams, is_validated=False) \
    #                         .select_related('user')

    def get_related_entity(self):  # For generic views
        return self.creme_entity

    @property
    def to_be_reminded(self):
        return not self.is_validated and not self.reminded
示例#4
0
class Action(creme_models.CremeModel):
    title = models.CharField(_('Title'), max_length=200)
    is_ok = models.BooleanField(
        _('Expected reaction has been done'),
        editable=False,
        default=False,
    )
    description = models.TextField(_('Source action'), blank=True)

    creation_date = creme_fields.CreationDateTimeField(_('Creation date'),
                                                       editable=False)
    expected_reaction = models.TextField(_('Target action'), blank=True)
    deadline = models.DateTimeField(_('Deadline'))
    validation_date = models.DateTimeField(
        _('Validation date'),
        blank=True,
        null=True,
        editable=False,
    )

    user = creme_fields.CremeUserForeignKey(verbose_name=_('Owner user'))

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+',
                                                             editable=False)
    entity = models.ForeignKey(
        creme_models.CremeEntity,
        related_name='assistants_actions',
        editable=False,
        on_delete=models.CASCADE,
    ).set_tags(viewable=False)
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type',
        fk_field='entity',
    )

    objects = ActionManager()

    creation_label = _('Create an action')
    save_label = _('Save the action')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('Action')
        verbose_name_plural = _('Actions')

    def __str__(self):
        return self.title

    def get_edit_absolute_url(self):
        return reverse('assistants__edit_action', args=(self.id, ))

    def get_related_entity(self):  # For generic views
        return self.creme_entity
示例#5
0
class Memo(creme_models.CremeModel):
    content       = models.TextField(_('Content'))
    on_homepage   = models.BooleanField(_('Displayed on homepage'), blank=True, default=False)
    creation_date = creme_fields.CreationDateTimeField(_('Creation date'), editable=False)
    user          = creme_fields.CremeUserForeignKey(verbose_name=_('Owner user'))

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+', editable=False)
    entity              = models.ForeignKey(creme_models.CremeEntity,  related_name='assistants_memos',
                                            editable=False, on_delete=models.CASCADE,
                                           ).set_tags(viewable=False)
    creme_entity        = creme_fields.RealEntityForeignKey(ct_field='entity_content_type', fk_field='entity')

    objects = MemoManager()

    creation_label = _('Create a memo')
    save_label     = _('Save the memo')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('Memo')
        verbose_name_plural = _('Memos')

    def __str__(self):
        # NB: translate for unicode can not take 2 arguments...
        return ellipsis(self.content.strip().replace('\n', ''), 25)

    def get_edit_absolute_url(self):
        return reverse('assistants__edit_memo', args=(self.id,))

    # @staticmethod
    # def get_memos(entity):
    #     warnings.warn('Memo.get_memos() is deprecated.', DeprecationWarning)
    #     return Memo.objects.filter(entity_id=entity.id).select_related('user')

    # @staticmethod
    # def get_memos_for_home(user):
    #     warnings.warn('Memo.get_memos_for_home() is deprecated.', DeprecationWarning)
    #     return Memo.objects.filter(on_homepage=True,
    #                                user__in=[user] + user.teams,
    #                               ) \
    #                       .select_related('user')

    # @staticmethod
    # def get_memos_for_ctypes(ct_ids, user):
    #     warnings.warn('Memo.get_memos_for_ctypes() is deprecated.', DeprecationWarning)
    #     return Memo.objects.filter(entity_content_type__in=ct_ids, user__in=[user] + user.teams) \
    #                        .select_related('user')

    def get_related_entity(self):  # For generic views
        return self.creme_entity
示例#6
0
文件: todo.py 项目: mrjmad/creme_crm
class ToDo(CremeModel):
    title = models.CharField(_('Title'), max_length=200)
    is_ok = models.BooleanField(_('Done?'), editable=False, default=False)

    # Needed by creme_core.core.reminder
    reminded = models.BooleanField(_('Notification sent'), editable=False, default=False)

    description = models.TextField(_('Description'), blank=True)
    creation_date = creme_fields.CreationDateTimeField(_('Creation date'), editable=False)
    deadline = models.DateTimeField(_('Deadline'), blank=True, null=True)
    user = creme_fields.CremeUserForeignKey(verbose_name=_('Owner user'))

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+', editable=False)
    entity = models.ForeignKey(
        CremeEntity, related_name='assistants_todos',
        editable=False, on_delete=models.CASCADE,
    ).set_tags(viewable=False)
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type', fk_field='entity',
    )

    objects = ToDoManager()

    creation_label = _('Create a todo')
    save_label     = _('Save the todo')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('Todo')
        verbose_name_plural = _('Todos')

    def __str__(self):
        return self.title

    def get_edit_absolute_url(self):
        return reverse('assistants__edit_todo', args=(self.id,))

    def get_related_entity(self):  # For generic views
        return self.creme_entity

    @property
    def to_be_reminded(self):
        return self.deadline and not self.is_ok and not self.reminded
class CommercialApproach(creme_models.CremeModel):
    title = models.CharField(_('Title'), max_length=200)
    description = models.TextField(_('Description'), blank=True)
    creation_date = creme_fields.CreationDateTimeField(_('Creation date'),
                                                       editable=False)

    related_activity = models.ForeignKey(
        settings.ACTIVITIES_ACTIVITY_MODEL,
        null=True,
        editable=False,
        on_delete=models.CASCADE,
    )

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+',
                                                             editable=False)
    entity = models.ForeignKey(
        creme_models.CremeEntity,
        related_name='commercial_approaches',
        editable=False,
        on_delete=models.CASCADE,
    )  # .set_tags(viewable=False) uncomment if it becomes an auxiliary (get_related_entity())
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type', fk_field='entity')

    creation_label = _('Create a commercial approach')
    save_label = _('Save the commercial approach')

    class Meta:
        app_label = 'commercial'
        verbose_name = _('Commercial approach')
        verbose_name_plural = _('Commercial approaches')

    def __str__(self):
        return self.title

    @staticmethod
    def get_approaches(entity_pk=None):
        queryset = CommercialApproach.objects.select_related(
            'related_activity')

        return queryset.filter(entity_id=entity_pk) if entity_pk else \
               queryset.exclude(entity__is_deleted=True)
示例#8
0
class UserMessage(CremeModel):
    title = models.CharField(_('Title'), max_length=200)
    body = models.TextField(_('Message body'))
    creation_date = models.DateTimeField(_('Creation date'))
    priority = models.ForeignKey(
        UserMessagePriority,
        verbose_name=_('Priority'),
        on_delete=models.PROTECT,
    )

    sender = creme_fields.CremeUserForeignKey(
        verbose_name=_('Sender'),
        related_name='sent_assistants_messages_set',
    )
    recipient = creme_fields.CremeUserForeignKey(
        verbose_name=_('Recipient'),
        related_name='received_assistants_messages_set',
    )
    email_sent = models.BooleanField(default=False)

    entity_content_type = creme_fields.EntityCTypeForeignKey(
        null=True,
        related_name='+',
        editable=False,
    )
    entity = models.ForeignKey(
        CremeEntity,
        null=True,
        related_name='assistants_messages',
        editable=False,
        on_delete=models.CASCADE,
    ).set_tags(viewable=False)
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type',
        fk_field='entity',
    )

    creation_label = _('Create a message')
    save_label = _('Save the message')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('User message')
        verbose_name_plural = _('User messages')

    def __str__(self):
        return self.title

    @classmethod
    @atomic
    def create_messages(cls, users, title, body, priority_id, sender, entity):
        """Create UserMessages instances to sent to several users.
        Notice that teams are treated as several Users.
        @param users: A sequence of CremeUser objects ; duplicates are removed.
        """
        users_map = {}
        for user in users:
            if user.is_team:
                users_map.update(user.teammates)
            else:
                users_map[user.id] = user

        build_msg = partial(
            cls,
            creation_date=now(),
            title=title,
            body=body,
            priority_id=priority_id,
            sender=sender,
            creme_entity=entity,
        )
        cls.objects.bulk_create(
            build_msg(recipient=user) for user in users_map.values())

        from ..creme_jobs import usermessages_send_type

        usermessages_send_type.refresh_job()

    @classmethod
    def send_mails(cls, job):
        from django.conf import settings
        from django.core.mail import EmailMessage, get_connection

        usermessages = [*cls.objects.filter(email_sent=False)]

        if not usermessages:
            return

        subject_format = gettext('User message from Creme: {}')
        body_format = gettext('{user} sent you the following message:\n{body}')
        EMAIL_SENDER = settings.EMAIL_SENDER

        messages = [
            EmailMessage(
                subject_format.format(msg.title),
                body_format.format(user=msg.sender, body=msg.body),
                EMAIL_SENDER,
                [msg.recipient.email],
            ) for msg in usermessages if msg.recipient.email
        ]

        try:
            with get_connection() as connection:
                connection.send_messages(messages)
        except Exception as e:
            logger.critical('Error while sending user-messages emails (%s)', e)
            JobResult.objects.create(
                job=job,
                messages=[
                    gettext('An error occurred while sending emails'),
                    gettext('Original error: {}').format(e),
                ],
            )

        cls.objects.filter(pk__in=[m.id for m in usermessages]) \
                   .update(email_sent=True)
示例#9
0
class ToDo(CremeModel):
    title = models.CharField(_('Title'), max_length=200)
    is_ok = models.BooleanField(_('Done ?'), editable=False, default=False)
    reminded = models.BooleanField(
        _('Notification sent'), editable=False,
        default=False)  # Needed by creme_core.core.reminder
    description = models.TextField(_('Description'), blank=True)
    creation_date = creme_fields.CreationDateTimeField(_('Creation date'),
                                                       editable=False)
    deadline = models.DateTimeField(_('Deadline'), blank=True, null=True)
    user = creme_fields.CremeUserForeignKey(verbose_name=_('Owner user'))

    entity_content_type = creme_fields.EntityCTypeForeignKey(related_name='+',
                                                             editable=False)
    entity = models.ForeignKey(
        CremeEntity,
        related_name='assistants_todos',
        editable=False,
        on_delete=models.CASCADE,
    ).set_tags(viewable=False)
    creme_entity = creme_fields.RealEntityForeignKey(
        ct_field='entity_content_type', fk_field='entity')

    objects = ToDoManager()

    creation_label = _('Create a todo')
    save_label = _('Save the todo')

    class Meta:
        app_label = 'assistants'
        verbose_name = _('Todo')
        verbose_name_plural = _('Todos')

    def __str__(self):
        return self.title

    def get_edit_absolute_url(self):
        return reverse('assistants__edit_todo', args=(self.id, ))

    # @staticmethod
    # def get_todos(entity):
    #     warnings.warn('ToDo.get_todos() is deprecated.', DeprecationWarning)
    #     return ToDo.objects.filter(entity_id=entity.id).select_related('user')

    # @staticmethod
    # def get_todos_for_home(user):
    #     warnings.warn('ToDo.get_todos_for_home() is deprecated ; '
    #                   'use ToDo.objects.filter_by_user() instead.',
    #                   DeprecationWarning
    #                  )
    #     return ToDo.objects.filter(user__in=[user] + user.teams)\
    #                        .select_related('user')

    # @staticmethod
    # def get_todos_for_ctypes(ct_ids, user):
    #     warnings.warn('ToDo.get_todos_for_ctypes() is deprecated.', DeprecationWarning)
    #     return ToDo.objects.filter(entity_content_type__in=ct_ids,
    #                                user__in=[user] + user.teams
    #                               ).select_related('user')

    def get_related_entity(self):  # For generic views
        return self.creme_entity

    @property
    def to_be_reminded(self):
        return self.deadline and not self.is_ok and not self.reminded
示例#10
0
class AbstractAddress(CremeModel):
    name       = models.CharField(_('Name'),       max_length=100, blank=True)
    address    = models.TextField(_('Address'),    blank=True)
    po_box     = models.CharField(_('PO box'),     max_length=50,  blank=True).set_tags(optional=True)
    zipcode    = models.CharField(_('Zip code'),   max_length=100, blank=True).set_tags(optional=True)
    city       = models.CharField(_('City'),       max_length=100, blank=True).set_tags(optional=True)
    department = models.CharField(_('Department'), max_length=100, blank=True).set_tags(optional=True)
    state      = models.CharField(_('State'),      max_length=100, blank=True).set_tags(optional=True)
    country    = models.CharField(_('Country'),    max_length=40,  blank=True).set_tags(optional=True)

    content_type = creme_fields.EntityCTypeForeignKey(related_name='+', editable=False) \
                               .set_tags(viewable=False)
    object       = models.ForeignKey(CremeEntity, related_name='persons_addresses',
                                     editable=False, on_delete=models.CASCADE,
                                    ).set_tags(viewable=False)
    owner        = creme_fields.RealEntityForeignKey(ct_field='content_type', fk_field='object')

    creation_label = _('Create an address')
    save_label     = _('Save the address')

    STR_FIELD_NAMES = [
        ['address', 'zipcode', 'city', 'department'],
        ['po_box', 'state', 'country'],
    ]
    STR_SEPARATOR = ' '

    # class Meta:
    class Meta(CremeModel.Meta):
        abstract = True
        app_label = 'persons'
        verbose_name = _('Address')
        verbose_name_plural = _('Addresses')
        ordering = ('id',)

    def __str__(self):
        s = ''
        join = self.STR_SEPARATOR.join
        allowed_fnames = {*self.info_field_names()}
        get_field_value = (lambda fname: None if fname not in allowed_fnames else
                                         getattr(self, fname))

        for field_names in self.STR_FIELD_NAMES:
            s = join(filter(None, (get_field_value(fn) for fn in field_names)))

            if s:
                break

        return s

    def get_edit_absolute_url(self):
        return reverse('persons__edit_address', args=(self.id,))

    def get_related_entity(self):  # For generic views
        return self.owner

    def __bool__(self):  # Used by forms to detect empty addresses
        return any(fvalue for fname, fvalue in self.info_fields)

    def clone(self, entity):
        """Returns a new cloned (saved) address for a (saved) entity."""
        # return Address.objects.create(owner=entity, **dict(self.info_fields))
        return type(self).objects.create(owner=entity, **dict(self.info_fields))

    @classmethod
    def info_field_names(cls):
        is_field_hidden = FieldsConfig.get_4_model(cls).is_field_hidden
        excluded = {'id', 'content_type', 'object'}  # TODO: just exclude not viewable ?
        return tuple(f.name
                        for f in cls._meta.fields
                            if f.name not in excluded and not is_field_hidden(f)
                    )

    @property
    def info_fields(self):
        for fname in self.info_field_names():
            yield fname, getattr(self, fname)