import arrow from datetime import timedelta from typing import List, Union, Any from schemas.base_imports import ( CrudCollection, mapped_column, Mapped, relationship, String, Integer, Boolean, ForeignKey, Index, TIMESTAMP, Text, Numeric, or_, and_, ) 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_1", 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"}, )