Exemple #1
0
 def setup_two_view(self):
     if (PROP.getProperty(self.request, PROP.SITE_SETUP) == True):
         return HTTPFound(location=self.request.route_path("welcome"))
     elif (PROP.getProperty(self.request, PROP.VERSION) == None):
         return HTTPFound(location=self.request.route_path("setup_stageone"))
     # Check if the password has already been changed, default is 'password'
     admin_usr = self.request.root.users["admin"]
     test_password = salt_password("password", admin_usr.password_salt)
     if test_password != admin_usr.password:
         self.request.session.flash("It looks like someone has already changed the default password on the account, if this wasn't you then contact support!", "info")
         return HTTPFound(location=self.request.route_path("setup_stagethree"))
     # Get password for admin user and double check
     if "password_one" in self.request.POST and  "password_two" in self.request.POST:
         pwd_1 = self.request.POST["password_one"]
         pwd_2 = self.request.POST["password_two"]
         if len(pwd_1) < 5:
             self.request.session.flash("The passwords entered are too short, they must be of 5 characters or longer.", "error")
             return {}
         elif pwd_1 != pwd_2:
             self.request.session.flash("The passwords entered do not match.", "error")
             return {}
         # Set the administrator password
         admin_usr.password_salt = Coding().generateUniqueCode()
         admin_usr.password = salt_password(pwd_1, admin_usr.password_salt)
         return HTTPFound(location=self.request.route_path("setup_stagethree"))
     return {}
Exemple #2
0
 def compose_from_template(self, template, replacements):
     base_path = self.request.registry._settings["base_dir"]
     rich_path = os.path.join(base_path, "templates/mail/%s_rich.html" % template)
     plain_path = os.path.join(base_path, "templates/mail/%s_plain.txt" % template)
     # Read in the templates
     # - Rich Template
     rich_content = None
     if os.path.isfile(rich_path):
         with open(rich_path, "r") as f:
             rich_content = f.read()
     if rich_content != None:
         rich_content = rich_content.replace("\n","").replace("\t","")
     # - Plain Template
     plain_content = None
     if os.path.isfile(plain_path):
         with open(plain_path, "r") as f:
             plain_content = f.read()
     # Run replacements
     replacements['AUTOINCLUDEDTEXT'] = PROP_KEYS.getProperty(self.request, PROP_KEYS.AUTO_EMAIL_INCLUDED_TEXT)
     replacements['AUTOINCLUDEDCONTACT'] = PROP_KEYS.getProperty(self.request, PROP_KEYS.AUTO_EMAIL_CONTACT_DETAILS)
     for key in replacements:
         rep_key = "!!%s!!" % key.upper()
         if rich_content != None: rich_content = rich_content.replace(rep_key, str(replacements[key]))
         if plain_content != None: plain_content = plain_content.replace(rep_key, str(replacements[key]))
     return {
         "rich":     rich_content,
         "plain":    plain_content
     }
Exemple #3
0
 def setup_three_view(self):
     if (PROP.getProperty(self.request, PROP.SITE_SETUP) == True):
         return HTTPFound(location=self.request.route_path("welcome"))
     elif (PROP.getProperty(self.request, PROP.VERSION) == None):
         return HTTPFound(location=self.request.route_path("setup_stageone"))
     event_date = PROP.getProperty(self.request, PROP.EVENT_DATE)
     
     if "submit" in self.request.POST:
         # Save the event details
         day = int(float(self.request.POST["event_day"]))
         month = int(float(self.request.POST["event_month"]))
         year = int(float(self.request.POST["event_year"]))
         event_name = self.request.POST["event_name"]
         min_age = int(float(self.request.POST["min_age"]))
         self.request.root.properties[PROP.EVENT_DATE] = datetime(year, month, day)
         self.request.root.properties[PROP.EVENT_NAME] = event_name
         self.request.root.properties[PROP.MINIMUM_AGE] = min_age
         return HTTPFound(location=self.request.route_path("setup_done"))
     return {
         "event_day": event_date.day,
         "event_month": event_date.month,
         "event_year": event_date.year,
         "event_name": PROP.getProperty(self.request, PROP.EVENT_NAME),
         "min_age": PROP.getProperty(self.request, PROP.MINIMUM_AGE)
     }
Exemple #4
0
 def setup_done_view(self):
     if (PROP.getProperty(self.request, PROP.SITE_SETUP) == True):
         return HTTPFound(location=self.request.route_path("welcome"))
     elif (PROP.getProperty(self.request, PROP.VERSION) == None):
         return HTTPFound(location=self.request.route_path("setup_stageone"))
     self.request.root.properties[PROP.SITE_SETUP] = True
     return {}
Exemple #5
0
 def pay_view(self):
     # Check we can be here
     # - First check queue/active status
     if Queue(self.request).timed_out():
         return HTTPFound(self.request.route_path("purchase_timeout"))
     # Now details
     elif not self.details_complete:
         self.request.session.flash(
             "You must complete all of your guest's details before continuing.",
             "error")
         return HTTPFound(location=self.request.route_path("order_details"))
     elif "method" in self.request.GET:
         logging.info("%s: Chose %s as their payment method" %
                      (self.user.username, self.request.GET["method"]))
         # Check this is a valid, registered payment method
         method = [
             x for x in PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
             if x.enabled
             and x.__name__.lower() == self.request.GET["method"].lower()
         ]
         if len(method) > 0:
             method = method[0]
             # Look for a route to make this payment by
             try:
                 route_url = self.request.route_path("pay_" +
                                                     method.__name__)
                 return HTTPFound(location=route_url)
             except (KeyError):
                 self.request.session.flash(
                     "An error occurred with the payment method you selected, please try again.",
                     "error")
                 logging.info(
                     "%s: Tried to request an unknown payment method" %
                     self.user.username)
         else:
             self.request.session.flash(
                 "An error occurred with the payment method you selected, please try again.",
                 "error")
             logging.info("%s: Tried to request an unknown payment method" %
                          self.user.username)
     # Clear any previous payment reference
     self.request.session.pop("payment_id", None)
     # Ok, all good
     user = self.request.root.users[self.request.session["user_id"]]
     tickets = [x for x in user.tickets if x.payment == None]
     if len(tickets) == 0:
         return HTTPFound(location=self.request.route_path("buy_tickets"))
     # Work out what payment methods are available to us
     enabled_methods = [
         x for x in PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
         if x.enabled and x.public
     ]
     eligible_methods = [
         x for x in enabled_methods
         if len(x.groups) == 0 or self.user.__parent__ in x.groups
     ]
     return {"methods": eligible_methods}
Exemple #6
0
    def setup_one_view(self):
        if (PROP.getProperty(self.request, PROP.SITE_SETUP) == True):
            return HTTPFound(location=self.request.route_path("welcome"))

        setup = False
        if (PROP.getProperty(self.request, PROP.VERSION) != None):
            print "Database already setup!"
        else:
            # Setup the database
            self.db_run_setup(self.request.root)
            setup = True

        return {"setup": setup}
Exemple #7
0
 def send_bulk_email(self, user_ids, subject, content):
     emails = []
     for user_id in user_ids:
         if not user_id in self.request.root.users: continue
         user = self.request.root.users[user_id]
         if user.profile == None or user.profile.email == None: continue
         emails.append(user.email)
     if len(emails) <= 0: return False
     try:
         # Compose message
         send_name = self.request.registry._settings["sender_name"]
         send_email = self.request.registry._settings["sender_email"]
         message = Message(
             author  = '%s <%s>' % (send_name, send_email),
             subject = "%s - %s" % (PROP_KEYS.getProperty(self.request, PROP_KEYS.EVENT_NAME), subject),
             bcc     = emails,
             rich    = content["rich"],
             plain   = content["plain"]
         )
         # Dispatch Message
         get_mailer(self.request).send(message)
         logging.info("Sent email with subject '%s' to emails %s" % (subject, emails))
         return True
     except socket.error:
         logging.exception("Socket error occurred when sending email to user %s" % user_id)
         return False
     except Exception:
         logging.exception("Email send exception occurred to user %s" % user_id)
         return False
