예제 #1
0
    def test_cache_clears_at_batch_exit(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

        cache_2 = BatchController.get_cache(self.USER_1)

        self.assertIsNot(cache_1, cache_2)
예제 #2
0
    def test_cache_clears_at_batch_exit(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

        cache_2 = BatchController.get_cache(self.USER_1)

        self.assertIsNot(cache_1, cache_2)
예제 #3
0
    def test_cart_discounts_only_calculated_at_end_of_batches(self):
        def count_discounts(cart):
            return cart.cart.discountitem_set.count()

        cart = TestingCartController.for_user(self.USER_1)
        self.make_discount_ceiling("FLOOZLE")
        count_0 = count_discounts(cart)

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)

            with BatchController.batch(self.USER_1):
                # Memoise the cart
                same_cart_2 = TestingCartController.for_user(self.USER_1)

                same_cart_2.add_to_cart(self.PROD_1, 1)
                count_1 = count_discounts(same_cart_2)

            count_2 = count_discounts(same_cart)

        count_3 = count_discounts(cart)

        self.assertEqual(0, count_0)
        self.assertEqual(0, count_1)
        self.assertEqual(0, count_2)
        self.assertEqual(1, count_3)
예제 #4
0
    def test_cart_discounts_only_calculated_at_end_of_batches(self):
        def count_discounts(cart):
            return cart.cart.discountitem_set.count()

        cart = TestingCartController.for_user(self.USER_1)
        self.make_discount_ceiling("FLOOZLE")
        count_0 = count_discounts(cart)

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)

            with BatchController.batch(self.USER_1):
                # Memoise the cart
                same_cart_2 = TestingCartController.for_user(self.USER_1)

                same_cart_2.add_to_cart(self.PROD_1, 1)
                count_1 = count_discounts(same_cart_2)

            count_2 = count_discounts(same_cart)

        count_3 = count_discounts(cart)

        self.assertEqual(0, count_0)
        self.assertEqual(0, count_1)
        self.assertEqual(0, count_2)
        self.assertEqual(1, count_3)
