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 {}
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 }
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) }
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 {}
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}
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}
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
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
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
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]
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 }
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)
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}
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 }
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 }
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) }
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)
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
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 }
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) }
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 }
def cookie_policy_view(self): agreement_doc = PROP_KEYS.getProperty(self.request, PROP_KEYS.COOKIE_POLICY) return {"document": agreement_doc}
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." )
def privacy_policy_view(self): agreement_doc = PROP_KEYS.getProperty(self.request, PROP_KEYS.PRIVACY_POLICY) return {"document": agreement_doc}
def purchase_agreement_view(self): agreement_doc = PROP_KEYS.getProperty(self.request, PROP_KEYS.PURCHASE_AGREEMENT) return {"document": agreement_doc}
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." )
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
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"}
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"}
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 {}