Changeset - 2a720bd46bb4
[Not reviewed]
0 5 2
Joel Addison - 4 years ago 2020-11-23 12:22:00
joel@addison.net.au
Tickets for LCA2021

Disable lots of inventory that does not exist for a virtual conf.
Add Swag Badge category and product.
Adjust attendee profile to hide irrelevant questions.
7 files changed with 358 insertions and 275 deletions:
0 comments (0 inline, 0 general)
pinaxcon/registrasion/forms.py
Show inline comments
...
 
@@ -13,19 +13,25 @@ class YesNoField(forms.TypedChoiceField):
 
            choices=((None, '--------'), (False, 'No'), (True, 'Yes')),
 
            **kwargs
 
        )
 

	
 

	
 
class ProfileForm(forms.ModelForm):
 
    ''' A form for requesting badge and profile information. '''
 

	
 
    required_css_class = 'label-required'
 

	
 
    class Meta:
 
        model = models.AttendeeProfile
 
        exclude = ['attendee']
 
        exclude = [
 
            'attendee',
 
            'of_legal_age',
 
            'dietary_restrictions',
 
            'children',
 
            'future_conference',
 
        ]
 
        widgets = {
 
            'past_lca': forms.widgets.CheckboxSelectMultiple
 
        }
 
        field_classes = {
 
            "of_legal_age": YesNoField,
 
        }
pinaxcon/registrasion/management/commands/populate_inventory.py
Show inline comments
...
 
@@ -72,96 +72,110 @@ class Command(BaseCommand):
 
            ("name",),
 
            name="Terms, Conditions, and Code of Conduct Acceptance",
 
            description="I agree to the "
 
                        "<a href=\"/attend/terms-and-conditions/\"> "
 
                        "terms and conditions of attendance</a>, and I have read, "
 
                        "understood, and agree to act according to the standards set "
 
                        "forth in our <a href=\"/attend/code-of-conduct/\">"
 
                        "Code of Conduct</a>.",
 
            required=True,
 
            render_type=inv.Category.RENDER_TYPE_CHECKBOX,
 
            order=10,
 
        )
 
        self.penguin_dinner = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Penguin Dinner Ticket",
 
            description="Tickets to our conference dinner on the evening of "
 
                        f"{settings.PENGUIN_DINNER_TICKET_DATE: %A %d %B}. "
 
                        "All attendees may purchase "
 
                        "seats at the dinner, even if a dinner ticket is not "
 
                        "included in your conference ticket price.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
            limit_per_user=10,
 
            order=20,
 
        )
 
        self.speakers_dinner_ticket = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Speakers' Dinner Ticket",
 
            description="Tickets to our exclusive Speakers' Dinner on the "
 
                        "evening of "
 
                        f"{settings.SPEAKER_DINNER_TICKET_DATE: %A %d %B}.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
            limit_per_user=1,
 
            order=30,
 
        )
 
        self.pdns_category = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Professional Delegates Networking Session Ticket",
 
            description="Tickets to our Professional Delegates Networking session. "
 
                        "This event will be held on the evening of "
 
                        f"{settings.PDNS_TICKET_DATE: %A %d %B} "
 
                        "and is restricted to Professional Ticket "
 
                        "holders, speakers, miniconf organisers, and invited "
 
                        "guests.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_RADIO,
 
            limit_per_user=1,
 
            order=40,
 
        )
 
        self.t_shirt = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Shirt",
 
            description="Commemorative conference shirts, featuring the "
 
                        f"linux.conf.au {settings.LCA_START.year} artwork. "
 
                        "View the <a href=\"/attend/shirts/\">"
 
                        "sizing guide</a>.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_ITEM_QUANTITY,
 
            order=50,
 
        )
 
        # self.penguin_dinner = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Penguin Dinner Ticket",
 
        #     description="Tickets to our conference dinner on the evening of "
 
        #                 f"{settings.PENGUIN_DINNER_TICKET_DATE: %A %d %B}. "
 
        #                 "All attendees may purchase "
 
        #                 "seats at the dinner, even if a dinner ticket is not "
 
        #                 "included in your conference ticket price.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
        #     limit_per_user=10,
 
        #     order=20,
 
        # )
 
        # self.speakers_dinner_ticket = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Speakers' Dinner Ticket",
 
        #     description="Tickets to our exclusive Speakers' Dinner on the "
 
        #                 "evening of "
 
        #                 f"{settings.SPEAKER_DINNER_TICKET_DATE: %A %d %B}.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
        #     limit_per_user=1,
 
        #     order=30,
 
        # )
 
        # self.pdns_category = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Professional Delegates Networking Session Ticket",
 
        #     description="Tickets to our Professional Delegates Networking session. "
 
        #                 "This event will be held on the evening of "
 
        #                 f"{settings.PDNS_TICKET_DATE: %A %d %B} "
 
        #                 "and is restricted to Professional Ticket "
 
        #                 "holders, speakers, miniconf organisers, and invited "
 
        #                 "guests.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
 
        #     limit_per_user=1,
 
        #     order=40,
 
        # )
 
        # self.t_shirt = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Shirt",
 
        #     description="Commemorative conference shirts, featuring the "
 
        #                 f"linux.conf.au {settings.LCA_START.year} artwork. "
 
        #                 "View the <a href=\"/attend/shirts/\">"
 
        #                 "sizing guide</a>.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_ITEM_QUANTITY,
 
        #     order=50,
 
        # )
 
        # self.accommodation = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Accommodation at University of Tasmania",
 
        #     description="Accommodation at the University of Tasmania colleges "
 
        #                 "and apartments. You can come back and book your "
 
        #                 "accommodation at a later date, provided rooms remain "
 
        #                 "available. Rooms may only be booked from Sunday 15 "
 
        #                 "January--Saturday 21 January. If you wish to stay "
 
        #                 "for only a part of the 6-day period, you must book "
 
        #                 "accommodation for the full 6-day period. Rooms at "
 
        #                 "other hotels, including Wrest Point can be booked "
 
        #                 "elsewhere. For full details, see [LINK]our "
 
        #                 "accommodation page.[/LINK]",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
 
        #     limit_per_user=1,
 
        #     order=50,
 
        # )
 
        self.badge_category = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Swag Badge",
 
            description="We have a limited number of "
 
                        "<a href=\"/attend/shirts/\">Swag Badges</a> available "
 
                        "for attendees of linux.conf.au 2021. "
 
                        "They will be allocated on a first come, first serve basis. "
 
                        "Please note that they are only available to Australian "
 
                        "attendees due to shipping limitations.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_CHECKBOX,
 
            order=50,
 
        )
 
        self.extras = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Extras",
 
            description="Other items that can improve your conference "
 
                        "experience.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
            order=60,
 
        )
 

	
 
        # Tickets