Exemple #8
0
 def send_email(self, user_id, subject, content, pdf_attachment=None):
     if user_id not in self.request.root.users:
         logging.error("When sending email, user ID %s does not exist" % user_id)
         return False
     user = self.request.root.users[user_id]
     if user.profile == None or user.profile.email == None:
         logging.error("When sending email, user ID %s does not have a profile or email address" % user_id)
         return False
     try:
         # Compose message
         send_name = self.request.registry._settings["sender_name"]
         send_email = self.request.registry._settings["sender_email"]
         message = Message(
             author  = '%s <%s>' % (send_name, send_email),
             subject = "%s - %s" % (PROP_KEYS.getProperty(self.request, PROP_KEYS.EVENT_NAME), subject),
             to      = user.profile.email,
             rich    = content["rich"],
             plain   = content["plain"]
         )
         # Attach any available PDFs
         if pdf_attachment != None:
             message.attach("tickets.pdf", data=pdf_attachment, maintype="application", subtype="pdf")
         # Dispatch Message
         get_mailer(self.request).send(message)
         logging.info("Sent email with subject '%s' to email %s" % (subject, user.profile.email))
         return True
     except socket.error:
         logging.exception("Socket error occurred when sending email to user %s" % user_id)
         return False
     except Exception:
         logging.exception("Email send exception occurred to user %s" % user_id)
         return False
Exemple #9
0
 def refund_stripe_charge(self, charge_id):
     all_methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
     method = [x for x in all_methods if x.__name__ == "stripe"]
     method = method[0] if len(method) > 0 else None
     if method == None:
         logging.exception(
             self.user.username +
             ": Could not refund %s because could not find stripe payment method"
             % charge_id)
         return False
     priv_api_key = method.settings[PROP.STRIPE_API_KEY].value
     try:
         stripe.api_key = priv_api_key
         refund = stripe.Refund.create(charge=charge_id, reason="duplicate")
         if refund != None and "id" in refund:
             logging.info(self.user.username +
                          ": Refunded charge %s with refund id %s" %
                          (charge_id, refund["id"]))
             return True
         else:
             logging.error(self.user.username +
                           ": Refund of charge %s may have failed" %
                           charge_id)
             return False
     except Exception, e:
         logging.error(self.user.username +
                       ": Exception was thrown during refund: %s" % e)
         return False
Exemple #10
0
 def get_payment_method(self, key):
     if key == None:
         return None
     methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
     method = [x for x in methods if x.__name__.lower() == key.lower()]
     if len(method) == 0:
         return None
     else:
         return method[0]
Exemple #11
0
    def alter_pay_stripe_view(self, error=None):
        # Retrieve the payment
        payment_id = self.request.matchdict[
            "payment_id"] if "payment_id" in self.request.matchdict else None
        payment = self.request.root.payments[
            payment_id] if payment_id != None else None
        if payment == None:
            self.request.session.flash(
                "Could not find the requested payment, please try again.",
                "info")
            return HTTPFound(location=self.request.route_path("user_profile"))

        # Verify stripe is enabled
        all_methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [
            x for x in all_methods
            if x.__name__ == "stripe" and x.enabled == True
        ]
        method = method[0] if len(method) > 0 else None
        if method == None:
            self.request.session.flash(
                "An error occurred with the payment method you selected, please try another.",
                "error")
            return HTTPFound(location=self.request.route_path("user_profile"))

        # Retrieve stripe processing values
        process_percentage = method.settings[
            PROP.PAYMENT_PROCESSING_PERCENTAGE].value
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value
        pub_api_key = method.settings[PROP.STRIPE_PUBLIC_KEY].value
        organisation_name = method.settings[PROP.ORGANISATION_NAME].value
        contact_email = method.settings[PROP.STRIPE_CONTACT_EMAIL].value

        # Calculate the amount to pay
        subtotal = payment.amount_remaining
        processing = int(ceil(subtotal * process_percentage) + process_fee)
        total = int(ceil(subtotal + processing))

        # Render the payment page
        return {
            "error": error,
            "method": method,
            "subtotal": self.format_price(subtotal),
            "processing": self.format_price(processing),
            "total": self.format_price(total),
            "org_name": organisation_name,
            "contact_email": contact_email,
            "stripe_pub_key": pub_api_key,
            "penny_total": total,
            "pay_description": str(len(payment.tickets)) + " Ticket(s)",
            "alteration": True,
            "payment": payment
        }
Exemple #12
0
    def add_ticket_to_pdf(self, pdf, ticket, offset=0):
        if offset < 10:
            offset = offset * 75
        # Generate and save the QR code temporarily
        tmp_path = self.request.registry._settings["base_dir"] + "/data/tmp/"
        qr_img = qrcode.make("id:" + ticket.__name__ + ":pay:" +
                             ticket.payment.__name__ + ":owner:" +
                             ticket.owner.profile.fullname + ":price:" +
                             str(ticket.tick_type.cost) + ":type:" +
                             ticket.tick_type.name)
        qr_tmp_path = tmp_path + ticket.__name__ + ".png"
        qr_img.save(qr_tmp_path, "PNG")

        # Draw a ticket background if it exists
        bg_path = self.request.registry._settings[
            "base_dir"] + "/data/ticket_backer.png"
        if os.path.isfile(bg_path):
            pdf.image(bg_path, x=10, y=10 + offset, w=190, h=70, type='PNG')

        # Draw the QR Code
        pdf.image(qr_tmp_path, x=12, y=12 + offset, w=66, h=66, type='PNG')

        pdf.set_font('Arial', 'B', 16)
        pdf.set_text_color(0, 0, 0)
        title = self.event_name
        if len(title) > 30:
            title = title[:30] + "..."
        pdf.text(x=80, y=23 + offset, txt=title)
        pdf.set_font('Arial', 'I', 13)
        pdf.text(x=80,
                 y=30 + offset,
                 txt=PROP_KEYS.getProperty(
                     self.request,
                     PROP_KEYS.EVENT_DATE).strftime('%A %d %B %Y'))
        pdf.set_font('Arial', '', 16)
        pdf.text(x=80, y=37 + offset, txt=ticket.guest_info.fullname)
        pdf.text(x=80, y=44 + offset, txt=ticket.tick_type.name)
        pdf.text(x=80,
                 y=52 + offset,
                 txt=self.format_price(ticket.tick_type.cost))
        pdf.set_font('Arial', '', 16)
        pdf.set_text_color(150, 150, 150)
        pdf.text(x=80, y=60 + offset, txt="Ticket ID: " + ticket.__name__)
        pdf.text(x=80,
                 y=68 + offset,
                 txt="Payment ID:" + ticket.payment.__name__)

        # Draw the ticket box outline
        pdf.set_draw_color(100, 100, 100)
        pdf.set_line_width(0.1)
        pdf.rect(10, 10 + offset, 190, 70)
