"""Ставки фондирования портфелей по валютам (D27).""" from __future__ import annotations import logging from datetime import date import streamlit as st from app.db.base import run_db from app.services import funding from app.services.funding import FundingError, FundingOptions, FundingRateInput from app.services.manual_operations import ManualOperationError, parse_decimal from app.ui.common import as_table, call_db, current_user, download_xlsx logger = logging.getLogger(__name__) _ON_DATE_COLUMNS = { "currency": "Валюта", "rate": "Ставка, % год.", "effective_from": "Действует с", } _HISTORY_COLUMNS = { "effective_from": "Действует с", "currency": "Валюта", "rate": "Ставка, % год.", "updated_by": "Кто", "updated_at": "Когда", } def render() -> None: st.header("Фондирование") st.caption( "Ставка портфеля в валюте, % годовых, действует с указанной даты до " "следующей. Повторный ввод на ту же дату заменяет ставку. Стоимость " "фондирования пока не считается." ) options = call_db(funding.load_options(), "Не удалось загрузить справочники") if options is None: return portfolio = st.selectbox( "Портфель", list(options.portfolios), format_func=lambda c: f"{c} — {options.portfolios[c]}", key="funding_portfolio", ) on_date = st.date_input( "Ставки на дату", value=date.today(), format="DD.MM.YYYY", key="funding_on" ) rates = call_db( funding.rates_on(portfolio, on_date), "Не удалось загрузить ставки на дату" ) if rates is not None: st.dataframe(as_table(rates, _ON_DATE_COLUMNS), hide_index=True) st.subheader("Новая ставка") _render_form(options, portfolio) st.subheader("История ставок") history = call_db( funding.rate_history(portfolio), "Не удалось загрузить историю ставок" ) if history: st.dataframe(as_table(history, _HISTORY_COLUMNS), hide_index=True) download_xlsx( history, _HISTORY_COLUMNS, "Ставки фондирования", f"ставки_фондирования_{portfolio}.xlsx", ) elif history is not None: st.caption("Ставок пока нет.") def _render_form(options: FundingOptions, portfolio: str) -> None: with st.form(f"funding_rate_{portfolio}", clear_on_submit=True): currency = st.selectbox("Валюта", options.currencies) effective_from = st.date_input( "Действует с", value=date.today(), format="DD.MM.YYYY" ) rate_text = st.text_input("Ставка, % годовых", placeholder="например 16,5") submitted = st.form_submit_button("Сохранить ставку", type="primary") if submitted: _save(portfolio, currency, effective_from, rate_text) def _save(portfolio: str, currency: str, effective_from: date, rate_text: str) -> None: try: value = FundingRateInput( portfolio_code=portfolio, currency_code=currency, effective_from=effective_from, rate=parse_decimal(rate_text, "Ставка"), ) run_db(funding.set_rate(value, current_user())) except (ManualOperationError, FundingError) as exc: st.error(str(exc)) return except Exception as exc: # noqa: BLE001 logger.exception("Ошибка сохранения ставки %s %s", portfolio, currency) st.error(f"Не удалось сохранить ставку: {exc}") return st.toast(f"Ставка {portfolio}, {currency} с {effective_from:%d.%m.%Y} сохранена.") st.rerun()