Exemple #1
0
    def get_context_data(self, **kwargs) -> dict:
        lecture_year = datetime_to_lectureyear(timezone.now())

        years = {x: {} for x in reversed(range(1990, lecture_year + 1))}
        for year in years:
            years[year] = {
                "documents": {
                    "policy": None,
                    "report": None,
                    "financial": None
                },
                "general_meetings": [],
            }

        for document in AnnualDocument.objects.filter(subcategory="policy"):
            years[document.year]["documents"]["policy"] = document
        for document in AnnualDocument.objects.filter(subcategory="report"):
            years[document.year]["documents"]["report"] = document
        for document in AnnualDocument.objects.filter(subcategory="financial"):
            years[document.year]["documents"]["financial"] = document

        for obj in GeneralMeeting.objects.all():
            meeting_year = datetime_to_lectureyear(obj.datetime)
            years[meeting_year]["general_meetings"].append(obj)

        context = super().get_context_data(**kwargs)
        context.update({
            "association_documents":
            AssociationDocument.objects.order_by(
                f"name_{get_language()}").all(),
            "years":
            list(years.items()),
        })
        return context
Exemple #2
0
    def lookups(self, request, model_admin):
        current_year = datetime_to_lectureyear(timezone.now())
        first_year = datetime_to_lectureyear(
            models.MemberGroupMembership.objects.earliest("since").since
        )

        return [
            (year, "{}-{}".format(year, year + 1))
            for year in range(first_year, current_year + 1)
        ]
Exemple #3
0
    def lookups(self, request, model_admin):
        objects_end = models.Event.objects.aggregate(Max("end"))
        objects_start = models.Event.objects.aggregate(Min("start"))

        if objects_end["end__max"] and objects_start["start__min"]:
            year_end = datetime_to_lectureyear(objects_end["end__max"])
            year_start = datetime_to_lectureyear(objects_start["start__min"])

            return [
                (year, "{}-{}".format(year, year + 1))
                for year in range(year_end, year_start - 1, -1)
            ]
        return []
Exemple #4
0
def gen_stats_year() -> Dict[str, Dict[str, int]]:
    """
    Generate list with 6 entries, where each entry represents the total amount
    of Thalia members in a year. The sixth element contains all the multi-year
    students.
    """
    stats_year = {}
    current_year = datetime_to_lectureyear(date.today())

    for i in range(5):
        new = {}
        for key, _ in Membership.MEMBERSHIP_TYPES:
            new[key] = (Membership.objects.filter(
                user__profile__starting_year=current_year -
                i).filter(since__lte=date.today()).filter(
                    Q(until__isnull=True)
                    | Q(until__gt=date.today())).filter(type=key).count())
        stats_year[str(current_year - i)] = new

    # Add multi year members
    new = {}
    for key, _ in Membership.MEMBERSHIP_TYPES:
        new[key] = (Membership.objects.filter(
            user__profile__starting_year__lt=current_year -
            4).filter(since__lte=date.today()).filter(
                Q(until__isnull=True)
                | Q(until__gt=date.today())).filter(type=key).count())
    stats_year[str(gettext("Older"))] = new

    return stats_year
