class AddOrganisationForm(CremeForm):
    organisations = MultiCreatorEntityField(label=_('Organisations'),
                                            model=get_organisation_model())

    def __init__(self, entity, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._strategy = entity

    def save(self):
        eval_orgas = self._strategy.evaluated_orgas

        for orga in self.cleaned_data['organisations']:
            eval_orgas.add(orga)
Beispiel #2
0
class EmailTemplateAddAttachment(CremeForm):
    attachments = MultiCreatorEntityField(label=_('Attachments'), required=False, model=Document)

    blocks = FieldBlockManager(('general', _('Attachments'), '*'))

    def __init__(self, entity, *args, **kwargs):
        # super(EmailTemplateAddAttachment, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.template = entity

    def save(self):
        attachments = self.template.attachments

        for attachment in self.cleaned_data['attachments']:
            attachments.add(attachment)
Beispiel #3
0
class ProjectCreateForm(ProjectEditForm):
    responsibles = MultiCreatorEntityField(label=_('Project leaders'),
                                           model=get_contact_model())

    def _get_relations_to_create(self):
        instance = self.instance
        build_relation = partial(
            Relation,
            user=instance.user,
            type_id=REL_OBJ_PROJECT_MANAGER,
            subject_entity=instance,
        )

        return super()._get_relations_to_create().extend(
            build_relation(object_entity=contact)
            for contact in self.cleaned_data['responsibles'])
Beispiel #4
0
class PersonAddRepliesForm(CremeForm):
    # TODO: qfilter to exclude linked replies ??
    replies = MultiCreatorEntityField(
        label=_('Replies'),
        model=polls.get_pollreply_model(),
        credentials=EntityCredentials.CHANGE,
    )

    def __init__(self, entity, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.person = entity

    def save(self, *args, **kwargs):
        for reply in self.cleaned_data['replies']:
            reply.person = self.person
            reply.save()
Beispiel #5
0
class EmailTemplateForm(CremeEntityForm):
    body = CharField(label=_('Body'), widget=Textarea, help_text=_help_text())
    body_html = CharField(label=_('Body (HTML)'),
                          required=False,
                          widget=TinyMCEEditor(),
                          help_text=_help_text())
    attachments = MultiCreatorEntityField(label=_('Attachments'),
                                          required=False,
                                          model=Document)

    error_messages = {
        'invalid_vars': _('The following variables are invalid: %(vars)s'),
    }

    class Meta(CremeEntityForm.Meta):
        model = get_emailtemplate_model()

    def _clean_body(self, body):
        invalid_vars = []

        for varnode in Template(body).nodelist.get_nodes_by_type(VariableNode):
            varname = varnode.filter_expression.var.var
            if varname not in TEMPLATES_VARS:
                invalid_vars.append(varname)

        if invalid_vars:
            raise ValidationError(
                self.error_messages['invalid_vars'],
                params={'vars': invalid_vars},
                code='invalid_vars',
            )

        # TODO: return body

    def clean_body(self):
        body = self.cleaned_data['body']
        self._clean_body(body)

        return body

    def clean_body_html(self):
        body = self.cleaned_data['body_html']

        self._clean_body(body)

        return body
Beispiel #6
0
class TaskAddParentForm(CremeForm):
    parents = MultiCreatorEntityField(label=_('Parent tasks'), required=False, model=ProjectTask)

    class Meta:
        model = ProjectTask

    def __init__(self, instance, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.task = instance
        self.fields['parents'].q_filter =  Q(linked_project=instance.linked_project_id) & \
                                          ~Q(id__in=[t.id for t in instance.get_subtasks()]) & \
                                          ~Q(children_set=instance.pk)

    def save(self, *args, **kwargs):
        add_parent = self.task.parent_tasks.add

        for parent in self.cleaned_data['parents']:
            add_parent(parent)
Beispiel #7
0
class CampaignAddMLForm(CremeForm):
    mailing_lists = MultiCreatorEntityField(label=_('Lists'),
                                            required=False,
                                            model=get_mailinglist_model())

    blocks = FieldBlockManager(('general', _('Mailing lists'), '*'))

    def __init__(self, entity, *args, **kwargs):
        # super(CampaignAddMLForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.campaign = entity
        # self.fields['mailing_lists'].q_filter = {'~id__in': list(entity.mailing_lists.values_list('id', flat=True))}
        self.fields['mailing_lists'].q_filter = \
            ~Q(id__in=list(entity.mailing_lists.values_list('id', flat=True)))

    def save(self):
        add_ml = self.campaign.mailing_lists.add
        for ml in self.cleaned_data['mailing_lists']:
            add_ml(ml)
Beispiel #8
0
class TaskCreateForm(_TaskForm):
    parent_tasks = MultiCreatorEntityField(label=_('Parent tasks'), required=False, model=ProjectTask)

    def __init__(self, entity, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._project = entity

        fields = self.fields
        fields['parent_tasks'].q_filter = {'linked_project': entity.id}

    def save(self, *args, **kwargs):
        instance = self.instance
        project  = self._project

        instance.linked_project = project
        instance.order = project.attribute_order_task()

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

        return instance
Beispiel #9
0
class EmailTemplateAddAttachment(CremeForm):
    attachments = MultiCreatorEntityField(
        label=_('Attachments'),
        required=False,
        model=get_document_model(),
    )

    blocks = FieldBlockManager({
        'id': 'general',
        'label': _('Attachments'),
        'fields': '*',
    })

    def __init__(self, entity, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.template = entity

    def save(self):
        add = self.template.attachments.add

        for attachment in self.cleaned_data['attachments']:
            add(attachment)
Beispiel #10
0
class CampaignAddMLForm(CremeForm):
    mailing_lists = MultiCreatorEntityField(
        label=_('Lists'),
        required=False,
        model=emails.get_mailinglist_model(),
    )

    blocks = FieldBlockManager({
        'id': 'general',
        'label': _('Mailing lists'),
        'fields': '*',
    })

    def __init__(self, entity, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.campaign = entity
        self.fields['mailing_lists'].q_filter = ~Q(
            id__in=[*entity.mailing_lists.values_list('id', flat=True)], )

    def save(self):
        add_ml = self.campaign.mailing_lists.add
        for ml in self.cleaned_data['mailing_lists']:
            add_ml(ml)
class ParticipantCreateForm(CremeForm):
    my_participation    = UserParticipationField(label=_('Do I participate to this activity?'), empty_label=None)
    participating_users = ModelMultipleChoiceField(label=_('Other participating users'),
                                                   queryset=get_user_model().objects.filter(is_staff=False),
                                                   required=False,
                                                  )
    participants        = MultiCreatorEntityField(label=_('Participants'), model=Contact, required=False)

    def __init__(self, entity, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.activity = entity
        self.participants = set()

        user = self.user
        user_pk = user.pk
        fields = self.fields

        existing = Contact.objects.filter(relations__type=constants.REL_SUB_PART_2_ACTIVITY,
                                          relations__object_entity=entity.id,
                                         )

        participants_field = fields['participants']
        participants_field.q_filter = ~Q(pk__in=[c.id for c in existing]) & \
                                       Q(is_user__isnull=True)
        participants_field.force_creation = True  # TODO: in constructor ?

        # if entity.is_auto_orga_subject_enabled():
        if is_auto_orga_subject_enabled():
            participants_field.help_text = _('The organisations of the participants will '
                                             'be automatically added as subjects'
                                            )

        existing_users = [c.is_user.pk for c in existing if c.is_user]
        user_qs = get_user_model().objects.filter(is_staff=False) \
                                          .exclude(pk__in=existing_users) \
                                          .exclude(pk=user_pk)

        fields['participating_users'].queryset = user_qs
        if not user_qs:
            fields['participating_users'].widget.attrs = {'reduced': 'true'}

        if user_pk in existing_users:
            del fields['my_participation']

    def clean_participating_users(self):
        users = set()

        for user in self.cleaned_data['participating_users']:
            if not user.is_team:
                users.add(user)
            else:
                users.update(user.teammates.values())

        return validators.validate_linkable_entities(Contact.objects.filter(is_user__in=users),
                                                     self.user,
                                                    )

    # TODO: factorise with ActivityCreateForm
    def clean_my_participation(self):
        my_participation = self.cleaned_data['my_participation']

        if my_participation[0]:
            user = self.user
            self.participants.add(validators.validate_linkable_entity(user.linked_contact, user))

        return my_participation

    def clean(self):
        cleaned_data = super().clean()

        if not self._errors:
            activity = self.activity
            extend_participants = self.participants.update
            extend_participants(cleaned_data['participating_users'])
            extend_participants(cleaned_data['participants'])

            collisions = check_activity_collisions(activity.start, activity.end,
                                                   self.participants, busy=activity.busy,
                                                   exclude_activity_id=activity.id,
                                                  )
            if collisions:
                raise ValidationError(collisions)

        return cleaned_data

    def save(self):
        activity = self.activity
        create_relation = partial(Relation.objects.safe_create, object_entity=activity,
                                  type_id=constants.REL_SUB_PART_2_ACTIVITY, user=activity.user,
                                 )
        me = self.user

        for participant in self.participants:
            user = participant.is_user
            if user:
                activity.calendars.add(self.cleaned_data['my_participation'][1]
                                       if user == me else
                                       Calendar.objects.get_default_calendar(user)
                                      )

            create_relation(subject_entity=participant)
Beispiel #12
0
 def formfield(self, instance, user, **kwargs):
     return MultiCreatorEntityField(
         label=_('Project leaders'),
         model=get_contact_model(),
         user=user,
     )
Beispiel #13
0
class ActivityCreateForm(_ActivityCreateForm):
    my_participation = UserParticipationField(
        label=_(u'Do I participate to this activity?'), empty_label=None)

    other_participants = MultiCreatorEntityField(
        label=_(u'Other participants'), model=Contact, required=False)
    subjects = MultiGenericEntityField(label=_(u'Subjects'), required=False)
    linked_entities = MultiGenericEntityField(
        label=_(u'Entities linked to this activity'), required=False)

    error_messages = dict(
        _ActivityCreateForm.error_messages,
        no_participant=_('No participant'),
        alert_on_floating=_(
            'You cannot set a relative alert on a floating activity'),
    )

    blocks = _ActivityForm.blocks.new(
        ('datetime', _(u'When'),
         ['start', 'start_time', 'end', 'end_time', 'is_all_day']),
        ('participants', _(u'Participants'), [
            'my_participation', 'participating_users', 'other_participants',
            'subjects', 'linked_entities'
        ]),
        ('alert_datetime', _(u'Generate an alert on a specific date'),
         ['alert_start']),
        ('alert_period', _(u'Generate an alert in a while'), ['alert_period']),
        ('informed_users', _(u'Users to keep informed'), ['informed_users']),
    )

    def __init__(self, activity_type_id=None, *args, **kwargs):
        # super(ActivityCreateForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        user = self.user
        fields = self.fields

        if activity_type_id:
            # TODO: improve help_text of end (we know the type default duration)
            fields['type_selector'].types = ActivityType.objects.filter(
                pk=activity_type_id)

        fields['my_participation'].initial = (
            True, Calendar.get_user_default_calendar(user).id)

        subjects_field = fields['subjects']
        subjects_field.allowed_models = [
            ct.model_class() for ct in RelationType.objects.get(
                pk=constants.REL_SUB_ACTIVITY_SUBJECT).subject_ctypes.all()
        ]
        if self.instance.is_auto_orga_subject_enabled():
            subjects_field.help_text = _(
                'The organisations of the participants will be automatically added as subjects'
            )

        fields['participating_users'].queryset = get_user_model().objects.filter(is_staff=False) \
                                                                         .exclude(pk=user.id)

        other_f = fields['other_participants']
        other_f.q_filter = {'is_user__isnull': True}
        # The creation view cannot create a Contact with a non-null 'is_user'.
        other_f.force_creation = True  # TODO: in constructor

        if apps.is_installed('creme.assistants'):
            self._add_specified_alert_fields(fields)
            self._add_duration_alert_fields(fields)
            self._add_informed_users_fields(fields)

    @staticmethod
    def _add_specified_alert_fields(fields):
        fields['alert_start'] = DateTimeField(
            label=_(u'Generate an alert on a specific date'), required=False)

    @staticmethod
    def _add_duration_alert_fields(fields):
        fields['alert_period'] = DatePeriodField(
            label=_(u'Generate an alert in a while'),
            required=False,
            help_text=_(u"How long before the activity's"
                        u" start the alert is raised?"),
            period_names=('minutes', 'hours', 'days', 'weeks'),
        )

    @staticmethod
    def _add_informed_users_fields(fields):
        # try:
        #     sv = SettingValue.objects.get(key_id=constants.SETTING_FORM_USERS_MSG)
        # except SettingValue.DoesNotExist:
        #     logger.critical('SettingValue with key=%s cannot be found !'
        #                     ' ("creme_populate" command has not been run correctly)',
        #                     constants.SETTING_FORM_USERS_MSG
        #                    )
        # else:
        #     if sv.value:
        #         fields['informed_users'] = ModelMultipleChoiceField(queryset=get_user_model().objects.filter(is_staff=False),
        #                                                             required=False,
        #                                                             label=_(u'Users to keep informed'),
        #                                                            )
        if SettingValue.objects.get_4_key(form_user_messages_key,
                                          default=False).value:
            fields['informed_users'] = ModelMultipleChoiceField(
                queryset=get_user_model().objects.filter(is_staff=False),
                required=False,
                label=_('Users to keep informed'),
            )

    def clean_alert_period(self):
        cdata = self.cleaned_data
        alert_period = cdata['alert_period']

        if alert_period and not cdata.get('start'):
            raise ValidationError(
                self.error_messages['alert_on_floating'],
                code='alert_on_floating',
            )

        return alert_period

    def clean_my_participation(self):
        my_participation = self.cleaned_data['my_participation']

        if my_participation[0]:
            user = self.user
            self.participants.add(
                validators.validate_linkable_entity(user.linked_contact, user))

        return my_participation

    def clean_other_participants(self):
        participants = self.cleaned_data['other_participants']
        self.participants.update(participants)
        return participants

    def clean(self):
        if not self._errors:
            cdata = self.cleaned_data

            if not cdata['my_participation'][0] and not cdata[
                    'participating_users']:
                raise ValidationError(self.error_messages['no_participant'],
                                      code='no_participant')

        # return super(ActivityCreateForm, self).clean()
        return super().clean()

    def save(self, *args, **kwargs):
        # instance = super(ActivityCreateForm, self).save(*args, **kwargs)
        instance = super().save(*args, **kwargs)

        self._generate_alerts()
        self._generate_user_messages()

        cdata = self.cleaned_data

        i_participate, my_calendar = cdata['my_participation']
        if i_participate:
            instance.calendars.add(my_calendar)

        # TODO: improve Relation model in order to avoid duplication automatically + helper function
        create_relation = partial(
            Relation.objects.get_or_create,
            object_entity_id=instance.id,
            defaults={'user': instance.user},
        )

        for entities, rtype_id in (
            (cdata['subjects'], constants.REL_SUB_ACTIVITY_SUBJECT),
            (cdata['linked_entities'], constants.REL_SUB_LINKED_2_ACTIVITY),
        ):
            for entity in entities:
                create_relation(subject_entity_id=entity.id, type_id=rtype_id)

        return instance

    @staticmethod
    def _create_alert(activity, trigger_date):
        from creme.assistants.models import Alert

        Alert.objects.create(
            user=activity.user,
            trigger_date=trigger_date,
            creme_entity=activity,
            title=ugettext('Alert of activity'),
            description=ugettext(u'Alert related to {activity}').format(
                activity=activity),
        )

    def _generate_alerts(self):
        get = self.cleaned_data.get
        activity = self.instance
        alert_start = get('alert_start')

        if alert_start:
            self._create_alert(activity, alert_start)

        period = get('alert_period')
        if period:
            self._create_alert(activity,
                               activity.start - period.as_timedelta())

    def _generate_user_messages(self):
        cdata = self.cleaned_data
        raw_users = cdata.get('informed_users')

        if raw_users:
            from creme.assistants.models import UserMessage
            from creme.assistants.constants import PRIO_NOT_IMP_PK

            activity = self.instance
            title = ugettext(u'[Creme] Activity created: {activity}').format(
                activity=activity)
            body = ugettext(u"""A new activity has been created: {activity}.
    Description: {description}.
    Start: {start}.
    End: {end}.
    Subjects: {subjects}.
    Participants: {participants}.""").format(
                activity=activity,
                description=activity.description,
                start=activity.start or ugettext('not specified'),
                end=activity.end or ugettext('not specified'),
                subjects=u' / '.join(str(e) for e in cdata['subjects']),
                participants=u' / '.join(str(c) for c in self.participants),
            )

            # TODO: sender = the real user that created the activity ???
            UserMessage.create_messages(raw_users, title, body,
                                        PRIO_NOT_IMP_PK, activity.user,
                                        activity)