627 lines
21 KiB
Python
627 lines
21 KiB
Python
from datetime import timedelta
|
|
from typing import List, Union, Any
|
|
|
|
import arrow
|
|
from sqlalchemy.orm import mapped_column, relationship, Mapped
|
|
from sqlalchemy import (
|
|
String,
|
|
Integer,
|
|
Boolean,
|
|
ForeignKey,
|
|
Index,
|
|
TIMESTAMP,
|
|
Text,
|
|
Numeric,
|
|
or_,
|
|
)
|
|
from fastapi import HTTPException, status
|
|
|
|
from Controllers.Postgres.mixin import CrudCollection
|
|
|
|
|
|
class BuildTypes(CrudCollection):
|
|
"""
|
|
BuildTypes class based on declarative_base and BaseMixin via session
|
|
|
|
"""
|
|
|
|
__tablename__ = "build_types"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
|
|
function_code: Mapped[str] = mapped_column(
|
|
String(12), server_default="", nullable=False, comment="Function Code"
|
|
)
|
|
type_code: Mapped[str] = mapped_column(
|
|
String(12), server_default="", nullable=False, comment="Structure Type Code"
|
|
)
|
|
lang: Mapped[str] = mapped_column(
|
|
String(4), server_default="TR", nullable=False, comment="Language"
|
|
)
|
|
type_name: Mapped[str] = mapped_column(
|
|
String(48), server_default="", nullable=False, comment="Type Name"
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index("_build_types_ndx_00", type_code, function_code, lang, unique=True),
|
|
{"comment": "Function group of building types with their language information"},
|
|
)
|
|
|
|
|
|
class Part2Employee(CrudCollection):
|
|
"""
|
|
Employee2Parts class based on declarative_base and BaseMixin via session
|
|
In between start and end date, a part can be assigned to only one employee
|
|
"""
|
|
|
|
__tablename__ = "part2employee"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
|
|
build_id: Mapped[int] = mapped_column(Integer, comment="Building ID")
|
|
part_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build_parts.id"), nullable=False, comment="Part ID"
|
|
)
|
|
employee_id: Mapped[int] = mapped_column(
|
|
ForeignKey("employees.id"), nullable=False, comment="Employee ID"
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index("_part2employee_ndx_00", employee_id, part_id, unique=True),
|
|
{"comment": "Employee2Parts Information"},
|
|
)
|
|
|
|
|
|
class RelationshipEmployee2Build(CrudCollection):
|
|
"""
|
|
CompanyRelationship class based on declarative_base and CrudCollection via session
|
|
Company -> Sub Company -> Sub-Sub Company
|
|
|
|
"""
|
|
|
|
__tablename__ = "relationship_employee2build"
|
|
__exclude__fields__ = []
|
|
|
|
company_id: Mapped[int] = mapped_column(
|
|
ForeignKey("companies.id"), nullable=False
|
|
) # 1, 2, 3
|
|
employee_id: Mapped[int] = mapped_column(
|
|
ForeignKey("employees.id"), nullable=False
|
|
) # employee -> (n)person Evyos LTD
|
|
member_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build.id"), nullable=False
|
|
) # 2, 3, 4
|
|
|
|
relationship_type: Mapped[str] = mapped_column(
|
|
String, nullable=True, server_default="Employee"
|
|
) # Commercial
|
|
show_only: Mapped[bool] = mapped_column(Boolean, server_default="False")
|
|
|
|
__table_args__ = (
|
|
Index(
|
|
"relationship_build_employee_ndx_00",
|
|
company_id,
|
|
employee_id,
|
|
member_id,
|
|
relationship_type,
|
|
unique=True,
|
|
),
|
|
{"comment": "Build & Employee Relationship Information"},
|
|
)
|
|
|
|
|
|
class Build(CrudCollection):
|
|
"""
|
|
Builds class based on declarative_base and BaseMixin via session
|
|
"""
|
|
|
|
__tablename__ = "build"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
__access_by__ = []
|
|
# __many__table__ = RelationshipEmployee2Build
|
|
|
|
gov_address_code: Mapped[str] = mapped_column(
|
|
String, server_default="", unique=True
|
|
)
|
|
build_name: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Building Name"
|
|
)
|
|
build_no: Mapped[str] = mapped_column(
|
|
String(8), nullable=False, comment="Building Number"
|
|
)
|
|
|
|
max_floor: Mapped[int] = mapped_column(
|
|
Integer, server_default="1", nullable=False, comment="Max Floor"
|
|
)
|
|
underground_floor: Mapped[int] = mapped_column(
|
|
Integer, server_default="0", nullable=False, comment="Underground Floor"
|
|
)
|
|
build_date: Mapped[TIMESTAMP] = mapped_column(
|
|
TIMESTAMP(timezone=True), server_default="1900-01-01"
|
|
)
|
|
decision_period_date: Mapped[TIMESTAMP] = mapped_column(
|
|
TIMESTAMP(timezone=True),
|
|
server_default="1900-01-01",
|
|
comment="Building annual ordinary meeting period",
|
|
)
|
|
tax_no: Mapped[str] = mapped_column(String(24), server_default="")
|
|
lift_count: Mapped[int] = mapped_column(Integer, server_default="0")
|
|
heating_system: Mapped[bool] = mapped_column(Boolean, server_default="True")
|
|
cooling_system: Mapped[bool] = mapped_column(Boolean, server_default="False")
|
|
hot_water_system: Mapped[bool] = mapped_column(Boolean, server_default="False")
|
|
block_service_man_count: Mapped[int] = mapped_column(Integer, server_default="0")
|
|
security_service_man_count: Mapped[int] = mapped_column(Integer, server_default="0")
|
|
garage_count: Mapped[int] = mapped_column(
|
|
Integer, server_default="0", comment="Garage Count"
|
|
)
|
|
management_room_id: Mapped[int] = mapped_column(
|
|
Integer, nullable=True, comment="Management Room ID"
|
|
)
|
|
|
|
site_id: Mapped[int] = mapped_column(ForeignKey("build_sites.id"), nullable=True)
|
|
site_uu_id: Mapped[str] = mapped_column(String, comment="Site UUID", nullable=True)
|
|
address_id: Mapped[int] = mapped_column(ForeignKey("addresses.id"), nullable=False)
|
|
address_uu_id: Mapped[str] = mapped_column(
|
|
String, comment="Address UUID", nullable=False
|
|
)
|
|
build_types_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build_types.id"), nullable=False, comment="Building Type"
|
|
)
|
|
build_types_uu_id: Mapped[str] = mapped_column(String, comment="Building Type UUID")
|
|
|
|
parts: Mapped[List["BuildParts"]] = relationship(
|
|
"BuildParts", back_populates="buildings", foreign_keys="BuildParts.build_id"
|
|
)
|
|
decision_books: Mapped[List["BuildDecisionBook"]] = relationship(
|
|
"BuildDecisionBook",
|
|
back_populates="buildings",
|
|
foreign_keys="BuildDecisionBook.build_id",
|
|
)
|
|
|
|
# build_ibans: Mapped["BuildIbans"] = relationship(
|
|
# "BuildIbans", back_populates="building", foreign_keys="BuildIbans.build_id"
|
|
# )
|
|
# areas: Mapped["BuildArea"] = relationship(
|
|
# "BuildArea", back_populates="buildings", foreign_keys="BuildArea.build_id"
|
|
# )
|
|
# response_companies: Mapped["Companies"] = relationship(
|
|
# "Companies",
|
|
# back_populates="response_buildings",
|
|
# foreign_keys=[response_company_id],
|
|
# )
|
|
# addresses: Mapped[List["Address"]] = relationship(
|
|
# "Address", back_populates="buildings", foreign_keys=[address_id]
|
|
# )
|
|
# peoples: Mapped["People"] = relationship(
|
|
# "People", back_populates="buildings", foreign_keys=[people_id]
|
|
# )
|
|
# sites: Mapped["BuildSites"] = relationship(
|
|
# "BuildSites", back_populates="buildings", foreign_keys=[site_id]
|
|
# )
|
|
|
|
__table_args__ = (
|
|
Index("_builds_ndx_00", gov_address_code),
|
|
Index("_builds_ndx_01", build_name, build_no),
|
|
{
|
|
"comment": "Build objects are building that are created for living and store purposes"
|
|
},
|
|
)
|
|
|
|
@property
|
|
def management_room(self):
|
|
with self.new_session() as db_session:
|
|
if management_room := BuildParts.filter_by_one(
|
|
system=True, id=self.management_room_id, build_id=self.id, db=db_session
|
|
).data:
|
|
return management_room
|
|
return None
|
|
|
|
@property
|
|
def top_flat(self):
|
|
max_flat_no = 0
|
|
for part in self.parts:
|
|
if part.part_no > self.max_floor:
|
|
max_flat_no = part.part_no
|
|
return max_flat_no
|
|
|
|
@property
|
|
def bottom_flat(self):
|
|
min_flat_no = 0
|
|
for part in self.parts:
|
|
if part.part_no < self.max_floor:
|
|
min_flat_no = part.part_no
|
|
return min_flat_no
|
|
|
|
@property
|
|
def human_livable_parts(self) -> tuple:
|
|
parts = list(part for part in self.parts if part.human_livable)
|
|
return parts, len(parts)
|
|
|
|
@property
|
|
def livable_part_count(self):
|
|
with self.new_session() as db_session:
|
|
livable_parts = BuildParts.filter_all(
|
|
BuildParts.build_id == self.id,
|
|
BuildParts.human_livable == True,
|
|
db=db_session,
|
|
)
|
|
if not livable_parts.data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="There is no livable part in this building.",
|
|
)
|
|
return livable_parts.count
|
|
|
|
@property
|
|
def part_type_count(self):
|
|
with self.new_session() as db_session:
|
|
building_types = None
|
|
for part in self.parts:
|
|
building_types = {}
|
|
build_type = BuildTypes.filter_by_one(
|
|
system=True, id=part.build_part_type_id, db=db_session
|
|
).data
|
|
if build_type.type_code in building_types:
|
|
building_types[build_type.type_code]["list"].append(part.part_no)
|
|
else:
|
|
building_types[build_type.type_code] = {"list": [part.part_no]}
|
|
|
|
# for key, val in building_types.items():
|
|
# list_parts = val["list"]
|
|
# building_types[key] = {
|
|
# "list": list_parts,
|
|
# "min": min(list_parts),
|
|
# "max": max(list_parts),
|
|
# "count": len(list_parts),
|
|
# }
|
|
return building_types
|
|
|
|
|
|
class BuildParts(CrudCollection):
|
|
"""
|
|
BuildParts class based on declarative_base and BaseMixin via session
|
|
Attentions: Part_no is unique for each building and Every building must have a management section.!!! default no 0
|
|
"""
|
|
|
|
__tablename__ = "build_parts"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
__enum_list__ = [("part_direction", "Directions", "NN")]
|
|
|
|
# https://adres.nvi.gov.tr/VatandasIslemleri/AdresSorgu
|
|
address_gov_code: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Goverment Door Code"
|
|
)
|
|
# part_name: Mapped[str] = mapped_column(String(24), server_default="", nullable=False, comment="Part Name")
|
|
part_no: Mapped[int] = mapped_column(
|
|
Integer, server_default="0", nullable=False, comment="Part Number"
|
|
)
|
|
part_level: Mapped[int] = mapped_column(
|
|
Integer, server_default="0", comment="Building Part Level"
|
|
)
|
|
part_code: Mapped[str] = mapped_column(
|
|
String, server_default="", nullable=False, comment="Part Code"
|
|
)
|
|
part_gross_size: Mapped[int] = mapped_column(
|
|
Integer, server_default="0", comment="Part Gross Size"
|
|
)
|
|
part_net_size: Mapped[int] = mapped_column(
|
|
Integer, server_default="0", comment="Part Net Size"
|
|
)
|
|
default_accessory: Mapped[str] = mapped_column(
|
|
Text, server_default="0", comment="Default Accessory"
|
|
)
|
|
human_livable: Mapped[bool] = mapped_column(
|
|
Boolean, server_default="1", comment="Human Livable"
|
|
)
|
|
due_part_key: Mapped[str] = mapped_column(
|
|
String, server_default="", nullable=False, comment="Constant Payment Group"
|
|
)
|
|
|
|
build_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build.id"), nullable=False, comment="Building ID"
|
|
)
|
|
build_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Building UUID"
|
|
)
|
|
part_direction_id: Mapped[int] = mapped_column(
|
|
ForeignKey("api_enum_dropdown.id"), nullable=True
|
|
)
|
|
part_direction_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Part Direction UUID"
|
|
)
|
|
part_type_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build_types.id"), nullable=False, comment="Building Part Type"
|
|
)
|
|
part_type_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Building Part Type UUID"
|
|
)
|
|
|
|
buildings: Mapped["Build"] = relationship(
|
|
"Build", back_populates="parts", foreign_keys=[build_id]
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index("build_parts_ndx_01", build_id, part_no, unique=True),
|
|
{"comment": "Part objects that are belong to building objects"},
|
|
)
|
|
|
|
def part_name(self, db):
|
|
if build_type := BuildTypes.filter_by_one(
|
|
system=True, id=self.part_type_id, db=db
|
|
).data:
|
|
return (
|
|
f"{str(build_type.type_name).upper()} : {str(self.part_no).upper()}"
|
|
)
|
|
return f"Undefined:{str(build_type.type_name).upper()}"
|
|
|
|
|
|
class BuildLivingSpace(CrudCollection):
|
|
"""
|
|
LivingSpace class based on declarative_base and BaseMixin via session
|
|
Owner or live person = Occupant of the build part
|
|
+ Query OR(owner_person_id == person_id, life_person_id == person_id) AND (now(date))
|
|
"""
|
|
|
|
__tablename__ = "build_living_space"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
|
|
fix_value: Mapped[float] = mapped_column(
|
|
Numeric(20, 6),
|
|
server_default="0",
|
|
comment="Fixed value is deducted from debit.",
|
|
)
|
|
fix_percent: Mapped[float] = mapped_column(
|
|
Numeric(6, 2),
|
|
server_default="0",
|
|
comment="Fixed percent is deducted from debit.",
|
|
)
|
|
|
|
agreement_no: Mapped[str] = mapped_column(
|
|
String, server_default="", comment="Agreement No"
|
|
)
|
|
marketing_process: Mapped[bool] = mapped_column(Boolean, server_default="False")
|
|
marketing_layer: Mapped[int] = mapped_column(Integer, server_default="0")
|
|
|
|
build_parts_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build_parts.id"),
|
|
nullable=False,
|
|
index=True,
|
|
comment="Build Part ID",
|
|
)
|
|
build_parts_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Build Part UUID"
|
|
)
|
|
person_id: Mapped[int] = mapped_column(
|
|
ForeignKey("people.id"),
|
|
nullable=False,
|
|
index=True,
|
|
comment="Responsible People ID",
|
|
)
|
|
person_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Responsible People UUID"
|
|
)
|
|
occupant_type_id: Mapped[int] = mapped_column(
|
|
ForeignKey("occupant_types.id"),
|
|
nullable=False,
|
|
comment="Occupant Type",
|
|
)
|
|
occupant_type_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Occupant Type UUID"
|
|
)
|
|
|
|
__table_args__ = (
|
|
{"comment": "Living Space inside building parts that are related to people"},
|
|
)
|
|
|
|
@classmethod
|
|
def find_living_from_customer_id(
|
|
cls, customer_id, process_date, add_days: int = 32
|
|
):
|
|
with cls.new_session() as db_session:
|
|
formatted_date = arrow.get(str(process_date))
|
|
living_spaces = cls.filter_all(
|
|
or_(
|
|
cls.owner_person_id == customer_id,
|
|
cls.life_person_id == customer_id,
|
|
),
|
|
cls.start_date < formatted_date - timedelta(days=add_days),
|
|
cls.stop_date > formatted_date + timedelta(days=add_days),
|
|
db=db_session,
|
|
)
|
|
return living_spaces.data, living_spaces.count
|
|
|
|
|
|
class BuildManagement(CrudCollection):
|
|
|
|
__tablename__ = "build_management"
|
|
__exclude__fields__ = []
|
|
|
|
discounted_percentage: Mapped[float] = mapped_column(
|
|
Numeric(6, 2), server_default="0.00"
|
|
) # %22
|
|
discounted_price: Mapped[float] = mapped_column(
|
|
Numeric(20, 2), server_default="0.00"
|
|
) # Normal: 78.00 TL
|
|
calculated_price: Mapped[float] = mapped_column(
|
|
Numeric(20, 2), server_default="0.00"
|
|
) # sana düz 75.00 TL yapar
|
|
|
|
occupant_type: Mapped[int] = mapped_column(
|
|
ForeignKey("occupant_types.id"),
|
|
nullable=False,
|
|
comment="Occupant Type",
|
|
)
|
|
occupant_type_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Occupant Type UUID"
|
|
)
|
|
build_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build.id"), nullable=False, comment="Building ID"
|
|
)
|
|
build_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Building UUID"
|
|
)
|
|
build_parts_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build_parts.id"),
|
|
nullable=False,
|
|
index=True,
|
|
comment="Build Part ID",
|
|
)
|
|
build_parts_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=False, comment="Build Part UUID"
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index(
|
|
"build_management_ndx_00",
|
|
build_parts_id,
|
|
occupant_type,
|
|
"expiry_starts",
|
|
unique=True,
|
|
),
|
|
{"comment": "Management of the building parts that are related to people"},
|
|
)
|
|
|
|
|
|
class BuildArea(CrudCollection):
|
|
"""
|
|
Builds class based on declarative_base and BaseMixin via session
|
|
"""
|
|
|
|
__tablename__ = "build_area"
|
|
__exclude__fields__ = []
|
|
|
|
area_name: Mapped[str] = mapped_column(String, server_default="")
|
|
area_code: Mapped[str] = mapped_column(String, server_default="")
|
|
area_type: Mapped[str] = mapped_column(String, server_default="GREEN")
|
|
area_direction: Mapped[str] = mapped_column(String(2), server_default="NN")
|
|
area_gross_size: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
|
|
area_net_size: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
|
|
width = mapped_column(Integer, server_default="0")
|
|
size = mapped_column(Integer, server_default="0")
|
|
|
|
build_id: Mapped[int] = mapped_column(ForeignKey("build.id"))
|
|
build_uu_id: Mapped[str] = mapped_column(String, comment="Building UUID")
|
|
part_type_id: Mapped[int] = mapped_column(
|
|
ForeignKey("build_types.id"), nullable=True, comment="Building Part Type"
|
|
)
|
|
part_type_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Building Part Type UUID"
|
|
)
|
|
|
|
# buildings: Mapped["Build"] = relationship(
|
|
# "Build", back_populates="areas", foreign_keys=[build_id]
|
|
# )
|
|
|
|
_table_args_ = (
|
|
Index("_edm_build_parts_area_ndx_00", build_id, area_code, unique=True),
|
|
)
|
|
|
|
|
|
class BuildSites(CrudCollection):
|
|
"""
|
|
Builds class based on declarative_base and BaseMixin via session
|
|
"""
|
|
|
|
__tablename__ = "build_sites"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
|
|
site_name: Mapped[str] = mapped_column(String(24), nullable=False)
|
|
site_no: Mapped[str] = mapped_column(String(8), nullable=False)
|
|
|
|
address_id: Mapped[int] = mapped_column(ForeignKey("addresses.id"))
|
|
address_uu_id: Mapped[str] = mapped_column(String, comment="Address UUID")
|
|
|
|
# addresses: Mapped["Address"] = relationship(
|
|
# "Address", back_populates="site", foreign_keys=[address_id]
|
|
# )
|
|
# buildings: Mapped["Build"] = relationship(
|
|
# "Build", back_populates="sites", foreign_keys="Build.site_id"
|
|
# )
|
|
|
|
__table_args__ = (
|
|
Index("_sites_ndx_01", site_no, site_name),
|
|
{"comment": "Sites that groups building objets"},
|
|
)
|
|
|
|
|
|
class BuildCompaniesProviding(CrudCollection):
|
|
""" """
|
|
|
|
__tablename__ = "build_companies_providing"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
|
|
build_id = mapped_column(
|
|
ForeignKey("build.id"), nullable=False, comment="Building ID"
|
|
)
|
|
build_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Providing UUID"
|
|
)
|
|
company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
|
|
company_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Providing UUID"
|
|
)
|
|
provide_id: Mapped[int] = mapped_column(
|
|
ForeignKey("api_enum_dropdown.id"), nullable=True
|
|
)
|
|
provide_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Providing UUID"
|
|
)
|
|
contract_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("companies.id"), nullable=True
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index(
|
|
"_build_companies_providing_ndx_00",
|
|
build_id,
|
|
company_id,
|
|
provide_id,
|
|
unique=True,
|
|
),
|
|
{"comment": "Companies providing services for building"},
|
|
)
|
|
|
|
|
|
class BuildPersonProviding(CrudCollection):
|
|
""" """
|
|
|
|
__tablename__ = "build_person_providing"
|
|
__exclude__fields__ = []
|
|
__include__fields__ = []
|
|
|
|
build_id = mapped_column(
|
|
ForeignKey("build.id"), nullable=False, comment="Building ID"
|
|
)
|
|
build_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Providing UUID"
|
|
)
|
|
people_id: Mapped[int] = mapped_column(ForeignKey("people.id"))
|
|
people_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="People UUID"
|
|
)
|
|
provide_id: Mapped[int] = mapped_column(
|
|
ForeignKey("api_enum_dropdown.id"), nullable=True
|
|
)
|
|
provide_uu_id: Mapped[str] = mapped_column(
|
|
String, nullable=True, comment="Providing UUID"
|
|
)
|
|
contract_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("companies.id"), nullable=True
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index(
|
|
"_build_person_providing_ndx_00",
|
|
build_id,
|
|
people_id,
|
|
provide_id,
|
|
unique=True,
|
|
),
|
|
{"comment": "People providing services for building"},
|
|
)
|