Exemple #5
0
    def test_create_payment_for_entry(self):
        self.e1.username = "******"
        self.e1.save()
        self.e2.username = "******"
        self.e2.save()

        p1 = services._create_payment_for_entry(self.e1)  # 'year' payment
        p2 = services._create_payment_for_entry(self.e2)  # 'study' payment

        lecture_year = datetime_to_lectureyear(timezone.now())
        Membership.objects.create(
            type=Membership.MEMBER,
            since=timezone.datetime(year=lecture_year, month=9, day=1),
            until=timezone.datetime(year=lecture_year + 1, month=9, day=1),
            user=self.e3.member,
        )
        Membership.objects.create(
            type=Membership.MEMBER,
            since=timezone.datetime(year=lecture_year, month=9, day=1),
            until=timezone.datetime(year=lecture_year + 1, month=9, day=1),
            user=self.e4.member,
        )
        Membership.objects.create(
            type=Membership.MEMBER,
            since=timezone.now() - timedelta(days=31),
            until=timezone.now() - timedelta(days=2),
            user=self.e5.member,
        )

        # upgrade 'study'
        p3 = services._create_payment_for_entry(self.e3)
        # upgrade 'year'
        p4 = services._create_payment_for_entry(self.e4)
        # upgrade 'study' after membership end
        p5 = services._create_payment_for_entry(self.e5)

        self.e1.membership_type = Membership.BENEFACTOR
        self.e1.contribution = 10
        p6 = services._create_payment_for_entry(self.e1)  # contribu payment

        self.assertEqual(p1.amount, settings.MEMBERSHIP_PRICES["year"])
        self.assertEqual(p1.processed, False)
        self.assertEqual(p2.amount, settings.MEMBERSHIP_PRICES["study"])
        self.assertEqual(p2.processed, False)
        self.assertEqual(
            p3.amount,
            settings.MEMBERSHIP_PRICES["study"] -
            settings.MEMBERSHIP_PRICES["year"],
        )
        self.assertEqual(p3.processed, False)
        self.assertEqual(p4.amount, settings.MEMBERSHIP_PRICES["year"])
        self.assertEqual(p4.processed, False)
        self.assertEqual(
            p5.amount,
            settings.MEMBERSHIP_PRICES["study"] -
            settings.MEMBERSHIP_PRICES["year"],
        )
        self.assertEqual(p5.processed, False)
        self.assertEqual(p6.amount, 10)
        self.assertEqual(p6.processed, False)
Exemple #6
0
def get_automatic_mailinglists():
    """Return mailing list names that should be generated automatically."""
    lectureyear = datetime_to_lectureyear(timezone.now())
    list_names = [
        "leden",
        "members",
        "begunstigers",
        "benefactors",
        "ereleden",
        "honorary",
        "mentors",
        "activemembers",
        "commissievoorzitters",
        "committeechairs",
        "optin",
        "oldboards",
        "oudbesturen",
    ]
    if Board.objects.exists():
        for year in range(
                Board.objects.earliest("since").since.year, lectureyear):
            board = Board.objects.get(since__year=year)
            if board is not None:
                years = str(board.since.year)[-2:] + str(board.until.year)[-2:]
                list_names += [f"bestuur{years}", f"board{years}"]
    return list_names
Exemple #7
0
    def __init__(self, *args, **kwargs):
        """Initialize form and set the year choices."""
        super().__init__(*args, **kwargs)

        self.initial["year"] = datetime_to_lectureyear(timezone.now())
        self.fields["year"] = forms.ChoiceField(
            label="Academic year", choices=association_year_choices())
Exemple #8
0
def _create_membership_from_entry(entry: Entry,
                                  member: Member = None
                                  ) -> Union[Membership, None]:
    """
    Create or update Membership model based on Entry model information

    :param entry: Entry model
    :type entry: Entry
    :return: The created or updated membership
    :rtype: Membership
    """
    lecture_year = datetime_to_lectureyear(timezone.now())
    since = calculate_membership_since()
    until = None
    if timezone.now().month == 8:
        lecture_year += 1

    if entry.length == Entry.MEMBERSHIP_YEAR:
        # If entry is Renewal set since to current membership until + 1 day
        # Unless there is no current membership
        try:
            member = entry.renewal.member
            membership = member.current_membership
            if membership is not None:
                if membership.until is None:
                    raise ValueError("This member already has a never ending "
                                     "membership")
                since = membership.until
        except Renewal.DoesNotExist:
            pass
        until = timezone.datetime(year=lecture_year + 1, month=9, day=1).date()
    elif entry.length == Entry.MEMBERSHIP_STUDY:
        try:
            renewal = entry.renewal
            member = renewal.member
            membership = member.latest_membership
            # Having a latest membership which has an until date implies that
            # this membership last(s/ed) till the end of the lecture year
            # This means it's possible to renew the 'year' membership
            # to a 'study' membership thus the until date should now be None
            # and no new membership is needed.
            # The rules for this behaviour are taken from the HR
            if membership is not None:
                if membership.until is None:
                    raise ValueError("This member already has a never ending "
                                     "membership")
                if entry.created_at.date() < membership.until:
                    membership.until = None
                    membership.save()
                    return membership
        except Renewal.DoesNotExist:
            pass
    else:
        return None

    return Membership.objects.create(user=member,
                                     since=since,
                                     until=until,
                                     type=entry.membership_type)