Exemple #13
0
 def admin_payment_settings_view(self):
     # Deal with the different payment methods
     methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
     if "submit" in self.request.POST:
         errored = False
         # Process method settings
         for key in self.request.POST.keys():
             if "enable_" in key:
                 sect_key = key.split("enable_")[1]
                 method = [x for x in methods if x.__name__ == sect_key]
                 if len(method) > 0:
                     method = method[0]
                     method.enabled = (
                         self.request.POST[key].lower() == "yes")
                     # Go through properties
                     for prop_key in method.settings:
                         post_key = sect_key + "+" + prop_key
                         prop = method.settings[prop_key]
                         if post_key in self.request.POST:
                             good = prop.update_value(
                                 self.request.POST[post_key])
                             if not good:
                                 errored = True
                     # Go through eligible groups
                     if method.groups == None:
                         method.groups = PersistentList()
                     del method.groups[:]
                     for group_key in self.request.root.groups.keys():
                         post_key = sect_key + "+" + group_key + "+group"
                         if post_key in self.request.POST and self.request.POST[
                                 post_key] == group_key:
                             method.groups.append(
                                 self.request.root.groups[group_key])
         if errored:
             self.request.session.flash(
                 "Some data was not saved as it didn't pass validation.",
                 "error")
     elif "action" in self.request.GET and self.request.GET[
             "action"] == "resetdefaults":
         setup = Initial(self.context, self.request)
         # Clear payment methods
         methods = self.request.root.properties[PROP.PAYMENT_METHODS]
         del methods[:]  # Remove all payment methods
         # Run the setup
         setup.db_setup_pay_methods(self.request.root)
         self.request.session.flash(
             "Payment methods reset to default values.", "info")
         # Mark methods as changed
         methods._p_changed = True
     return {"methods": methods}
Exemple #14
0
 def purchase_agreement_view(self):
     if self.user.purchase_agreement:
         return HTTPFound(location=self.request.route_path("privacy_policy_act"))
     agreement_doc = PROP_KEYS.getProperty(self.request, PROP_KEYS.PURCHASE_AGREEMENT)
     if "submit" in self.request.POST:
         # Verify the checkbox is checked
         chk_response = ("agreement" in self.request.POST and self.request.POST["agreement"] == "agreed")
         if chk_response:
             self.user.purchase_agreement = True
             return HTTPFound(location=self.request.route_path("privacy_policy_act"))
         else:
             self.request.session.flash("The form was submitted without you accepting the purchase agreement. Please first accept the agreement and then click submit.", "error")
     return {
         "document": agreement_doc
     }
Exemple #15
0
 def alter_payment_view(self):
     tick_id = self.request.matchdict["tick_id"]
     user = self.user
     ticket = None
     # Find ticket
     for tick in user.tickets:
         if tick.__name__ == tick_id:
             ticket = tick
             break
     # If not found, user doesn't own it!
     if ticket == None:
         self.request.session.flash("The requested ticket does not exist.", "error")
         return HTTPFound(location=self.request.route_path("user_profile"))
     # Check this is not a purchased ticket
     elif ticket.payment.paid:
         self.request.session.flash("The requested ticket has already been paid for.", "error")
         return HTTPFound(location=self.request.route_path("user_profile"))
     # Move to the payment stage
     elif "method" in self.request.GET:
         logging.info(self.user.username + " has chosen " + self.request.GET["method"] + " as payment method")
         # Check this is a valid, registered payment method
         method = self.get_payment_method(self.request.GET["method"].lower())
         if method != None:
             # Look for a route to make this payment by
             try:
                 route_url = self.request.route_path("alter_pay_" + method.__name__, payment_id=ticket.payment.__name__)
                 return HTTPFound(location=route_url)
             except(KeyError):
                 self.request.session.flash("An error occurred with the payment method you selected, please try again.", "error")
                 logging.warn(self.user.username + " has requested a payment route that doesn't exist")
         else:
             self.request.session.flash("An error occurred with the payment method you selected, please try again.", "error")
             logging.warn(self.user.username + " has requested a payment method either that doesn't exist or is disabled")
     # Get payment method
     orig_method = self.get_payment_method(ticket.payment.history[-1].method)
     orig_method_name = "Unknown"
     if orig_method != None:
         orig_method_name = orig_method.name
     # Work out what payment methods are available to us
     enabled_methods = [x for x in PROP.getProperty(self.request, PROP.PAYMENT_METHODS) if x.enabled and x.public]
     eligible_methods = [x for x in enabled_methods if len(x.groups) == 0 or self.user.__parent__ in x.groups]
     return {
         "tick_id": tick_id,
         "payment" : ticket.payment,
         "orig_method_name": orig_method_name,
         "orig_method": orig_method,
         "methods": eligible_methods
     }
Exemple #16
0
 def change_payment_method_view(self):
     payments = self.request.root.payments
     # Get payment if possible
     if not self.request.matchdict["ref_code"] in self.request.root.payments:
         return HTTPFound(
             location=self.request.route_path("admin_payments"))
     payment = payments[self.request.matchdict["ref_code"]]
     active_stage = (payment.history[len(payment.history) - 1] if
                     (len(payment.history) > 0) else None)
     # Check if already marked as paid
     if payment.paid:
         return HTTPFound(location=self.request.route_path(
             'admin_single_payment', ref_code=payment.__name__))
     # Deal with post request
     if "submit" in self.request.POST:
         if not "method" in self.request.POST:
             self.request.session.flash(
                 "Make sure to select a new payment method.", "error")
         else:
             method = self.request.POST["method"]
             # - First check if the active stage is the current method
             if active_stage.method != method:
                 # Update payment method to match that entered
                 active_stage = PaymentStage()
                 active_stage.__parent__ = payment
                 active_stage.method = method
                 active_stage.stage_owner = payment.owner.__name__
                 active_stage.amount_paid = 0
                 active_stage.processing_charge = 0
                 active_stage.completed = False
                 payment.history.append(active_stage)
             self.request.session.flash(
                 "Payment details have been updated.", "info")
             return HTTPFound(location=self.request.route_path(
                 'admin_single_payment', ref_code=payment.__name__))
     return {
         "payment":
         payment,
         "active_stage":
         active_stage,
         "methods":
         PROP_KEYS.getProperty(self.request, PROP_KEYS.PAYMENT_METHODS)
     }
Exemple #17
0
 def compose_and_send(self,
                      subject,
                      raw_message,
                      user_id,
                      pdf_attachment=None):
     if not user_id in self.request.root.users: return False
     user = self.request.root.users[user_id]
     data = {
         "EVENTNAME":
         PROP_KEYS.getProperty(self.request, PROP_KEYS.EVENT_NAME),
         "NAME": (user.profile.fullname
                  if user.profile and user.profile.fullname else "-"),
         "MESSAGE":
         raw_message
     }
     # Send
     mailer = Mail(self.request)
     message = mailer.compose_from_template("generic", data)
     return mailer.send_email(user_id,
                              subject,
                              message,
                              pdf_attachment=pdf_attachment)
