Beispiel #1
0
def translate_user_payment_status(payment_status):
    translated_status = {
        'nytt_medlemsår': date.today() >= membership_year_start()['actual_date'],
        'inneværende_år': payment_status['is_paid'],
        'neste_år': payment_status.get('next_year'),
    }
    return translated_status
Beispiel #2
0
    def has_paid_next_year(self):
        from core.util import membership_year_start
        if not date.today() >= membership_year_start()['actual_date']:
            raise Exception("Doesn't make sense to call this method before årskravet")

        # If their payment is paid, and we're past årskravet, then it's a valid payment for next year
        return self.has_paid()
Beispiel #3
0
 def _has_paid_after_arskrav(self):
     """
     Returns True if and only if the membership is paid for the next year, after årskravet. Can only be called after
     årskravet.
     """
     if date.today() < membership_year_start()['actual_date']:
         raise Exception("Doesn't make sense to call this method before årskravet")
     # After årskravet, payment for next year is checked through the balance
     return self._balance_is_paid()
Beispiel #4
0
 def _has_paid(self):
     """Returns True if the membership for this user is currently valid"""
     if date.today() < membership_year_start()['actual_date']:
         # Before årskravet, the membership is simply valid if it's paid for this year
         return self._has_paid_before_arskrav()
     else:
         # After årskravet, the membership is valid if it was paid for last year or if they have purchased a new
         # membership for next year
         return self._has_paid_before_arskrav() or self._has_paid_after_arskrav()
Beispiel #5
0
 def _has_paid_before_arskrav(self):
     """
     Returns True if and only if the membership is paid for the current year, that is, before årskravet. Any
     membership paid before årskravet is valid for the remainder of the year, regardless of whether it's paid for the
     next year as well.
     Note that the membership may be still valid for this year even though this method returns False, IF they have
     paid for the next year.
     """
     if date.today() < membership_year_start()['actual_date']:
         # Before årskravet, all we have to do is check the balance
         return self._balance_is_paid()
     else:
         if self.member.get_membership_start_date() > membership_year_start()['actual_date']:
             # Members enrolled after årskravet have implicitly not paid for the previous year
             return False
         else:
             # After årskravet but before year's end, members who have paid for the current year (but not the next)
             # have no end_date; while those who haven't paid for the current year do.
             return self.member.actor.end_date is None
Beispiel #6
0
 def should_renew_membership(self):
     """
     Returns True if this member ought to renew their membership. This may be the case if:
     - We haven't passed årskravet yet and the user hasn't paid *this* year, or
     - We have passed årskravet, and the user hasn't paid for *next* year
     """
     new_membership_year = date.today() >= membership_year_start()['actual_date']
     not_paid_this_year = not new_membership_year and not self.status['this_year']
     not_paid_next_year = new_membership_year and not self.status['next_year']
     return not_paid_this_year or not_paid_next_year
Beispiel #7
0
def family_conversion_applies_next_year():
    """Returns True if the current date is in the period where family conversions apply for the next
    membership year"""
    today = date.today()
    start_date = date(
        year=today.year,
        month=settings.FAMILY_CONVERSION_APPLIES_NEXT_YEAR[0],
        day=settings.FAMILY_CONVERSION_APPLIES_NEXT_YEAR[1],
    )
    # Note that the period doesn't end at year's end, but at the *membership year's* end.
    end_date = membership_year_start()['public_date']
    return today >= start_date and today <= end_date
 def status(self):
     """
     Returns a dict with the following keys:
     - is_paid: True if the enrollment was paid and confirmed
     - pending_payment_method: either 'card' or 'invoice', depending on the payment method chosen during enrollment
     """
     status = {
         'is_paid': self.enrollment.payment_confirmed(),
         'this_year': self._has_paid_this_year(),
         'pending_payment_method': self.enrollment.payment_method_code(),
     }
     if date.today() >= membership_year_start()['actual_date']:
         status['next_year'] = self._has_paid_next_year()
     return status
