class CreditNoteRelatedForm(base.CremeForm): credit_notes = MultiCreatorEntityField(label=_('Credit notes'), model=CreditNote) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.billing_document = entity existing = Relation.objects.filter( subject_entity=entity.id, type=constants.REL_OBJ_CREDIT_NOTE_APPLIED) # TODO waiting for automated change of status when a credit note is out of date by looking to expiration date # TODO Add another filter today <= expiration_date ?? q_filter = ~Q(pk__in=[rel.object_entity_id for rel in existing]) & \ Q(currency=entity.currency.id, # status=CreditNoteStatus.objects.get(pk=ISSUED_CREDIT_NOTE).id, # TODO workflow status relations__type=constants.REL_SUB_BILL_RECEIVED, relations__object_entity=entity.get_real_entity().get_target().id, ) self.fields['credit_notes'].q_filter = q_filter def save(self): create_relation = partial( Relation.objects.safe_create, subject_entity=self.billing_document, type_id=constants.REL_OBJ_CREDIT_NOTE_APPLIED, user=self.user, ) for entity in self.cleaned_data['credit_notes']: create_relation(object_entity=entity)
class CampaignAddListForm(CremeForm): messaging_lists = MultiCreatorEntityField(label=_('Lists'), required=False, model=MessagingList) # error_messages = { # 'already_linked': _('Following lists are already related to this campaign: %(lists)s'), # } blocks = FieldBlockManager(('general', _('Messaging lists'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.campaign = entity self.fields['messaging_lists'].q_filter = ~Q( id__in=[*entity.lists.values_list('id', flat=True)], ) # # In fact duplicate is not a problem with django's m2m # def clean_lists(self): # messaging_lists = self.cleaned_data['messaging_lists'] # current_lists = frozenset(self.campaign.lists.values_list('pk', flat=True)) # duplicate = [mlist for mlist in messaging_lists if mlist.id in current_lists] # # if duplicate: # raise ValidationError( # self.error_messages['already_linked'], # params={'lists': ', '.join(mlist.name for mlist in duplicate)}, # code='already_linked', # ) # # return messaging_lists def save(self): add_mlist = self.campaign.lists.add for mlist in self.cleaned_data['messaging_lists']: add_mlist(mlist)
class ProductLineMultipleAddForm(_LineMultipleAddForm): items = MultiCreatorEntityField(label=_('Products'), model=products.get_product_model()) blocks = core_forms.FieldBlockManager( ('general', _('Products choice'), ['items']), ('additional', _('Optional global information applied to your selected products'), ['quantity', 'vat', 'discount_value'])) def _get_line_class(self): return ProductLine
class AddOrganisationsForm(CremeForm): # TODO: factorise recipients = MultiCreatorEntityField( label=_('Organisations'), required=False, model=Organisation, ) # other filter (name + email)?? blocks = FieldBlockManager(('general', _('Organisations recipients'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity def save(self): organisations = self.ml.organisations # TODO: check if email if ok ???? for organisation in self.cleaned_data['recipients']: organisations.add(organisation)
class AddContactsForm(CremeForm): recipients = MultiCreatorEntityField( label=_('Contacts'), required=False, model=Contact, ) # other filter (name + email)?? blocks = FieldBlockManager(('general', _('Contacts recipients'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity def save(self): contacts = self.ml.contacts # TODO: check if email if ok ???? for contact in self.cleaned_data['recipients']: contacts.add(contact)
class CampaignAddListForm(CremeForm): messaging_lists = MultiCreatorEntityField( label=_('Lists'), required=False, model=MessagingList, ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Messaging lists'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.campaign = entity self.fields['messaging_lists'].q_filter = ~Q( id__in=[*entity.lists.values_list('id', flat=True)], ) def save(self): add_mlist = self.campaign.lists.add for mlist in self.cleaned_data['messaging_lists']: add_mlist(mlist)
class AddContactsForm(CremeForm): # TODO: other filter (name + email) ? recipients = MultiCreatorEntityField( label=_('Contacts'), required=False, model=Contact, ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Contacts recipients'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.messaging_list = entity def save(self): contacts = self.messaging_list.contacts # TODO: check if email if ok ???? for contact in self.cleaned_data['recipients']: contacts.add(contact)
class ServiceLineMultipleAddForm(_LineMultipleAddForm): items = MultiCreatorEntityField(label=_('Services'), model=products.get_service_model()) blocks = core_forms.FieldBlockManager( { 'id': 'general', 'label': _('Services choice'), 'fields': ['items'], }, { 'id': 'additional', 'label': _('Optional global information applied to your selected services'), 'fields': ['quantity', 'vat', 'discount_value'], }, ) def _get_line_class(self): return ServiceLine
class EntityEmailForm(base_forms.CremeModelForm): """Mails are related to the selected contacts/organisations & the 'current' entity. Mails are send to selected contacts/organisations. """ sender = EmailField(label=_('Sender')) c_recipients = MultiCreatorEntityField(label=_('Contacts'), required=False, model=Contact, q_filter={'email__gt': ''}) o_recipients = MultiCreatorEntityField(label=_('Organisations'), required=False, model=Organisation, q_filter={'email__gt': ''}) send_me = BooleanField(label=_('Send me a copy of this mail'), required=False) error_messages = { 'no_person': _('Select at least a Contact or an Organisation'), } blocks = base_forms.FieldBlockManager( ('recipients', _('Who'), ['user', 'sender', 'send_me', 'c_recipients', 'o_recipients']), ('content', _('What'), ['subject', 'body', 'body_html']), ('extra', _('With'), ['signature', 'attachments']), ) class Meta: model = EntityEmail fields = ('user', 'sender', 'subject', 'body', 'body_html', 'signature', 'attachments') def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.entity = entity if isinstance(entity, (Contact, Organisation)): fn, msg = ('c_recipients', _('Beware: the contact «{}» has no email address!')) \ if isinstance(entity, Contact) else \ ('o_recipients', _('Beware: the organisation «{}» has no email address!')) field = self.fields[fn] if entity.email: field.initial = [entity.pk] else: field.help_text = msg.format(entity) self.user_contact = contact = self.user.linked_contact if contact.email: self.fields['sender'].initial = contact.email def finalize_recipient_field(name, model): if FieldsConfig.get_4_model(model).is_fieldname_hidden('email'): self.fields[name] = CharField( label=self.fields[name].label, required=False, widget=Label, initial=gettext( 'Beware: the field «Email address» is hidden ;' ' please contact your administrator.'), ) finalize_recipient_field('c_recipients', Contact) finalize_recipient_field('o_recipients', Organisation) def _clean_recipients(self, field_name): if isinstance(self.fields[field_name].widget, Label): return [] recipients = self.cleaned_data.get(field_name) or [] bad_entities = [] for entity in recipients: try: validate_email(entity.email) except ValidationError: bad_entities.append(entity) if bad_entities: msg_format = gettext('The email address for {} is invalid') user = self.user for entity in bad_entities: self.add_error(field_name, msg_format.format(entity.allowed_str(user))) return recipients def clean_c_recipients(self): return self._clean_recipients('c_recipients') def clean_o_recipients(self): return self._clean_recipients('o_recipients') def clean(self): cdata = super().clean() if not self._errors and not cdata['c_recipients'] and not cdata[ 'o_recipients']: raise ValidationError(self.error_messages['no_person'], code='no_person') return cdata def save(self): cdata = self.cleaned_data get_data = cdata.get sender = get_data('sender') subject = get_data('subject') body = get_data('body') body_html = get_data('body_html') signature = get_data('signature') attachments = get_data('attachments') user = get_data('user') sending_error = False def create_n_send_mail(recipient_address): nonlocal sending_error email = EntityEmail.create_n_send_mail( sender=sender, recipient=recipient_address, subject=subject, user=user, body=body, body_html=body_html, signature=signature, attachments=attachments, ) if email.status == MAIL_STATUS_SENDINGERROR: sending_error = True return email with atomic(): if get_data('send_me'): create_n_send_mail(sender) user_contact = self.user_contact create_relation = partial(Relation.objects.create, user=user) for recipient in chain(cdata['c_recipients'], cdata['o_recipients']): email = create_n_send_mail(recipient.email) create_relation(subject_entity=email, type_id=REL_SUB_MAIL_SENDED, object_entity=user_contact) create_relation(subject_entity=email, type_id=REL_SUB_MAIL_RECEIVED, object_entity=recipient) if sending_error: entity_emails_send_type.refresh_job()