Exemple #18
0
 def guest_info_edit_pay_view(self):
     # Get the ticket details
     user = self.user
     tick_id = (self.request.matchdict["tick_id"]
                if "tick_id" in self.request.matchdict else None)
     if tick_id == None:
         self.request.session.flash(
             "An error occurred whilst trying to retrieve the ticket details.",
             "error")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Check guest details requirement is actually enabled
     if not self.guest_details_required:
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Try getting the ticket
     try:
         ticket = [x for x in user.tickets if x.__name__ == tick_id][0]
     except Exception:
         self.request.session.flash(
             "An error occurred whilst trying to retrieve the ticket details.",
             "error")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Check if this ticket is locked down
     locked_down = ticket.tick_type.locked_down
     if not locked_down:  # Check all addons as well
         for addon in ticket.addons.values():
             if addon.locked_down:
                 locked_down = True
                 break
     if locked_down:
         self.request.session.flash(
             "Editing of guest details for this ticket has been disabled.",
             "info")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Check that we haven't already paid for editing of this ticket and that we have to in the first place!
     if (self.details_fee_enabled
             and ticket.change_enabled) or not self.details_fee_enabled:
         return HTTPFound(location=self.request.route_path(
             "ticket_edit_guest", tick_id=tick_id))
     # Check if the user first needs to complete payment
     if not ticket.payment.paid:
         self.request.session.flash(
             "You must complete payment for this ticket before editing guest details.",
             "info")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # If this is the owners ticket then don't allow them to change the details
     if ticket.guest_info == ticket.owner.profile:
         return HTTPFound(
             location=self.request.route_path("user_profile_edit"))
     # If we receive a payment then deal with it
     if "stripeToken" in self.request.POST:
         # Run Stripe payment to authorise
         organisation_name = self.get_payment_method('stripe').settings[
             PROP_KEYS.ORGANISATION_NAME].value
         details_fee = PROP_KEYS.getProperty(self.request,
                                             PROP_KEYS.DETAILS_FEE)
         token = self.request.POST["stripeToken"]
         stripe.api_key = self.get_payment_method('stripe').settings[
             PROP_KEYS.STRIPE_API_KEY].value
         charge = None
         error = None
         try:
             charge = stripe.Charge.create(amount=details_fee,
                                           currency="gbp",
                                           source=token,
                                           description=organisation_name)
             if "paid" in charge and charge["paid"] == True:
                 # Update the ticket that a guest alteration is allowed and then forward to the editing form
                 ticket.change_enabled = True
                 # Append a payment stage covering the detail change charge
                 charge_stage = PaymentStage()
                 charge_stage.__parent__ = ticket.payment
                 charge_stage.method_properties["last_four"] = charge[
                     "source"]["last4"]
                 charge_stage.method_properties["ref_code"] = charge["id"]
                 charge_stage.amount_paid = details_fee
                 charge_stage.processing_charge = details_fee
                 charge_stage.completed = charge_stage.received = charge_stage.cashed = True
                 charge_stage.stage_owner = self.user.__name__
                 charge_stage.date = datetime.now()
                 charge_stage.method = "stripe"
                 charge_stage.transfer = True
                 ticket.payment.history.append(charge_stage)
                 # Forward to the page to actually edit details
                 return HTTPFound(location=self.request.route_path(
                     "ticket_edit_guest", tick_id=tick_id))
             else:
                 error = "The payment failed, please check your details and try again!"
                 if "failure_message" in charge and charge[
                         "failure_message"] != None:
                     error = charge["failure_message"]
         except stripe.error.CardError, e:
             logging.error(self.user.username +
                           ": Stripe invalid card error occurred: %s" % e)
             error = e
         except stripe.error.InvalidRequestError, e:
             logging.error(self.user.username +
                           ": Stripe invalid card request occurred: %s" % e)
             error = e
Exemple #19
0
 def guest_info_view_do(self):
     user = self.user
     tick_id = None
     post_purchase = (
         self.request.matched_route.name == "ticket_edit_guest")
     # Find the ticket ID
     if "tick_id" in self.request.matchdict:
         tick_id = self.request.matchdict["tick_id"]
     elif "tick" in self.request.GET:
         tick_id = self.request.GET["tick"]
     elif "tickid" in self.request.POST:
         tick_id = self.request.POST["tick_id"]
     else:
         if post_purchase:
             self.request.session.flash(
                 "An error occurred whilst trying to retrieve the ticket details.",
                 "error")
             return HTTPFound(location=self.request.route_path(
                 "ticket_details", tick_id=tick_id))
         else:
             return HTTPFound(
                 location=self.request.route_path("order_details"))
     # Try getting the ticket
     try:
         ticket = [x for x in user.tickets if x.__name__ == tick_id][0]
     except Exception:
         if post_purchase:
             self.request.session.flash(
                 "An error occurred whilst trying to retrieve the ticket details.",
                 "error")
             return HTTPFound(location=self.request.route_path(
                 "ticket_details", tick_id=tick_id))
         else:
             return HTTPFound(
                 location=self.request.route_path("order_details"))
     # Check if this ticket is locked down
     locked_down = ticket.tick_type.locked_down
     if not locked_down:  # Check all addons as well
         for addon in ticket.addons.values():
             if addon.locked_down:
                 locked_down = True
                 break
     if locked_down:
         self.request.session.flash(
             "Editing of guest details for this ticket has been disabled.",
             "info")
         return HTTPFound(location=self.request.route_path("user_profile"))
     # Check if this ticket is allowed to be edited
     if post_purchase and self.details_fee_enabled and not ticket.change_enabled:
         self.request.session.flash(
             "Editing of guest details for this ticket has not been paid for.",
             "info")
         return HTTPFound(location=self.request.route_path(
             "ticket_edit_guest_pay", tick_id=tick_id))
     elif post_purchase and not ticket.payment.paid:
         self.request.session.flash(
             "You must complete payment for this ticket before editing guest details.",
             "info")
         return HTTPFound(location=self.request.route_path("user_profile",
                                                           tick_id=tick_id))
     # If this is the owners ticket then don't allow them to change the details
     if ticket.guest_info == ticket.owner.profile:
         if post_purchase:
             return HTTPFound(
                 location=self.request.route_path("user_profile_edit"))
         else:
             return HTTPFound(
                 location=self.request.route_path("order_details"))
     # Ok - process the form and validate all details
     processor = ProcessAndValidate(
         self.request.POST,
         self.request.registry._settings["base_dir"],
         PROP_KEYS.getProperty(self.request, PROP_KEYS.MINIMUM_AGE),
         PROP_KEYS.getProperty(self.request, PROP_KEYS.EVENT_DATE),
         photo_required=PROP_KEYS.getProperty(self.request,
                                              PROP_KEYS.PHOTO_REQUIRED),
         phone_number_required=False)
     try:
         data = processor.process()
         # If we get this far all data is valid and we can continue
         if ticket.guest_info == None:
             ticket.guest_info = UserProfile()
             ticket.guest_info.__parent__ = ticket
             ticket.guest_info.ticket = ticket
             ticket._p_changed = True
         # - Fill in details
         info = ticket.guest_info
         info.title = data["title"]
         info.forename = data["forename"]
         info.surname = data["surname"]
         info.email = data["email"]
         info.raven_user = data["atcambridge"]
         info.photo_file = data["photofile"]
         info.dob = data["dob"]
         if info.raven_user:
             info.crsid = data["crsid"]
             info.email = info.crsid + "@cam.ac.uk"
             info.college = data["college"]
             info.grad_status = data["grad_status"]
         info._p_changed = True
         # If we are post purchase, and charging for detail changes make sure we lock again
         if post_purchase:
             ticket.change_enabled = False
     except ValueError, e:
         message = str(e)
         self.request.session.flash(message, "error")
         # Get title
         title = ""
         if "title" in self.request.POST:
             title = self.request.POST["title"]
             if title == "Other":
                 title = self.request.POST["othertitle"]
         email = crsid = college = grad_status = None
         if (self.request.POST["atcambridge"] == "yes"):
             email = self.request.POST["crsid"].replace(" ",
                                                        "") + "@cam.ac.uk"
             crsid = self.request.POST["crsid"]
             college = self.request.POST["college"]
             grad_status = self.request.POST["grad_status"]
         else:
             email = self.request.POST["email"]
         return {
             "tick_id":
             tick_id,
             "title":
             title,
             "othertitle":
             (title not in ["Mr", "Mrs", "Miss", "Ms", "Dr", "Prof", "Rev"]
              and len(title) > 0),
             "forename":
             self.request.POST["forename"],
             "surname":
             self.request.POST["surname"],
             "email":
             email,
             "dob_year":
             self.request.POST["dob_year"],
             "dob_month":
             self.request.POST["dob_month"],
             "dob_day":
             self.request.POST["dob_day"],
             "atcambridge":
             self.request.POST["atcambridge"],
             "crsid":
             crsid,
             "college":
             college,
             "grad_status":
             grad_status,
             "post_purchase":
             post_purchase
         }
