diff options
Diffstat (limited to 'python/report_ops/wires.py')
| -rw-r--r-- | python/report_ops/wires.py | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/python/report_ops/wires.py b/python/report_ops/wires.py index 094ae967..13834410 100644 --- a/python/report_ops/wires.py +++ b/python/report_ops/wires.py @@ -2,20 +2,44 @@ import datetime from csv import DictReader from typing import ClassVar from functools import partial -from dataclasses import dataclass, field +from dataclasses import dataclass, field, Field import pandas as pd -from serenitas.ops.trade_dataclasses import Deal, Ccy +from serenitas.ops.trade_dataclasses import Ccy from serenitas.ops.dataclass_mapping import Fund from serenitas.analytics.dates import prev_business_day from serenitas.analytics.exceptions import MissingDataError from serenitas.utils.env import DAILY_DIR +from serenitas.utils.db2 import dbconn from .misc import get_dir, dt_from_fname, Custodian +class Report: + _sql_insert: ClassVar[str] + _insert_queue: ClassVar[list] + _insert_fields: ClassVar[list] + _conn: ClassVar = dbconn("dawndb") + _registry = {} + + def __init_subclass__(cls, table_name: str): + cls._insert_fields = list(filter(cls.is_insert_field, cls.__annotations__)) + place_holders = ",".join(["%s"] * len(cls._insert_fields)) + cls._sql_insert = f"INSERT INTO {table_name}({','.join(cls._insert_fields)}) VALUES({place_holders}) ON CONFLICT (unique_ref) DO NOTHING RETURNING *" + cls._insert_queue = [] + + @classmethod + def is_insert_field(cls, attr): + """fields are insertable by default unless specified otherwise""" + match getattr(cls, attr, None): + case Field(metadata={"insert": False}) | Field(init=False): + return False + case _: + return True + + @dataclass -class WireReport(Deal, table_name="custodian_wires", deal_type="custodian_wires"): +class WireReport(Report, table_name="custodian_wires"): date: datetime.date fund: Fund custodian: ClassVar[Custodian] @@ -26,17 +50,16 @@ class WireReport(Deal, table_name="custodian_wires", deal_type="custodian_wires" amount: float wire_details: str unique_ref: str - dtkey: ClassVar = field(metadata={"insert": False, "select": False}) + dtkey: ClassVar = field(metadata={"insert": False}) def __init_subclass__(cls, custodian, dtkey, **kwargs): - cls._sql_insert = ( - cls._sql_insert.removesuffix("RETURNING *") - + "ON CONFLICT (unique_ref) DO NOTHING RETURNING *" - ) cls.custodian = custodian cls._registry[custodian] = cls cls.dtkey = dtkey + def __class_getitem__(cls, custodian): + return cls._registry[custodian] + def __post_init__(self): if isinstance(self.amount, str): self.amount = self.amount.replace(",", "") @@ -45,6 +68,11 @@ class WireReport(Deal, table_name="custodian_wires", deal_type="custodian_wires" else: self.amount = float(self.amount) + def stage(self): + self._insert_queue.append( + tuple([getattr(self, col) for col in self._insert_fields]) + ) + @classmethod def get_report(cls, date, fund, prefix=None): report_dir = get_dir(date) @@ -62,9 +90,18 @@ class WireReport(Deal, table_name="custodian_wires", deal_type="custodian_wires" return p @classmethod + def commit(cls): + conn = cls._conn + with conn.cursor() as c: + c.executemany(cls._sql_insert, cls._insert_queue) + conn.commit() + cls._insert_queue.clear() + + @classmethod def to_db(cls, date, fund): for line in cls.yield_rows(date, fund): - cls.from_report_line(line | {"fund": fund}).stage() + trade = cls.from_report_line(line | {"fund": fund}) + trade.stage() cls.commit() |