Exemple #9
0
 def setup(self, request, *args, **kwargs) -> None:
     super().setup(request, *args, **kwargs)
     current_lectureyear = datetime_to_lectureyear(date.today())
     self.year_range = list(
         reversed(range(current_lectureyear - 5, current_lectureyear + 1))
     )
     self.keywords = request.GET.get("keywords", "").split() or None
     self.query_filter = kwargs.get("filter", None)
Exemple #10
0
def association_year_choices():
    current_year = datetime_to_lectureyear(timezone.now())

    choices = []
    for year in range(1990, current_year + 2):
        choices.append((year, "{}-{}".format(year, year + 1)))
    choices.reverse()

    return choices
Exemple #11
0
def association_year_choices():
    """Return the academic years Thalia existed."""
    current_year = datetime_to_lectureyear(timezone.now())

    choices = []
    for year in range(1990, current_year + 2):
        choices.append((year, "{}-{}".format(year, year + 1)))
    choices.reverse()

    return choices
Exemple #12
0
    def test_gen_stats_different_years(self):
        current_year = datetime_to_lectureyear(date.today())

        # postgres does not define random access directly on unsorted querysets
        members = [member for member in Member.objects.all()]

        # one first year student
        m = members[0]
        m.profile.starting_year = current_year
        m.profile.save()

        # one second year student
        m = members[1]
        m.profile.starting_year = current_year - 1
        m.profile.save()

        # no third year students

        # one fourth year student
        m = members[2]
        m.profile.starting_year = current_year - 3
        m.profile.save()

        # no fifth year students

        # one >5 year student
        m = members[3]
        m.profile.starting_year = current_year - 5
        m.profile.save()

        # 4 active members
        result = gen_stats_year()
        self.assertEqual(4, self.sum_members(result))
        self.assertEqual(4, self.sum_members(result, Membership.MEMBER))

        # one first year student
        self.assertEqual(1, result["2019"][Membership.MEMBER])

        # one second year student
        self.assertEqual(1, result["2018"][Membership.MEMBER])

        # no third year students
        self.assertEqual(0, result["2017"][Membership.MEMBER])

        # one fourth year student
        self.assertEqual(1, result["2016"][Membership.MEMBER])

        # no fifth year students
        self.assertEqual(0, result["2015"][Membership.MEMBER])

        # one >5 year student
        self.assertEqual(1, result["Older"][Membership.MEMBER])
Exemple #13
0
def generate_category_statistics():
    """
    Generate statistics about events, number of events per category
    :return: Dict with key, value resp. being category, event count.
    """
    year = datetime_to_lectureyear(timezone.now())

    data = {}
    for i in range(5):
        year_start = date(year=year - i, month=9, day=1)
        year_end = date(year=year - i + 1, month=9, day=1)
        data[str(year - i)] = {
            str(display): Event.objects.filter(
                category=key, start__gte=year_start, end__lte=year_end
            ).count()
            for key, display in Event.EVENT_CATEGORIES
        }

    return data
Exemple #14
0
class AddSummaryForm(ModelForm):
    """
    Custom form to add summaries, orders courses by name and formats the
    year as lecture years
    """

    course = ModelChoiceField(
        queryset=Course.objects.order_by("name"),
        empty_label=None,
    )

    this_year = datetime_to_lectureyear(timezone.now())
    years = reversed([(x, "{} - {}".format(x, x + 1))
                      for x in range(this_year - 20, this_year + 1)])

    year = TypedChoiceField(choices=years, coerce=int, empty_value=this_year)

    class Meta:
        model = Summary
        fields = ("name", "year", "language", "file", "course", "author")
Exemple #15
0
    def handle(self, *args, **options):
        """
        Handle the command being executed

        :param options: the passed-in options
        """
        opts = [
            "all",
            "board",
            "committee",
            "event",
            "partner",
            "pizza",
            "user",
            "vacancy",
            "document",
            "newsletter",
            "course",
            "registration",
            "payment",
            "photoalbum",
        ]

        if all([not options[opt] for opt in opts]):
            self.stdout.write("Use ./manage.py help createfixtures to find out"
                              " how to call this command")

        if options["all"]:
            self.stdout.write("all argument given, overwriting"
                              " all other inputs")
            options = {
                "user": 20,
                "board": 3,
                "committee": 3,
                "society": 3,
                "event": 20,
                "partner": 6,
                "vacancy": 4,
                "pizza": 5,
                "newsletter": 2,
                "document": 8,
                "course": 10,
                "registration": 20,
                "payment": 5,
                "photoalbum": 5,
            }

        # Users need to be generated before boards and committees
        if options["user"]:
            for __ in range(options["user"]):
                self.create_user()

        if options["board"]:
            lecture_year = datetime_to_lectureyear(date.today())
            for i in range(options["board"]):
                self.create_board(lecture_year - i)

        # Member groups need to be generated before events
        if options["committee"]:
            for __ in range(options["committee"]):
                self.create_member_group(Committee)

        if options["society"]:
            for __ in range(options["society"]):
                self.create_member_group(Society)

        if options["event"]:
            for __ in range(options["event"]):
                self.create_event()

        # Partners need to be generated before vacancies
        if options["partner"]:
            for __ in range(options["partner"]):
                self.create_partner()

            # Make one of the partners the main partner
            try:
                Partner.objects.get(is_main_partner=True)
            except Partner.DoesNotExist:
                main_partner = random.choice(Partner.objects.all())
                main_partner.is_active = True
                main_partner.is_main_partner = True
                main_partner.save()

        if options["vacancy"]:
            categories = VacancyCategory.objects.all()
            if not categories:
                self.stdout.write("No vacancy categories found. "
                                  "Creating 5 categories.")
                for __ in range(5):
                    self.create_vacancy_category()
                categories = VacancyCategory.objects.all()

            partners = Partner.objects.all()
            for __ in range(options["vacancy"]):
                self.create_vacancy(partners, categories)

        if options["pizza"]:
            for __ in range(options["pizza"]):
                self.create_pizza()

        if options["newsletter"]:
            for __ in range(options["newsletter"]):
                self.create_newsletter()

        if options["document"]:
            for __ in range(options["document"]):
                self.create_document()

        # Courses need to be created before exams and summaries
        if options["course"]:
            # Create course categories if needed
            if len(Category.objects.all()) < 5:
                for _ in range(5):
                    category = Category()
                    category.name_nl = _generate_title()
                    category.name_en = category.name_nl

                    category.save()

            for _ in range(options["course"]):
                self.create_course()

        # Registrations need to be created before payments
        if options["registration"]:
            for _ in range(options["registration"]):
                self.create_event_registration()

        if options["payment"]:
            for _ in range(options["payment"]):
                self.create_payment()

        if options["photoalbum"]:
            for _ in range(options["photoalbum"]):
                self.create_photo_album()
Exemple #16
0
 def year_choices():
     """Get the lecture years"""
     current = datetime_to_lectureyear(timezone.now())
     return [(year, "{}-{}".format(year, year + 1))
             for year in range(current + 1, 1989, -1)]
Exemple #17
0
 def current_year():
     """Get the current lecture year"""
     return datetime_to_lectureyear(timezone.now())