Beispiel #9
0
    def get_age(self):
        """Returns the age this user will be within the end of the membership year. Hence, it will always be the same
        for the same person within one membership-year."""
        if self.dob is None:
            raise BirthDateNotDefined("User %s does not have a birth date defined" % self)

        age = date.today().year - self.dob.year

        # After membership year start, the enrollment is really for the next year,
        # hence they'll be one year older than they are this year.
        if date.today() >= membership_year_start()['actual_date']:
            age += 1

        return age
Beispiel #10
0
 def get_invoice(self):
     """Returns the current invoice for this member. Raises DoesNotExist or MultipleObjectReturned if there isn't
     exactly one invoice - which is likely, and will need to be handled by callers. See the docstring on
     `focus.models.InvoiceHead` for what those cases mean."""
     # We need to select invoices created after the initiation date for the *last membership
     # year*, because that was the date for which new memberships apply for the following year as
     # well.
     from core.models import Settings
     from core.util import membership_year_start
     if date.today() >= membership_year_start()['actual_date']:
         # New membership year has started! Use this year's membership date
         last_membership_year = date.today().year
     else:
         # New membership year not started yet, use last year's membership date
         last_membership_year = date.today().year - 1
     return self.invoices.get(invoice_date__gte=Settings.get_cached().arskrav_initiation_date_last_year)
Beispiel #11
0
 def status(self):
     """
     Return a dict depicting the user's current payment status:
     - 'is_paid': True if the membership fee is currently paid and valid
     - 'amount_due': Remaining amount of the membership fee to be paid
     - 'this_year': True if the membership fee for the current year is paid (note: not membership year)
     - 'next_year': True if the membership fee for next year is paid (applicable only after årskravet)
     """
     status = {
         'is_paid': self._has_paid(),
         'amount_due': self.amount_due(),
         'this_year': self._has_paid_before_arskrav(),
     }
     if date.today() < membership_year_start()['actual_date']:
         status['next_year'] = None
     else:
         status['next_year'] = self._has_paid_after_arskrav()
     return status
Beispiel #12
0
    def status_text(self, prefix=None):
        """Outputs a readable text summary of the current payment status"""
        if prefix is not None:
            prefix_paid, prefix_not_paid = prefix.split(',')
        else:
            prefix_paid = _('Medlem')
            prefix_not_paid = _('Ikke medlem')

        today = date.today()
        current_year = today.year
        next_year = today.year + 1

        if self.member.is_lifelong_member():
            return '%s (livsvarig)' % (prefix_paid)

        if date.today() < membership_year_start()['actual_date']:
            if self.status['is_paid']:
                return '%s %s' % (prefix_paid, current_year)
            else:
                return '%s %s' % (prefix_not_paid, current_year)
        else:
            if self.status['next_year']:
                return _('%(prefix_paid)s ut %(current_year)s, samt hele %(next_year)s') % {
                    'prefix_paid': prefix_paid,
                    'current_year': current_year,
                    'next_year': next_year,
                }
            elif self.status['this_year']:
                return _('%(prefix_paid)s ut %(current_year)s, men ikke %(next_year)s') % {
                    'prefix_paid': prefix_paid,
                    'current_year': current_year,
                    'next_year': next_year,
                }
            else:
                return _('%(prefix_paid)s %(current_year)s eller %(next_year)s') % {
                    'prefix_paid': prefix_not_paid,
                    'current_year': current_year,
                    'next_year': next_year,
                }
