generated from daniil-berg/boilerplate-py
Compare commits
3 Commits
9f487d515d
...
284986f763
Author | SHA1 | Date | |
---|---|---|---|
284986f763 | |||
b417ac16e0 | |||
3f6be9adbc |
@ -18,20 +18,23 @@ from compub.settings import settings
|
||||
from sqlmodel import create_engine, Session
|
||||
|
||||
|
||||
DEFAULT_PK_TYPE = int
|
||||
|
||||
|
||||
class DB:
|
||||
def __init__(self):
|
||||
self._engine: AsyncEngine | Engine | None = None
|
||||
self._session_maker: sessionmaker | None = None
|
||||
self.session_maker: sessionmaker | None = None
|
||||
|
||||
def start_engine(self) -> None:
|
||||
if settings.db_uri is None:
|
||||
raise NoDatabaseConfigured
|
||||
if settings.db_uri.scheme == 'sqlite':
|
||||
self._engine = create_engine(settings.db_uri)
|
||||
self._session_maker = sessionmaker(self.engine, expire_on_commit=False, class_=Session)
|
||||
self._engine = create_engine(settings.db_uri, echo=True)
|
||||
self.session_maker = sessionmaker(self.engine, expire_on_commit=False, class_=Session)
|
||||
else:
|
||||
self._engine = create_async_engine(settings.db_uri, future=True)
|
||||
self._session_maker = sessionmaker(self.engine, expire_on_commit=False, class_=AsyncSession)
|
||||
self.session_maker = sessionmaker(self.engine, expire_on_commit=False, class_=AsyncSession)
|
||||
force_auto_coercion()
|
||||
|
||||
@property
|
||||
@ -41,19 +44,29 @@ class DB:
|
||||
assert isinstance(self._engine, (AsyncEngine, Engine))
|
||||
return self._engine
|
||||
|
||||
async def get_session(self) -> Session | AsyncSession:
|
||||
if self._session_maker is None:
|
||||
async def get_session(self) -> AsyncSession:
|
||||
if self.session_maker is None:
|
||||
self.start_engine()
|
||||
assert isinstance(self._session_maker, sessionmaker)
|
||||
session = self._session_maker()
|
||||
assert isinstance(self.session_maker.class_, AsyncSession)
|
||||
session = self.session_maker()
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
await session.close()
|
||||
|
||||
def get_session_blocking(self) -> Session:
|
||||
if self.session_maker is None:
|
||||
self.start_engine()
|
||||
assert isinstance(self.session_maker.class_, Session)
|
||||
session = self.session_maker()
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
class AbstractBase(SQLModel):
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
id: Optional[DEFAULT_PK_TYPE] = Field(default=None, primary_key=True)
|
||||
date_created: Optional[datetime] = Field(
|
||||
default=None, sa_column=Column(TIMESTAMP(timezone=False), server_default=db_now())
|
||||
)
|
||||
|
@ -7,19 +7,21 @@ from sqlalchemy.event.api import listens_for
|
||||
from sqlalchemy.orm.mapper import Mapper
|
||||
from sqlalchemy.sql.expression import select
|
||||
from sqlalchemy.sql.functions import count
|
||||
from sqlalchemy.sql.schema import Column
|
||||
from sqlalchemy.sql.schema import Column, Index
|
||||
from sqlalchemy.sql.sqltypes import Unicode
|
||||
from sqlalchemy_utils.types import CountryType
|
||||
from sqlmodel.main import Field, Relationship
|
||||
|
||||
from compub.utils import multi_max
|
||||
from .base import AbstractBase
|
||||
from .geography import Address
|
||||
|
||||
|
||||
__all__ = [
|
||||
'LegalForm',
|
||||
'LegalFormSubcategory',
|
||||
'Industry',
|
||||
'Executive',
|
||||
'Company',
|
||||
'CompanyName',
|
||||
]
|
||||
@ -44,6 +46,9 @@ class LegalForm(AbstractBase, table=True):
|
||||
|
||||
class LegalFormSubcategory(AbstractBase, table=True):
|
||||
__tablename__ = 'legal_form_subcategory'
|
||||
__table_args__ = (
|
||||
Index('ux_legal_form_subcategory', 'short', 'legal_form_id', unique=True),
|
||||
)
|
||||
|
||||
# Fields
|
||||
short: str = Field(max_length=32, nullable=False, index=True)
|
||||
@ -66,18 +71,32 @@ class LegalFormSubcategory(AbstractBase, table=True):
|
||||
|
||||
|
||||
class CompanyIndustryLink(AbstractBase, table=True):
|
||||
__tablename__ = 'company_industries'
|
||||
__tablename__ = 'company_industry'
|
||||
__table_args__ = (
|
||||
Index('ux_company_industry', 'company_id', 'industry_id', unique=True),
|
||||
)
|
||||
|
||||
# Relationships
|
||||
company_id: Optional[int] = Field(foreign_key='company.id', default=None, nullable=False, primary_key=True)
|
||||
industry_id: Optional[int] = Field(foreign_key='industry.id', default=None, nullable=False, primary_key=True)
|
||||
|
||||
|
||||
class CompanyExecutiveLink(AbstractBase, table=True):
|
||||
__tablename__ = 'company_executive'
|
||||
__table_args__ = (
|
||||
Index('ux_company_executive', 'company_id', 'executive_id', unique=True),
|
||||
)
|
||||
|
||||
# Relationships
|
||||
company_id: Optional[int] = Field(foreign_key='company.id', default=None, nullable=False, primary_key=True)
|
||||
executive_id: Optional[int] = Field(foreign_key='executive.id', default=None, nullable=False, primary_key=True)
|
||||
|
||||
|
||||
class Industry(AbstractBase, table=True):
|
||||
__tablename__ = 'industry'
|
||||
|
||||
# Fields
|
||||
name: str = Field(max_length=255, nullable=False, index=True)
|
||||
name: str = Field(max_length=255, nullable=False, index=True, sa_column_kwargs={'unique': True})
|
||||
|
||||
# Relationships
|
||||
companies: list['Company'] = Relationship(
|
||||
@ -88,6 +107,24 @@ class Industry(AbstractBase, table=True):
|
||||
return str(self.name)
|
||||
|
||||
|
||||
class Executive(AbstractBase, table=True):
|
||||
__tablename__ = 'executive'
|
||||
__MAX_LENGTH_NAME__: int = 255
|
||||
|
||||
# Fields
|
||||
name: str = Field(
|
||||
max_length=__MAX_LENGTH_NAME__, sa_column=Column(Unicode(__MAX_LENGTH_NAME__), nullable=False, index=True)
|
||||
)
|
||||
|
||||
# Relationships
|
||||
companies: list['Company'] = Relationship(
|
||||
back_populates='executives', link_model=CompanyExecutiveLink, sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.name)
|
||||
|
||||
|
||||
class Company(AbstractBase, table=True):
|
||||
__tablename__ = 'company'
|
||||
|
||||
@ -96,7 +133,8 @@ class Company(AbstractBase, table=True):
|
||||
insolvent: bool = Field(default=False, nullable=False, index=True)
|
||||
founding_data: Optional[date]
|
||||
liquidation_date: Optional[date]
|
||||
city: str = Field(max_length=255, index=True) # TODO: Get rid of city; implement address properly
|
||||
# TODO: Get rid of city; implement address properly
|
||||
city: Optional[str] = Field(max_length=255, nullable=True, index=True)
|
||||
|
||||
# Relationships
|
||||
legal_form_id: Optional[int] = Field(
|
||||
@ -109,11 +147,18 @@ class Company(AbstractBase, table=True):
|
||||
address_id: Optional[int] = Field(
|
||||
foreign_key='address.id', default=None, index=True
|
||||
)
|
||||
address: Optional[Address] = Relationship(
|
||||
back_populates='companies', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
industries: list[Industry] = Relationship(
|
||||
back_populates='companies', link_model=CompanyIndustryLink, sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
executives: list[Executive] = Relationship(
|
||||
back_populates='companies', link_model=CompanyExecutiveLink, sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
names: list['CompanyName'] = Relationship(
|
||||
back_populates='company', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
@ -128,12 +173,16 @@ class Company(AbstractBase, table=True):
|
||||
|
||||
class CompanyName(AbstractBase, table=True):
|
||||
__tablename__ = 'company_name'
|
||||
__MAX_NAME_LENGTH__: int = 768
|
||||
__table_args__ = (
|
||||
Index('ux_company_name_company_id', 'name', 'company_id', unique=True),
|
||||
)
|
||||
|
||||
__MAX_LENGTH_NAME__: int = 768
|
||||
__MAX_SLUG_LENGTH__: int = 255
|
||||
|
||||
# Fields
|
||||
name: str = Field(
|
||||
max_length=__MAX_NAME_LENGTH__, sa_column=Column(Unicode(__MAX_NAME_LENGTH__), nullable=False, index=True)
|
||||
max_length=__MAX_LENGTH_NAME__, sa_column=Column(Unicode(__MAX_LENGTH_NAME__), nullable=False, index=True)
|
||||
)
|
||||
date_registered: Optional[date]
|
||||
slug: Optional[str] = Field(default=None, max_length=__MAX_SLUG_LENGTH__, index=True)
|
||||
|
110
src/compub/models/courts.py
Normal file
110
src/compub/models/courts.py
Normal file
@ -0,0 +1,110 @@
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy.sql.schema import Column, Index
|
||||
from sqlalchemy.sql.sqltypes import Unicode
|
||||
from sqlmodel.main import Field, Relationship
|
||||
|
||||
from .base import AbstractBase, DEFAULT_PK_TYPE
|
||||
from .geography import StateProvince, Address
|
||||
|
||||
|
||||
# Amtsgericht -> Landgericht -> OLG -> BGH
|
||||
class CourtClass(AbstractBase, table=True):
|
||||
__tablename__ = 'court_class'
|
||||
|
||||
# Fields
|
||||
short: str = Field(max_length=32, nullable=False, index=True)
|
||||
name: str = Field(max_length=255, sa_column=Column(Unicode(255)))
|
||||
|
||||
# Relationships
|
||||
courts: list['Court'] = Relationship(
|
||||
back_populates='court_class', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.name)
|
||||
|
||||
|
||||
class CourtDepartmentCourtLink(AbstractBase, table=True):
|
||||
__tablename__ = 'court_department_court'
|
||||
__table_args__ = (
|
||||
Index('ux_court_department_court', 'court_department_id', 'court_id', unique=True),
|
||||
)
|
||||
|
||||
# Relationships
|
||||
court_department_id: Optional[DEFAULT_PK_TYPE] = Field(
|
||||
foreign_key='court_department.id', default=None, nullable=False, primary_key=True
|
||||
)
|
||||
court_id: Optional[DEFAULT_PK_TYPE] = Field(
|
||||
foreign_key='court.id', default=None, nullable=False, primary_key=True
|
||||
)
|
||||
|
||||
|
||||
# Abteilung innerhalb eines Amtsgerichts (z. B. Registergericht, Insolvenzgericht etc.)
|
||||
class CourtDepartment(AbstractBase, table=True):
|
||||
__tablename__ = 'court_department'
|
||||
|
||||
__REG_COURT_PK__ = 1
|
||||
__INS_COURT_PK__ = 2
|
||||
|
||||
# Fields
|
||||
name: str = Field(max_length=255, sa_column=Column(Unicode(255)))
|
||||
|
||||
# Relationships
|
||||
courts: list['Court'] = Relationship(
|
||||
back_populates='court_departments', link_model=CourtDepartmentCourtLink,
|
||||
sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.name)
|
||||
|
||||
|
||||
class Court(AbstractBase, table=True):
|
||||
__tablename__ = 'court'
|
||||
|
||||
# Fields
|
||||
name: str = Field(max_length=255, sa_column=Column(Unicode(255)))
|
||||
|
||||
# Relationships
|
||||
court_class_id: Optional[DEFAULT_PK_TYPE] = Field(
|
||||
foreign_key='court_class.id', default=None, nullable=False, index=True
|
||||
)
|
||||
court_class: Optional[CourtClass] = Relationship(
|
||||
back_populates='courts', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
state_province_id: Optional[DEFAULT_PK_TYPE] = Field(
|
||||
foreign_key='state_province.id', default=None, nullable=True, index=True
|
||||
)
|
||||
state_province: Optional[StateProvince] = Relationship(
|
||||
back_populates='courts', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
address_id: Optional[DEFAULT_PK_TYPE] = Field(
|
||||
foreign_key='address.id', default=None, nullable=True, index=True
|
||||
)
|
||||
address: Optional[Address] = Relationship(
|
||||
back_populates='courts', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
parent_court_id: Optional[DEFAULT_PK_TYPE] = Field(
|
||||
foreign_key='court.id', default=None, nullable=True, index=True
|
||||
)
|
||||
parent_court: Optional['Court'] = Relationship(
|
||||
back_populates='sub_courts',
|
||||
sa_relationship_kwargs=dict(
|
||||
lazy='selectin',
|
||||
remote_side='Court.id'
|
||||
)
|
||||
)
|
||||
sub_courts: list['Court'] = Relationship(
|
||||
back_populates='parent_court', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
court_departments: list[CourtDepartment] = Relationship(
|
||||
back_populates='courts', link_model=CourtDepartmentCourtLink, sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.name)
|
@ -1,7 +1,7 @@
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, TYPE_CHECKING
|
||||
|
||||
from pydantic import validator
|
||||
from sqlalchemy.sql.schema import Column
|
||||
from sqlalchemy.sql.schema import Column, Index
|
||||
from sqlalchemy.sql.sqltypes import Unicode
|
||||
from sqlalchemy_utils.primitives.country import Country
|
||||
from sqlalchemy_utils.types import CountryType
|
||||
@ -9,6 +9,10 @@ from sqlmodel.main import Field, Relationship
|
||||
|
||||
from .base import AbstractBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .companies import Company
|
||||
from .courts import Court
|
||||
|
||||
|
||||
__all__ = [
|
||||
'StateProvince',
|
||||
@ -20,6 +24,9 @@ __all__ = [
|
||||
|
||||
class StateProvince(AbstractBase, table=True):
|
||||
__tablename__ = 'state_province'
|
||||
__table_args__ = (
|
||||
Index('ux_state_province_name_country', 'name', 'country', unique=True),
|
||||
)
|
||||
|
||||
# Fields
|
||||
country: str = Field(sa_column=Column(CountryType, nullable=False, index=True))
|
||||
@ -30,6 +37,10 @@ class StateProvince(AbstractBase, table=True):
|
||||
back_populates='state_province', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
courts: list['Court'] = Relationship(
|
||||
back_populates='state_province', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
@validator('country', pre=True)
|
||||
def country_as_uppercase_string(cls, v: Any) -> str:
|
||||
if isinstance(v, Country):
|
||||
@ -41,6 +52,9 @@ class StateProvince(AbstractBase, table=True):
|
||||
|
||||
class City(AbstractBase, table=True):
|
||||
__tablename__ = 'city'
|
||||
__table_args__ = (
|
||||
Index('ux_city_name_zip_state', 'name', 'zip_code', 'state_province_id', unique=True),
|
||||
)
|
||||
|
||||
# Fields
|
||||
zip_code: str = Field(max_length=5, nullable=False, index=True)
|
||||
@ -92,3 +106,11 @@ class Address(AbstractBase, table=True):
|
||||
street: Optional[Street] = Relationship(
|
||||
back_populates='addresses', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
companies: list['Company'] = Relationship(
|
||||
back_populates='address', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
||||
courts: list['Court'] = Relationship(
|
||||
back_populates='address', sa_relationship_kwargs={'lazy': 'selectin'}
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user