Exemple #18
0
    def test_gen_stats_active(self):
        """
        Testing if active and non-active objects are counted correctly
        """
        current_year = datetime_to_lectureyear(date.today())

        # Set start date to current year - 1:
        for m in Member.objects.all():
            m.profile.starting_year = current_year - 1
            m.profile.save()
        result = gen_stats_year()
        self.assertEqual(10, self.sum_members(result))
        self.assertEqual(10, self.sum_members(result, Membership.MEMBER))

        result = {k: v for k, v in gen_stats_member_type().items()}
        self.assertEqual(10, self.sum_member_types(result))

        # Change one membership to benefactor should decrease amount of members
        m = Membership.objects.all()[0]
        m.type = Membership.BENEFACTOR
        m.save()

        result = gen_stats_year()
        self.assertEqual(10, self.sum_members(result))
        self.assertEqual(9, self.sum_members(result, Membership.MEMBER))
        self.assertEqual(1, self.sum_members(result, Membership.BENEFACTOR))

        result = {k: v for k, v in gen_stats_member_type().items()}
        self.assertEqual(10, self.sum_member_types(result))
        self.assertEqual(9, result[Membership.MEMBERSHIP_TYPES[0][1]])
        self.assertEqual(1, result[Membership.MEMBERSHIP_TYPES[1][1]])

        # Same for honorary members
        m = Membership.objects.all()[1]
        m.type = Membership.HONORARY
        m.save()

        result = gen_stats_year()
        self.assertEqual(10, self.sum_members(result))
        self.assertEqual(8, self.sum_members(result, Membership.MEMBER))
        self.assertEqual(1, self.sum_members(result, Membership.BENEFACTOR))
        self.assertEqual(1, self.sum_members(result, Membership.HONORARY))

        result = {k: v for k, v in gen_stats_member_type().items()}
        self.assertEqual(10, self.sum_member_types(result))
        self.assertEqual(8, result[Membership.MEMBERSHIP_TYPES[0][1]])
        self.assertEqual(1, result[Membership.MEMBERSHIP_TYPES[1][1]])
        self.assertEqual(1, result[Membership.MEMBERSHIP_TYPES[2][1]])

        # Terminate one membership by setting end date to current_year -1,
        # should decrease total amount and total members
        m = Membership.objects.all()[2]
        m.until = timezone.now() - timedelta(days=365)
        m.save()
        result = gen_stats_year()
        self.assertEqual(9, self.sum_members(result))
        self.assertEqual(7, self.sum_members(result, Membership.MEMBER))
        self.assertEqual(1, self.sum_members(result, Membership.BENEFACTOR))
        self.assertEqual(1, self.sum_members(result, Membership.HONORARY))

        result = {k: v for k, v in gen_stats_member_type().items()}
        self.assertEqual(9, self.sum_member_types(result))
        self.assertEqual(7, result[Membership.MEMBERSHIP_TYPES[0][1]])
        self.assertEqual(1, result[Membership.MEMBERSHIP_TYPES[1][1]])
        self.assertEqual(1, result[Membership.MEMBERSHIP_TYPES[2][1]])