Beispiel #13
0
def renew_membership(request):
    if request.method != 'POST':
        return redirect('user:account')

    if 'stripeToken' not in request.POST:
        return redirect('user:account')

    description = "Fornying av medlemskap"

    if date.today() < membership_year_start()['public_date']:
        applicable_year = membership_year_start()['public_date'].year
    else:
        applicable_year = membership_year_start()['public_date'].year + 1

    metadata = {
        'Periode': 'Medlemsåret %s' % applicable_year,
    }

    if not request.user.has_family():
        # Single member, pay their own invoice
        amount = request.user.payment.status['amount_due']
        metadata['Medlemskap'] = request.user.membership_type()['name']
        metadata['Medlem'] = '%s (medlemsnr: %s)' % (request.user.get_full_name(), request.user.memberid)
        request.user.clear_cache()
    elif request.user.family.relation == 'family':
        # Family membership, pay the invoice of the parent
        amount = request.user.payment.status['amount_due']
        metadata['Medlemskap'] = 'Familiemedlemskap'
        metadata['Familie hovedmedlem'] = '%s (medlemsnr: %s)' % (
            request.user.family.parent.get_full_name(),
            request.user.family.parent.memberid,
        )
        metadata['Alle familiemedlemmer'] = ', '.join([
            '%s (medlemsnr: %s)' % (u.get_full_name(), u.memberid)
            for u in request.user.family.all_members()
        ])
        request.user.family.clear_cache()
    elif request.user.family.relation == 'household':
        # Household membership, each member has their own invoice.
        amount = request.user.family.payment_amount_due()
        metadata['Medlemskap'] = 'Husstandsmedlemskap'
        metadata['Medlemmer'] = ', '.join([
            '%s (medlemsnr: %s, %s, %s)' % (
                u.get_full_name(),
                u.memberid,
                u.membership_type()['name'],
                currency(u.payment.status['amount_due']),
            )
            for u in request.user.family.payment_members()
        ])
        request.user.family.clear_cache()

    charge = Charge.new_charge(
        Forening.get_cached_forening(id=Forening.DNT_CENTRAL_ID).payment_auth()['stripe_user_id'],
        request.user,
        request.POST['stripeToken'],
        amount,
        description,
        metadata,
    )

    try:
        if not charge.was_success():
            # Unsuccessful payment. Store the error message and display it on the account page
            request.session['membership.%s.payment_failure' % request.user.memberid] = {
                'error_display': charge.get_error_code_display(),
                'error_message': charge.error_message,
            }
        else:
            # Payment was succesful; save it to Focus
            if not request.user.has_family() or request.user.family.relation == 'family':
                request.user.payment.save_pending_payment(charge.charge_id, amount)
            else:
                for household_member in request.user.family.payment_members():
                    household_member.payment.save_pending_payment(
                        charge.charge_id,
                        household_member.payment.status['amount_due'],
                    )
    except:
        # Problem during pending payment registration - likely connection issue with Focus.
        # - Since the payment isn't stored in Focus, the user will not get the confirmation, so add an error message
        #   explaining the situation.
        # - Manual followup is required by memberservice, so send email to memberservice with required information
        # - Log an error to be able to trace events, in case it's ever needed
        messages.error(request, 'payment_registration_failure')
        logger.error(
            "Feil ved lagring av medlemskapsfornyelse i Focus",
            exc_info=sys.exc_info(),
            extra={
                'request': request,
                'amount': amount,
                'metadata': metadata,
                'charge': charge,
            },
        )
        try:
            context = {
                'amount': amount,
                'metadata': metadata,
                'charge': charge,
            }
            message = render_to_string('common/focus/payment_registration_failure.txt', context, request=request)
            send_mail(
                "Fornying av medlemskap kunne ikke lagres i Focus",
                message,
                settings.DEFAULT_FROM_EMAIL,
                [settings.MEMBERSERVICE_EMAIL],
            )
        except (SMTPException, SSLError, UnicodeEncodeError):
            # Jesus. Error upon error. Log it, hopefully devs will be able to follow up.
            logger.error(
                "Kunne ikke sende varselsepost til medlemsservice, beskjed må gis manuelt",
                extra={
                    'request': request,
                    'message': message,
                    'amount': amount,
                    'metadata': metadata,
                    'charge': charge,
                },
            )
    finally:
        return redirect('%s#forny-medlemskap' % reverse('user:account'))
    def _has_paid_next_year(self):
        assert date.today() >= membership_year_start()['actual_date']

        # If payment is confirmed and we're past årskravet, then it's a valid payment for next year
        return self.enrollment.payment_confirmed()