예제 #1
0
    def test_proposal_cancelled_disables_condition(self):
        self._create_proposals()
        self._create_flag_for_primary_speaker()

        # USER_1 cannot see PROD_1 until proposal is promoted.
        available = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )
        self.assertNotIn(self.PROD_1, available)

        # promote proposal_1 so that USER_1 becomes a speaker
        promote_proposal(self.PROPOSAL_1)
        presentation = schedule_models.Presentation.objects.get(
            proposal_base=self.PROPOSAL_1
        )
        presentation.cancelled = True
        presentation.save()

        # USER_1 can *NOT* see PROD_1 because proposal_1 has been cancelled
        available_after_cancelled = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )
        self.assertNotIn(self.PROD_1, available_after_cancelled)
예제 #2
0
    def test_additional_speaker_enables_item(self):
        self._create_proposals()
        self._create_flag_for_additional_speaker()

        # USER_2 cannot see PROD_1 until proposal is promoted.
        available = ProductController.available_products(
            self.USER_2,
            products=[self.PROD_1],
        )
        self.assertNotIn(self.PROD_1, available)

        # promote proposal_1 so that USER_2 becomes an additional speaker
        promote_proposal(self.PROPOSAL_1)

        # USER_2 can see PROD_1
        available_2 = ProductController.available_products(
            self.USER_2,
            products=[self.PROD_1],
        )
        self.assertIn(self.PROD_1, available_2)
        # USER_1 can *NOT* see PROD_1 because they're a presenter
        available_1 = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )
        self.assertNotIn(self.PROD_1, available_1)
예제 #3
0
    def test_available_products_works_with_no_conditions_set(self):
        prods = ProductController.available_products(
            self.USER_1,
            category=self.CAT_1,
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)

        prods = ProductController.available_products(
            self.USER_1,
            category=self.CAT_2,
        )

        self.assertTrue(self.PROD_3 in prods)
        self.assertTrue(self.PROD_4 in prods)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2, self.PROD_3, self.PROD_4],
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)
        self.assertTrue(self.PROD_3 in prods)
        self.assertTrue(self.PROD_4 in prods)
예제 #4
0
    def test_available_products_works_with_no_conditions_set(self):
        prods = ProductController.available_products(
            self.USER_1,
            category=self.CAT_1,
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)

        prods = ProductController.available_products(
            self.USER_1,
            category=self.CAT_2,
        )

        self.assertTrue(self.PROD_3 in prods)
        self.assertTrue(self.PROD_4 in prods)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2, self.PROD_3, self.PROD_4],
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)
        self.assertTrue(self.PROD_3 in prods)
        self.assertTrue(self.PROD_4 in prods)
예제 #5
0
    def test_available_products_on_products_works_when_condition_not_met(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2],
        )

        self.assertTrue(self.PROD_1 not in prods)
        self.assertTrue(self.PROD_2 in prods)
예제 #6
0
    def test_available_products_on_products_works_when_condition_not_met(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2],
        )

        self.assertTrue(self.PROD_1 not in prods)
        self.assertTrue(self.PROD_2 in prods)
예제 #7
0
    def test_speaker_on_different_proposal_kind_does_not_enable_item(self):
        self._create_proposals()
        self._create_flag_for_primary_speaker()

        # USER_1 cannot see PROD_1 until proposal is promoted.
        available = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )
        self.assertNotIn(self.PROD_1, available)

        # promote proposal_2 so that USER_1 becomes a speaker, but of
        # KIND_2, which is not covered by this condition
        promote_proposal(self.PROPOSAL_2)

        # USER_1 cannot see PROD_1
        available_1 = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )
        self.assertNotIn(self.PROD_1, available_1)
예제 #8
0
    def test_available_products_on_products_works_when_condition_is_met(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        cart_1 = TestingCartController.for_user(self.USER_1)
        cart_1.add_to_cart(self.PROD_2, 1)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2],
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)
예제 #9
0
    def test_available_products_on_products_works_when_condition_is_met(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        cart_1 = TestingCartController.for_user(self.USER_1)
        cart_1.add_to_cart(self.PROD_2, 1)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2],
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)
예제 #10
0
    def test_flag_ceiling_aggregates_products(self):
        # Create two carts, add 1xprod_1 to each. Ceiling should disappear
        # after second.
        self.make_ceiling("Multi-product limit ceiling", limit=2)

        for i in xrange(2):
            cart = TestingCartController.for_user(self.USER_1)
            cart.add_to_cart(self.PROD_1, 1)
            cart.next_cart()

        products = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )

        self.assertEqual(0, len(products))
예제 #11
0
    def test_flag_ceiling_aggregates_products(self):
        # Create two carts, add 1xprod_1 to each. Ceiling should disappear
        # after second.
        self.make_ceiling("Multi-product limit ceiling", limit=2)

        for i in xrange(2):
            cart = TestingCartController.for_user(self.USER_1)
            cart.add_to_cart(self.PROD_1, 1)
            cart.next_cart()

        products = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )

        self.assertEqual(0, len(products))
예제 #12
0
def product_category(request, category_id):
    ''' Registration selections form for a specific category of items.
    '''

    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)

    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)
예제 #13
0
def product_category(request, category_id):
    ''' Registration selections form for a specific category of items.
    '''

    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)

    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)
예제 #14
0
    def available_categories(cls, user, products=AllProducts):
        ''' Returns the categories available to the user. Specify `products` if
        you want to restrict to just the categories that hold the specified
        products, otherwise it'll do all. '''

        # STOPGAP -- this needs to be elsewhere tbqh
        from registrasion.controllers.product import ProductController

        if products is AllProducts:
            products = inventory.Product.objects.all().select_related(
                "category", )

        available = ProductController.available_products(
            user,
            products=products,
        )

        return set(i.category for i in available)
예제 #15
0
def staff_products_form_factory(user):
    ''' Creates a StaffProductsForm that restricts the available products to
    those that are available to a user. '''

    products = inventory.Product.objects.all()
    products = ProductController.available_products(user, products=products)

    product_ids = [product.id for product in products]
    product_set = inventory.Product.objects.filter(id__in=product_ids)

    class StaffProductsForm(forms.Form):
        ''' Form for allowing staff to add an item to a user's cart. '''

        product = forms.ModelChoiceField(
            widget=forms.Select,
            queryset=product_set,
        )

        quantity = forms.IntegerField(min_value=0, )

    return StaffProductsForm
예제 #16
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)
예제 #17
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)
예제 #18
0
 def get_prods():
     return ProductController.available_products(
         self.USER_1,
         products=[self.PROD_2, self.PROD_3, self.PROD_4],
     )
예제 #19
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)
예제 #20
0
 def get_prods():
     return ProductController.available_products(
         self.USER_1,
         products=[self.PROD_2, self.PROD_3, self.PROD_4],
     )
예제 #21
0
def guided_registration(request, page_id=0):
    ''' Goes through the registration process in order,
    making sure user sees all valid categories.

    WORK IN PROGRESS: the finalised version of this view will allow
    grouping of categories into a specific page. Currently, it just goes
    through each category one by one
    '''

    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")

        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)