def bill_url(self, name): # TODO: check country bill_url = gocardless.client.new_bill_url( amount=self.amount, name=name, redirect_uri=external_url('gocardless_complete', payment_id=self.id), cancel_uri=external_url('gocardless_cancel', payment_id=self.id), currency=self.currency, ) return bill_url
def attach_tickets(msg, user): # Attach tickets to a mail Message page = render_receipt(user, pdf=True) url = external_url('tickets.receipt', user_id=user.id) pdf = render_pdf(url, page) msg.attach('EMF{}.pdf'.format(event_start().year), 'application/pdf', pdf.read())
def tickets_receipt_qr(receipt): qrfile = StringIO() qr = qrcode.make(external_url('tickets_receipt', receipt=receipt), box_size=2) qr.save(qrfile, 'PNG') qrfile.seek(0) return send_file(qrfile, mimetype='image/png')
def message_batch(): proposals, filtered = filter_proposal_request() form = SendMessageForm() if form.validate_on_submit(): if form.send.data: for proposal in proposals: msg = CFPMessage() msg.is_to_admin = False msg.from_user_id = current_user.id msg.proposal_id = proposal.id msg.message = form.message.data db.session.add(msg) db.session.commit() app.logger.info('Sending message from %s to %s', current_user.id, proposal.user_id) msg_url = external_url('cfp.proposal_messages', proposal_id=proposal.id) msg = Message('New message about your EMF proposal', sender=app.config['CONTENT_EMAIL'], recipients=[proposal.user.email]) msg.body = render_template('cfp_review/email/new_message.txt', url=msg_url, to_user=proposal.user, from_user=current_user, proposal=proposal) mail.send(msg) flash('Messaged %s proposals' % len(proposals), 'info') return redirect(url_for('.proposals', **request.args)) return render_template('cfp_review/message_batch.html', form=form, proposals=proposals)
def add_event(room, event): url = external_url('schedule.line_up_proposal', proposal_id=event['id'], slug=event['slug']) event_node = etree.SubElement(room, 'event', id=str(event['id']), guid=str(uuid5(NAMESPACE_URL, url))) _add_sub_with_text(event_node, 'room', room.attrib['name']) _add_sub_with_text(event_node, 'title', event['title']) _add_sub_with_text(event_node, 'type', event.get('type', 'talk')) _add_sub_with_text(event_node, 'date', event['start_date'].isoformat()) # Start time _add_sub_with_text(event_node, 'start', event['start_date'].strftime('%H:%M')) duration = get_duration(event['start_date'], event['end_date']) _add_sub_with_text(event_node, 'duration', duration) _add_sub_with_text(event_node, 'abstract', event['description']) _add_sub_with_text(event_node, 'description', event['description']) _add_sub_with_text( event_node, 'slug', 'emf%s-%s-%s' % (event_start().year, event['id'], event['slug'])) _add_sub_with_text(event_node, 'subtitle', '') _add_sub_with_text(event_node, 'track', '') add_persons(event_node, event) add_recording(event_node, event)
def attach_tickets(msg, user): # Attach tickets to a mail Message page = render_receipt(user, pdf=True) url = external_url("tickets.receipt", user_id=user.id) pdf = render_pdf(url, page) msg.attach("EMF{}.pdf".format(event_year()), pdf.read(), "application/pdf")
def add_event(room, event): url = external_url('schedule.line_up_proposal', proposal_id=event['id'], slug=event['slug']) event_node = etree.SubElement(room, 'event', id=str(event['id']), guid=str(uuid5(NAMESPACE_URL, url))) _add_sub_with_text(event_node, 'room', room.attrib['name']) _add_sub_with_text(event_node, 'title', event['title']) _add_sub_with_text(event_node, 'type', event.get('type', 'talk')) _add_sub_with_text(event_node, 'date', event['start_date'].isoformat()) # Start time _add_sub_with_text(event_node, 'start', event['start_date'].strftime('%H:%M')) duration = get_duration(event['start_date'], event['end_date']) _add_sub_with_text(event_node, 'duration', duration) _add_sub_with_text(event_node, 'abstract', event['description']) _add_sub_with_text(event_node, 'description', '') _add_sub_with_text(event_node, 'slug', 'emf%s-%s-%s' % (event_start().year, event['id'], event['slug'])) _add_sub_with_text(event_node, 'subtitle', '') _add_sub_with_text(event_node, 'track', '') add_persons(event_node, event) add_recording(event_node, event)
def user_tickets(user_id, ext=None): user = User.query.get_or_404(user_id) receipt = render_receipt(user) if ext == '.pdf': url = external_url('.user_tickets', user_id=user_id) return send_file(render_pdf(url, receipt), mimetype='application/pdf', cache_timeout=60) return receipt
def _get_proposal_dict(proposal: Proposal, favourites_ids): res = { "id": proposal.id, "slug": proposal.slug, "start_date": event_tz.localize(proposal.start_date), "end_date": event_tz.localize(proposal.end_date) if proposal.end_date else None, "venue": proposal.scheduled_venue.name, "latlon": proposal.latlon, "map_link": proposal.map_link, "title": proposal.display_title, "speaker": proposal.published_names or proposal.user.name, "pronouns": proposal.published_pronouns, "user_id": proposal.user.id, "description": proposal.published_description or proposal.description, "type": proposal.type, "may_record": proposal.may_record, "is_fave": proposal.id in favourites_ids, "is_family_friendly": proposal.family_friendly, "is_from_cfp": not proposal.user_scheduled, "content_note": proposal.content_note, "source": "database", "link": external_url( ".item", year=event_year(), proposal_id=proposal.id, slug=proposal.slug, ), } if proposal.type in ["workshop", "youthworkshop"]: res["cost"] = proposal.display_cost res["equipment"] = proposal.display_participant_equipment res["age_range"] = proposal.display_age_range res["attendees"] = proposal.attendees return res
def message_proposer(proposal_id): form = SendMessageForm() proposal = Proposal.query.get_or_404(proposal_id) if form.validate_on_submit(): if form.send.data: msg = CFPMessage() msg.is_to_admin = False msg.from_user_id = current_user.id msg.proposal_id = proposal_id msg.message = form.message.data db.session.add(msg) db.session.commit() app.logger.info( "Sending message from %s to %s", current_user.id, proposal.user_id ) msg_url = external_url("cfp.proposal_messages", proposal_id=proposal_id) msg = EmailMessage( "New message about your EMF proposal", from_email=from_email("CONTENT_EMAIL"), to=[proposal.user.email], ) msg.body = render_template( "cfp_review/email/new_message.txt", url=msg_url, to_user=proposal.user, from_user=current_user, proposal=proposal, ) msg.send() count = proposal.mark_messages_read(current_user) db.session.commit() app.logger.info( "Marked %s messages to admin on proposal %s as read" % (count, proposal.id) ) return redirect(url_for(".message_proposer", proposal_id=proposal_id)) # Admin can see all messages sent in relation to a proposal messages = ( CFPMessage.query.filter_by(proposal_id=proposal_id).order_by("created").all() ) return render_template( "cfp_review/message_proposer.html", form=form, messages=messages, proposal=proposal, )
def user_tickets(user_id, ext=None): user = User.query.get_or_404(user_id) receipt = render_receipt(user) if ext == ".pdf": url = external_url(".user_tickets", user_id=user_id) return send_file( render_pdf(url, receipt), mimetype="application/pdf", cache_timeout=60 ) return receipt
def invoice(payment_id): payment = get_user_payment_or_abort(payment_id, allow_admin=True) form = InvoiceForm() if form.validate_on_submit(): current_user.company = form.company.data db.session.commit() flash('Company name updated') return redirect(url_for('.invoice', payment_id=payment_id)) if request.method != 'POST': form.company.data = current_user.company edit_company = bool(request.args.get('edit_company')) if request.args.get('js') == '0': flash("Please use your browser's print feature or download the PDF") invoice_lines = Purchase.query.filter_by(payment_id=payment_id).join(PriceTier, Product) \ .with_entities(PriceTier, func.count(Purchase.price_tier_id)) \ .group_by(PriceTier, Product.name).order_by(Product.name).all() ticket_sum = sum(pt.get_price(payment.currency).value_ex_vat * count for pt, count in invoice_lines) if payment.provider == 'stripe': premium = payment.__class__.premium(payment.currency, ticket_sum) else: premium = Decimal(0) subtotal = ticket_sum + premium vat = subtotal * Decimal('0.2') app.logger.debug('Invoice subtotal %s + %s = %s', ticket_sum, premium, subtotal) # FIXME: we should use a currency-specific quantization here (or rounder numbers) if subtotal + vat - payment.amount > Decimal('0.01'): app.logger.error('Invoice total mismatch: %s + %s - %s = %s', subtotal, vat, payment.amount, subtotal + vat - payment.amount) flash('Your invoice cannot currently be displayed') return redirect(url_for('users.purchases')) app.logger.debug('Invoice total: %s + %s = %s', subtotal, vat, payment.amount) page = render_template('invoice.html', payment=payment, invoice_lines=invoice_lines, form=form, premium=premium, subtotal=subtotal, vat=vat, edit_company=edit_company) if request.args.get('pdf'): url = external_url('.invoice', payment_id=payment_id) return send_file(render_pdf(url, page), mimetype='application/pdf', cache_timeout=60) return page
def invoice(payment_id): payment = get_user_payment_or_abort(payment_id, allow_admin=True) form = InvoiceForm() if form.validate_on_submit(): current_user.company = form.company.data db.session.commit() flash('Company name updated') return redirect(url_for('.invoice', payment_id=payment_id)) if request.method != 'POST': form.company.data = current_user.company edit_company = bool(request.args.get('edit_company')) if request.args.get('js') == '0': flash("Please use your browser's print feature") invoice_lines = Purchase.query.filter_by(payment_id=payment_id).join(PriceTier, Product) \ .with_entities(PriceTier, func.count(Purchase.price_tier_id)) \ .group_by(PriceTier, Product.name).order_by(Product.name).all() ticket_sum = sum(pt.get_price(payment.currency).value_ex_vat * count for pt, count in invoice_lines) if payment.provider == 'stripe': premium = payment.__class__.premium(payment.currency, ticket_sum) else: premium = Decimal(0) subtotal = ticket_sum + premium vat = subtotal * Decimal('0.2') app.logger.debug('Invoice subtotal %s + %s = %s', ticket_sum, premium, subtotal) # FIXME: we should use a currency-specific quantization here (or rounder numbers) if subtotal + vat - payment.amount > Decimal('0.01'): app.logger.error('Invoice total mismatch: %s + %s - %s = %s', subtotal, vat, payment.amount, subtotal + vat - payment.amount) flash('Your invoice cannot currently be displayed') return redirect(url_for('users.purchases')) app.logger.debug('Invoice total: %s + %s = %s', subtotal, vat, payment.amount) page = render_template('invoice.html', payment=payment, invoice_lines=invoice_lines, form=form, premium=premium, subtotal=subtotal, vat=vat, edit_company=edit_company) if request.args.get('pdf'): url = external_url('.invoice', payment_id=payment_id) return send_file(render_pdf(url, page), mimetype='application/pdf') return page
def create_bar_training_webhook(): # This doesn't work, despite documentation and consistent return value _, form_id = app.config['BAR_TRAINING_FORM'].rsplit('/', 1) webhook_url = TYPEFORM_BASE + '/forms/{}/webhooks/{}'.format(form_id, get_auth_tag()) response = requests.get(webhook_url, headers=typeform_headers()) if response.status_code == 404: url = external_url('volunteer.bar_training_webhook', tag=get_auth_tag()) args = {"url": url, "enabled": True} response = requests.put(webhook_url, json.dumps(args), headers=typeform_headers()) response.raise_for_status() if response.status_code == 200: return response.json()["id"]
def attach_tickets(msg, user): # Attach tickets to a mail Message page = render_receipt(user, pdf=True) url = external_url('tickets.receipt', user_id=user.id) pdf = render_pdf(url, page) receipt_types = ['admissions', 'campervan', 'parking', 'merchandise'] tickets = Ticket.query.filter_by(owner_id=user.id, is_paid_for=True) \ .options(joinedload(Ticket.product).joinedload(Product.parent)) \ .filter(ProductGroup.type.in_(receipt_types)) plural = (tickets.count() != 1 and 's' or '') msg.attach('Ticket%s.pdf' % plural, 'application/pdf', pdf.read()) for t in tickets: t.set_state('receipt-emailed')
def message_proposer(proposal_id): form = SendMessageForm() proposal = Proposal.query.get_or_404(proposal_id) if request.method == 'POST': if form.send.data and form.message.data: msg = CFPMessage() msg.is_to_admin = False msg.from_user_id = current_user.id msg.proposal_id = proposal_id msg.message = form.message.data db.session.add(msg) db.session.commit() app.logger.info('Sending message from %s to %s', current_user.id, proposal.user_id) msg_url = external_url('cfp.proposal_messages', proposal_id=proposal_id) msg = Message('New message about your EMF proposal', sender=app.config['CONTENT_EMAIL'], recipients=[proposal.user.email]) msg.body = render_template('cfp_review/email/new_message.txt', url=msg_url, to_user=proposal.user, from_user=current_user, proposal=proposal) mail.send(msg) if form.mark_read.data or form.send.data: count = proposal.mark_messages_read(current_user) app.logger.info( 'Marked %s messages to admin on proposal %s as read' % (count, proposal.id)) return redirect(url_for('.message_proposer', proposal_id=proposal_id)) # Admin can see all messages sent in relation to a proposal messages = CFPMessage.query.filter_by( proposal_id=proposal_id).order_by('created').all() return render_template('cfp_review/message_proposer.html', form=form, messages=messages, proposal=proposal)
def attach_tickets(msg, user): # Attach tickets to a mail Message page = render_receipt(user, pdf=True) url = external_url('tickets.receipt', user_id=user.id) pdf = render_pdf(url, page) # Types of product groups we include on receipts receipt_types = ['admissions', 'campervan', 'parking', 'tees'] tickets = user.owned_tickets.filter( Purchase.type.in_(receipt_types), Purchase.is_paid_for == True, # noqa: E712 ) plural = (tickets.count() != 1 and 's' or '') msg.attach('Ticket%s.pdf' % plural, 'application/pdf', pdf.read()) for t in tickets: t.set_state('receipt-emailed')
def _get_ical_dict(event, favourites_ids): return { 'id': -event.id, 'start_date': event_tz.localize(event.start_dt), 'end_date': event_tz.localize(event.end_dt), 'venue': event.location or '(Unknown)', 'latlon': event.latlon, 'map_link': event.map_link, 'title': event.summary, 'speaker': '', 'user_id': None, 'description': event.description, 'type': 'talk', 'may_record': False, 'is_fave': event.id in favourites_ids, 'source': 'external', 'link': external_url('.line_up_external', event_id=event.id), }
def receipt(user_id=None): if current_user.has_permission('admin') and user_id is not None: user = User.query.get(user_id) else: user = current_user if not user.owned_purchases.filter_by(is_paid_for=True).all(): abort(404) png = bool(request.args.get('png')) pdf = bool(request.args.get('pdf')) page = render_receipt(user, png, pdf) if pdf: url = external_url('tickets.receipt', user_id=user_id) return send_file(render_pdf(url, page), mimetype='application/pdf', cache_timeout=60) return page
def attach_tickets(msg, user): # Attach tickets to a mail Message page = render_receipt(user, pdf=True) url = external_url('tickets.receipt', user_id=user.id) pdf = render_pdf(url, page) msg.attach('EMF{}.pdf'.format(event_start().year), 'application/pdf', pdf.read()) purchases = user.owned_purchases.filter_by(is_paid_for=True, state='paid') \ .join(PriceTier, Product, ProductGroup) \ .filter(ProductGroup.type.in_(RECEIPT_TYPES)) \ .with_entities(Purchase) \ .group_by(Purchase) \ .order_by(Purchase.id) for p in purchases: p.set_state('receipt-emailed')
def receipt(user_id=None): if current_user.has_permission('admin') and user_id is not None: user = User.query.get(user_id) else: user = current_user if not user.owned_tickets.filter_by(is_paid_for=True).all(): abort(404) png = bool(request.args.get('png')) pdf = bool(request.args.get('pdf')) page = render_receipt(user, png, pdf) if pdf: url = external_url('tickets.receipt', user_id=user_id) return send_file(render_pdf(url, page), mimetype='application/pdf') return page
def create_bar_training_webhook(): # This doesn't work, despite documentation and consistent return value _, form_id = app.config['BAR_TRAINING_FORM'].rsplit('/', 1) webhook_url = TYPEFORM_BASE + '/forms/{}/webhooks/{}'.format( form_id, get_auth_tag()) response = requests.get(webhook_url, headers=typeform_headers()) if response.status_code == 404: url = external_url('volunteer.bar_training_webhook', tag=get_auth_tag()) args = {"url": url, "enabled": True} response = requests.put(webhook_url, json.dumps(args), headers=typeform_headers()) response.raise_for_status() if response.status_code == 200: return response.json()["id"]
def gocardless_start(payment): logger.info("Starting GoCardless flow for payment %s", payment.id) prefilled_customer = { "email": payment.user.email, } match = re.match(r'^ *([^ ,]+) +([^ ,]+) *$', payment.user.name) if match: prefilled_customer.update({ "given_name": match.group(1), "family_name": match.group(2), }) params = { "description": "Electromagnetic Field", "session_token": str(payment.id), "success_redirect_url": external_url('payments.gocardless_complete', payment_id=payment.id), "prefilled_customer": prefilled_customer, } if payment.currency == 'GBP': params["scheme"] = "bacs" elif payment.currency == 'EUR': # sepa_cor1 isn't an option, so let's hope it upgrades automatically params["scheme"] = "sepa_core" redirect_flow = gocardless_client.redirect_flows.create(params=params) logger.debug('GoCardless redirect ID: %s', redirect_flow.id) assert payment.redirect_id is None payment.redirect_id = redirect_flow.id # "Redirect flows expire 30 minutes after they are first created. You cannot complete an expired redirect flow." # https://developer.gocardless.com/api-reference/#core-endpoints-redirect-flows payment.expires = datetime.utcnow() + timedelta(minutes=30) db.session.commit() return redirect(redirect_flow.redirect_url)
def attach_tickets(msg, user): # Attach tickets to a mail Message page = render_receipt(user, pdf=True) url = external_url('tickets.receipt', user_id=user.id) pdf = render_pdf(url, page) # Types of product groups we include on receipts # TODO: `user.owned_tickets` has changed here, there's some oddness with type... assert False receipt_types = ['admissions', 'campervan', 'parking', 'tees'] tickets = user.owned_tickets.filter( Purchase.type.in_(receipt_types), Purchase.is_paid_for == True, # noqa: E712 ) plural = (tickets.count() != 1 and 's' or '') msg.attach('Ticket%s.pdf' % plural, 'application/pdf', pdf.read()) for t in tickets: t.set_state('receipt-emailed')
def receipt(user_id=None): if current_user.has_permission("admin") and user_id is not None: user = User.query.get(user_id) else: user = current_user if not user.owned_purchases.filter_by(is_paid_for=True).all(): abort(404) png = bool(request.args.get("png")) pdf = bool(request.args.get("pdf")) page = render_receipt(user, png, pdf) if pdf: url = external_url("tickets.receipt", user_id=user_id) return send_file( render_pdf(url, page), mimetype="application/pdf", cache_timeout=60 ) return page
def _get_ical_dict(event, favourites_ids): res = { "id": -event.id, "start_date": event_tz.localize(event.start_dt), "end_date": event_tz.localize(event.end_dt), "venue": event.location or "(Unknown)", "latlon": event.latlon, "map_link": event.map_link, "title": event.summary, "speaker": "", "user_id": None, "description": event.description, "type": "talk", "may_record": False, "is_fave": event.id in favourites_ids, "source": "external", "link": external_url(".item_external", year=event_year(), slug=event.slug, event_id=event.id), } if event.type in ["workshop", "youthworkshop"]: res["cost"] = event.display_cost res["equipment"] = event.display_participant_equipment res["age_range"] = event.display_age_range return res
def message_batch(): proposals, filtered = filter_proposal_request() form = SendMessageForm() if form.validate_on_submit(): if form.send.data: for proposal in proposals: msg = CFPMessage() msg.is_to_admin = False msg.from_user_id = current_user.id msg.proposal_id = proposal.id msg.message = form.message.data db.session.add(msg) db.session.commit() app.logger.info( "Sending message from %s to %s", current_user.id, proposal.user_id ) msg_url = external_url("cfp.proposal_messages", proposal_id=proposal.id) msg = EmailMessage( "New message about your EMF proposal", from_email=from_email("CONTENT_EMAIL"), to=[proposal.user.email], ) msg.body = render_template( "cfp_review/email/new_message.txt", url=msg_url, to_user=proposal.user, from_user=current_user, proposal=proposal, ) msg.send() flash("Messaged %s proposals" % len(proposals), "info") return redirect(url_for(".proposals", **request.args)) return render_template( "cfp_review/message_batch.html", form=form, proposals=proposals )
def _get_proposal_dict(proposal, favourites_ids): res = { 'id': proposal.id, 'start_date': event_tz.localize(proposal.scheduled_time), 'end_date': event_tz.localize(proposal.end_date), 'venue': proposal.scheduled_venue.name, 'latlon': proposal.latlon, 'map_link': proposal.map_link, 'title': proposal.title, 'speaker': proposal.published_names or proposal.user.name, 'user_id': proposal.user.id, 'description': proposal.description, 'type': proposal.type, 'may_record': proposal.may_record, 'is_fave': proposal.id in favourites_ids, 'source': 'database', 'link': external_url('.line_up_proposal', proposal_id=proposal.id), } if proposal.type == 'workshop': res['cost'] = proposal.cost return res
def message_proposer(proposal_id): form = SendMessageForm() proposal = Proposal.query.get_or_404(proposal_id) if request.method == "POST": if form.send.data and form.message.data: msg = CFPMessage() msg.is_to_admin = False msg.from_user_id = current_user.id msg.proposal_id = proposal_id msg.message = form.message.data db.session.add(msg) db.session.commit() app.logger.info("Sending message from %s to %s", current_user.id, proposal.user_id) msg_url = external_url("cfp.proposal_messages", proposal_id=proposal_id) send_template_email( "New message about your EMF proposal", proposal.user.email, app.config["CONTENT_EMAIL"], "cfp_review/email/new_message.txt", url=msg_url, to_user=proposal.user, from_user=current_user, proposal=proposal, ) if form.mark_read.data or form.send.data: count = proposal.mark_messages_read(current_user) app.logger.info("Marked %s messages to admin on proposal %s as read" % (count, proposal.id)) return redirect(url_for(".message_proposer", proposal_id=proposal_id)) # Admin can see all messages sent in relation to a proposal messages = CFPMessage.query.filter_by(proposal_id=proposal_id).order_by("created").all() return render_template("cfp_review/message_proposer.html", form=form, messages=messages, proposal=proposal)
def message_proposer(proposal_id): form = SendMessageForm() proposal = Proposal.query.get_or_404(proposal_id) if form.validate_on_submit(): if form.send.data: msg = CFPMessage() msg.is_to_admin = False msg.from_user_id = current_user.id msg.proposal_id = proposal_id msg.message = form.message.data db.session.add(msg) db.session.commit() app.logger.info('Sending message from %s to %s', current_user.id, proposal.user_id) msg_url = external_url('cfp.proposal_messages', proposal_id=proposal_id) msg = Message('New message about your EMF proposal', sender=app.config['CONTENT_EMAIL'], recipients=[proposal.user.email]) msg.body = render_template('cfp_review/email/new_message.txt', url=msg_url, to_user=proposal.user, from_user=current_user, proposal=proposal) mail.send(msg) count = proposal.mark_messages_read(current_user) db.session.commit() app.logger.info('Marked %s messages to admin on proposal %s as read' % (count, proposal.id)) return redirect(url_for('.message_proposer', proposal_id=proposal_id)) # Admin can see all messages sent in relation to a proposal messages = CFPMessage.query.filter_by( proposal_id=proposal_id ).order_by('created').all() return render_template('cfp_review/message_proposer.html', form=form, messages=messages, proposal=proposal)
def _get_ical_dict(event, favourites_ids): res = { 'id': -event.id, 'start_date': event_tz.localize(event.start_dt), 'end_date': event_tz.localize(event.end_dt), 'venue': event.location or '(Unknown)', 'latlon': event.latlon, 'map_link': event.map_link, 'title': event.summary, 'speaker': '', 'user_id': None, 'description': event.description, 'type': 'talk', 'may_record': False, 'is_fave': event.id in favourites_ids, 'source': 'external', 'link': external_url('.line_up_external', event_id=event.id), } if event.type in ['workshop', 'youthworkshop']: res['cost'] = event.display_cost res['equipment'] = event.display_participant_equipment res['age_range'] = event.display_age_range return res
def add_event(room, event): url = external_url("schedule.item", year=event_year(), proposal_id=event["id"], slug=event["slug"]) event_node = etree.SubElement(room, "event", id=str(event["id"]), guid=str(uuid5(NAMESPACE_URL, url))) _add_sub_with_text(event_node, "room", room.attrib["name"]) _add_sub_with_text(event_node, "title", event["title"]) _add_sub_with_text(event_node, "type", event.get("type", "talk")) _add_sub_with_text(event_node, "date", event["start_date"].isoformat()) # Start time _add_sub_with_text(event_node, "start", event["start_date"].strftime("%H:%M")) duration = get_duration(event["start_date"], event["end_date"]) _add_sub_with_text(event_node, "duration", duration) _add_sub_with_text(event_node, "abstract", event["description"]) _add_sub_with_text(event_node, "description", "") _add_sub_with_text( event_node, "slug", "emf%s-%s-%s" % (event_year(), event["id"], event["slug"]), ) _add_sub_with_text(event_node, "subtitle", "") _add_sub_with_text(event_node, "track", "") add_persons(event_node, event) add_recording(event_node, event)
def _get_proposal_dict(proposal, favourites_ids): res = { "id": proposal.id, "slug": proposal.slug, "start_date": event_tz.localize(proposal.start_date), "end_date": event_tz.localize(proposal.end_date), "venue": proposal.scheduled_venue.name, "latlon": proposal.latlon, "map_link": proposal.map_link, "title": proposal.display_title, "speaker": proposal.published_names or proposal.user.name, "user_id": proposal.user.id, "description": proposal.published_description or proposal.description, "type": proposal.type, "may_record": proposal.may_record, "is_fave": proposal.id in favourites_ids, "source": "database", "link": external_url(".line_up_proposal", proposal_id=proposal.id), } if proposal.type in ["workshop", "youthworkshop"]: res["cost"] = proposal.display_cost res["equipment"] = proposal.display_participant_equipment res["age_range"] = proposal.display_age_range return res
def _get_proposal_dict(proposal, favourites_ids): res = { 'id': proposal.id, 'slug': proposal.slug, 'start_date': event_tz.localize(proposal.start_date), 'end_date': event_tz.localize(proposal.end_date), 'venue': proposal.scheduled_venue.name, 'latlon': proposal.latlon, 'map_link': proposal.map_link, 'title': proposal.display_title, 'speaker': proposal.published_names or proposal.user.name, 'user_id': proposal.user.id, 'description': proposal.published_description or proposal.description, 'type': proposal.type, 'may_record': proposal.may_record, 'is_fave': proposal.id in favourites_ids, 'source': 'database', 'link': external_url('.line_up_proposal', proposal_id=proposal.id), } if proposal.type in ['workshop', 'youthworkshop']: res['cost'] = proposal.display_cost res['equipment'] = proposal.display_participant_equipment res['age_range'] = proposal.display_age_range return res
def invoice(payment_id, fmt=None): pdf = False if fmt == "pdf": pdf = True elif fmt: abort(404) payment = get_user_payment_or_abort(payment_id, allow_admin=True) form = InvoiceForm() if form.validate_on_submit(): current_user.company = form.company.data payment.issue_vat_invoice_number() db.session.commit() flash("Company name updated") return redirect(url_for(".invoice", payment_id=payment_id)) if request.method != "POST": form.company.data = current_user.company edit_company = bool(request.args.get("edit_company")) if request.args.get("js") == "0": flash("Please use your browser's print feature or download the PDF") invoice_lines = ( Purchase.query.filter_by(payment_id=payment_id) .join(PriceTier, Product) .with_entities(PriceTier, func.count(Purchase.price_tier_id)) .group_by(PriceTier, Product.name) .order_by(Product.name) .all() ) ticket_sum = sum( pt.get_price(payment.currency).value_ex_vat * count for pt, count in invoice_lines ) if payment.provider == "stripe": premium = payment.__class__.premium(payment.currency, ticket_sum) else: premium = Decimal(0) subtotal = ticket_sum + premium vat = subtotal * Decimal("0.2") # FIXME: we should use a currency-specific quantization here (or rounder numbers) if subtotal + vat - payment.amount > Decimal("0.01"): app.logger.error( "Invoice total mismatch: %s + %s - %s = %s", subtotal, vat, payment.amount, subtotal + vat - payment.amount, ) flash("Your invoice cannot currently be displayed") return redirect(url_for("users.purchases")) if payment.vat_invoice_number: mode = "invoice" invoice_number = payment.issue_vat_invoice_number() else: mode = "receipt" invoice_number = None page = render_template( "payments/invoice.html", mode=mode, payment=payment, invoice_lines=invoice_lines, form=form, premium=premium, subtotal=subtotal, vat=vat, edit_company=edit_company, invoice_number=invoice_number, ) url = external_url(".invoice", payment_id=payment_id) if pdf: return send_file( render_pdf(url, page), mimetype="application/pdf", cache_timeout=60, attachment_filename=f"emf_{mode}.pdf", as_attachment=True, ) if mode == "invoice": invoice_dir = "/vat_invoices" if not os.path.exists(invoice_dir): logger.warn( "Not exporting VAT invoice as directory (%s) does not exist", invoice_dir, ) return page with open(os.path.join(invoice_dir, f"{invoice_number}.pdf"), "wb") as f: shutil.copyfileobj(render_pdf(url, page), f) return page
def product_view_bulk_add_vouchers_by_email(view_id): view = ProductView.query.get_or_404(view_id) form = BulkVoucherEmailForm() if not form.validate_on_submit() or form.preview.data: preview = None if form.preview.data: preview = format_trusted_html_email( form.text.data, form.subject.data, voucher_url="http://VOUCHER_URL_PLACEHOLDER", expiry=form.expires.data, reason=form.reason.data, ) return render_template( "admin/products/view-bulk-add-voucher.html", view=view, form=form, preview=preview, ) emails = set(e.strip() for e in re.split(r"[\s,]+", form.emails.data)) if len(emails) >= 250: flash("More than 250 emails provided. Please submit <250 at a time.") return redirect( url_for(".product_view_bulk_add_vouchers_by_email", view_id=view_id)) added = existing = sent_total = 0 with mail.get_connection() as conn: for email in emails: if Voucher.query.filter_by(email=email).first(): existing += 1 continue voucher = Voucher( view, code=random_voucher(), email=email, expiry=form.expires.data, purchases_remaining=form.num_purchases.data, tickets_remaining=form.num_tickets.data, ) voucher_url = external_url("tickets.tickets_voucher", voucher_code=voucher.code) plaintext = format_trusted_plaintext_email( form.text.data, voucher_url=voucher_url, expiry=form.expires.data) html = format_trusted_html_email( form.text.data, form.subject.data, voucher_url=voucher_url, expiry=form.expires.data, reason=form.reason.data, ) app.logger.info("Emailing %s volunteer voucher: %s", email, voucher.code) sent_count = mail.send_mail( subject=form.subject.data, message=plaintext, from_email=from_email("TICKETS_EMAIL"), recipient_list=[email], fail_silently=True, connection=conn, html_message=html, ) db.session.commit() sent_total += sent_count added += 1 flash( f"{added} vouchers added, {sent_total} emails sent, {existing} duplicates skipped." ) return redirect( url_for(".product_view_bulk_add_vouchers_by_email", view_id=view_id))