...
 
@@ -193,51 +207,33 @@ class Command(BaseCommand):
 
            reservation_duration=hours(24),
 
            order=20,
 
        )
 
        self.ticket_student = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.STUDENT.name,
 
            price=settings.STUDENT.regular_price,
 
            reservation_duration=hours(24),
 
            order=30,
 
        )
 
        self.ticket_miniconfs_mt = self.find_or_make(
 
        self.ticket_miniconf_only = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.MINICONF_MT.name,
 
            price=settings.MINICONF_MT.regular_price,
 
            name=settings.MINICONF_ONLY.name,
 
            price=settings.MINICONF_ONLY.regular_price,
 
            reservation_duration=hours(24),
 
            order=40,
 
        )
 
        self.ticket_miniconfs_mon = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.MINICONF_M.name,
 
            price=settings.MINICONF_M.regular_price,
 
            reservation_duration=hours(24),
 
            order=42,
 
        )
 
        self.ticket_miniconfs_tue = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.MINICONF_MT.name,
 
            price=settings.MINICONF_MT.regular_price,
 
            reservation_duration=hours(24),
 
            order=44,
 
        )
 
        self.ticket_speaker = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.SPEAKER.name,
 
            price=settings.SPEAKER.regular_price,
 
            reservation_duration=hours(24),
 
            order=50,
 
        )
 
        self.ticket_media = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
...
 