Exemple #20
0
    def settings_view(self):
        # Copy in existing setting values
        settings = {}
        for key in self.settings_map:
            if key in self.request.root.properties:
                settings[key] = self.request.root.properties[key]

        # Process posted data
        if "submit" in self.request.POST:
            # Store settings and then verify
            for key in self.settings_map:
                param = self.settings_map[key]
                field = param["field"]
                prep_value = None
                # Convert to a suitable format
                try:
                    if param["type"] == "hidden":
                        prep_value = (
                            self.request.POST[field] == param["test_val"])
                    elif param["type"] == "int":
                        prep_value = int(float(self.request.POST[field]))
                    elif param["type"] == "float":
                        prep_value = float(self.request.POST[field])
                    elif param["type"] == "money":
                        prep_value = int(
                            float(self.request.POST[field]) * 100.0)
                    elif param["type"] == "date":
                        raw_val = self.request.POST[field]
                        if raw_val == None:
                            continue
                        parts = raw_val.split("/")
                        if len(parts) != 3:
                            continue
                        day = int(float(parts[0]))
                        month = int(float(parts[1]))
                        year = (int(float(parts[2]))
                                if int(float(parts[2])) > 1000 else
                                (int(float(parts[2])) + 1000))
                        prep_value = datetime(year, month, day)
                    elif param["type"] == "password":
                        raw_val = self.request.POST[field]
                        prep_value = (raw_val if not '*' in raw_val else
                                      self.request.root.properties[key])
                    elif param["type"] == "checkbox":
                        prep_value = (field in self.request.POST
                                      and self.request.POST[field]
                                      == param["test_val"])
                    elif param["type"] == "text":
                        prep_value = self.request.POST[field]
                except Exception as e:
                    print "Exception caught when storing setting", e
                # Store the value into the settings dictionary
                if prep_value != None:
                    settings[key] = prep_value
            # Perform some basic verification
            if settings[PROP.PAYMENT_WINDOW] <= 0:
                self.request.session.flash(
                    "Payment window must be greater than zero days.", "error")
            elif settings[PROP.MAX_SESSION_TIME] < 5:
                self.request.session.flash(
                    "The maximum session time must be greater than 5 minutes to ensure smooth check-out.",
                    "error")
            elif settings[PROP.CONCURRENT_NUM] <= 0:
                self.request.session.flash(
                    "The maximum number of concurrent customers must be greater than zero.",
                    "error")
            elif settings[PROP.MAX_TICKETS] < 1:
                self.request.session.flash(
                    "The maximum ticket number must be at least one.", "error")
            elif settings[PROP.MINIMUM_AGE] < 0:
                self.request.session.flash(
                    "The minimum age must be greater than zero.", "error")
            else:
                # Copy across to actually save
                for key in settings:
                    self.request.root.properties[key] = settings[key]
                # Save selected control groups
                groups = self.request.params.getall("selgroup")
                to_remove = []
                for group in self.request.root.properties[PROP.CONTROL_GROUPS]:
                    if group not in groups:
                        to_remove.append(group)
                for group in to_remove:
                    self.request.root.properties[PROP.CONTROL_GROUPS].remove(
                        group)
                for group in groups:
                    if group not in self.request.root.properties[
                            PROP.CONTROL_GROUPS]:
                        self.request.root.properties[
                            PROP.CONTROL_GROUPS].append(group)
            # Change the enabled payment methods
            methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
            enabled_methods = []
            for key in [
                    x for x in self.request.POST.keys()
                    if "pm_enable_" in x.lower()
            ]:
                method_key = key.split("pm_enable_")[1]
                enabled_methods.append(method_key.lower())
            for method in methods:
                method.enabled = (
                    method.__name__.lower() in enabled_methods
                    and self.request.POST[("pm_enable_" +
                                           method.__name__.lower())] == "yes")

        # Prepare the values to be rendered
        rendered_values = {}
        for key in self.settings_map:
            param = self.settings_map[key]
            if key in settings:
                rendered_values[param["field"]] = settings[key]
            else:
                rendered_values[param["field"]] = ""

        # Do not publicly show the API key or passwords
        rendered_values["stripe_api_key"] = '*' * 20

        # Return data to renderer
        return {
            "settings":
            rendered_values,
            "control_groups":
            PROP.getProperty(self.request, PROP.CONTROL_GROUPS),
            "purchase_agreement":
            (self.request.root.properties[PROP.PURCHASE_AGREEMENT].main_body
             and len(self.request.root.properties[
                 PROP.PURCHASE_AGREEMENT].main_body) > 0),
            "privacy_policy":
            (self.request.root.properties[PROP.PRIVACY_POLICY].main_body and
             len(self.request.root.properties[PROP.PRIVACY_POLICY].main_body) >
             0),
            "cookie_policy":
            (self.request.root.properties[PROP.COOKIE_POLICY].main_body and
             len(self.request.root.properties[PROP.COOKIE_POLICY].main_body) >
             0),
            "payment_methods":
            PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        }
Exemple #21
0
    def pay_stripe_view(self, error=None):
        # Check if the customer's session has timed out
        if Queue(self.request).timed_out():
            return HTTPFound(self.request.route_path("purchase_timeout"))

        # Check the customer is ready to pay
        if not self.details_complete:
            self.request.session.flash(
                "Your guest details are incomplete, please update these before continuing.",
                "info")
            return HTTPFound(location=self.request.route_path("order_details"))

        # Verify stripe is enabled
        all_methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [
            x for x in all_methods
            if x.__name__ == "stripe" and x.enabled == True
        ]
        method = method[0] if len(method) > 0 else None
        if method == None:
            self.request.session.flash(
                "An error occurred with the payment method you selected, please try another.",
                "error")
            return HTTPFound(location=self.request.route_path("order_details"))

        # Retrieve stripe processing values
        process_percentage = method.settings[
            PROP.PAYMENT_PROCESSING_PERCENTAGE].value
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value
        pub_api_key = method.settings[PROP.STRIPE_PUBLIC_KEY].value
        organisation_name = method.settings[PROP.ORGANISATION_NAME].value
        contact_email = method.settings[PROP.STRIPE_CONTACT_EMAIL].value

        # Check what the user has to buy
        if len(self.session_tickets) == 0:
            self.request.session.flash(
                "No tickets were found in your shopping basket, please try again.",
                "error")
            return HTTPFound(location=self.request.route_path("user_profile"))

        # Calculate the amount to pay
        subtotal = 0
        for tick in self.session_tickets:
            subtotal += tick.total_cost
        processing = int(ceil(subtotal * process_percentage) + process_fee)
        total = subtotal + processing

        # Render the payment page
        return {
            "error": error,
            "method": method,
            "subtotal": self.format_price(subtotal),
            "processing": self.format_price(processing),
            "total": self.format_price(total),
            "org_name": organisation_name,
            "contact_email": contact_email,
            "stripe_pub_key": pub_api_key,
            "penny_total": total,
            "pay_description": str(len(self.session_tickets)) + " Ticket(s)",
            "alteration": False,
            "payment": None
        }
Exemple #22
0
 def cookie_policy_view(self):
     agreement_doc = PROP_KEYS.getProperty(self.request,
                                           PROP_KEYS.COOKIE_POLICY)
     return {"document": agreement_doc}
