from flask import (request, render_template, redirect, url_for, send_from_directory, send_file, g) from .models import ModelForm, BondDeal, Counterparties from sqlalchemy.exc import IntegrityError from wtforms.fields import BooleanField import pandas as pd from pandas.tseries.offsets import BDay import os import datetime import redis from .utils import load_counterparties, load_trades, add_triggers, bump_rev, simple_serialize from PyPDF2 import PdfFileMerger from io import BytesIO from Dawn import app import socket def cp_choices(): return Counterparties.query.order_by('name').\ with_entities(Counterparties.code, Counterparties.name) def get_queue(): q = getattr(g, 'queue', None) if q is None: hostname = socket.gethostname() if hostname == 'debian': q = g.queue = redis.Redis(unix_socket_path='/var/run/redis/redis.sock') elif hostname =='gomez': q = g.queue = redis.Redis(host='debian') return q class CounterpartyForm(ModelForm): class Meta: model = Counterparties class BondForm(ModelForm): upload_globeop = BooleanField(label="Upload to globeop?") class Meta: model = BondDeal include_foreign_keys = True exclude = ['dealid', 'lastupdate', #we generate it with a trigger at the server level 'principal_payment', 'accrued_payment'] @app.route('/trades/', methods=['GET', 'POST']) @app.route('/trades/', defaults={'tradeid': None}, methods=['GET', 'POST']) def trade_manage(tradeid): trade = BondDeal.query.get(tradeid) if tradeid else BondDeal() if tradeid: bond_form = BondForm(obj = trade) old_ticket_name = trade.ticket else: bond_form = BondForm(trade_date = pd.datetime.today().date(), settle_date = pd.datetime.today().date() + 3 * BDay()) #add extra empty fields bond_form.folder.choices = [(None, '')] + bond_form.folder.choices bond_form.buysell.choices = [(None, '')] + bond_form.buysell.choices bond_form.asset_class.choices = [(None, '')] + bond_form.asset_class.choices bond_form.cp_code.choices = bond_form.cp_code.choices + list(cp_choices()) if bond_form.is_submitted(): if bond_form.validate(): bond_form.populate_obj(trade) session = bond_form.get_session() ticket_file = trade.ticket trade.ticket = None if not tradeid: session.add(trade) if ticket_file.filename == '': if tradeid: trade.ticket = old_ticket_name else: if tradeid and old_ticket_name: trade.ticket = bump_rev(old_ticket_name) else: trade.ticket = "{0} {1}.pdf".format(str(trade.trade_date), trade.description) ticket_file.save(os.path.join(app.config['TICKETS_FOLDER'], trade.ticket)) try: session.commit() except IntegrityError as e: app.logger.error(e) finally: if bond_form.upload_globeop.data: q = get_queue() q.rpush('trades', simple_serialize(trade)) return redirect(url_for('list_trades')) else: return str(bond_form.errors) return render_template('trade_entry.html', form=bond_form, trade_id=tradeid) @app.route('/blotter/') def list_trades(): trade_list = BondDeal.query.order_by(BondDeal.trade_date.desc(), BondDeal.id.desc()) return render_template('blotter.html', trades=trade_list.all()) @app.route('/tickets/') def download_ticket(tradeid): trade = BondDeal.query.get(tradeid) pdf = PdfFileMerger() pdf.append(os.path.join(app.config['TICKETS_FOLDER'], trade.ticket)) pdf.append(os.path.join(app.config['CP_FOLDER'], trade.counterparty.instructions)) fh = BytesIO() pdf.write(fh) pdf.close() fh.seek(0) return send_file(fh, mimetype='application/pdf') @app.route('/counterparties/', methods=['GET']) @app.route('/counterparties/', defaults={'instr': None}, methods=['GET']) def list_counterparties(instr): if instr: return send_from_directory(filename = instr, directory = app.config['CP_FOLDER'], mimetype='application/pdf') else: cp_list = Counterparties.query.order_by(Counterparties.name) return render_template('counterparties.html', counterparties = cp_list.all()) @app.route('/edit_cp/', methods=['GET', 'POST']) def edit_counterparty(cpcode): cp = Counterparties.query.get(cpcode) cp_form = CounterpartyForm(obj = cp) old_instructions = cp.instructions if cp_form.is_submitted(): if cp_form.validate(): cp_form.populate_obj(cp) session = cp_form.get_session() instructions = cp.instructions if instructions.filename == '': cp.instructions = old_instructions else: cp.instructions = cp.name + '.pdf' instructions.save(os.path.join(app.config['CP_FOLDER'], cp.instructions)) session.commit() return redirect(url_for('list_counterparties')) return render_template('edit_cp.html', form=cp_form, code=cpcode)