@@ -278,153 +274,163 @@ class Command(BaseCommand):
 
        # Agreements
 
        self.accept_terms = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.terms,
 
            name="I Accept",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(24),
 
            order=10,
 
            limit_per_user=1,
 
        )
 

	
 
        for t in settings.PENGUIN_DINNER.tickets:
 
            self.find_or_make(
 
                inv.Product,
 
                ("name", "category",),
 
                category=self.penguin_dinner,
 
                name=t.name,
 
                description=t.description,
 
                price=t.price,
 
                reservation_duration=t.reservation,
 
                order=t.order()
 
            )
 

	
 
        for t in settings.SPEAKERS_DINNER.tickets:
 
            self.find_or_make(
 
                inv.Product,
 
                ("name", "category",),
 
                category=self.speakers_dinner_ticket,
 
                name=t.name,
 
                description=t.description,
 
                price=t.price,
 
                reservation_duration=t.reservation,
 
                order=t.order()
 
            )
 
        # for t in settings.PENGUIN_DINNER.tickets:
 
        #     self.find_or_make(
 
        #         inv.Product,
 
        #         ("name", "category",),
 
        #         category=self.penguin_dinner,
 
        #         name=t.name,
 
        #         description=t.description,
 
        #         price=t.price,
 
        #         reservation_duration=t.reservation,
 
        #         order=t.order()
 
        #     )
 

	
 
        # for t in settings.SPEAKERS_DINNER.tickets:
 
        #     self.find_or_make(
 
        #         inv.Product,
 
        #         ("name", "category",),
 
        #         category=self.speakers_dinner_ticket,
 
        #         name=t.name,
 
        #         description=t.description,
 
        #         price=t.price,
 
        #         reservation_duration=t.reservation,
 
        #         order=t.order()
 
        #     )
 

	
 
        # PDNS
 

	
 
        self.pdns = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.pdns_category,
 
            name="Conference Attendee",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(1),
 
            limit_per_user=1,
 
            order=10,
 
        )
 
        # self.pdns = self.find_or_make(
 
        #     inv.Product,
 
        #     ("name", "category",),
 
        #     category=self.pdns_category,
 
        #     name="Conference Attendee",
 
        #     price=Decimal("00.00"),
 
        #     reservation_duration=hours(1),
 
        #     limit_per_user=1,
 
        #     order=10,
 
        # )
 

	
 
        # # Accommodation
 

	
 
        # self.accommodation_week = self.find_or_make(
 
        #     inv.Product,
 
        #     ("name", "category",),
 
        #     category=self.accommodation,
 
        #     name="Single Bedroom with Shared Bathrooms, includes full "
 
        #          "breakfast, Sunday 15 January 2017--Saturday 21 January 2017",
 
        #     price=Decimal("396.00"),
 
        #     reservation_duration=hours(24),
 
        #     limit_per_user=1,
 
        #     order=10,
 
        # )
 

	
 
        # Extras
 

	
 
        self.swag_badge = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.badge_category,
 
            name="I would like a Swag Badge (if available)",
 
            price=Decimal("0.00"),
 
            reservation_duration=hours(24),
 
            limit_per_user=1,
 
            order=10,
 
        )
 

	
 
        self.carbon_offset = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.extras,
 
            name="Offset the carbon pollution generated by your attendance, "
 
                 "thanks to fifteen trees.",
 
            price=Decimal("5.00"),
 
            reservation_duration=hours(1),
 
            reservation_duration=hours(24),
 
            order=10,
 
        )
 

	
 

	
 
        # Shirts
 
        ShirtGroup = namedtuple("ShirtGroup", ("prefix", "sizes"))
 
        shirt_names = {
 
            "straight": ShirtGroup(
 
                "Straight Cut",
 
                ("S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL"),
 
            ),
 
            "semi_fitted": ShirtGroup(
 
                "Semi-Fitted",
 
                ("XS", "S", "M", "L", "XL", "2XL"),
 
            ),
 
            "fitted": ShirtGroup(
 
                "Fitted",
 
                ("XS", "S", "M", "L", "XL", "2XL"),
 
            ),
 
        }
 

	
 
        self.shirts = {}
 
        order = 0
 
        for name, group in shirt_names.items():
 
            self.shirts[name] = {}
 
            prefix = group.prefix
 
            for size in group.sizes:
 
                product_name = "%s %s" % (prefix, size)
 
                order += 10
 
                self.shirts[name][size] = self.find_or_make(
 
                    inv.Product,
 
                    ("name", "category",),
 
                    name=product_name,
 
                    category=self.t_shirt,
 
                    price=settings.TSHIRT_PRICE,
 
                    reservation_duration=hours(1),
 
                    order=order,
 
                )
 
        # ShirtGroup = namedtuple("ShirtGroup", ("prefix", "sizes"))
 
        # shirt_names = {
 
        #     "straight": ShirtGroup(
 
        #         "Straight Cut",
 
        #         ("S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL"),
 
        #     ),
 
        #     "semi_fitted": ShirtGroup(
 
        #         "Semi-Fitted",
 
        #         ("XS", "S", "M", "L", "XL", "2XL"),
 
        #     ),
 
        #     "fitted": ShirtGroup(
 
        #         "Fitted",
 
        #         ("XS", "S", "M", "L", "XL", "2XL"),
 
        #     ),
 
        # }
 

	
 
        # self.shirts = {}
 
        # order = 0
 
        # for name, group in shirt_names.items():
 
        #     self.shirts[name] = {}
 
        #     prefix = group.prefix
 
        #     for size in group.sizes:
 
        #         product_name = "%s %s" % (prefix, size)
 
        #         order += 10
 
        #         self.shirts[name][size] = self.find_or_make(
 
        #             inv.Product,
 
        #             ("name", "category",),
 
        #             name=product_name,
 
        #             category=self.t_shirt,
 
        #             price=settings.TSHIRT_PRICE,
 
        #             reservation_duration=hours(1),
 
        #             order=order,
 
        #         )
 

	
 
    def populate_restrictions(self):
 

	
 
        # Hide the products that will eventually need a voucher
 
        hide_voucher_products = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="Can see hidden products",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        hide_voucher_products.group.set([self.group_unpublish])
 
        hide_voucher_products.products.set([
 
            self.ticket_media,
 
            self.ticket_sponsor,
 
            self.ticket_miniconfs_mt,
 
            self.ticket_miniconfs_mon,
 
            self.ticket_miniconfs_tue,
 
        ])
 

	
 
        hide_all_tickets = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="Can pre-purchase tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        hide_all_tickets.group.set([self.group_prepurchase])
 
        hide_all_tickets.products.set([
 
            self.ticket_contributor,
 
            self.ticket_professional,
 
            self.ticket_hobbyist,
 
            self.ticket_student,
 
            self.ticket_miniconf_only,
 
        ])
 

	
 
        # Set limits.
 
        public_ticket_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="Public ticket cap",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=600,
 
        )
 
        public_ticket_cap.products.set([
 
            self.ticket_contributor,
...
 
@@ -488,56 +494,56 @@ class Command(BaseCommand):
 

	
 
        speaker_ticket_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="Reserved for speakers (and miniconf organisers)",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=104,
 
        )
 
        speaker_ticket_cap.products.set([
 
            self.ticket_speaker,
 
        ])
 

	
 
        penguin_dinner_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="Penguin dinner ticket cap",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=900,
 
        )
 
        penguin_dinner_cap.categories.set([
 
            self.penguin_dinner,
 
        ])
 

	
 
        speakers_dinner_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="Speakers dinner ticket cap",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=135,
 
        )
 
        speakers_dinner_cap.categories.set([
 
            self.speakers_dinner_ticket,
 
        ])
 

	
 
        pdns_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="PDNS ticket cap",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=400,
 
        )
 
        pdns_cap.categories.set([
 
            self.pdns_category,
 
        ])
 
        # penguin_dinner_cap = self.find_or_make(
 
        #     cond.TimeOrStockLimitFlag,
 
        #     ("description", ),
 
        #     description="Penguin dinner ticket cap",
 
        #     condition=cond.FlagBase.DISABLE_IF_FALSE,
 
        #     limit=900,
 
        # )
 
        # penguin_dinner_cap.categories.set([
 
        #     self.penguin_dinner,
 
        # ])
 

	
 
        # speakers_dinner_cap = self.find_or_make(
 
        #     cond.TimeOrStockLimitFlag,
 
        #     ("description", ),
 
        #     description="Speakers dinner ticket cap",
 
        #     condition=cond.FlagBase.DISABLE_IF_FALSE,
 
        #     limit=135,
 
        # )
 
        # speakers_dinner_cap.categories.set([
 
        #     self.speakers_dinner_ticket,
 
        # ])
 

	
 
        # pdns_cap = self.find_or_make(
 
        #     cond.TimeOrStockLimitFlag,
 
        #     ("description", ),
 
        #     description="PDNS ticket cap",
 
        #     condition=cond.FlagBase.DISABLE_IF_FALSE,
 
        #     limit=400,
 
        # )
 
        # pdns_cap.categories.set([
 
        #     self.pdns_category,
 
        # ])
 

	
 
        # Volunteer tickets are for volunteers only
 
        volunteers = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="Volunteer tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        volunteers.group.set([self.group_volunteers])
 
        volunteers.products.set([
 
            self.ticket_volunteer,
 
        ])
