def initialize(self): self.name = "join" self.invoice_email = open('invoice-email.txt').read() self.welcome_email = open('welcome-email.txt').read() self.config = yaml.load(open('paypal.conf.yml'))[options.mode] self.paypal = PayPalAPI(self.config)
class NewMemberFormHandler(tornado.web.RequestHandler): def initialize(self): self.name = "join" self.invoice_email = open('invoice-email.txt').read() self.welcome_email = open('welcome-email.txt').read() self.config = yaml.load(open('paypal.conf.yml'))[options.mode] self.paypal = PayPalAPI(self.config) def validate(self, data): try: form_data = json.loads(data) except: logging.error(data) raise HTTPError(400, "invalid form data") cleaned = {} mandatory_fields = [ 'given_names', 'surname', 'date_of_birth', 'residential_address', 'residential_postcode', 'residential_state', 'residential_suburb', 'submission', 'declaration', 'email', 'primary_phone', 'membership_level', 'payment_method', 'payment_amount' ] optional_fields = [ 'gender', 'postal_address', 'postal_postcode', 'postal_state', 'postal_suburb', 'secondary_phone', 'opt_out_state_parties', 'other_party_in_last_12_months' ] for field in mandatory_fields: if field in form_data.keys(): cleaned[field] = form_data[field] else: raise HTTPError(400, "missing fields: %s" % field) for field in optional_fields: if field in form_data.keys(): cleaned[field] = form_data[field] if cleaned['membership_level'] not in ("full", "associate"): raise HTTPError(400, "invalid membership level") if cleaned['payment_method'] not in ("paypal", "direct_deposit", "cheque"): raise HTTPError(400, "invalid payment method") if cleaned['declaration'] != True or cleaned['submission'] != True: raise HTTPError(400, "invalid declaration or submission flag") try: x = abs(int(cleaned['payment_amount']) * 100) cleaned['payment_amount'] = x if x == 0: cleaned['payment_method'] = 'direct_deposit' #cleaned['payment_amount'] = 2000 except: raise HTTPError(400, "invalid payment amount") try: cleaned['date_of_birth'] = datetime.datetime.strptime(cleaned['date_of_birth'], "%d/%m/%Y") except: logging.error(form_data) raise HTTPError(400, "invalid form data (date of birth)") return cleaned def create_member_record(self, data): id = uuid.uuid4() ts = datetime.datetime.utcnow() details = { "given_names": data['given_names'], "surname": data['surname'], "date_of_birth": data['date_of_birth'], "gender": data.get('gender', None), "residential_address": data['residential_address'], "residential_suburb": data['residential_suburb'], "residential_state": data['residential_state'], "residential_postcode": data['residential_postcode'], "postal_address": data.get('postal_address', None), "postal_suburb": data.get('postal_suburb', None), "postal_state": data.get('postal_state', None), "postal_postcode": data.get('postal_postcode', None), "email": data['email'], "primary_phone": data['primary_phone'], "secondary_phone": data.get('secondary_phone', None), "membership_level": data['membership_level'], "opt_out_state_parties": data.get('opt_out_state_parties', False), "other_party_in_last_12_months": data.get('other_party_in_last_12_months', None), "joined_on": ts } invoice = self.create_invoice_record(data['membership_level'], data['payment_method'], data['payment_amount']) return { "_id": id, "history": [{ "action": "new", "ts": ts, "details": details, "v": 1 }, { "action": "new-invoice", "ts": invoice['ts'], "invoice": invoice, "v": 1 }], "invoices": [invoice], "details": details, "v": 1 } def create_invoice_record(self, membership_level, payment_method, price=None): if price is None: if membership_level in ("full", "associate"): price = 2000 issued_date = datetime.datetime.utcnow() due_date = issued_date + datetime.timedelta(days=30) if membership_level == "full": out = { "v": 1, "ts": datetime.datetime.utcnow(), "items": [{ "item": "Full Membership - 12 Months", "qty": 1, "price": price }], "payment_method": payment_method, "due_date": due_date, "issued_date": issued_date, "status": "pending" } if payment_method != "paypal": c = self._get_counter('new_member') if c is None: raise HTTPError(500, "mongodb keeled over at counter time") out["reference"] = "FM%s" % c elif membership_level == "associate": out = { "v": 1, "ts": datetime.datetime.utcnow(), "items": [{ "item": "Associate Membership - 12 Months", "qty": 1, "price": price }], "payment_method": payment_method, "due_date": due_date, "issued_date": issued_date, "status": "pending" } if payment_method != "paypal": c = self._get_counter('new_member_am') if c is None: raise HTTPError(500, "mongodb keeled over at counter time") out["reference"] = "AM%s" % c return out def create_and_send_invoice(self, member, invoice): if invoice['payment_method'] == "paypal": biller_info = self.paypal.create_biller_info( member['given_names'], member['surname'], member['primary_phone'], member['residential_address'], None, member['residential_suburb'], member['residential_state'], member['residential_postcode'] ) response = self.paypal.create_and_send_invoice( self.config['email'], member['email'], self.paypal.get_merchant_info(), biller_info, self.paypal.create_invoice_item(invoice['items'][0]['item'], str(invoice['items'][0]['price']/100)), payment_terms="Net30" ) if response['responseEnvelope']['ack'].startswith("Success"): invoice['reference'] = response['invoiceNumber'] invoice['paypal_id'] = response['invoiceID'] return invoice else: return None elif invoice['payment_method'] in ("direct_deposit", "cheque"): personal = { "name": "Pirate Party Australia Incorporated", "address": [], "contact": { "Email": "*****@*****.**", "Website": "<a href='http://pirateparty.org.au'>http://pirateparty.org.au</a>" }, "business_number": "99 462 965 754", "payment_methods": [ { "Direct Deposit": [ "Name: Pirate Party Australia Incorporated", "BSB: 012084", "Account number: 213142205", "Bank: ANZ" ] }, { "Cheque": [ "Address:", "Pirate Party Australia", "PO Box 385", "Figtree NSW 2525" ] } ] } member_level = "INVALID" if member['membership_level'] == "full": member_level = "Full Membership" elif member['membership_level'] == "associate": member_level = "Associate Membership" invoice_tmpl = { "regarding": member_level, "name": "%s %s" % (member['given_names'], member['surname']), "reference": invoice['reference'], "items": [ { "rate_price": invoice['items'][0]['price'], "tax": "0", "description": invoice['items'][0]['item'], "hours_qty": "1" } ], "already_paid": "0", "details": "", "address": [ member['residential_address'], "%s %s %s" % (member['residential_suburb'], member['residential_state'], member['residential_postcode']) ], "date": invoice['issued_date'].strftime("%d/%m/%Y"), "message": "Thanks for joining Pirate Party Australia!", "payment_due": invoice['due_date'].strftime("%d/%m/%Y") } pdf_data = Invoice(invoice_tmpl, personal).to_pdf() try: sendmail(create_email( frm="*****@*****.**", to="%s %s <%s>" % (member['given_names'], member['surname'], member['email']), subject="Pirate Party Membership Invoice (%s)" % invoice_tmpl['reference'], text=self.invoice_email.format(name=member['given_names'].split(" ")[0]), attachments=[create_attachment("ppau-invoice.pdf", pdf_data)] )) return invoice except Exception as e: logging.error("Failed to send invoice - %s" % e) return None else: raise Exception("How did you even get here?") def send_admin_message(self, member_record): member = member_record['details'] msg = "New %s member: %s %s [%s] (%s)" % (member['membership_level'], member['given_names'], member['surname'], member['email'], member['residential_state']) id = member_record['_id'].hex sendmail(create_email( frm='*****@*****.**', reply_to=member['email'], to='*****@*****.**', subject=msg, text="%s\n%s\n$%s" % (id, member_record['invoices'][0]['payment_method'], member_record['invoices'][0]['items'][0]['price']/100) )) logging.info("New member: %s %s" % (msg, id)) logging.debug(dumps(member_record, indent=2)) def send_confirmation(self, member_record): member = member_record['details'] sendmail(create_email( frm="*****@*****.**", to="%s %s <%s>" % (member['given_names'], member['surname'], member['email']), subject="Welcome to Pirate Party Australia!", text=self.welcome_email.format(name=member['given_names'].split(" ")[0]) )) def get(self): self.render(self.name + '.html', record=None) def post(self): data = self.validate(self.get_argument('data', None)) member_record = self.create_member_record(data) invoice_record = self.create_and_send_invoice(member_record['details'], member_record['invoices'][0]) if not invoice_record: raise HTTPError(500, "invoice failed to send") member_record['invoices'][0] = invoice_record if not safe_insert(db.members, member_record): raise HTTPError(500, "mongodb keeled over") self.send_confirmation(member_record) self.send_admin_message(member_record) def _get_counter(self, name): record = safe_modify(db.counters, {"_id": name}, {"$inc": {"count": 1}}, True) logging.info("Current count for '%s': %s" % (name, record['count'])) if record != False: return record['count']