def send_signup_notifications(self): # send email to new Stadlander tenant language = get_language() context = { 'cc3_system_name': getattr(settings, "CC3_SYSTEM_NAME", "SamenDoen"), 'user_profile': self.profile } # provide both member and profile for backward compatibility send_mail_to(recipients=(self.profile, ), mail_type=MAIL_TYPE_NEW_STADLANDER_REGISTRATION, language=language, context=context)
def send_signup_notifications(self, profile): # send email confirmation to new participant, and # notification to the contact email language = get_language() context = self._common_mail_context() # provide both member and profile for backward compatibility context['member'] = profile context['profile'] = profile send_mail_to(recipients=(profile, ), mail_type=MAIL_TYPE_CAMPAIGN_SIGNUP_CONFIRM, language=language, context=context) send_mail_to(recipients=(), recipient_addresses=(self.owner_email, ), mail_type=MAIL_TYPE_CAMPAIGN_SIGNUP_NOTIFY, language=language, context=context)
def notify_participant_of_removal(self, reason=''): language = get_language() context = self.campaign._common_mail_context() context['reason'] = reason context['profile'] = self.profile return send_mail_to(recipients=(self.profile, ), mail_type=MAIL_TYPE_CAMPAIGN_UNSUBSCRIBED, language=language, context=context)
def notify_participants(self, mail_type): sent = 0 language = get_language() context = self._common_mail_context() for p in self.participants.all(): context['profile'] = p.profile sent += send_mail_to(recipients=(p.profile, ), mail_type=mail_type, language=language, context=context)
def send_mail(self, subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None): language = get_language() user = context['user'] protocol = context['protocol'] domain = context['domain'] suffix = reverse( 'auth_password_reset_confirm', kwargs={ 'uidb64': context['uid'], 'token': context['token'], }) url = "{}://{}{}".format(protocol, domain, suffix) first_name = None last_name = None middle_initials = None if user is not None: try: profile = UserProfile.objects.get(user=user) first_name = profile.first_name last_name = profile.last_name middle_initials = profile.tussenvoegsel if middle_initials == '': middle_initials = None except UserProfile.DoesNotExist: pass if first_name is None or first_name == '': first_name = user.first_name if last_name is None or last_name == '': last_name = user.last_name email_context = { 'link': url, 'first_name': first_name, 'last_name': last_name, 'middle_initials': middle_initials, } if user is not None and hasattr(user, 'email') and user.email is not None: sent = send_mail_to( recipients=(), mail_type=MAIL_TYPE_PASSWORD_RESET, language=language, context=email_context, recipient_addresses=(user.email,)) else: LOG.error("Cannot send activation email. User has no email address.")
def send_creation_notifications(self): sent = 0 if self.status != CAMPAIGN_STATUS_VISIBLE: return sent target_groups = getattr(settings, 'CYCLOS_CUSTOMER_MEMBER_GROUPS', ()) language = get_language() context = self._common_mail_context() for community in self.communities.filter( newcampaign_notify_members=True): for member in community.cc3profile_set.filter( email_new_campaigns=True, cyclos_group__name__in=target_groups): # provide both member and profile for backward compatibility context['member'] = member context['profile'] = member sent += send_mail_to(recipients=(member, ), mail_type=MAIL_TYPE_CAMPAIGN_CREATED, language=language, context=context) return sent
class BusinessProfile(models.Model): """ iCare4u specific Business CC3Profile model. """ profile = models.OneToOneField(UserProfile, null=True, related_name='business_profile') account_holder = models.CharField(max_length=255, default='', blank=True) iban = IBANField(verbose_name=_('IBAN number'), null=True, blank=True) bic_code = models.CharField(_('BIC code'), max_length=11, validators=[swift_bic_validator], null=True, blank=True) mandate_id = models.CharField(_('mandate ID'), max_length=35, null=True, blank=True) signature_date = models.DateField(_('date of signature'), null=True, blank=True) latest_payment_date = models.DateTimeField( null=True, blank=True, help_text=_('Time of the latest SEPA debit processing time.')) registration_number = models.CharField(max_length=14, default='', blank=True, help_text=_('KvK number')) vat_number = models.CharField(max_length=14, default='', blank=True, help_text=_('VAT Number')) class Meta: verbose_name = _(u'business profile') verbose_name_plural = _(u'business profiles') ordering = ('profile', ) def __unicode__(self): return u'{0}'.format(self.profile.full_name or str(self.pk)) def save(self, **kwargs): """ Overrides the base ``save`` method to set ``CyclosGroup`` and the ``CyclosGroupSet`` to the correct Positoos preselected one, if any. """ if not self.profile.groupset: try: group_set = CyclosGroupSet.objects.get(prefix='PST') self.profile.groupset = group_set self.profile.save() except CyclosGroupSet.DoesNotExist: LOG.critical(u"Cyclos groupset 'PST' does not exist") if not self.pk: group = getattr(settings, 'CYCLOS_BUSINESS_MEMBER_GROUP', None) if group: try: cyclos_group = CyclosGroup.objects.get(name=group) self.profile.cyclos_group = cyclos_group self.profile.save() except CyclosGroup.DoesNotExist: LOG.critical( u"Cyclos group '{0}' does not exist".format(group)) else: LOG.critical( u"'CYCLOS_BUSINESS_MEMBER_GROUP' setting not defined") if not self.profile.slug: # This is the THIRD time the ``CC3Profile`` is saved if all # conditions are met. 3 database hits for the same action... :( # [ was marked 'fix me', but there are other more hideous things # lurking in the system, like cyclos_group attached to two # different models. this is v rarely called self.profile.update_slug() super(BusinessProfile, self).save(**kwargs) def create_invoice(self, amount, invoice_description): """ Create a euro invoice from Positoos BV (marked unpaid) for this business. """ vat_rate = 0 # 1570, no VAT/BTW should be added for now. today = datetime.date.today() currency, created = Currency.objects.get_or_create(code='EUR', defaults={ 'name': 'Euro', 'symbol': '€' }) nr_days_due = getattr(settings, "SEPA_EXPORT_CREDIT_INVOICE_DAYS_DUE", 15) sender, created = User.objects.get_or_create( username=getattr(settings, "CC3_BANK_USER", "Positoos Reserve")) to_be_paid_status, created = PaymentStatus.objects.get_or_create( description="Pending", is_active=True, is_paid=False) if amount > 0: is_debit = True else: is_debit = False invoice_type = "debit" if is_debit else "credit" invoice = Invoice.objects.create( from_user=sender, to_user=self.profile.user, inv_date=today, due_date=today + datetime.timedelta(days=nr_days_due), currency=currency, payment_status=to_be_paid_status, invoice_type=invoice_type, automatic_invoice=True, admin_comment=u"Automatic invoice of type {0}".format( invoice_type)) InvoiceLine.objects.create(invoice=invoice, description=invoice_description, quantity=1, amount=amount, tax_rate=vat_rate) LOG.info(u"Created {2} invoice from reserve to user {0}, total amount " u"invoice: {1}".format(self.profile.user, invoice.get_total_display(), invoice_type)) def invoice_description(self, from_date, to_date, transactions, reset_transfer_descriptions=[]): """ For a date-range and a list of cc3.cyclos Transaction objects, give the proper description to be used for the invoice. Note that we only count since the most recent balance reset. This is currently determined based on the description of the transfer, as I've not yet been able to determine the transaction type id (it isn't returned in the Transaction object). """ spent = 0 spent_eur = 0 received = 0 received_eur = 0 for transaction in transactions: if transaction.description in reset_transfer_descriptions: # Reset-transaction found spent = 0 received = 0 from_date = transaction.created.date() continue if transaction.amount > 0: received += transaction.amount else: spent += transaction.amount div_by = Decimal("100.00") if spent: spent = spent * Decimal("-1.0") spent_eur = spent / div_by if received: received_eur = received / div_by total = spent - received total_eur = Decimal("0.00") if total: total_eur = total / div_by is_debit = False if total > 0: is_debit = True if is_debit: af_bijschrijving = _(u'Afschrijving') receive_or_pay = _(u'betalen') else: af_bijschrijving = _(u'Bijschrijving') receive_or_pay = _(u'ontvangen') return _(u"{af_bijschrijving} maandelijkse verrekening {from_date} " u"tot {to_date}.\n\n " u"Uitgegeven Positoos: {spent} Positoos (€ {spent_eur})\n" u"Ingenomen Positoos: {received} Positoos (€ " u"{received_eur})\n" u"Saldoverrekening: {plus}{total} Positoos te " u"{receive_or_pay}, € {total_eur}").format( af_bijschrijving=af_bijschrijving, from_date=from_date.strftime('%d-%m-%Y'), to_date=to_date.strftime('%d-%m-%Y'), spent=format(spent, '.0f'), spent_eur=format(spent_eur, '.2f'), received=format(received, '.0f'), received_eur=format(received_eur, '.2f'), plus=u'+' if is_debit else '', total=format(total, '.0f'), receive_or_pay=receive_or_pay, total_eur=format( total_eur if is_debit else total_eur * Decimal("-1.0"), '.2f')) def reset_balance(self): """ Resets the current user Positoos balance to zero. Taking into account the ``accountStatus.balance`` of the user, it makes a payment from or to the system for a similar amount, turning the balance equal to zero. """ # Getting settings - defaulting to Positoos values if settings missing. debit_transfer_type_id = getattr(settings, 'SEPA_EXPORT_DEBIT_TRANSFER_TYPE_ID', 39) debit_transfer_description = getattr( settings, 'SEPA_EXPORT_DEBIT_TRANSFER_DESCRIPTION', "Bijschrijving na automatisch incasso") credit_transfer_type_id = getattr( settings, 'SEPA_EXPORT_CREDIT_TRANSFER_TYPE_ID', 36) credit_transfer_description = getattr( settings, 'SEPA_EXPORT_CREDIT_TRANSFER_DESCRIPTION', "Afschrijving na automatisch incasso") to_date = datetime.date.today() from_date = last_month_first_of_month() div_by = Decimal("100.00") try: balance = backends.get_account_status( self.profile.user.username).accountStatus.balance transactions = backends.transactions( username=self.profile.user.username, from_date=from_date, to_date=to_date) except MemberNotFoundException: LOG.error(u'Member not found (in Cyclos): {0}'.format( self.profile.user.username)) return False LOG.info(u"Resetting balance for user {0}, current balance {1}".format( self.profile.user.username, balance)) if balance == 0: LOG.info(u"Not resetting balance, no transaction required as " u"balance is already 0") return True invoice_description = self.invoice_description( from_date, to_date, transactions, reset_transfer_descriptions=[ debit_transfer_description, credit_transfer_description ]) try: if balance > 0: # Positive balance. Move the cash from user to the system. # From Organisatie rekening (member) to Reserve account # (system), # Transfer type ID 36. # Transfer Type 'Take out of circulation'. LOG.info(u"Credit transfer, ID: {0}, {1}".format( credit_transfer_type_id, credit_transfer_description)) backends.to_system_payment( self.profile.user.username, balance, credit_transfer_description, transfer_type_id=credit_transfer_type_id) LOG.info( _(u'Monthly balance for business {0} reconciled. {1} ' u'Positoos recovered by Cyclos system'.format( self.profile.user.username, balance))) self.create_invoice((balance / div_by) * Decimal("-1.00"), invoice_description) else: # Negative balance. Move some cash from system to user. # From Reserve account (system) to Organisatie rekening # (member). # Transfer type ID 39. # Transfer Type 'Acquiring Positoos'. LOG.info(u"Debit transfer, ID: {0}, {1}".format( debit_transfer_type_id, debit_transfer_description)) backends.from_system_payment( self.profile.user.username, -balance, debit_transfer_description, transfer_type_id=debit_transfer_type_id) LOG.info( _(u'Monthly balance for business {0} reconciled. {1} ' u'Positoos paid by Cyclos system'.format( self.profile.user.username, balance))) self.create_invoice((balance / div_by) * Decimal("-1.00"), invoice_description) except TransactionException, e: LOG.error(u'Unable to perform balance reset. The transaction ' u'failed: {0}\nSure the user is a business?'.format(e)) return False # notify the business by email site = Site.objects.get_current() link_url = "https://{0}{1}".format(site.domain, reverse('invoice_list')) if getattr(settings, "SEND_SEPA_MONTHLY_RESET_INVOICE", False): send_mail_to( [ self.profile, ], MAIL_TYPE_MONTHLY_INVOICE, translation.get_language(), { 'invoice_text': invoice_description, 'contact_name': self.profile.name, 'business_name': self.profile.full_name, 'link_url': link_url, }) return True