예제 #5
0
    def test_caches_are_independent_for_different_users(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

            with BatchController.batch(self.USER_2):
                cache_2 = BatchController.get_cache(self.USER_2)

        self.assertIsNot(cache_1, cache_2)
예제 #6
0
    def test_memoisation_clears_outside_batches(self):
        with BatchController.batch(self.USER_1):
            output_1 = self._memoiseme(self.USER_1)

        with BatchController.batch(self.USER_1):
            output_2 = self._memoiseme(self.USER_1)

        self.assertIsNot(output_1, output_2)
예제 #7
0
    def test_caches_are_independent_for_different_users(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

            with BatchController.batch(self.USER_2):
                cache_2 = BatchController.get_cache(self.USER_2)

        self.assertIsNot(cache_1, cache_2)
예제 #8
0
    def test_memoisation_happens_in_batch_context(self):
        with BatchController.batch(self.USER_1):
            output_1 = self._memoiseme(self.USER_1)

            with BatchController.batch(self.USER_1):
                output_2 = self._memoiseme(self.USER_1)

        self.assertIs(output_1, output_2)
예제 #9
0
    def test_memoisation_happens_in_batch_context(self):
        with BatchController.batch(self.USER_1):
            output_1 = self._memoiseme(self.USER_1)

            with BatchController.batch(self.USER_1):
                output_2 = self._memoiseme(self.USER_1)

        self.assertIs(output_1, output_2)
예제 #10
0
    def test_memoisation_clears_outside_batches(self):
        with BatchController.batch(self.USER_1):
            output_1 = self._memoiseme(self.USER_1)

        with BatchController.batch(self.USER_1):
            output_2 = self._memoiseme(self.USER_1)

        self.assertIsNot(output_1, output_2)
예제 #11
0
    def test_memoisation_is_user_independent(self):
        with BatchController.batch(self.USER_1):
            output_1 = self._memoiseme(self.USER_1)
            with BatchController.batch(self.USER_2):
                output_2 = self._memoiseme(self.USER_2)
                output_3 = self._memoiseme(self.USER_1)

        self.assertIsNot(output_1, output_2)
        self.assertIs(output_1, output_3)
예제 #12
0
    def test_memoisation_is_user_independent(self):
        with BatchController.batch(self.USER_1):
            output_1 = self._memoiseme(self.USER_1)
            with BatchController.batch(self.USER_2):
                output_2 = self._memoiseme(self.USER_2)
                output_3 = self._memoiseme(self.USER_1)

        self.assertIsNot(output_1, output_2)
        self.assertIs(output_1, output_3)
예제 #13
0
    def test_caches_identical_within_nestings(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

            with BatchController.batch(self.USER_2):
                cache_2 = BatchController.get_cache(self.USER_1)

            cache_3 = BatchController.get_cache(self.USER_1)

        self.assertIs(cache_1, cache_2)
        self.assertIs(cache_2, cache_3)
예제 #14
0
    def test_caches_identical_within_nestings(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

            with BatchController.batch(self.USER_2):
                cache_2 = BatchController.get_cache(self.USER_1)

            cache_3 = BatchController.get_cache(self.USER_1)

        self.assertIs(cache_1, cache_2)
        self.assertIs(cache_2, cache_3)
예제 #15
0
    def test_cart_revision_does_not_increment_if_not_modified(self):
        cart = TestingCartController.for_user(self.USER_1)
        rev_0 = cart.cart.revision

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)
            # Do nothing on exit
        
        rev_1 = self.reget(cart.cart).revision
        self.assertEqual(rev_0, rev_1)
예제 #16
0
    def test_cart_revision_does_not_increment_if_not_modified(self):
        cart = TestingCartController.for_user(self.USER_1)
        rev_0 = cart.cart.revision

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            TestingCartController.for_user(self.USER_1)
            # Do nothing on exit

        rev_1 = self.reget(cart.cart).revision
        self.assertEqual(rev_0, rev_1)
예제 #17
0
    def test_batch_end_functionality_is_called(self):
        class Ender(object):
            end_count = 0
            def end_batch(self):
                self.end_count += 1

        @BatchController.memoise
        def get_ender(user):
            return Ender()

        # end_batch should get called once on exiting the batch
        with BatchController.batch(self.USER_1):
            ender = get_ender(self.USER_1)
        self.assertEquals(1, ender.end_count)

        # end_batch should get called once on exiting the batch
        # no matter how deep the object gets cached
        with BatchController.batch(self.USER_1):
            with BatchController.batch(self.USER_1):
                ender = get_ender(self.USER_1)
        self.assertEquals(1, ender.end_count)
예제 #18
0
    def test_cart_revision_only_increments_at_end_of_batches(self):
        cart = TestingCartController.for_user(self.USER_1)
        rev_0 = cart.cart.revision

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)
            same_cart.add_to_cart(self.PROD_1, 1)
            rev_1 = self.reget(same_cart.cart).revision

        rev_2 = self.reget(cart.cart).revision

        self.assertEqual(rev_0, rev_1)
        self.assertNotEqual(rev_0, rev_2)
예제 #19
0
    def test_cart_revision_only_increments_at_end_of_batches(self):
        cart = TestingCartController.for_user(self.USER_1)
        rev_0 = cart.cart.revision

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)
            same_cart.add_to_cart(self.PROD_1, 1)
            rev_1 = self.reget(same_cart.cart).revision

        rev_2 = self.reget(cart.cart).revision

        self.assertEqual(rev_0, rev_1)
        self.assertNotEqual(rev_0, rev_2)
예제 #20
0
    def test_new_caches_for_new_batches(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

        with BatchController.batch(self.USER_1):
            cache_2 = BatchController.get_cache(self.USER_1)

            with BatchController.batch(self.USER_1):
                cache_3 = BatchController.get_cache(self.USER_1)

        self.assertIs(cache_2, cache_3)
        self.assertIsNot(cache_1, cache_2)
예제 #21
0
    def test_new_caches_for_new_batches(self):
        with BatchController.batch(self.USER_1):
            cache_1 = BatchController.get_cache(self.USER_1)

        with BatchController.batch(self.USER_1):
            cache_2 = BatchController.get_cache(self.USER_1)

            with BatchController.batch(self.USER_1):
                cache_3 = BatchController.get_cache(self.USER_1)

        self.assertIs(cache_2, cache_3)
        self.assertIsNot(cache_1, cache_2)
예제 #22
0
def guided_registration(request):
    ''' Goes through the registration process in order, making sure user sees
    all valid categories.

    The user must be logged in to see this view.

    Returns:
        render: Renders ``registrasion/guided_registration.html``,
            with the following data::

                {
                    "current_step": int(),  # The current step in the
                                            # registration
                    "sections": sections,   # A list of
                                            # GuidedRegistrationSections
                    "title": str(),         # The title of the page
                    "total_steps": int(),   # The total number of steps
                }

    '''

    SESSION_KEY = "guided_registration_categories"
    ASK_FOR_PROFILE = 777  # Magic number. Meh.

    next_step = redirect("guided_registration")

    sections = []

    attendee = people.Attendee.get_instance(request.user)

    if attendee.completed_registration:
        return redirect(review)

    # Step 1: Fill in a badge and collect a voucher code
    try:
        profile = attendee.attendeeprofilebase
    except ObjectDoesNotExist:
        profile = None

    # Figure out if we need to show the profile form and the voucher form
    show_profile_and_voucher = False
    if SESSION_KEY not in request.session:
        if not profile:
            show_profile_and_voucher = True
    else:
        if request.session[SESSION_KEY] == ASK_FOR_PROFILE:
            show_profile_and_voucher = True

    if show_profile_and_voucher:
        # Keep asking for the profile until everything passes.
        request.session[SESSION_KEY] = ASK_FOR_PROFILE

        voucher_form, voucher_handled = _handle_voucher(request, "voucher")
        profile_form, profile_handled = _handle_profile(request, "profile")

        voucher_section = GuidedRegistrationSection(
            title="Voucher Code",
            form=voucher_form,
        )

        profile_section = GuidedRegistrationSection(
            title="Profile and Personal Information",
            form=profile_form,
        )

        title = "Attendee information"
        current_step = 1
        sections.append(voucher_section)
        sections.append(profile_section)
    else:
        # We're selling products

        starting = attendee.guided_categories_complete.count() == 0

        # Get the next category
        cats = inventory.Category.objects
        if SESSION_KEY in request.session:
            _cats = request.session[SESSION_KEY]
            cats = cats.filter(id__in=_cats)
        else:
            cats = cats.exclude(
                id__in=attendee.guided_categories_complete.all(),
            )

        cats = cats.order_by("order")

        request.session[SESSION_KEY] = []

        if starting:
            # Only display the first Category
            title = "Select ticket type"
            current_step = 2
            cats = [cats[0]]
        else:
            # Set title appropriately for remaining categories
            current_step = 3
            title = "Additional items"

        all_products = inventory.Product.objects.filter(
            category__in=cats,
        ).select_related("category")

        with BatchController.batch(request.user):
            available_products = set(ProductController.available_products(
                request.user,
                products=all_products,
            ))

            if len(available_products) == 0:
                # We've filled in every category
                attendee.completed_registration = True
                attendee.save()
                return next_step

            for category in cats:
                products = [
                    i for i in available_products
                    if i.category == category
                ]

                prefix = "category_" + str(category.id)
                p = _handle_products(request, category, products, prefix)
                products_form, discounts, products_handled = p

                section = GuidedRegistrationSection(
                    title=category.name,
                    description=category.description,
                    discounts=discounts,
                    form=products_form,
                )

                if products:
                    # This product category has items to show.
                    sections.append(section)
                    # Add this to the list of things to show if the form
                    # errors.
                    request.session[SESSION_KEY].append(category.id)

                    if request.method == "POST" and not products_form.errors:
                        # This is only saved if we pass each form with no
                        # errors, and if the form actually has products.
                        attendee.guided_categories_complete.add(category)

    if sections and request.method == "POST":
        for section in sections:
            if section.form.errors:
                break
        else:
            attendee.save()
            if SESSION_KEY in request.session:
                del request.session[SESSION_KEY]
            # We've successfully processed everything
            return next_step

    data = {
        "current_step": current_step,
        "sections": sections,
        "title": title,
        "total_steps": 3,
    }
    return render(request, "registrasion/guided_registration.html", data)
예제 #23
0
    def test_no_caches_outside_of_batches(self):
        cache_1 = BatchController.get_cache(self.USER_1)
        cache_2 = BatchController.get_cache(self.USER_2)

        # Identity testing is important here
        self.assertIsNot(cache_1, cache_2)
예제 #24
0
def product_category(request, category_id):
    ''' Form for selecting products from an individual product category.

    Arguments:
        category_id (castable to int): The id of the category to display.

    Returns:
        redirect or render:
            If the form has been sucessfully submitted, redirect to
            ``dashboard``. Otherwise, render
            ``registrasion/product_category.html`` with data::

                {
                    "category": category,         # An inventory.Category for
                                                  # category_id
                    "discounts": discounts,       # A list of
                                                  # DiscountAndQuantity
                    "form": products_form,        # A form for selecting
                                                  # products
                    "voucher_form": voucher_form, # A form for entering a
                                                  # voucher code
                }

    '''

    PRODUCTS_FORM_PREFIX = "products"
    VOUCHERS_FORM_PREFIX = "vouchers"

    # Handle the voucher form *before* listing products.
    # Products can change as vouchers are entered.
    v = _handle_voucher(request, VOUCHERS_FORM_PREFIX)
    voucher_form, voucher_handled = v

    category_id = int(category_id)  # Routing is [0-9]+
    category = inventory.Category.objects.get(pk=category_id)

    with BatchController.batch(request.user):
        products = ProductController.available_products(
            request.user,
            category=category,
        )

        if not products:
            messages.warning(
                request,
                (
                    "There are no products available from category: " +
                    category.name
                ),
            )
            return redirect("dashboard")

        p = _handle_products(request, category, products, PRODUCTS_FORM_PREFIX)
        products_form, discounts, products_handled = p

    if request.POST and not voucher_handled and not products_form.errors:
        # Only return to the dashboard if we didn't add a voucher code
        # and if there's no errors in the products form
        if products_form.has_changed():
            messages.success(
                request,
                "Your reservations have been updated.",
            )
        return redirect(review)

    data = {
        "category": category,
        "discounts": discounts,
        "form": products_form,
        "voucher_form": voucher_form,
    }

    return render(request, "registrasion/product_category.html", data)
예제 #25
0
def product_category(request, category_id):
    ''' Form for selecting products from an individual product category.

    Arguments:
        category_id (castable to int): The id of the category to display.

    Returns:
        redirect or render:
            If the form has been sucessfully submitted, redirect to
            ``dashboard``. Otherwise, render
            ``registrasion/product_category.html`` with data::

                {
                    "category": category,         # An inventory.Category for
                                                  # category_id
                    "discounts": discounts,       # A list of
                                                  # DiscountAndQuantity
                    "form": products_form,        # A form for selecting
                                                  # products
                    "voucher_form": voucher_form, # A form for entering a
                                                  # voucher code
                }

    '''

    PRODUCTS_FORM_PREFIX = "products"
    VOUCHERS_FORM_PREFIX = "vouchers"

    # Handle the voucher form *before* listing products.
    # Products can change as vouchers are entered.
    v = _handle_voucher(request, VOUCHERS_FORM_PREFIX)
    voucher_form, voucher_handled = v

    category_id = int(category_id)  # Routing is [0-9]+
    category = inventory.Category.objects.get(pk=category_id)

    with BatchController.batch(request.user):
        products = ProductController.available_products(
            request.user,
            category=category,
        )

        if not products:
            messages.warning(
                request,
                "There are no products available from category: " + category.name,
            )
            return redirect("dashboard")

        p = _handle_products(request, category, products, PRODUCTS_FORM_PREFIX)
        products_form, discounts, products_handled = p

    if request.POST and not voucher_handled and not products_form.errors:
        # Only return to the dashboard if we didn't add a voucher code
        # and if there's no errors in the products form
        messages.success(
            request,
            "Your reservations have been updated.",
        )
        return redirect("dashboard")

    data = {
        "category": category,
        "discounts": discounts,
        "form": products_form,
        "voucher_form": voucher_form,
    }

    return render(request, "registrasion/product_category.html", data)
예제 #26
0
def guided_registration(request):
    ''' Goes through the registration process in order, making sure user sees
    all valid categories.

    The user must be logged in to see this view.

    Returns:
        render: Renders ``registrasion/guided_registration.html``,
            with the following data::

                {
                    "current_step": int(),  # The current step in the
                                            # registration
                    "sections": sections,   # A list of
                                            # GuidedRegistrationSections
                    "title": str(),         # The title of the page
                    "total_steps": int(),   # The total number of steps
                }

    '''

    SESSION_KEY = "guided_registration_categories"
    ASK_FOR_PROFILE = 777  # Magic number. Meh.

    next_step = redirect("guided_registration")

    sections = []

    attendee = people.Attendee.get_instance(request.user)

    if attendee.completed_registration:
        return render(
            request,
            "registrasion/guided_registration_complete.html",
            {},
        )

    # Step 1: Fill in a badge and collect a voucher code
    try:
        profile = attendee.attendeeprofilebase
    except ObjectDoesNotExist:
        profile = None

    # Figure out if we need to show the profile form and the voucher form
    show_profile_and_voucher = False
    if SESSION_KEY not in request.session:
        if not profile:
            show_profile_and_voucher = True
    else:
        if request.session[SESSION_KEY] == ASK_FOR_PROFILE:
            show_profile_and_voucher = True

    if show_profile_and_voucher:
        # Keep asking for the profile until everything passes.
        request.session[SESSION_KEY] = ASK_FOR_PROFILE

        voucher_form, voucher_handled = _handle_voucher(request, "voucher")
        profile_form, profile_handled = _handle_profile(request, "profile")

        voucher_section = GuidedRegistrationSection(
            title="Voucher Code",
            form=voucher_form,
        )

        profile_section = GuidedRegistrationSection(
            title="Profile and Personal Information",
            form=profile_form,
        )

        title = "Attendee information"
        current_step = 1
        sections.append(voucher_section)
        sections.append(profile_section)
    else:
        # We're selling products

        starting = attendee.guided_categories_complete.count() == 0

        # Get the next category
        cats = inventory.Category.objects
        if SESSION_KEY in request.session:
            _cats = request.session[SESSION_KEY]
            cats = cats.filter(id__in=_cats)
        else:
            cats = cats.exclude(
                id__in=attendee.guided_categories_complete.all(),
            )

        cats = cats.order_by("order")

        request.session[SESSION_KEY] = []

        if starting:
            # Only display the first Category
            title = "Select ticket type"
            current_step = 2
            cats = [cats[0]]
        else:
            # Set title appropriately for remaining categories
            current_step = 3
            title = "Additional items"

        all_products = inventory.Product.objects.filter(
            category__in=cats,
        ).select_related("category")

        with BatchController.batch(request.user):
            available_products = set(ProductController.available_products(
                request.user,
                products=all_products,
            ))

            if len(available_products) == 0:
                # We've filled in every category
                attendee.completed_registration = True
                attendee.save()
                return next_step

            for category in cats:
                products = [
                    i for i in available_products
                    if i.category == category
                ]

                prefix = "category_" + str(category.id)
                p = _handle_products(request, category, products, prefix)
                products_form, discounts, products_handled = p

                section = GuidedRegistrationSection(
                    title=category.name,
                    description=category.description,
                    discounts=discounts,
                    form=products_form,
                )

                if products:
                    # This product category has items to show.
                    sections.append(section)
                    # Add this to the list of things to show if the form
                    # errors.
                    request.session[SESSION_KEY].append(category.id)

                    if request.method == "POST" and not products_form.errors:
                        # This is only saved if we pass each form with no
                        # errors, and if the form actually has products.
                        attendee.guided_categories_complete.add(category)

    if sections and request.method == "POST":
        for section in sections:
            if section.form.errors:
                break
        else:
            attendee.save()
            if SESSION_KEY in request.session:
                del request.session[SESSION_KEY]
            # We've successfully processed everything
            return next_step

    data = {
        "current_step": current_step,
        "sections": sections,
        "title": title,
        "total_steps": 3,
    }
    return render(request, "registrasion/guided_registration.html", data)
예제 #27
0
 def test_cart_controller_for_user_is_memoised(self):
     # - that for_user is memoised
     with BatchController.batch(self.USER_1):
         cart = TestingCartController.for_user(self.USER_1)
         cart_2 = TestingCartController.for_user(self.USER_1)
     self.assertIs(cart, cart_2)
예제 #28
0
 def test_cart_controller_for_user_is_memoised(self):
     # - that for_user is memoised
     with BatchController.batch(self.USER_1):
         cart = TestingCartController.for_user(self.USER_1)
         cart_2 = TestingCartController.for_user(self.USER_1)
     self.assertIs(cart, cart_2)
예제 #29
0
    def test_no_caches_outside_of_batches(self):
        cache_1 = BatchController.get_cache(self.USER_1)
        cache_2 = BatchController.get_cache(self.USER_2)

        # Identity testing is important here
        self.assertIsNot(cache_1, cache_2)