DRRK/alembic/versions/7c2e5a9d1f30_operation_save.py

130 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""operation: валюта, расчётная сумма, связь со строкой файла; типы UWFEE, ADJ
Revision ID: 7c2e5a9d1f30
Revises: 3b9f1c2a7d41
Create Date: 2026-10-19 00:00:00
Запись операций из QUIK и ручной ввод (D20, D21, D22). Таблица operation до
этой ревизии не заполнялась, поэтому currency_id сразу NOT NULL.
"""
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
from app.core.config import settings
# revision identifiers, used by Alembic.
revision: str = "7c2e5a9d1f30"
down_revision: Union[str, None] = "3b9f1c2a7d41"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
_schema = settings.DATABASE_SCHEMA or None
# Типы зафиксированы в ревизии, как и в начальной миграции.
_AMOUNT = sa.Numeric(20, 6)
_SEED_USER = "system"
_NEW_TYPES = [
("UWFEE", "Комиссия за андеррайтинг"),
("ADJ", "Корректировка"),
]
def _trade_number_index(create: bool) -> None:
# В SQLite batch пересоздаёт таблицу и теряет WHERE частичного индекса —
# снимаем его на время batch и создаём заново.
if create:
op.create_index(
"ux_operation_portfolio_trade_number",
"operation",
["portfolio_id", "trade_number"],
unique=True,
schema=_schema,
postgresql_where=sa.text("trade_number IS NOT NULL"),
sqlite_where=sa.text("trade_number IS NOT NULL"),
)
else:
op.drop_index(
"ux_operation_portfolio_trade_number",
table_name="operation",
schema=_schema,
)
def upgrade() -> None:
"""Upgrade schema."""
_trade_number_index(create=False)
with op.batch_alter_table("operation", schema=_schema) as batch:
batch.add_column(sa.Column("currency_id", sa.BigInteger(), nullable=False))
batch.add_column(sa.Column("settlement_amount", _AMOUNT, nullable=True))
batch.add_column(sa.Column("source_row", sa.Integer(), nullable=True))
batch.create_foreign_key(
"fk_operation_currency",
"currency",
["currency_id"],
["id"],
referent_schema=_schema,
)
batch.create_foreign_key(
"fk_operation_import_batch",
"import_batch",
["import_batch_id"],
["id"],
referent_schema=_schema,
)
batch.create_unique_constraint(
"uq_operation_batch_row", ["import_batch_id", "source_row"]
)
_trade_number_index(create=True)
op.create_index(
"ix_operation_portfolio_security_date",
"operation",
["portfolio_id", "security_id", "trade_date"],
schema=_schema,
)
operation_type = sa.table(
"operation_type",
sa.column("code", sa.String),
sa.column("name", sa.String),
sa.column("created_by", sa.String),
sa.column("updated_by", sa.String),
schema=_schema,
)
op.bulk_insert(
operation_type,
[
{
"code": code,
"name": name,
"created_by": _SEED_USER,
"updated_by": _SEED_USER,
}
for code, name in _NEW_TYPES
],
)
def downgrade() -> None:
"""Downgrade schema."""
codes = ", ".join(f"'{code}'" for code, _ in _NEW_TYPES)
table = f"{_schema}.operation_type" if _schema else "operation_type"
op.execute(f"DELETE FROM {table} WHERE code IN ({codes})")
op.drop_index(
"ix_operation_portfolio_security_date",
table_name="operation",
schema=_schema,
)
_trade_number_index(create=False)
with op.batch_alter_table("operation", schema=_schema) as batch:
batch.drop_constraint("uq_operation_batch_row", type_="unique")
batch.drop_constraint("fk_operation_import_batch", type_="foreignkey")
batch.drop_constraint("fk_operation_currency", type_="foreignkey")
batch.drop_column("source_row")
batch.drop_column("settlement_amount")
batch.drop_column("currency_id")
_trade_number_index(create=True)