...
 
@@ -558,104 +564,104 @@ class Command(BaseCommand):
 
        speaker_tickets = self.find_or_make(
 
            cond.SpeakerFlag,
 
            ("description", ),
 
            description="Speaker tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
            is_presenter=True,
 
            is_copresenter=False,
 
        )
 
        speaker_tickets.proposal_kind.set(self.main_conference_proposals)
 
        speaker_tickets.products.set([self.ticket_speaker, ])
 

	
 
        # Speaker dinner tickets are for primary speakers only
 
        speaker_dinner_tickets = self.find_or_make(
 
            cond.SpeakerFlag,
 
            ("description", ),
 
            description="Speaker dinner tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
            is_presenter=True,
 
            is_copresenter=False,
 
        )
 
        speaker_dinner_tickets.proposal_kind.set(self.main_conference_proposals)
 
        speaker_dinner_tickets.categories.set([self.speakers_dinner_ticket, ])
 
        # speaker_dinner_tickets = self.find_or_make(
 
        #     cond.SpeakerFlag,
 
        #     ("description", ),
 
        #     description="Speaker dinner tickets",
 
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        #     is_presenter=True,
 
        #     is_copresenter=False,
 
        # )
 
        # speaker_dinner_tickets.proposal_kind.set(self.main_conference_proposals)
 
        # speaker_dinner_tickets.categories.set([self.speakers_dinner_ticket, ])
 

	
 
        # PDNS tickets are complicated.
 
        # They can be enabled by tickets
 
        pdns_by_ticket = self.find_or_make(
 
            cond.ProductFlag,
 
            ("description", ),
 
            description="PDNS available by ticket",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        pdns_by_ticket.enabling_products.set([
 
            self.ticket_professional,
 
            self.ticket_contributor,
 
            self.ticket_media,
 
            self.ticket_sponsor,
 
        ])
 
        pdns_by_ticket.categories.set([self.pdns_category, ])
 
        # pdns_by_ticket = self.find_or_make(
 
        #     cond.ProductFlag,
 
        #     ("description", ),
 
        #     description="PDNS available by ticket",
 
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        # )
 
        # pdns_by_ticket.enabling_products.set([
 
        #     self.ticket_professional,
 
        #     self.ticket_contributor,
 
        #     self.ticket_media,
 
        #     self.ticket_sponsor,
 
        # ])
 
        # pdns_by_ticket.categories.set([self.pdns_category, ])
 

	
 
        # They are available to speakers
 
        pdns_by_speaker = self.find_or_make(
 
            cond.SpeakerFlag,
 
            ("description", ),
 
            description="PDNS available to speakers",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
            is_presenter=True,
 
            is_copresenter=True,
 
        # pdns_by_speaker = self.find_or_make(
 
        #     cond.SpeakerFlag,
 
        #     ("description", ),
 
        #     description="PDNS available to speakers",
 
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        #     is_presenter=True,
 
        #     is_copresenter=True,
 

	
 
        )
 
        pdns_by_speaker.proposal_kind.set(self.main_conference_proposals)
 
        pdns_by_speaker.categories.set([self.pdns_category, ])
 
        # )
 
        # pdns_by_speaker.proposal_kind.set(self.main_conference_proposals)
 
        # pdns_by_speaker.categories.set([self.pdns_category, ])
 

	
 
        # They are available to staff
 
        pdns_by_staff = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="PDNS available to staff",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        pdns_by_staff.group.set([
 
            self.group_team,
 
        ])
 
        pdns_by_staff.categories.set([self.pdns_category, ])
 
        # pdns_by_staff = self.find_or_make(
 
        #     cond.GroupMemberFlag,
 
        #     ("description", ),
 
        #     description="PDNS available to staff",
 
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        # )
 
        # pdns_by_staff.group.set([
 
        #     self.group_team,
 
        # ])
 
        # pdns_by_staff.categories.set([self.pdns_category, ])
 

	
 
        # Don't allow people to get anything if they don't have a ticket first
 
        needs_a_ticket = self.find_or_make(
 
            cond.CategoryFlag,
 
            ("description", ),
 
            description="GottaGettaTicketFirst",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            enabling_category=self.ticket
 
        )
 
        needs_a_ticket.categories.set([
 
            self.extras,
 
            self.t_shirt,
 
            self.penguin_dinner,
 
            self.pdns_category,
 
            # self.t_shirt,
 
            # self.penguin_dinner,
 
            # self.pdns_category,
 
        ])
 
        # Require attendees to accept the T&Cs and Code of Conduct
 
        needs_agreement = self.find_or_make(
 
            cond.CategoryFlag,
 
            ("description", ),
 
            description="Must Accept Terms",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            enabling_category=self.terms,
 
        )
 
        needs_agreement.categories.set([
 
            self.extras,
 
            self.t_shirt,
 
            self.penguin_dinner,
 
            self.pdns_category,
 
            self.speakers_dinner_ticket,
 
            # self.t_shirt,
 
            # self.penguin_dinner,
 
            # self.pdns_category,
 
            # self.speakers_dinner_ticket,
 
        ])
 

	
 
    def populate_discounts(self):
 
        def add_early_birds(discount):
 
            self.find_or_make(
 
                cond.DiscountForProduct,
 
                ("discount", "product"),
 
                discount=discount,
 
                product=self.ticket_contributor,
 
                price=settings.CONTRIBUTOR.earlybird_discount(),
 
                quantity=1,  # Per user
 
            )
...
 
@@ -670,133 +676,133 @@ class Command(BaseCommand):
 

	
 
        def free_category(parent_discount, category, quantity=1):
 
            self.find_or_make(
 
                cond.DiscountForCategory,
 
                ("discount", "category",),
 
                discount=parent_discount,
 
                category=category,
 
                percentage=Decimal("100.00"),
 
                quantity=quantity,
 
            )
 

	
 
        # Early Bird Discount (general public)
 
        early_bird_hobbyist_discount = self.find_or_make(
 
            cond.TimeOrStockLimitDiscount,
 
            ("description", ),
 
            description="Early Bird Discount - Hobbyist",
 
            end_time=settings.EARLY_BIRD_DEADLINE,
 
            limit=150,  # Across all users
 
        )
 
        self.find_or_make(
 
                cond.DiscountForProduct,
 
                ("discount", "product"),
 
                discount=early_bird_hobbyist_discount,
 
                product=self.ticket_hobbyist,
 
                price=settings.HOBBYIST.earlybird_discount(),
 
                quantity=1,  # Per user
 
        )
 
        # early_bird_hobbyist_discount = self.find_or_make(
 
        #     cond.TimeOrStockLimitDiscount,
 
        #     ("description", ),
 
        #     description="Early Bird Discount - Hobbyist",
 
        #     end_time=settings.EARLY_BIRD_DEADLINE,
 
        #     limit=150,  # Across all users
 
        # )
 
        # self.find_or_make(
 
        #         cond.DiscountForProduct,
 
        #         ("discount", "product"),
 
        #         discount=early_bird_hobbyist_discount,
 
        #         product=self.ticket_hobbyist,
 
        #         price=settings.HOBBYIST.earlybird_discount(),
 
        #         quantity=1,  # Per user
 
        # )
 

	
 
        early_bird = self.find_or_make(
 
            cond.TimeOrStockLimitDiscount,
 
            ("description", ),
 
            description="Early Bird Discount - Professional",
 
            end_time=settings.EARLY_BIRD_DEADLINE,
 
            limit=200,  # Across professionals and fairy sponsors
 
        )
 
        add_early_birds(early_bird)
 
        # early_bird = self.find_or_make(
 
        #     cond.TimeOrStockLimitDiscount,
 
        #     ("description", ),
 
        #     description="Early Bird Discount - Professional",
 
        #     end_time=settings.EARLY_BIRD_DEADLINE,
 
        #     limit=200,  # Across professionals and fairy sponsors
 
        # )
 
        # add_early_birds(early_bird)
 

	
 
        # Early bird rates for speakers
 
        speaker_ticket_discounts = self.find_or_make(
 
            cond.SpeakerDiscount,
 
            ("description", ),
 
            description="Speaker Ticket Discount",
 
            is_presenter=True,
 
            is_copresenter=True,
 
        )
 
        speaker_ticket_discounts.proposal_kind.set(
 
            self.main_conference_proposals,
 
        )
 
        add_early_birds(speaker_ticket_discounts)
 

	
 
        # Primary speaker gets a free speaker dinner ticket
 
        primary_speaker = self.find_or_make(
 
            cond.SpeakerDiscount,
 
            ("description", ),
 
            description="Complimentary for primary proposer",
 
            is_presenter=True,
 
            is_copresenter=False,
 
        )
 
        primary_speaker.proposal_kind.set(self.main_conference_proposals)
 
        free_category(primary_speaker, self.speakers_dinner_ticket)
 
        # free_category(primary_speaker, self.speakers_dinner_ticket)
 

	
 
        # Professional-Like ticket inclusions
 
        ticket_prolike_inclusions = self.find_or_make(
 
            cond.IncludedProductDiscount,
 
            ("description", ),
 
            description="Complimentary for ticket holder (Professional-level)",
 
        )
 
        ticket_prolike_inclusions.enabling_products.set([
 
            self.ticket_contributor,
 
            self.ticket_professional,
 
            self.ticket_media,
 
            self.ticket_sponsor,
 
            self.ticket_speaker,
 
        ])
 
        free_category(ticket_prolike_inclusions, self.penguin_dinner)
 
        free_category(ticket_prolike_inclusions, self.t_shirt)
 
        # free_category(ticket_prolike_inclusions, self.penguin_dinner)
 
        # free_category(ticket_prolike_inclusions, self.t_shirt)
 

	
 
        # Hobbyist ticket inclusions
 
        ticket_hobbyist_inclusions = self.find_or_make(
 
            cond.IncludedProductDiscount,
 
            ("description", ),
 
            description="Complimentary for ticket holder (Hobbyist-level)",
 
        )
 
        ticket_hobbyist_inclusions.enabling_products.set([
 
            self.ticket_hobbyist,
 
        ])
 
        free_category(ticket_hobbyist_inclusions, self.t_shirt)
 
        # free_category(ticket_hobbyist_inclusions, self.t_shirt)
 

	
 
        # Student ticket inclusions
 
        ticket_student_inclusions = self.find_or_make(
 
            cond.IncludedProductDiscount,
 
            ("description", ),
 
            description="Complimentary for ticket holder (Student-level)",
 
        )
 
        ticket_student_inclusions.enabling_products.set([
 
            self.ticket_student,
 
        ])
 
        free_category(ticket_student_inclusions, self.t_shirt)
 
        # free_category(ticket_student_inclusions, self.t_shirt)
 

	
 
        # Team ticket inclusions
 
        ticket_staff_inclusions = self.find_or_make(
 
            cond.IncludedProductDiscount,
 
            ("description", ),
 
            description="Complimentary for ticket holder (Staff)",
 
        )
 
        ticket_staff_inclusions.enabling_products.set([
 
            self.ticket_team,
 
        ])
 
        free_category(ticket_staff_inclusions, self.penguin_dinner)
 
        # free_category(ticket_staff_inclusions, self.penguin_dinner)
 

	
 
        # Team & volunteer shirts, regardless of ticket type
 
        staff_t_shirts = self.find_or_make(
 
            cond.GroupMemberDiscount,
 
            ("description", ),
 
            description="Shirts complimentary for staff and volunteers",
 
        )
 
        staff_t_shirts.group.set([
 
            self.group_team,
 
            self.group_volunteers,
 
        ])
 
        free_category(staff_t_shirts, self.t_shirt, quantity=5)
 
        # staff_t_shirts = self.find_or_make(
 
        #     cond.GroupMemberDiscount,
 
        #     ("description", ),
 
        #     description="Shirts complimentary for staff and volunteers",
 
        # )
 
        # staff_t_shirts.group.set([
 
        #     self.group_team,
 
        #     self.group_volunteers,
 
        # ])
 
        # free_category(staff_t_shirts, self.t_shirt, quantity=5)
 

	
 
        print(f"{self.count} categories found/made")
 

	
 
    def find_or_make(self, model, search_keys, **k):
 
        ''' Either makes or finds an object of type _model_, with the given
 
        kwargs.
 

	
 
        Arguments:
 
            search_keys ([str, ...]): A sequence of keys that are used to search
 
            for an existing version in the database. The remaining arguments are
 
            only used when creating a new object.
 
        '''
pinaxcon/registrasion/migrations/0001_initial.py
Show inline comments
...
 
@@ -17,24 +17,27 @@ _PAST_EVENTS = (
 
    (2006, "2006 Dunedin"),
 
    (2007, "2007 Sydney"),
 
    (2008, "2008 Melbourne"),
 
    (2009, "2009 Hobart"),
 
    (2010, "2010 Wellington"),
 
    (2011, "2011 Brisbane"),
 
    (2012, "2012 Ballarat"),
 
    (2013, "2013 Canberra"),
 
    (2014, "2014 Perth"),
 
    (2015, "2015 Auckland"),
 
    (2016, "2016 Geelong"),
 
    (2017, "2017 Hobart"),
 
    (2018, "2018 Sydney"),
 
    (2019, "2019 Christchurch"),
 
    (2020, "2020 Gold Coast"),
 
)
 

	
 

	
 
def populate(apps, schema_editor):
 
    PastEvent = apps.get_model("pinaxcon_registrasion","PastEvent")
 

	
 
    all_such = PastEvent.objects.all()
 
    by_year = dict((event.year, event) for event in all_such)
 

	
 
    events = []
 
    for past_event in _PAST_EVENTS:
 
        if past_event[0] in by_year:
pinaxcon/registrasion/migrations/0014_auto_20201123_2319.py
Show inline comments
 
new file 100644
 
# Generated by Django 2.2.17 on 2020-11-23 12:19
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('pinaxcon_registrasion', '0013_auto_20201008_2036'),
 
    ]
 

	
 
    operations = [
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='address_line_1',
 
            field=models.CharField(blank=True, help_text='This address, if provided, will appear on your invoices. It is also where we will ship your Swag Badge if you are allocated one.', max_length=1024, verbose_name='Address line 1'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='future_conference',
 
            field=models.BooleanField(blank=True, default=False, help_text='Select to have your login details made available to future Linux Australia conferences who share the same Single Sign On system.', verbose_name='Reuse my login for future Linux Australia conferences?'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='lca_announce',
 
            field=models.BooleanField(blank=True, help_text='Select to be subscribed to the low-traffic lca-announce mailing list', verbose_name='Subscribe to lca-announce list'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='lca_chat',
 
            field=models.BooleanField(blank=True, help_text='lca-chat is a high-traffic mailing list used by attendees during the week of the conference for general discussion.', verbose_name='Subscribe to the LCA chat list'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='linux_australia',
 
            field=models.BooleanField(blank=True, help_text="Select this field to register for free <a href='http://www.linux.org.au/'>Linux Australia</a> membership.", verbose_name='Linux Australia membership'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='of_legal_age',
 
            field=models.BooleanField(blank=True, default=False, help_text='Being under 18 will not stop you from attending the conference. We need to know whether you are over 18 to allow us to cater for you at venues that serve alcohol.', verbose_name='Are you over 18?'),
 
        ),
 
    ]
pinaxcon/registrasion/models.py
Show inline comments
...
 
@@ -105,25 +105,27 @@ class AttendeeProfile(rego.AttendeeProfileBase):
 
    # Other important Information
 
    name_per_invoice = models.CharField(
 
        verbose_name="Your legal name (for invoicing purposes)",
 
        max_length=256,
 
        help_text="If your legal name is different to the name on your badge, "
 
                  "fill this in, and we'll put it on your invoice. Otherwise, "
 
                  "leave it blank.",
 
        blank=True,
 
        )
 

	
 
    address_line_1 = models.CharField(
 
        verbose_name="Address line 1",
 
        help_text="This address, if provided, will appear on your invoices.",
 
        help_text="This address, if provided, will appear on your invoices. "
 
                  "It is also where we will ship your Swag Badge "
 
                  "if you are allocated one.",
 
        max_length=1024,
 
        blank=True,
 
    )
 
    address_line_2 = models.CharField(
 
        verbose_name="Address line 2",
 
        max_length=1024,
 
        blank=True,
 
    )
 
    address_suburb = models.CharField(
 
        verbose_name="City/Town/Suburb",
 
        max_length=1024,
 
        blank=True,
...
 
@@ -140,24 +142,26 @@ class AttendeeProfile(rego.AttendeeProfileBase):
 
    state = models.CharField(
 
        max_length=256,
 
        verbose_name="State/Territory/Province",
 
        help_text="If your Country is Australia, you must list a state.",
 
        blank=True,
 
    )
 

	
 
    of_legal_age = models.BooleanField(
 
        verbose_name="Are you over 18?",
 
        help_text="Being under 18 will not stop you from attending the "
 
                  "conference. We need to know whether you are over 18 to "
 
                  "allow us to cater for you at venues that serve alcohol.",
 
        blank=True, # LCA2021 - not needed.
 
        default=False,
 
    )
 
    dietary_restrictions = models.CharField(
 
        verbose_name="Food allergies, intolerances, or dietary restrictions",
 
        max_length=256,
 
        blank=True,
 
    )
 
    accessibility_requirements = models.CharField(
 
        verbose_name="Accessibility-related requirements",
 
        max_length=256,
 
        blank=True,
 
    )
 
    gender = models.CharField(
...
 
@@ -199,24 +203,25 @@ class AttendeeProfile(rego.AttendeeProfileBase):
 
        help_text="lca-chat is a high-traffic mailing list used by "
 
                  "attendees during the week of the conference for general "
 
                  "discussion.",
 
        blank=True,
 
    )
 

	
 
    future_conference = models.BooleanField(
 
        verbose_name = "Reuse my login for future Linux Australia conferences?",
 
        help_text="Select to have your login details made available to future "
 
                  "Linux Australia conferences who share the same Single Sign "
 
                  "On system.",
 
        blank=True,
 
        default=False,
 
    )
 

	
 
    past_lca = models.ManyToManyField(
 
        PastEvent,
 
        verbose_name="Which past linux.conf.au events have you attended?",
 
        blank=True,
 
    )
 

	
 
    def first_name(self):
 
        return wrap(self.name, 15, break_long_words=False)[0]
 

	
 
    def last_name(self):
pinaxcon/settings.py
Show inline comments
...
 
@@ -514,32 +514,29 @@ class PenguinDinnerCat(Category):
 

	
 

	
 
_TZINFO = pytz.timezone(TIME_ZONE)
 
LCA_START = datetime(2021, 1, 23, tzinfo=_TZINFO)
 
LCA_END = datetime(2021, 1, 25, tzinfo=_TZINFO)
 
EARLY_BIRD_DEADLINE = datetime(2020, 12, 1, tzinfo=_TZINFO)
 
PENGUIN_DINNER_TICKET_DATE = date(2021, 1, 23)
 
SPEAKER_DINNER_TICKET_DATE = date(2021, 1, 25)
 
PDNS_TICKET_DATE = date(2021, 1, 24)
 

	
 
TSHIRT_PRICE = Decimal("25.00")
 

	
 
CONTRIBUTOR = Ticket("Contributor", Decimal("1999.00"), Decimal("1849.00"))
 
PROFESSIONAL = Ticket("Professional", Decimal("1099.00"), Decimal("949.00"))
 
HOBBYIST = Ticket("Hobbyist", Decimal("549.00"), Decimal("399.00"))
 
STUDENT = Ticket("Student", Decimal("199.00"), None)
 

	
 
MINICONF_MT = Ticket("Monday and Tuesday Only", Decimal("198.00"), None)
 
MINICONF_M = Ticket("Monday Only", Decimal("99.00"), None)
 
MINICONF_T = Ticket("Tuesday Only", Decimal("99.00"), None)
 
CONTRIBUTOR = Ticket("Contributor", Decimal("300.00"), Decimal("250.00"))
 
PROFESSIONAL = Ticket("Professional", Decimal("125.00"), Decimal("100.00"))
 
HOBBYIST = Ticket("Hobbyist", Decimal("70.00"), None)
 
STUDENT = Ticket("Student", Decimal("30.00"), None)
 
MINICONF_ONLY = Ticket("Miniconf Only", Decimal("25.00"), None)
 

	
 
MEDIA = Ticket("Media", Decimal("0.0"), None)
 
SPEAKER = Ticket("Speaker", Decimal("0.0"), None)
 
SPONSOR = Ticket("Sponsor", Decimal("0.0"), None)
 

	
 
CONFERENCE_ORG = Ticket("Conference Organiser", Decimal("0.0"), None)
 
CONFERENCE_VOL = Ticket("Conference Volunteer", Decimal("0.0"), None)
 

	
 
PENGUIN_DINNER = PenguinDinnerCat
 
PENGUIN_DINNER_ADULT = PenguinDinnerCat.create(
 
    "Adult", Decimal("95.00"),
 
    "Includes an adult's meal and full beverage service.",
vendor/symposion/speakers/migrations/0009_auto_20201123_2256.py
Show inline comments
 
new file 100644
 
# Generated by Django 2.2.17 on 2020-11-23 11:56
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('symposion_speakers', '0008_auto_20190624_2328'),
 
    ]
 

	
 
    operations = [
 
        migrations.AlterField(
 
            model_name='speaker',
 
            name='accommodation_assistance',
 
            field=models.BooleanField(blank=True, default=False, help_text='Check this box if you require us to provide you with accommodation in order to present your proposed sessions.', verbose_name='Accommodation assistance required'),
 
        ),
 
        migrations.AlterField(
 
            model_name='speaker',
 
            name='travel_assistance',
 
            field=models.BooleanField(blank=True, default=False, help_text='Check this box if you require assistance to travel to linux.conf.au in order to present your proposed sessions.', verbose_name='Travel assistance required'),
 
        ),
 
    ]
0 comments (0 inline, 0 general)