def create_ticket(old_id=None, event_id=None, order_id=None, eventdate_id=None, ticket_type=None, name=None, price=None, status=None, ticket_number=None): data = { 'old_id': old_id, 'event_id': event_id, 'order_id': order_id, 'ticket_type': ticket_type, 'eventdate_id': eventdate_id, 'name': name, 'price': price, 'status': status, 'ticket_number': ticket_number, } ticket = Ticket(**data) dao_create_record(ticket) return ticket
def create_order(old_id=1, created_at=None, member_id=None, old_member_id=1, email_address='*****@*****.**', buyer_name='Test buyer', txn_id='1122334455', txn_type='cart', payment_status='completed', payment_total='10.0', params='some_test_params&test_param2', address_street='1 Test Steeet', address_city='Test City', address_postal_code='T11 2TS', address_state='London', address_country='UK', address_country_code='GB', delivery_zone='UK', delivery_status='completed', delivery_balance=0.0, books=[], tickets=[], errors=[], linked_txn_id=None): data = { 'old_id': old_id, 'created_at': created_at, 'member_id': member_id, 'old_member_id': old_member_id, 'email_address': email_address, 'buyer_name': buyer_name, 'txn_id': txn_id, 'txn_type': txn_type, 'payment_status': payment_status, 'payment_total': payment_total, 'params': params, 'address_street': address_street, 'address_city': address_city, 'address_postal_code': address_postal_code, 'address_state': address_state, 'address_country': address_country, 'address_country_code': address_country_code, 'delivery_zone': delivery_zone, 'delivery_status': delivery_status, 'delivery_balance': delivery_balance, 'books': books, 'tickets': tickets, 'errors': errors } if linked_txn_id: data.update(linked_txn_id=linked_txn_id) order = Order(**data) dao_create_record(order) if books: for book in books: dao_update_book_to_order_quantity(book.id, order.id, 1) return order
def import_magazine(): data = request.get_json(force=True) validate(data, post_import_magazine_schema) magazine = Magazine(old_id=data['old_id'], title=data['title'], old_filename=data['old_filename'], filename=data['filename']) dao_create_record(magazine) return jsonify(magazine.serialize()), 201
def create_magazine(): data = request.get_json(force=True) validate(data, post_create_magazine_schema) new_filename = get_magazine_filename(data['filename']) if new_filename: magazine = Magazine(title=data['title'], filename=new_filename) dao_create_record(magazine) upload_tasks.upload_magazine.apply_async( (str(magazine.id), data['pdf_data'])) return jsonify(magazine.serialize()), 201 raise InvalidRequest( 'Invalid filename for magazine: {}'.format(data['filename']), 400)
def create_magazine( old_id=None, title='title', old_filename=None, filename='new filename', tags='', ): data = { 'old_id': old_id, 'title': title, 'old_filename': old_filename, 'filename': filename, 'tags': tags } magazine = Magazine(**data) dao_create_record(magazine) return magazine
def paypal_ipn(params=None, allow_emails=True, replace_order=False): message = '' bypass_verify = False if not params: params = request.form.to_dict(flat=False) else: bypass_verify = True current_app.logger.info('IPN params: %r', params) def get_data(params): data = {} for key in params.keys(): if isinstance(params[key], list): data[key] = params[key][0] else: data[key] = params[key] return data if bypass_verify or (current_app.config['TEST_VERIFY'] and current_app.config['ENVIRONMENT'] != 'live'): v_response = 'VERIFIED' current_app.logger.info('Test paypal verify') else: VERIFY_URL = current_app.config['PAYPAL_VERIFY_URL'] params['cmd'] = '_notify-validate' headers = { 'content-type': 'application/x-www-form-urlencoded', 'user-agent': 'Python-IPN-Verification-Script' } current_app.logger.info("params: %r", params) # debug r = requests.post(VERIFY_URL, params=params, headers=headers, verify=True) r.raise_for_status() v_response = r.text if v_response == 'VERIFIED': current_app.logger.info('VERIFIED: %s', params['txn_id']) # Check return message and take action as needed if v_response == 'VERIFIED': status = product_message = delivery_message = error_message = '' diff = 0.0 data = get_data(params) order_data, tickets, events, products, delivery_zones, errors = parse_ipn( data, replace_order) if 'payment already made' in (','.join(errors)): current_app.logger.info("Transaction payment already made %r", data['txn_id']) return "Duplicate transaction %s" % {data['txn_id']} order_data['params'] = json.dumps(params) if 'is_donation' in order_data.keys( ) and order_data['is_donation'] == "Donation": order_data['is_donation'] = True order_data['linked_txn_id'] = None order = Order(**order_data) dao_create_record(order) if order_data['payment_status'] != 'Completed': err_msg = f"Payment not Completed: {order_data['payment_status']}" errors = [err_msg] else: message = f"<p>Thank you for your order ({order.id})</p>" if order_data['txn_type'] == 'web_accept' and order_data[ 'linked_txn_id']: linked_order = dao_get_order_with_txn_id( order_data['linked_txn_id']) diff = linked_order.delivery_balance - Decimal( order_data['payment_total']) if diff == 0: status = statuses.DELIVERY_EXTRA_PAID elif diff > 0: status = statuses.DELIVERY_EXTRA current_app.logger.warning( 'Delivery balance not paid in full') elif diff < 0: status = statuses.DELIVERY_REFUND current_app.logger.warning('Delivery balance overpaid') dao_update_record(Order, linked_order.id, delivery_status=status, payment_total=linked_order.payment_total + Decimal(order_data['payment_total']), delivery_balance=abs(diff)) order_data['delivery_status'] = status order_data['delivery_zone'] = linked_order.delivery_zone order_data['delivery_balance'] = abs(diff) _payment_total = _get_nice_cost(order.payment_total) _diff = _get_nice_cost(diff) if status == statuses.DELIVERY_EXTRA_PAID: message += f"<div>Outstanding payment for order ({order_data['linked_txn_id']}) of £" \ f"{_payment_total} for delivery to {order_data['delivery_zone']} has been paid.</div>" elif status == statuses.DELIVERY_EXTRA: message += f"<div>Outstanding payment for order ({order_data['linked_txn_id']}) of £" \ f"{_payment_total} for delivery to {order_data['delivery_zone']} has been " \ f"partially paid.</div><div>Not enough delivery paid, £{_diff} due.</div>" elif status == statuses.DELIVERY_REFUND: message += f"<p>You have overpaid for delivery on order ({order_data['linked_txn_id']}) " \ f"by £{_diff}, please send a message to website admin if there is " \ "no refund within 5 working days.</p>" else: if products: for product in products: if product['type'] == BOOK: book_to_order = BookToOrder( book_id=product['book_id'], order_id=order.id, quantity=product['quantity']) dao_create_book_to_order(book_to_order) product_message += ( f'<tr><td>{product["title"]}</td><td> x {product["quantity"]}</td>' f'<td> = {_get_nice_cost(product["price"] * product["quantity"])}</td></tr>' ) product_message = f'<table>{product_message}</table>' address_delivery_zone = None if 'address_country_code' not in order_data: delivery_message = "No address supplied. " status = "missing_address" else: address_delivery_zone = get_delivery_zone( order_data['address_country_code']) admin_message = "" total_cost = 0 for dz in delivery_zones: _d = [ _dz for _dz in DELIVERY_ZONES if _dz['name'] == dz ] if _d: d = _d[0] total_cost += d['price'] _price = _get_nice_cost(d['price']) admin_message += f"<tr><td>{d['name']}</td><td>{_price}</td></tr>" else: errors.append(f'Delivery zone: {dz} not found') admin_message += f"<tr><td>{dz}</td><td>Not found</td></tr>" _total_cost = _get_nice_cost(total_cost) _price = _get_nice_cost(address_delivery_zone['price']) diff = total_cost - address_delivery_zone['price'] if diff != 0: admin_message = f"<p>Order delivery zones: <table>{admin_message}" \ f"</table>Total: £{_total_cost}</p>" admin_message += "<p>Expected delivery zone: " \ f"{address_delivery_zone['name']} - £{_price}</p>" order_data['delivery_balance'] = _get_nice_cost( diff) if diff > 0: status = "refund" delivery_message = f"Refund of £{order_data['delivery_balance']} " \ "due as wrong delivery fee paid" elif diff < 0: _diff = _get_nice_cost(diff) status = "extra" delivery_message = "{}, £{} due. ".format( "No delivery fee paid" if total_cost == 0 else "Not enough delivery paid", order_data['delivery_balance']) admin_message = f"Transaction ID: {order.txn_id}<br>Order ID: {order.id}" \ f"<br>{delivery_message}.{admin_message}" for user in dao_get_admin_users(): send_smtp_email(user.email, f'New Acropolis {status}', admin_message) else: status = statuses.DELIVERY_PAID dao_update_record( Order, order.id, delivery_status=status, delivery_zone=address_delivery_zone['name'] if address_delivery_zone else None, delivery_balance=str(abs(diff))) if delivery_message: order_data['delivery_status'] = status if status == 'refund': delivery_message = f"<p>{delivery_message}, please send a message " \ "to website admin if there is no refund within 5 working days.</p>" else: order_data['delivery_zone'] = address_delivery_zone['name']\ if address_delivery_zone else None else: product_message = ( f'{product_message}<br><div>Delivery to: {order_data["address_street"]},' f'{order_data["address_city"]}, ' f'{order_data["address_postal_code"]}, {order_data["address_country"]}</div>' ) if tickets: for i, _ticket in enumerate(tickets): _ticket['order_id'] = order.id ticket = Ticket(**_ticket) dao_create_record(ticket) tickets[i]['ticket_id'] = ticket.id tickets[i]['title'] = ticket.event.title storage = Storage(current_app.config['STORAGE']) for ticket in tickets: link_to_post = '{}{}'.format( current_app.config['API_BASE_URL'], url_for('.use_ticket', ticket_id=ticket['ticket_id'])) img = pyqrcode.create(link_to_post) buffer = io.BytesIO() img.png(buffer, scale=2) img_b64 = base64.b64encode(buffer.getvalue()) target_image_filename = '{}/{}'.format( 'qr_codes', str(ticket['ticket_id'])) storage.upload_blob_from_base64string( 'qr.code', target_image_filename, img_b64) message += '<div><span><img src="{}/{}"></span>'.format( current_app.config['IMAGES_URL'], target_image_filename) event_date = dao_get_event_date_by_id( ticket['eventdate_id']) minutes = ':%M' if event_date.event_datetime.minute > 0 else '' message += "<div>{} on {}</div></div>".format( ticket['title'], event_date.event_datetime.strftime( '%-d %b at %-I{}%p'.format(minutes))) if event_date.event.remote_access: message += f"<br><div>Meeting id: {event_date.event.remote_access}" if event_date.event.remote_pw: message += f", Password: {event_date.event.remote_pw}" message += "</div>" message += f"<div><a href='https://zoom.us/j/{event_date.event.remote_access}'>"\ "Join zoom event</a></div>" if errors: error_message = '' for error in errors: error_message += f"<div>{error}</div>" order.errors.append(OrderError(error=error)) error_message = f"<p>Errors in order: {error_message}</p>" if status in [ statuses.DELIVERY_EXTRA, statuses.DELIVERY_MISSING_ADDRESS, statuses.DELIVERY_NOT_PAID ]: _delivery_zone_balance = '' if 'delivery_balance' in order_data: _delivery_balance = _get_nice_cost( order_data['delivery_balance']) _delivery_zone_balance = f"/{order_data['delivery_zone']}/{_delivery_balance}"\ if order_data['delivery_zone'] else '' delivery_message = ( f"<p>{delivery_message}Please " f"<a href='{current_app.config['FRONTEND_URL']}/order/{order_data['delivery_status']}/" f"{order_data['txn_id']}{_delivery_zone_balance}'>complete</a> " "your order.</p>") if allow_emails: send_email( order.email_address, 'New Acropolis Order', message + product_message + delivery_message + error_message) else: if v_response == 'INVALID': current_app.logger.info('INVALID %r', params['txn_id']) else: current_app.logger.info('UNKNOWN response %r', params['txn_id']) data = get_data(params) data[ 'txn_id'] = f"XX-{v_response}_{int(datetime.utcnow().timestamp())}-{data['txn_id']}" order_data, tickets, events, products, delivery_zones, errors = parse_ipn( data) order_data['params'] = json.dumps(params) order = Order(**order_data) order.errors.append(OrderError(error=f"{v_response} verification")) dao_create_record(order) return 'Paypal IPN'
def paypal_ipn(): VERIFY_URL = current_app.config['PAYPAL_VERIFY_URL'] params = request.form.to_dict(flat=False) current_app.logger.info('IPN params: %r', params) params['cmd'] = '_notify-validate' headers = { 'content-type': 'application/x-www-form-urlencoded', 'user-agent': 'Python-IPN-Verification-Script' } r = requests.post(VERIFY_URL, params=params, headers=headers, verify=True) r.raise_for_status() # Check return message and take action as needed if r.text == 'VERIFIED': current_app.logger.info('VERIFIED: %s', params['txn_id']) data = {} for key in params.keys(): if isinstance(params[key], list): data[key] = params[key][0] else: data[key] = params[key] order_data, tickets, events = parse_ipn(data) if not order_data: return 'Paypal IPN no order created' order_data['params'] = json.dumps(params) order = Order(**order_data) dao_create_record(order) for i, _ticket in enumerate(tickets): _ticket['order_id'] = order.id ticket = Ticket(**_ticket) dao_create_record(ticket) tickets[i]['ticket_id'] = ticket.id storage = Storage(current_app.config['STORAGE']) message = "<p>Thank you for your order:<p>" for i, event in enumerate(events): link_to_post = '{}{}'.format( current_app.config['API_BASE_URL'], url_for('.use_ticket', ticket_id=tickets[i]['ticket_id'])) img = pyqrcode.create(link_to_post) buffer = io.BytesIO() img.png(buffer, scale=2) img_b64 = base64.b64encode(buffer.getvalue()) target_image_filename = '{}{}'.format('qr_codes', str(tickets[i]['ticket_id'])) storage.upload_blob_from_base64string('qr.code', target_image_filename, img_b64) message += '<div><span><img src="{}/{}"></span>'.format( current_app.config['IMAGES_URL'], target_image_filename) event_date = dao_get_event_date_by_id(tickets[i]['eventdate_id']) minutes = ':%M' if event_date.event_datetime.minute > 0 else '' message += "<span>{} on {}</span></div>".format( event.title, event_date.event_datetime.strftime( '%-d %b at %-I{}%p'.format(minutes))) send_email(order.email_address, 'New Acropolis Event Tickets', message) elif r.text == 'INVALID': current_app.logger.info('INVALID %r', params['txn_id']) else: current_app.logger.info('UNKNOWN response %r', params['txn_id']) return 'Paypal IPN'