Exemple #23
0
    def alter_pay_stripe_completion_do(self):
        # Check that we have a stripe charge object
        stripe_charge = self.request.session[
            "stripe_charge"] if "stripe_charge" in self.request.session else None
        if stripe_charge == None:
            logging.exception(
                self.user.username +
                ": Stripe charge object was not found in session")
            return self.alter_pay_stripe_view(
                error=
                "During processing the Stripe transaction has been lost, please contact the ticketing officer."
            )

        # Clear the charge object from the session
        self.request.session.pop("stripe_charge", None)

        # Retrieve the payment
        payment_id = self.request.matchdict[
            "payment_id"] if "payment_id" in self.request.matchdict else None
        payment = self.request.root.payments[
            payment_id] if payment_id != None else None
        if payment == None:
            logging.exception(
                self.user.username +
                ": Payment could not be located whilst trying to update payment with Stripe charge %s"
                % stripe_charge["id"])
            self.refund_stripe_charge(stripe_charge["id"])
            return self.alter_pay_stripe_view(
                error=
                "During processing a critical error occurred, please contact the ticketing officer immediately."
            )

        # Pickup the stripe method (regardless of if disabled as we now have made a charge!)
        all_methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [x for x in all_methods if x.__name__ == "stripe"]
        method = method[0] if len(method) > 0 else None
        if method == None:
            logging.exception(
                self.user.username +
                ": Method could not be found whilst trying to update payment %s with Stripe charge %s"
                % (payment_id, stripe_charge["id"]))
            self.refund_stripe_charge(stripe_charge["id"])
            return self.alter_pay_stripe_view(
                error=
                "During processing a critical error occurred, please contact the ticketing officer immediately."
            )

        # Retrieve stripe processing values
        process_percentage = method.settings[
            PROP.PAYMENT_PROCESSING_PERCENTAGE].value
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value

        # Calculate the amount to pay
        subtotal = payment.amount_remaining
        processing = int(ceil(subtotal * process_percentage) + process_fee)
        total = int(ceil(subtotal + processing))

        try:
            # Acquire the source information
            charge_id = stripe_charge[
                "id"] if "source" in stripe_charge else None
            source = stripe_charge[
                "source"] if "source" in stripe_charge else None
            last_four = source[
                "last4"] if source != None and "last4" in source else None
            logging.info(self.user.username +
                         ": Constructing payment from Stripe charge %s" %
                         charge_id)

            # Attach new payment stage to the payment
            stage = PaymentStage()
            stage.__parent__ = payment
            stage.method = "stripe"
            stage.method_properties["last_four"] = last_four
            stage.method_properties["ref_code"] = charge_id
            stage.amount_paid = total
            stage.processing_charge = processing
            stage.completed = True
            stage.received = stage.cashed = True
            stage.stage_owner = self.user.__name__
            payment.history.append(stage)
            payment.completed_date = datetime.now()
            self.request.session["payment_id"] = payment.ref_code
            logging.info(
                self.user.username +
                ": Successfully updated payment %s with Stripe charge %s" %
                (payment.ref_code, charge_id))
            return HTTPFound(location=self.request.route_path(
                "alter_confirm", payment_id=payment_id))

        except Exception as e:
            logging.exception(self.user.username +
                              ": Exception thrown in Stripe checkout: %s" % e)
            # We need to refund immediately as this is an error
            charge_id = stripe_charge[
                "id"] if "source" in stripe_charge else None
            if not self.refund_stripe_charge(charge_id):
                return self.alter_pay_stripe_view(
                    error=
                    "An error occurred during Stripe checkout and the system could not refund you automatically: %s"
                    % e)
            else:
                return self.alter_pay_stripe_view(
                    error=
                    "An error occurred during Stripe checkout but you have been automatically refunded the full amount: %s"
                    % e)
        # We should never get here!
        logging.exception(self.user.username +
                          ": Stripe payment completion escaped expected block")
        return self.alter_pay_stripe_view(
            error=
            "An unexpected error occurred during checkout, please contact the ticketing officer."
        )
Exemple #24
0
 def privacy_policy_view(self):
     agreement_doc = PROP_KEYS.getProperty(self.request,
                                           PROP_KEYS.PRIVACY_POLICY)
     return {"document": agreement_doc}
Exemple #25
0
 def purchase_agreement_view(self):
     agreement_doc = PROP_KEYS.getProperty(self.request,
                                           PROP_KEYS.PURCHASE_AGREEMENT)
     return {"document": agreement_doc}
Exemple #26
0
    def alter_pay_stripe_view_do(self):
        # Retrieve the payment
        payment_id = self.request.matchdict[
            "payment_id"] if "payment_id" in self.request.matchdict else None
        payment = self.request.root.payments[
            payment_id] if payment_id != None else None
        if payment == None:
            self.request.session.flash(
                "Could not find the requested payment, please try again.",
                "info")
            return HTTPFound(location=self.request.route_path("user_profile"))

        # This view performs the Stripe transaction as it takes significant time. If we were to
        # construct and process the payment here as well, we would have a database transaction
        # open for too long and hence we would run the risk of a database conflict. So, instead,
        # process the Stripe charge, attach the result to the session, and then move on to the
        # construction of the payment
        # Verify stripe is enabled
        all_methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [
            x for x in all_methods
            if x.__name__ == "stripe" and x.enabled == True
        ]
        method = method[0] if len(method) > 0 else None
        if method == None:
            self.request.session.flash(
                "An error occurred with the payment method you selected, please try another.",
                "error")
            return HTTPFound(location=self.request.route_path("user_profile"))

        # Check that we have been passed a Stripe purchase token
        purchase_token = self.request.POST[
            "stripeToken"] if "stripeToken" in self.request.POST else None
        if purchase_token == None:
            return self.alter_pay_stripe_view(
                error="No token was provided by Stripe, please try again.")

        # Retrieve stripe processing values
        process_percentage = method.settings[
            PROP.PAYMENT_PROCESSING_PERCENTAGE].value
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value
        organisation_name = method.settings[PROP.ORGANISATION_NAME].value
        priv_api_key = method.settings[PROP.STRIPE_API_KEY].value

        # Calculate the amount to pay
        subtotal = payment.amount_remaining
        processing = int(ceil(subtotal * process_percentage) + process_fee)
        total = int(ceil(subtotal + processing))

        charge = None
        try:
            logging.info(
                self.user.username +
                ": Attempting to make Stripe charge to alter payment %s with total %i with token %s"
                % (payment_id, total, purchase_token))
            stripe.api_key = priv_api_key
            charge = stripe.Charge.create(amount=int(ceil(total)),
                                          currency="gbp",
                                          description=organisation_name,
                                          source=purchase_token)
            # Handle a charge marked not paid
            if charge == None:
                logging.exception(self.user.username +
                                  ": Stripe returned a null charge object")
                return self.alter_pay_stripe_view(
                    error=
                    "Stripe failed to process the transaction, please get in touch with the ticketing officer."
                )

            if "paid" not in charge or charge["paid"] != True:
                logging.exception(
                    self.user.username +
                    ": Charge to Stripe failed with ID %s for amount %i %s" %
                    (charge["id"], charge["amount"], charge["currency"]))
                return self.alter_pay_stripe_view(
                    error="Stripe did not accept the charge, please try again."
                )

            # Attach the charge to the session and move on to the completion phase
            logging.info(
                self.user.username +
                ": Charge to Stripe succeeded with ID %s for amount %i %s" %
                (charge["id"], charge["amount"], charge["currency"]))
            self.request.session["stripe_charge"] = charge
            return HTTPFound(location=self.request.route_path(
                "alter_pay_stripe_completion", payment_id=payment.__name__))
        except stripe.error.CardError as e:
            logging.exception(self.user.username +
                              ": Stripe declined card, raised CardError: %s" %
                              e)
            return self.alter_pay_stripe_view(
                error="Stripe declined your card with error: %s" % e)
        except stripe.error.RateLimitError as e:
            logging.exception(
                self.user.username +
                ": Stripe declined transaction due to rate limit: %s" % e)
            return self.alter_pay_stripe_view(
                error=
                "Stripe was too busy to handle this transaction, please try again."
            )
        except stripe.error.InvalidRequestError as e:
            logging.exception(self.user.username +
                              ": Stripe raised an InvalidRequestError: %s" % e)
            return self.alter_pay_stripe_view(
                error="Stripe declined the payment request with error: %s" % e)
        except stripe.error.AuthenticationError as e:
            logging.exception(self.user.username +
                              ": Stripe raised AuthenticationError: %s" % e)
            return self.alter_pay_stripe_view(
                error=
                "Authentication with the Stripe service failed with error: %s"
                % e)
        except stripe.error.APIConnectionError as e:
            logging.exception(self.user.username +
                              ": Stripe raised APIConnectionError: %s" % e)
            return self.alter_pay_stripe_view(
                error=
                "API connection to the Stripe service failed with error: %s" %
                e)
        except stripe.error.StripeError as e:
            logging.exception(self.user.username +
                              ": Stripe a generic StripeError: %s" % e)
            return self.alter_pay_stripe_view(
                error="An error ocurred when accessing the Stripe service: %s"
                % e)
        except Exception as e:
            logging.exception(self.user.username +
                              ": Exception thrown in Stripe checkout: %s" % e)
            if charge != None and "paid" in charge and charge["paid"] == True:
                self.refund_stripe_charge(charge["id"])
                return self.alter_pay_stripe_view(
                    error=
                    "An unexpected error occurred during checkout, your card may have been charged - please get in touch with the ticketing officer immediately: %s"
                    % e)
            else:
                return self.alter_pay_stripe_view(
                    error="An unexpected error occurred during checkout")
        # We should never get here!
        logging.exception(self.user.username +
                          ": Stripe payment escaped expected block")
        return self.alter_pay_stripe_view(
            error=
            "An unexpected error occurred during checkout, please contact the ticketing officer."
        )
