예제 #1
0
    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)
예제 #2
0
 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)
예제 #3
0
 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)
예제 #4
0
 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)
예제 #5
0
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.")
예제 #6
0
    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
예제 #7
0
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