Exemple #19
0
def get_automatic_lists():
    """Return list of mailing lists that should be generated automatically."""
    current_committee_chairs = (
        MemberGroupMembership.active_objects.filter(group__board=None)
        .filter(group__society=None)
        .filter(chair=True)
        .select_related("member")
    )
    committee_chairs = _get_members_email_addresses(
        [x.member for x in current_committee_chairs]
    ) + ["*****@*****.**"]

    current_society_chairs = (
        MemberGroupMembership.active_objects.filter(group__board=None)
        .filter(group__committee=None)
        .filter(chair=True)
        .select_related("member")
    )
    society_chair_emails = _get_members_email_addresses(
        [x.member for x in current_society_chairs]
    ) + ["*****@*****.**"]

    active_committee_memberships = (
        MemberGroupMembership.active_objects.filter(group__board=None)
        .filter(group__society=None)
        .select_related("member")
    )

    active_members = _get_members_email_addresses(
        [x.member for x in active_committee_memberships]
    )

    lectureyear = datetime_to_lectureyear(timezone.now())
    # Change to next lecture year after December
    if 0 < timezone.now().month < 9:
        lectureyear += 1
    active_mentorships = Mentorship.objects.filter(year=lectureyear).prefetch_related(
        "member"
    )
    mentors = _get_members_email_addresses([x.member for x in active_mentorships])

    lists = [
        {
            "name": "members",
            "aliases": ["leden"],
            "description": "Automatic moderated mailinglist that can be used "
            "to send mail to all members",
            "addresses": _get_members_email_addresses(
                Member.all_with_membership("member")
            ),
            "moderated": True,
        },
        {
            "name": "benefactors",
            "aliases": ["begunstigers"],
            "description": "Automatic moderated mailinglist that can be used "
            "to send mail to all benefactors",
            "addresses": _get_members_email_addresses(
                Member.all_with_membership(Membership.BENEFACTOR)
            ),
            "moderated": True,
        },
        {
            "name": "honorary",
            "aliases": ["ereleden"],
            "description": "Automatic moderated mailinglist that can be used "
            "to send mail to all honorary members",
            "addresses": _get_members_email_addresses(
                Member.all_with_membership("honorary")
            ),
            "moderated": True,
        },
        {
            "name": "mentors",
            "description": "Automatic moderated mailinglist that can be used "
            "to send mail to all orientation mentors. These "
            "members should have a mentorship with the current "
            "calendar year.",
            "addresses": mentors,
            "moderated": True,
        },
        {
            "name": "activemembers",
            "description": "Automatic moderated mailinglist that can be used "
            "to send mail to all active members. These are all "
            "users that are currently a member of a committee.",
            "addresses": active_members,
            "moderated": True,
        },
        {
            "name": "committeechairs",
            "aliases": ["commissievoorzitters"],
            "description": "Automatic mailinglist that can be used to send "
            "mail to all committee chairs",
            "addresses": committee_chairs,
            "moderated": False,
        },
        {
            "name": "societychairs",
            "aliases": ["gezelschapvoorzitters"],
            "description": "Automatic mailinglist that can be used to send "
            "mail to all society chairs",
            "addresses": society_chair_emails,
            "moderated": False,
        },
        {
            "name": "optin",
            "description": "Automatic mailinglist that can be used to send "
            "mail to all members that have opted-in to receive "
            "these (mostly recruitment) emails.",
            "addresses": _get_members_email_addresses(
                Member.current_members.filter(profile__receive_optin=True)
            ),
            "moderated": True,
        },
        {
            "name": "committees",
            "description": "Automatic moderated mailinglist that is a "
            "collection of all committee lists",
            "addresses": [
                f"{c.contact_mailinglist.name}@{settings.GSUITE_DOMAIN}"
                for c in Committee.objects.exclude(
                    contact_mailinglist=None
                ).select_related("contact_mailinglist")
            ],
            "moderated": True,
        },
        {
            "name": "societies",
            "description": "Automatic moderated mailinglist that is a "
            "collection of all society lists",
            "addresses": [
                f"{c.contact_mailinglist.name}@{settings.GSUITE_DOMAIN}"
                for c in Society.objects.exclude(
                    contact_mailinglist=None
                ).select_related("contact_mailinglist")
            ],
            "moderated": True,
        },
    ]

    for language in settings.LANGUAGES:
        lists.append(
            {
                "name": f"newsletter-{language[0]}",
                "description": "Automatic moderated mailinglist that can be used "
                f"to send newsletters in {language[1]}",
                "addresses": _get_members_email_addresses(
                    Member.current_members.all().filter(
                        profile__receive_newsletter=True, profile__language=language[0]
                    )
                ),
                "moderated": True,
            }
        )

    all_previous_board_members = []

    for board in Board.objects.filter(since__year__lte=lectureyear).order_by(
        "since__year"
    ):
        board_members = [
            board.member
            for board in MemberGroupMembership.objects.filter(
                group=board
            ).prefetch_related("member")
        ]
        all_previous_board_members += board_members
        years = str(board.since.year)[-2:] + str(board.until.year)[-2:]
        lists.append(
            {
                "name": f"board{years}",
                "aliases": [f"bestuur{years}"],
                "description": "Automatic mailinglist to send email to all board "
                f"members of {board.since.year}-{board.until.year}",
                "addresses": _get_members_email_addresses(board_members),
                "moderated": False,
            }
        )

    lists.append(
        {
            "name": "oldboards",
            "aliases": ["oudbesturen"],
            "description": "Automatic mailinglist to send "
            "email to all previous board members",
            "moderated": True,
            "addresses": _get_members_email_addresses(all_previous_board_members),
        }
    )

    return lists
Exemple #20
0
 def year(self):
     return datetime_to_lectureyear(self.exam_date)