Exemple #27
0
class BoxOffice(BaseLayout):
    @view_config(route_name="buy_tickets",
                 context=Ticketing,
                 permission="basic",
                 renderer="templates/buy.pt")
    def buy_view(self):
        # Check agreements
        if not self.user.purchase_agreement:
            return HTTPFound(
                location=self.request.route_path("purchase_agreement_act"))
        elif not self.user.privacy_agreement:
            return HTTPFound(
                location=self.request.route_path("privacy_policy_act"))
        # Check we can be here
        # - First check queue/active status
        if Queue(self.request).timed_out():
            return HTTPFound(self.request.route_path("purchase_timeout"))
        # - Check if group is currently allowed to purchase
        elif self.request.root.properties[
                PROP.
                CUSTOMER_CONTROL_ENABLED] and self.group.__name__ not in self.request.root.properties[
                    PROP.CONTROL_GROUPS]:
            self.request.session.flash(
                "Sorry but you are currently not allowed to purchase tickets, please come back later.",
                "info")
            return HTTPFound(location=self.request.route_path("user_profile"))
        # - Now check user details
        elif not self.user_details_complete:
            self.request.session.flash(
                "You must complete all of your profile details before purchasing tickets.",
                "error")
            return HTTPFound(
                location=self.request.route_path("user_profile_edit"))
        # Ok, all good
        user = self.user
        # First ensure that the queuer object has reference to user
        queuer = self.queue_item
        if queuer != None:
            queuer.user_id = user.__name__
        # Then return any previous order
        issue = Issuer(self.request.root)
        try:
            issue.returnUnpurchasedTickets(user.__name__)
        except Exception, e:
            logging.exception(
                "%s: Had issue returning previously unpurchased tickets: %s" %
                (self.user.username, str(e)))
            self.request.session.flash(
                "Had an issue returning previously unpurchased tickets, please try again.",
                "error")
        # Deal with submission
        if "submit" in self.request.POST:
            # Check order for limit
            total_ticks = 0
            tickets = {}
            for key in self.request.POST:
                if "TYPE-" in key:
                    num_tick = int(self.request.POST[key])
                    tick_type = [
                        x.tick_type
                        for x in self.request.root.ticket_pools.values()
                        if x.tick_type.__name__ == key
                    ][0]
                    tickets[key] = {
                        "quantity": num_tick,
                        "name": tick_type.name,
                    }
                    total_ticks += num_tick
            if PROP.getProperty(
                    self.request,
                    PROP.LIMIT_ENABLED) and total_ticks > PROP.getProperty(
                        self.request, PROP.MAX_TICKETS):
                return {
                    "error":
                    "At the moment you can only purchase a maximum of %i tickets, please correct your order."
                    % PROP.getProperty(self.request, PROP.MAX_TICKETS)
                }
            elif total_ticks <= 0:
                return {
                    "error":
                    "You have not selected any tickets for purchase, please indicate the quantities you want and click Next."
                }
            # All good to go now
            error = None
            for key in tickets:
                quantity = tickets[key]["quantity"]
                name = tickets[key]["name"]
                # Check order
                if quantity > 0:
                    try:
                        issue.issueTickets(user.__name__, key, quantity)
                    except OutOfStock:
                        error = "There is too little stock left of %s to complete your order." % name
                        break
                    except UserAtLimit:
                        error = "Purchasing this number of tickets will exceed the limit of %i tickets." % PROP.getProperty(
                            self.request, PROP.MAX_TICKETS)
                        break
                    except UserAtTypeLimit, e:
                        error = "You are exceeding the max number of purchases allowed (%i) of ticket type \"%s\"." % (
                            e.limit, e.tick_type)
                        break
                    except Exception, e:
                        logging.exception(
                            "%s: unexpected error occurred whilst issuing tickets: %s"
                            % (self.user.username, str(e)))
                        error = "Something went wrong that we were not expecting, please try again."
                        break
Exemple #28
0
 def api_checkin_enact_post_view(self):
     try:
         # Check privileges are at a sufficient level
         self.verify_privileges("staff")
         # Check if check-in is active
         if (PROP.getProperty(self.request, PROP.CHECKIN_ACTIVE) != True):
             return {"error": "Check-in is not active"}
         # Check that at least one ticket ID has been provided
         if "ticket_ids" not in self.request.POST:
             logging.error(
                 "API: Ticket IDs not provided in request by user %s" %
                 self.auth_user.username)
             return {"error": "Ticket IDs missing from request"}
         ticket_ids = None
         try:
             ticket_ids = json.loads(self.request.POST["ticket_ids"])
         except Exception as e:
             logging.error(
                 "API: Ticket IDs were provided in an invalid format by user %s: %s"
                 % (self.auth_user.username, str(e)))
             return {"error": "Ticket ID format is invalid"}
         if ticket_ids == None:
             logging.error(
                 "API: Ticket IDs not provided in request by user %s" %
                 self.auth_user.username)
             return {"error": "No ticket IDs were provided"}
         ticket_ids = [x for x in ticket_ids if isinstance(x, basestring)]
         if len(ticket_ids) == 0:
             logging.error(
                 "API: Ticket IDs not provided in request by user %s" %
                 self.auth_user.username)
             return {"error": "No ticket IDs were provided"}
         # Check that all of the ticket IDs provided are valid
         all_tickets = []
         for payment in self.request.root.payments.values():
             all_tickets += payment.tickets
         tickets = [
             x for x in all_tickets
             if x.__name__ in ticket_ids and x.id_code in ticket_ids
         ]
         if len(tickets) == 0:
             logging.error(
                 "API: No tickets found for IDs %s provided by user %s" %
                 (self.request.POST["ticket_ids"], self.auth_user.username))
             return {"error": "No tickets were found for the IDs provided"}
         elif len(tickets) != len(ticket_ids):
             logging.error(
                 "API: Incorrect ticket count found for IDs %s provided by user %s"
                 %
                 (self.request.POST["ticket_ids"], self.auth_user.username))
             return {"error": "Some tickets were not found"}
         # Check all are paid and not already checked-in
         already_checked_in = []
         for tick in tickets:
             if not tick.payment.paid:
                 logging.error(
                     "API: Could not enact check in as at least one of the tickets is unpaid, tickets %s by user %s"
                     % (self.request.POST["ticket_ids"],
                        self.auth_user.username))
                 return {"error": "Payment is not complete for tickets"}
             elif tick.checked_in:
                 already_checked_in.append(tick.__name__)
         if len(already_checked_in) > 0:
             logging.error(
                 "API: Some tickets are already checked in %s, new check-in enaction by user %s"
                 % (",".join(already_checked_in), self.auth_user.username))
             return {
                 "error": "Some tickets are already checked-in",
                 "already_checked_in": already_checked_in,
                 "ticket_ids": ticket_ids
             }
         # Process the check-in for the tickets listed
         for tick in tickets:
             tick.checked_in = True
             tick.checkin_data = CheckIn()
             tick.checkin_data.__parent__ = tick
             tick.checkin_data.date = datetime.now()
             tick.checkin_data.enacted_by = self.auth_user
             tick.checkin_data.overriden = False
             # Log the action
             logging.info("API: Ticket %s was checked in by user %s" %
                          (tick.__name__, self.auth_user.username))
         return {"checked_in": ticket_ids}
     except APIPrivilegeException as e:
         logging.error(
             "API: A privilege exception was thrown for user %s during check-in enaction: %s"
             % (self.auth_user.username, str(e)))
         return {"error": str(e)}
     except APIAuthenticationException as e:
         logging.error(
             "API: User accessing check-in enaction is not authenticated")
         return {"error": str(e)}
     except Exception as e:
         if self.auth_user != None:
             logging.error(
                 "API: An exception was thrown for user %s during check-in enaction: %s"
                 % (self.auth_user.username, str(e)))
         else:
             logging.error(
                 "API: An exception was thrown during check-in enaction: %s"
                 % str(e))
         return {"error": "An unexpected error occurred"}
