diff options
Diffstat (limited to 'python/Dawn/views.py')
| -rw-r--r-- | python/Dawn/views.py | 155 |
1 files changed, 98 insertions, 57 deletions
diff --git a/python/Dawn/views.py b/python/Dawn/views.py index 761fdd5b..5acec034 100644 --- a/python/Dawn/views.py +++ b/python/Dawn/views.py @@ -1,23 +1,28 @@ +import datetime +import os +import pandas as pd +import psycopg2 +import redis +import socket + from flask import (request, render_template, redirect, url_for, send_from_directory, send_file, g, jsonify) -from .models import (ModelForm, + +from .models import (ModelForm, CASH_STRAT, BondDeal, CDSDeal, SwaptionDeal, FutureDeal, CashFlowDeal, Counterparties, Accounts) from sqlalchemy.exc import IntegrityError from wtforms.fields import BooleanField -import pandas as pd + from pandas.tseries.offsets import CustomBusinessDay from pandas.tseries.holiday import get_calendar, HolidayCalendarFactory, GoodFriday -import os -import datetime -import redis + from .utils import load_counterparties, bump_rev, simple_serialize from PyPDF2 import PdfFileMerger from io import BytesIO from . import app -import socket -import psycopg2 +from . import db fed_cal = get_calendar('USFederalHolidayCalendar') bond_cal = HolidayCalendarFactory('BondCalendar', fed_cal, GoodFriday) @@ -36,7 +41,7 @@ def cp_choices(kind='bond'): with_entities(Counterparties.code, Counterparties.name)) def account_codes(): - return Accounts.query.order_by('code').with_entities(Accounts.code, Accounts.code) + return Accounts.query.order_by('code').with_entities(Accounts.code, Accounts.name) def get_queue(): q = getattr(g, 'queue', None) @@ -96,13 +101,6 @@ class FutureForm(ModelForm): include_foreign_keys = True exclude = ['dealid', 'lastupdate'] -class WireForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - class Meta: - model = CashFlowDeal - include_foreign_keys = True - exclude = ['dealid', 'lastupdate'] - def get_deal(kind): if kind == 'cds': return CDSDeal @@ -164,9 +162,6 @@ def get_trade(tradeid, kind): Deal = get_deal(kind) return Deal.query.get(tradeid) if tradeid else Deal() -def get_wire(wiredid): - CashFlowDeal.query.get(wireid) - def save_ticket(trade, old_ticket_name): if trade.ticket: if old_ticket_name: @@ -180,42 +175,88 @@ def save_ticket(trade, old_ticket_name): else: trade.ticket = old_ticket_name +def split_direction(g, direction): + if direction == "outgoing": + return [{"folder": cf.folder, "amount": -cf.amount, "code": cf.code} + for cf in g if cf.amount < 0] + elif direction == "incoming": + return [{"folder": cf.folder, "amount": cf.amount, "code": cf.code} + for cf in g if cf.amount > 0] + else: + raise ValueError("direction can be one of 'outgoing' or 'incoming'") + +def gen_cashflow_deals(form): + action = form.get("action") + to_date = lambda s: datetime.datetime.strptime(s, "%Y-%m-%d") + trade_date = form.get("trade_date", None, to_date) + settle_date = form.get("settle_date", None, to_date) + for direction in ["incoming", "outgoing"]: + count = 1 + while True: + if f"{direction}-code-{count}" not in form: + break + else: + r = [form.get(f"{direction}-{field}-{count}") for field \ + in ["folder", "code", "amount"]] + count += 1 + if direction == "outgoing": + r[2] = -float(r[2]) + elif direction == "incoming": + r[2] = float(r[2]) + else: + raise ValueError("direction needs to be 'outgoing' or 'incoming'") + yield CashFlowDeal(trade_date=trade_date, + settle_date=settle_date, + action=action, + folder=r[0], + code=r[1], + amount=r[2]) + @app.route('/wires/<int:wire_id>', methods = ['GET', 'POST']) -@app.route('/wires/', defaults = {'wire_id': None}, methods = ['GET', 'POST']) +@app.route('/wires/', defaults={'wire_id': None}, methods=['GET', 'POST']) def wire_manage(wire_id): - if wire_id is None: - wire = CashFlowDeal() - else: - wire = CashFlowDeal().query.get(wire_id) - form = WireForm() - form.code.choices = form.code.choices + list(account_codes()) - if form.validate_on_submit(): - form.populate_obj(wire) - session = form.get_session() - if not wire_id: - session.add(wire) + if request.method == 'POST': + for wire in gen_cashflow_deals(request.form): + print(wire) + db.session.add(wire) + try: - session.commit() + db.session.commit() except IntegrityError as e: app.logger.error(e) - session.rollback() - return render_template('wire_entry.html', form=form, - action_url= - url_for('wire_manage', wire_id=wire_id)) + db.session.rollback() + return render_template('wire_entry.html', + strategies=[(e, e) for e in CASH_STRAT.enums], + accounts=account_codes(), + outgoing_wires=split_direction( + gen_cashflow_deals(request.form), "outgoing"), + incoming_wires=split_direction( + gen_cashflow_deals(request.form), "incoming"), + action=request.form.get('action'), + trade_date=request.form.get('trade_date'), + settle_date=request.form.get('settle_date')) else: - if form.upload_globeop.data: + if request.form.get('upload_globeop') == 'y': q = get_queue() - q.rpush('wires', simple_serialize(wire)) - return redirect(url_for('list_trades')) - else: - form = get_wire_form(wire) - form.code.choices = form.code.choices + list(account_codes()) - return render_template('wire_entry.html', form=form, - action_url = url_for('wire_manage', wire_id=wire_id)) + for wire in gen_cashflow_deals(request.form): + q.rpush('wires', simple_serialize(wire)) + return redirect(url_for('list_trades', kind='wire')) + + wire = CashFlowDeal() if wire_id is None else CashFlowDeal.query.get(wire_id) + return render_template('wire_entry.html', + strategies=[(e, e) for e in CASH_STRAT.enums], + accounts=account_codes(), + outgoing_wires=split_direction([wire], "outgoing") if wire_id else [], + incoming_wires=split_direction([wire], "incoming") if wire_id else [], + trade_date=wire.trade_date if wire_id else datetime.date.today(), + settle_date=wire.settle_date if wire_id else '', + action_url=url_for('wire_manage', wire_id=wire_id), + action=wire.action if wire_id else None) + -@app.route('/trades/<kind>/<int:tradeid>', methods = ['GET', 'POST']) -@app.route('/trades/<kind>/', defaults = {'tradeid': None}, methods = ['GET', 'POST']) -@app.route('/trades/', defaults = {'tradeid': None, 'kind': 'bond'}, methods = ['GET', 'POST']) +@app.route('/trades/<kind>/<int:tradeid>', methods=['GET', 'POST']) +@app.route('/trades/<kind>/', defaults = {'tradeid': None}, methods=['GET', 'POST']) +@app.route('/trades/', defaults = {'tradeid': None, 'kind': 'bond'}, methods=['GET', 'POST']) def trade_manage(tradeid, kind): trade = get_trade(tradeid, kind) form = _get_form(kind)() @@ -241,24 +282,24 @@ def trade_manage(tradeid, kind): else: if form.upload_globeop.data: q = get_queue() - q.rpush('{0}_trades'.format(kind), simple_serialize(trade)) + q.rpush(f'{kind}_trades', simple_serialize(trade)) return redirect(url_for('list_trades', kind=kind)) else: form = get_form(trade, kind) form.cp_code.choices = form.cp_code.choices + list(cp_choices(kind)) return render_template('trade_entry.html', form=form, - action_url = url_for('trade_manage', tradeid=tradeid, kind=kind)) + action_url=url_for('trade_manage', tradeid=tradeid, kind=kind)) @app.route('/', defaults={'kind': 'bond'}) @app.route('/blotter/<kind>') @app.route('/blotter/', defaults={'kind': 'bond'}) def list_trades(kind): if kind == 'wire': - Deal = CashFlowDeal() + Deal = CashFlowDeal else: Deal = get_deal(kind) trade_list = Deal.query.order_by(Deal.trade_date.desc(), Deal.id.desc()) - return render_template('{}_blotter.html'.format(kind), trades=trade_list.all()) + return render_template(f'{kind}_blotter.html', trades=trade_list.all()) @app.route('/tickets/<int:tradeid>') def download_ticket(tradeid): @@ -273,18 +314,18 @@ def download_ticket(tradeid): return send_file(fh, mimetype='application/pdf') @app.route('/counterparties/<path:instr>', methods = ['GET']) -@app.route('/counterparties/', defaults = {'instr': None}, 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'], + 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()) + return render_template('counterparties.html', counterparties=cp_list.all()) -@app.route('/edit_cp/<cpcode>', methods = ['GET', 'POST']) -@app.route('/edit_cp/', defaults = {'cpcode': None}, methods = ['GET', 'POST']) +@app.route('/edit_cp/<cpcode>', methods=['GET', 'POST']) +@app.route('/edit_cp/', defaults={'cpcode': None}, methods=['GET', 'POST']) def edit_counterparty(cpcode): if cpcode: cp = Counterparties.query.get(cpcode) @@ -310,7 +351,7 @@ def edit_counterparty(cpcode): else: return render_template('edit_cp.html', form=CounterpartyForm(obj=cp), code=cpcode) -@app.route('/_ajax', methods = ['GET']) +@app.route('/_ajax', methods=['GET']) def get_bbg_id(): bbg_id = request.args.get('bbg_id') try: |
