aboutsummaryrefslogtreecommitdiffstats
path: root/python/Dawn/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/Dawn/views.py')
-rw-r--r--python/Dawn/views.py155
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: