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)
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)
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'])
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()
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
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)
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)
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
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)
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)
def formfield(self, instance, user, **kwargs): return MultiCreatorEntityField( label=_('Project leaders'), model=get_contact_model(), user=user, )
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)