Exemple #29
0
 def api_checkin_query_post_view(self):
     try:
         # Check privileges are at a sufficient level
         self.verify_privileges("staff")
         # Check if check-in is active
         if (PROP.getProperty(self.request, PROP.CHECKIN_ACTIVE) != True):
             return {"error": "Check-in is not active"}
         # Check the form of the query
         if "query_type" not in self.request.POST or "query_value" not in self.request.POST:
             return {"error": "Query type or value missing from request"}
         query_type = self.request.POST["query_type"].lower()
         query_value = self.request.POST["query_value"]
         if query_type not in ["payment_id", "ticket_id", "checkin_code"]:
             logging.error(
                 "API: Check-in query requested with invalid type '%s' by user %s"
                 % (query_type, self.auth_user.username))
             return {"error": "Invalid query type"}
         # Log the query taking place
         logging.info(
             "API: Check-in query requested with type '%s' and value '%s' by user %s"
             % (query_type, query_value, self.auth_user.username))
         # Execute the query
         if query_type == "payment_id":
             if not query_value in self.request.root.payments:
                 return {"error": "No payment exists for the queried ID"}
             payment = self.request.root.payments[query_value]
             if payment.owner == None or payment.owner.profile == None:
                 return {"error": "Incomplete owner details"}
             # Prepare information on the tickets in the payment
             tickets = []
             for tick in payment.tickets:
                 if tick.guest_info != None:
                     tickets.append({
                         "ticket_id":
                         tick.__name__,
                         "type":
                         tick.tick_type.name,
                         "addons": [x.name for x in tick.addons.values()],
                         "notes":
                         tick.notes,
                         "guest_details": {
                             "title":
                             tick.guest_info.title,
                             "forename":
                             tick.guest_info.forename,
                             "surname":
                             tick.guest_info.surname,
                             "dob":
                             (tick.guest_info.dob.isoformat()
                              if tick.guest_info.dob != None else "n/a"),
                             "grad_status":
                             tick.guest_info.grad_status,
                             "college":
                             tick.guest_info.college
                         },
                         "checked_in":
                         tick.checked_in,
                         "checkin_details": ({
                             "date": (tick.checkin_data.date.isoformat()
                                      if tick.checkin_data.date else 0),
                             "enacted_by":
                             (tick.checkin_data.enacted_by.username if
                              tick.checkin_data.enacted_by.username != None
                              else 'n/a'),
                             "overridden":
                             tick.checkin_data.overridden
                         } if tick.checkin_data else 'n/a')
                     })
                 else:
                     tickets.append({
                         "ticket_id":
                         tick.__name__,
                         "type":
                         tick.tick_type.name,
                         "addons": [x.name for x in tick.addons.values()],
                         "notes":
                         tick.notes,
                         "checked_in":
                         tick.checked_in,
                         "checkin_details":
                         tick.checkin_data
                     })
             return {
                 "query_type": query_type,
                 "query_value": query_value,
                 # Payment details
                 "payment_id": payment.__name__,
                 "notes": payment.notes,
                 "paid": payment.paid,
                 "owner": {
                     "title":
                     payment.owner.profile.title,
                     "forename":
                     payment.owner.profile.forename,
                     "surname":
                     payment.owner.profile.surname,
                     "dob": (payment.owner.profile.dob.isoformat() if
                             payment.owner.profile.dob != None else "n/a"),
                     "grad_status":
                     payment.owner.profile.grad_status,
                     "college":
                     payment.owner.profile.college,
                     "notes":
                     payment.owner.notes
                 },
                 "tickets": tickets,
                 "num_tickets": len(payment.tickets)
             }
         elif query_type == "ticket_id":
             tickets = []
             for payment in self.request.root.payments.values():
                 tickets += payment.tickets
             tickets = [
                 x for x in tickets
                 if query_value.lower() in x.__name__.lower()
                 and query_value.lower() in x.id_code.lower()
             ]
             if len(tickets) == 1 and tickets[0].payment != None:
                 ticket = tickets[0]
                 payment = ticket.payment
                 return {
                     "query_type":
                     query_type,
                     "query_value":
                     query_value,
                     # Payment details
                     "payment_id":
                     payment.__name__,
                     "notes":
                     payment.notes,
                     "paid":
                     payment.paid,
                     "owner": {
                         "title":
                         payment.owner.profile.title,
                         "forename":
                         payment.owner.profile.forename,
                         "surname":
                         payment.owner.profile.surname,
                         "dob":
                         (payment.owner.profile.dob.isoformat()
                          if payment.owner.profile.dob != None else "n/a"),
                         "grad_status":
                         payment.owner.profile.grad_status,
                         "college":
                         payment.owner.profile.college,
                         "notes":
                         payment.owner.notes
                     },
                     "tickets": [{
                         "ticket_id":
                         ticket.__name__,
                         "type":
                         ticket.tick_type.name,
                         "addons": [x.name for x in ticket.addons.values()],
                         "notes":
                         ticket.notes,
                         "guest_details": {
                             "title":
                             ticket.guest_info.title,
                             "forename":
                             ticket.guest_info.forename,
                             "surname":
                             ticket.guest_info.surname,
                             "dob":
                             (ticket.guest_info.dob.isoformat()
                              if ticket.guest_info.dob != None else "n/a"),
                             "grad_status":
                             ticket.guest_info.grad_status,
                             "college":
                             ticket.guest_info.college
                         },
                         "checked_in":
                         ticket.checked_in,
                         "checkin_details": ({
                             "date": (ticket.checkin_data.date.isoformat()
                                      if ticket.checkin_data.date else 0),
                             "enacted_by":
                             (ticket.checkin_data.enacted_by.username
                              if ticket.checkin_data.enacted_by.username !=
                              None else 'n/a'),
                             "overriden":
                             ticket.checkin_data.overriden
                         } if ticket.checkin_data else 'n/a')
                     }],
                     "num_tickets":
                     1
                 }
             else:
                 return {
                     "query_type": query_type,
                     "query_value": query_value,
                     "error": "Requested ticket not found"
                 }
         else:
             return {
                 "query_type": query_type,
                 "query_value": query_value,
                 "error": "Method not implemented"
             }
     except APIPrivilegeException as e:
         logging.error(
             "API: A privilege exception was thrown for user %s during check-in query: %s"
             % (self.auth_user.username, str(e)))
         return {"error": str(e)}
     except APIAuthenticationException as e:
         logging.error(
             "API: User accessing check-in query is not authenticated")
         return {"error": str(e)}
     except Exception as e:
         if self.auth_user != None:
             logging.error(
                 "API: An exception was thrown for user %s during check-in query: %s"
                 % (self.auth_user.username, str(e)))
         else:
             logging.error(
                 "API: An exception was thrown during check-in query: %s" %
                 str(e))
         return {"error": "An unexpected error occurred"}
Exemple #30
0
 def start_setup_view(self):
     if "properties" in self.request.root.__dict__ and (PROP.getProperty(self.request, PROP.SITE_SETUP) == True):
         return HTTPFound(location=self.request.route_path("welcome"))
     return {}