Exemple #21
0
    def test_create_membership_from_entry(self):
        self.e1.username = "******"
        self.e1.save()
        self.e2.username = "******"
        self.e2.save()

        with freeze_time("2017-01-12"):
            lecture_year = datetime_to_lectureyear(timezone.now())
            self.assertEqual(lecture_year, 2016)

            m1 = services._create_member_from_registration(self.e1)
            m2 = services._create_member_from_registration(self.e2)

            # Registration to new 'year' membership starting today
            membership1 = services._create_membership_from_entry(self.e1, m1)

            self.assertEqual(membership1.since, timezone.now().date())
            self.assertEqual(
                membership1.until, timezone.datetime(year=2017, month=9, day=1).date()
            )
            self.assertEqual(membership1.user, m1)
            self.assertEqual(membership1.type, self.e1.membership_type)

            # Registration to new 'study' membership starting today
            membership2 = services._create_membership_from_entry(self.e2, m2)

            self.assertEqual(membership2.since, timezone.now().date())
            self.assertEqual(membership2.until, None)
            self.assertEqual(membership2.user, m2)
            self.assertEqual(membership2.type, self.e2.membership_type)

            membership2.delete()

        with freeze_time("2017-08-12"):
            # Check if since is new lecture year in august
            membership2 = services._create_membership_from_entry(self.e2, m2)

            self.assertEqual(
                membership2.since, timezone.datetime(year=2017, month=9, day=1).date()
            )
            self.assertEqual(membership2.until, None)
            self.assertEqual(membership2.user, m2)
            self.assertEqual(membership2.type, self.e2.membership_type)

        with freeze_time("2017-01-12"):
            # Renewal to new 'study' membership starting today
            self.e3.length = Entry.MEMBERSHIP_STUDY
            membership3 = services._create_membership_from_entry(self.e3)

            self.assertEqual(membership3.since, timezone.now().date())
            self.assertEqual(membership3.until, None)
            self.assertEqual(membership3.user, self.e3.member)
            self.assertEqual(membership3.type, self.e3.membership_type)

            membership3.delete()

            # Renewal to new 'year' membership starting today
            self.e3.length = Entry.MEMBERSHIP_YEAR
            membership3 = services._create_membership_from_entry(self.e3)

            self.assertEqual(membership3.since, timezone.now().date())
            self.assertEqual(
                membership3.until, timezone.datetime(month=9, day=1, year=2017).date()
            )
            self.assertEqual(membership3.user, self.e3.member)
            self.assertEqual(membership3.type, self.e3.membership_type)

            membership3.delete()

            self.e3.length = Entry.MEMBERSHIP_YEAR
            existing_membership = Membership.objects.create(
                type=Membership.MEMBER,
                since=timezone.datetime(year=2016, month=9, day=1).date(),
                until=timezone.datetime(year=2017, month=1, day=31).date(),
                user=self.e3.member,
            )

            # Renewal to new 'year' membership starting 1 day after
            # end of the previous membership
            self.e3.length = Entry.MEMBERSHIP_YEAR
            membership3 = services._create_membership_from_entry(self.e3)
            self.assertEqual(membership3.since, existing_membership.until)
            self.assertEqual(
                membership3.until, timezone.datetime(year=2017, month=9, day=1).date()
            )
            self.assertEqual(membership3.user, self.e3.member)
            self.assertEqual(membership3.type, self.e3.membership_type)

            membership3.delete()
            self.e3.length = Entry.MEMBERSHIP_STUDY

            # Renewal (aka upgrade) existing membership to 'study' membership
            # It doesn't work when the entry was made after the renewal
            # was due, so this is a new membership
            membership3 = services._create_membership_from_entry(self.e3)
            self.assertEqual(membership3.since, timezone.now().date())
            self.assertEqual(membership3.until, None)
            self.assertEqual(membership3.user, self.e3.member)
            self.assertEqual(membership3.type, self.e3.membership_type)

            membership3.delete()

            # But it does work when the entry was created before the renewal
            # was actually due. This modifies the existing membership
            self.e3.created_at = timezone.make_aware(timezone.datetime(2017, 1, 30))
            self.e3.save()
            membership3 = services._create_membership_from_entry(self.e3)
            self.assertEqual(membership3.since, existing_membership.since)
            self.assertEqual(membership3.until, None)
            self.assertEqual(membership3.user, self.e3.member)
            self.assertEqual(membership3.type, self.e3.membership_type)

            # Fail 'study' renewal of existing 'study' membership
            existing_membership.until = None
            existing_membership.save()
            with self.assertRaises(ValueError):
                services._create_membership_from_entry(self.e3)

            # Fail 'year' renewal of existing 'study' membership
            self.e3.length = Entry.MEMBERSHIP_YEAR
            existing_membership.until = None
            existing_membership.save()
            with self.assertRaises(ValueError):
                services._create_membership_from_entry(self.e3)
Exemple #22
0
 def dispatch(self, request, *args, **kwargs) -> HttpResponse:
     lecture_year = datetime_to_lectureyear(datetime.date.today())
     self.current_board = Board.objects.filter(since__year=lecture_year,
                                               until__year=lecture_year +
                                               1).first()
     return super().dispatch(request, *args, **kwargs)