Schemas updated

This commit is contained in:
berkay 2025-04-02 18:53:33 +03:00
parent 27c48bb86a
commit 3583d178e9
38 changed files with 2672 additions and 28 deletions

View File

@ -0,0 +1,28 @@
FROM python:3.12-slim
WORKDIR /
# Install system dependencies and Poetry
RUN apt-get update && apt-get install -y --no-install-recommends gcc \
&& rm -rf /var/lib/apt/lists/* && pip install --no-cache-dir poetry
# Copy Poetry configuration
COPY /pyproject.toml ./pyproject.toml
# Configure Poetry and install dependencies with optimizations
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi --no-root --only main \
&& pip cache purge && rm -rf ~/.cache/pypoetry
# Copy application code
COPY /ApiServices/AuthService /ApiServices/AuthService
COPY /Controllers /Controllers
COPY /Schemas/building /Schemas/building
COPY /Schemas/company /Schemas/company
COPY /Schemas/identity /Schemas/identity
# Set Python path to include app directory
ENV PYTHONPATH=/ PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
# Run the application using the configured uvicorn server
CMD ["poetry", "run", "python", "ApiServices/TemplateService/app.py"]

View File

View File

@ -0,0 +1,16 @@
import uvicorn
from config import api_config
from ApiServices.TemplateService.create_app import create_app
# from prometheus_fastapi_instrumentator import Instrumentator
app = create_app() # Create FastAPI application
# Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
if __name__ == "__main__":
# Run the application with Uvicorn Server
uvicorn_config = uvicorn.Config(**api_config.app_as_dict)
uvicorn.Server(uvicorn_config).run()

View File

@ -0,0 +1,64 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
from fastapi.responses import JSONResponse
class Configs(BaseSettings):
"""
ApiTemplate configuration settings.
"""
PATH: str = ""
HOST: str = "",
PORT: int = 0,
LOG_LEVEL: str = "info",
RELOAD: int = 0
ACCESS_TOKEN_TAG: str = ""
ACCESS_EMAIL_EXT: str = ""
TITLE: str = ""
ALGORITHM: str = ""
ACCESS_TOKEN_LENGTH: int = 90
REFRESHER_TOKEN_LENGTH: int = 144
EMAIL_HOST: str = ""
DATETIME_FORMAT: str = ""
FORGOT_LINK: str = ""
ALLOW_ORIGINS: list = ["http://localhost:3000"]
VERSION: str = "0.1.001"
DESCRIPTION: str = ""
@property
def app_as_dict(self) -> dict:
"""
Convert the settings to a dictionary.
"""
return {
"app": self.PATH,
"host": self.HOST,
"port": int(self.PORT),
"log_level": self.LOG_LEVEL,
"reload": bool(self.RELOAD)
}
@property
def api_info(self):
"""
Returns a dictionary with application information.
"""
return {
"title": self.TITLE,
"description": self.DESCRIPTION,
"default_response_class": JSONResponse,
"version": self.VERSION,
}
@classmethod
def forgot_link(cls, forgot_key):
"""
Generate a forgot password link.
"""
return cls.FORGOT_LINK + forgot_key
model_config = SettingsConfigDict(env_prefix="API_")
api_config = Configs()

View File

@ -0,0 +1,41 @@
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from ApiServices.TemplateService.create_route import RouteRegisterController
from ApiServices.TemplateService.endpoints.routes import get_routes
from ApiServices.TemplateService.open_api_creator import create_openapi_schema
from ApiServices.TemplateService.middlewares.token_middleware import token_middleware
from ApiServices.TemplateService.config import template_api_config
def create_app():
application = FastAPI(**template_api_config.api_info)
# application.mount(
# "/application/static",
# StaticFiles(directory="application/static"),
# name="static",
# )
application.add_middleware(
CORSMiddleware,
allow_origins=template_api_config.ALLOW_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@application.middleware("http")
async def add_token_middleware(request: Request, call_next):
return await token_middleware(request, call_next)
@application.get("/", description="Redirect Route", include_in_schema=False)
async def redirect_to_docs():
return RedirectResponse(url="/docs")
route_register = RouteRegisterController(app=application, router_list=get_routes())
application = route_register.register_routes()
application.openapi = lambda _=application: create_openapi_schema(_)
return application

View File

@ -0,0 +1,14 @@
from typing import List
from fastapi import APIRouter, FastAPI
class RouteRegisterController:
def __init__(self, app: FastAPI, router_list: List[APIRouter]):
self.router_list = router_list
self.app = app
def register_routes(self):
for router in self.router_list:
self.app.include_router(router)
return self.app

View File

@ -0,0 +1,20 @@
from fastapi import APIRouter
from .test_template.route import test_template_route
def get_routes() -> list[APIRouter]:
return [test_template_route]
def get_safe_endpoint_urls() -> list[tuple[str, str]]:
return [
("/", "GET"),
("/docs", "GET"),
("/redoc", "GET"),
("/openapi.json", "GET"),
("/auth/register", "POST"),
("/auth/login", "POST"),
("/metrics", "GET"),
("/test/template", "GET"),
("/test/template", "POST"),
]

View File

@ -0,0 +1,40 @@
from fastapi import APIRouter, Request, Response
test_template_route = APIRouter(prefix="/test", tags=["Test"])
@test_template_route.get(path="/template", description="Test Template Route")
def test_template(request: Request, response: Response):
"""
Test Template Route
"""
headers = dict(request.headers)
response.headers["X-Header"] = "Test Header GET"
return {
"completed": True,
"message": "Test Template Route",
"info": {
"host": headers.get("host", "Not Found"),
"user_agent": headers.get("user-agent", "Not Found"),
},
}
@test_template_route.post(
path="/template",
description="Test Template Route with Post Method",
)
def test_template_post(request: Request, response: Response):
"""
Test Template Route with Post Method
"""
headers = dict(request.headers)
response.headers["X-Header"] = "Test Header POST"
return {
"completed": True,
"message": "Test Template Route with Post Method",
"info": {
"host": headers.get("host", "Not Found"),
"user_agent": headers.get("user-agent", "Not Found"),
},
}

View File

@ -0,0 +1,17 @@
from fastapi import Request, Response
from ApiServices.TemplateService.endpoints.routes import get_safe_endpoint_urls
async def token_middleware(request: Request, call_next):
base_url = "/".join(request.url.path.split("/")[:3])
safe_endpoints = [_[0] for _ in get_safe_endpoint_urls()]
if base_url in safe_endpoints:
return await call_next(request)
token = request.headers.get("Authorization")
if not token:
return Response(content="Missing token", status_code=400)
response = await call_next(request)
return response

View File

@ -0,0 +1,118 @@
from typing import Any, Dict
from fastapi import FastAPI
from fastapi.routing import APIRoute
from fastapi.openapi.utils import get_openapi
from ApiServices.TemplateService.config import template_api_config
from ApiServices.TemplateService.endpoints.routes import get_safe_endpoint_urls
class OpenAPISchemaCreator:
"""
OpenAPI schema creator and customizer for FastAPI applications.
"""
def __init__(self, app: FastAPI):
"""
Initialize the OpenAPI schema creator.
Args:
app: FastAPI application instance
"""
self.app = app
self.safe_endpoint_list: list[tuple[str, str]] = get_safe_endpoint_urls()
self.routers_list = self.app.routes
@staticmethod
def create_security_schemes() -> Dict[str, Any]:
"""
Create security scheme definitions.
Returns:
Dict[str, Any]: Security scheme configurations
"""
return {
"BearerAuth": {
"type": "apiKey",
"in": "header",
"name": template_api_config.ACCESS_TOKEN_TAG,
"description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
}
}
def configure_route_security(
self, path: str, method: str, schema: Dict[str, Any]
) -> None:
"""
Configure security requirements for a specific route.
Args:
path: Route path
method: HTTP method
schema: OpenAPI schema to modify
"""
if not schema.get("paths", {}).get(path, {}).get(method):
return
# Check if endpoint is in safe list
endpoint_path = f"{path}:{method}"
list_of_safe_endpoints = [
f"{e[0]}:{str(e[1]).lower()}" for e in self.safe_endpoint_list
]
if endpoint_path not in list_of_safe_endpoints:
if "security" not in schema["paths"][path][method]:
schema["paths"][path][method]["security"] = []
schema["paths"][path][method]["security"].append({"BearerAuth": []})
def create_schema(self) -> Dict[str, Any]:
"""
Create the complete OpenAPI schema.
Returns:
Dict[str, Any]: Complete OpenAPI schema
"""
openapi_schema = get_openapi(
title=template_api_config.TITLE,
description=template_api_config.DESCRIPTION,
version=template_api_config.VERSION,
routes=self.app.routes,
)
# Add security schemes
if "components" not in openapi_schema:
openapi_schema["components"] = {}
openapi_schema["components"][
"securitySchemes"
] = self.create_security_schemes()
# Configure route security and responses
for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema:
path = str(route.path)
methods = [method.lower() for method in route.methods]
for method in methods:
self.configure_route_security(path, method, openapi_schema)
# Add custom documentation extensions
openapi_schema["x-documentation"] = {
"postman_collection": "/docs/postman",
"swagger_ui": "/docs",
"redoc": "/redoc",
}
return openapi_schema
def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
"""
Create OpenAPI schema for a FastAPI application.
Args:
app: FastAPI application instance
Returns:
Dict[str, Any]: Complete OpenAPI schema
"""
creator = OpenAPISchemaCreator(app)
return creator.create_schema()

View File

@ -0,0 +1 @@
from Schemas.building.build import BuildParts, BuildLivingSpace

View File

@ -1,6 +1,7 @@
import uvicorn
from ApiServices.TemplateService.config import template_api_config
from config import api_config
from ApiServices.TemplateService.create_app import create_app
# from prometheus_fastapi_instrumentator import Instrumentator
@ -11,5 +12,5 @@ app = create_app() # Create FastAPI app
if __name__ == "__main__":
# Run the application with Uvicorn Server
uvicorn_config = uvicorn.Config(**template_api_config.app_as_dict)
uvicorn_config = uvicorn.Config(**api_config.app_as_dict)
uvicorn.Server(uvicorn_config).run()

View File

@ -61,4 +61,4 @@ class Configs(BaseSettings):
model_config = SettingsConfigDict(env_prefix="API_")
template_api_config = Configs()
api_config = Configs()

View File

@ -1,8 +1,9 @@
from fastapi import APIRouter
from .test_template.route import test_template_route
def get_routes() -> list[APIRouter]:
return []
return [test_template_route]
def get_safe_endpoint_urls() -> list[tuple[str, str]]:
@ -14,4 +15,6 @@ def get_safe_endpoint_urls() -> list[tuple[str, str]]:
("/auth/register", "POST"),
("/auth/login", "POST"),
("/metrics", "GET"),
("/test/template", "GET"),
("/test/template", "POST"),
]

View File

@ -0,0 +1,40 @@
from fastapi import APIRouter, Request, Response
test_template_route = APIRouter(prefix="/test", tags=["Test"])
@test_template_route.get(path="/template", description="Test Template Route")
def test_template(request: Request, response: Response):
"""
Test Template Route
"""
headers = dict(request.headers)
response.headers["X-Header"] = "Test Header GET"
return {
"completed": True,
"message": "Test Template Route",
"info": {
"host": headers.get("host", "Not Found"),
"user_agent": headers.get("user-agent", "Not Found"),
},
}
@test_template_route.post(
path="/template",
description="Test Template Route with Post Method",
)
def test_template_post(request: Request, response: Response):
"""
Test Template Route with Post Method
"""
headers = dict(request.headers)
response.headers["X-Header"] = "Test Header POST"
return {
"completed": True,
"message": "Test Template Route with Post Method",
"info": {
"host": headers.get("host", "Not Found"),
"user_agent": headers.get("user-agent", "Not Found"),
},
}

View File

@ -1,12 +1,8 @@
from fastapi import Request, Response
def get_safe_endpoint_urls() -> list:
return []
from ApiServices.TemplateService.endpoints.routes import get_safe_endpoint_urls
async def token_middleware(request: Request, call_next):
# from application.routes.routes import get_safe_endpoint_urls
base_url = "/".join(request.url.path.split("/")[:3])
safe_endpoints = [_[0] for _ in get_safe_endpoint_urls()]

View File

@ -2,7 +2,9 @@ from typing import Any, Dict
from fastapi import FastAPI
from fastapi.routing import APIRoute
from fastapi.openapi.utils import get_openapi
from ApiServices.TemplateService.config import template_api_config
from ApiServices.TemplateService.endpoints.routes import get_safe_endpoint_urls
class OpenAPISchemaCreator:
@ -18,8 +20,11 @@ class OpenAPISchemaCreator:
app: FastAPI application instance
"""
self.app = app
self.safe_endpoint_list: list[tuple[str, str]] = get_safe_endpoint_urls()
self.routers_list = self.app.routes
def create_security_schemes(self) -> Dict[str, Any]:
@staticmethod
def create_security_schemes() -> Dict[str, Any]:
"""
Create security scheme definitions.
@ -36,6 +41,30 @@ class OpenAPISchemaCreator:
}
}
def configure_route_security(
self, path: str, method: str, schema: Dict[str, Any]
) -> None:
"""
Configure security requirements for a specific route.
Args:
path: Route path
method: HTTP method
schema: OpenAPI schema to modify
"""
if not schema.get("paths", {}).get(path, {}).get(method):
return
# Check if endpoint is in safe list
endpoint_path = f"{path}:{method}"
list_of_safe_endpoints = [
f"{e[0]}:{str(e[1]).lower()}" for e in self.safe_endpoint_list
]
if endpoint_path not in list_of_safe_endpoints:
if "security" not in schema["paths"][path][method]:
schema["paths"][path][method]["security"] = []
schema["paths"][path][method]["security"].append({"BearerAuth": []})
def create_schema(self) -> Dict[str, Any]:
"""
Create the complete OpenAPI schema.
@ -46,7 +75,7 @@ class OpenAPISchemaCreator:
openapi_schema = get_openapi(
title=template_api_config.TITLE,
description=template_api_config.DESCRIPTION,
version=template_api_config,
version=template_api_config.VERSION,
routes=self.app.routes,
)
@ -56,7 +85,7 @@ class OpenAPISchemaCreator:
openapi_schema["components"][
"securitySchemes"
] = self._create_security_schemes()
] = self.create_security_schemes()
# Configure route security and responses
for route in self.app.routes:

View File

@ -29,19 +29,19 @@ def example_get_json_iterator() -> None:
"""Example of using the JSON iterator for large datasets."""
keys = ["user", "profile", "*"]
for row in RedisActions.get_json_iterator(list_keys=keys):
print("Iterating over JSON row:", row.as_dict if isinstance(row.as_dict, dict) else row.as_dict())
print("Iterating over JSON row:", row.as_dict if isinstance(row.as_dict, dict) else row.as_dict)
# def example_delete_key() -> None:
# """Example of deleting a specific key."""
# key = "user:profile:123"
# result = RedisActions.delete_key(key)
# print("Delete specific key:", result)
#
# def example_delete() -> None:
# """Example of deleting multiple keys matching a pattern."""
# keys = ["user", "profile", "*"]
# result = RedisActions.delete(list_keys=keys)
# print("Delete multiple keys:", result)
def example_delete_key() -> None:
"""Example of deleting a specific key."""
key = "user:profile:123"
result = RedisActions.delete_key(key)
print("Delete specific key:", result)
def example_delete() -> None:
"""Example of deleting multiple keys matching a pattern."""
keys = ["user", "profile", "*"]
result = RedisActions.delete(list_keys=keys)
print("Delete multiple keys:", result)
def example_refresh_ttl() -> None:
"""Example of refreshing TTL for a key."""

15
Modules/Token/config.py Normal file
View File

@ -0,0 +1,15 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
class Configs(BaseSettings):
"""
ApiTemplate configuration settings.
"""
ACCESS_TOKEN_LENGTH: int = 90
REFRESHER_TOKEN_LENGTH: int = 144
model_config = SettingsConfigDict(env_prefix="API_")
token_config = Configs()

View File

@ -0,0 +1,39 @@
import hashlib
import uuid
import secrets
import random
from config import token_config
class PasswordModule:
@staticmethod
def generate_random_uu_id(str_std: bool = True):
return str(uuid.uuid4()) if str_std else uuid.uuid4()
@staticmethod
def generate_token(length=32) -> str:
letters = "abcdefghijklmnopqrstuvwxyz"
merged_letters = [letter for letter in letters] + [letter.upper() for letter in letters]
token_generated = secrets.token_urlsafe(length)
for i in str(token_generated):
if i not in merged_letters:
token_generated = token_generated.replace(i, random.choice(merged_letters), 1)
return token_generated
@classmethod
def generate_access_token(cls) -> str:
return cls.generate_token(int(token_config.ACCESS_TOKEN_LENGTH))
@classmethod
def generate_refresher_token(cls) -> str:
return cls.generate_token(int(token_config.REFRESHER_TOKEN_LENGTH))
@staticmethod
def create_hashed_password(domain: str, id_: str, password: str) -> str:
return hashlib.sha256(f"{domain}:{id_}:{password}".encode("utf-8")).hexdigest()
@classmethod
def check_password(cls, domain, id_, password, password_hashed) -> bool:
return cls.create_hashed_password(domain, id_, password) == password_hashed

View File

@ -0,0 +1,198 @@
from Schemas.account.account import (
AccountBooks,
AccountCodes,
AccountCodeParser,
AccountMaster,
AccountDetail,
AccountRecordExchanges,
AccountRecords,
)
from Schemas.account.iban import (
BuildIbans,
BuildIbanDescription,
)
from Schemas.address.address import (
RelationshipEmployee2PostCode,
AddressPostcode,
Addresses,
AddressGeographicLocations,
AddressCountry,
AddressState,
AddressCity,
AddressDistrict,
AddressLocality,
AddressNeighborhood,
AddressStreet,
)
from Schemas.building.build import (
BuildTypes,
Part2Employee,
RelationshipEmployee2Build,
Build,
BuildParts,
BuildLivingSpace,
BuildManagement,
BuildArea,
BuildSites,
BuildCompaniesProviding,
BuildPersonProviding,
)
from Schemas.building.decision_book import (
BuildDecisionBook,
BuildDecisionBookInvitations,
BuildDecisionBookPerson,
BuildDecisionBookPersonOccupants,
BuildDecisionBookItems,
BuildDecisionBookItemsUnapproved,
BuildDecisionBookPayments,
BuildDecisionBookLegal,
BuildDecisionBookProjects,
BuildDecisionBookProjectPerson,
BuildDecisionBookProjectItems,
)
from Schemas.building.budget import (
DecisionBookBudgetBooks,
DecisionBookBudgetCodes,
DecisionBookBudgetMaster,
DecisionBookBudgets,
)
from Schemas.company.company import (
Companies,
RelationshipDutyCompany,
)
from Schemas.company.employee import (
Employees,
EmployeesSalaries,
EmployeeHistory,
Staff,
)
from Schemas.company.department import (
Duty,
Duties,
Departments,
)
from Schemas.event.event import (
Modules,
Services,
Service2Events,
Events,
Event2Occupant,
Event2Employee,
Event2OccupantExtra,
Event2EmployeeExtra,
)
from Schemas.identity.identity import (
UsersTokens,
OccupantTypes,
People,
Users,
RelationshipDutyPeople,
Contracts,
)
from Schemas.address.address import (
Addresses,
AddressCity,
AddressStreet,
AddressLocality,
AddressDistrict,
AddressNeighborhood,
AddressState,
AddressCountry,
AddressPostcode,
AddressGeographicLocations,
RelationshipEmployee2PostCode,
)
from Schemas.others.enums import (
ApiEnumDropdown,
)
from Schemas.rules.rules import (
EndpointRestriction,
)
__all__ = [
"AccountBooks",
"AccountCodes",
"AccountCodeParser",
"AccountMaster",
"AccountDetail",
"AccountRecordExchanges",
"AccountRecords",
"BuildIbans",
"BuildIbanDescription",
"RelationshipEmployee2PostCode",
"AddressPostcode",
"Addresses",
"AddressGeographicLocations",
"AddressCountry",
"AddressState",
"AddressCity",
"AddressDistrict",
"AddressLocality",
"AddressNeighborhood",
"AddressStreet",
"BuildTypes",
"Part2Employee",
"RelationshipEmployee2Build",
"Build",
"BuildParts",
"BuildLivingSpace",
"BuildManagement",
"BuildArea",
"BuildSites",
"BuildCompaniesProviding",
"BuildPersonProviding",
"BuildDecisionBook",
"BuildDecisionBookInvitations",
"BuildDecisionBookPerson",
"BuildDecisionBookPersonOccupants",
"BuildDecisionBookItems",
"BuildDecisionBookItemsUnapproved",
"BuildDecisionBookPayments",
"BuildDecisionBookLegal",
"BuildDecisionBookProjects",
"BuildDecisionBookProjectPerson",
"BuildDecisionBookPersonOccupants",
"BuildDecisionBookProjectItems",
"DecisionBookBudgetBooks",
"DecisionBookBudgetCodes",
"DecisionBookBudgetMaster",
"DecisionBookBudgets",
"Companies",
"RelationshipDutyCompany",
"Employees",
"EmployeesSalaries",
"EmployeeHistory",
"Staff",
"Duty",
"Duties",
"Departments",
"Modules",
"Services",
"Service2Events",
"Events",
"Event2Occupant",
"Event2Employee",
"Event2OccupantExtra",
"Event2EmployeeExtra",
"Addresses",
"AddressCity",
"AddressStreet",
"AddressLocality",
"AddressDistrict",
"AddressNeighborhood",
"AddressState",
"AddressCountry",
"AddressPostcode",
"AddressGeographicLocations",
"UsersTokens",
"OccupantTypes",
"People",
"Users",
"RelationshipDutyPeople",
"RelationshipEmployee2PostCode",
"Contracts",
"ApiEnumDropdown",
"EndpointRestriction",
"RelationshipEmployee2Build",
# ------------------------------------------------
]

View File

@ -574,5 +574,3 @@ class AccountRecords(CrudCollection):
# )
# print("is all dues_type", payment_dict["dues_type"], paid_value)

571
Schemas/address/address.py Normal file
View File

@ -0,0 +1,571 @@
from sqlalchemy import (
String,
ForeignKey,
Index,
Numeric,
Boolean,
BigInteger,
Integer,
Text, or_,
)
from sqlalchemy.orm import mapped_column, Mapped
from Controllers.Postgres.mixin import CrudCollection
class RelationshipEmployee2PostCode(CrudCollection):
"""
Build2EmployeeRelationship class based on declarative_base and BaseMixin via session
"""
__tablename__ = "relationship_employee2postcode"
__exclude__fields__ = []
__include__fields__ = []
company_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=True
) # 1, 2, 3
employee_id: Mapped[int] = mapped_column(ForeignKey("employees.id"), nullable=False)
member_id: Mapped[int] = mapped_column(
ForeignKey("address_postcode.id"), nullable=False
)
relationship_type: Mapped[str] = mapped_column(
String, nullable=True, server_default="Employee"
) # Commercial
show_only: Mapped[bool] = mapped_column(Boolean, server_default="0")
__table_args__ = ({"comment": "Build2Employee Relationship Information"},)
class AddressPostcode(CrudCollection):
"""
Postcode class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_postcode"
__exclude__fields__ = []
__access_by__ = []
__many__table__ = RelationshipEmployee2PostCode
street_id: Mapped[int] = mapped_column(ForeignKey("address_street.id"))
street_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Street UUID"
)
postcode: Mapped[str] = mapped_column(
String(32), nullable=False, comment="Postcode"
)
__table_args__ = ({"comment": "Postcode Information"},)
class Addresses(CrudCollection):
"""
Address class based on declarative_base and BaseMixin via session
"""
__tablename__ = "addresses"
__exclude__fields__ = []
build_number: Mapped[str] = mapped_column(
String(24), nullable=False, comment="Build Number"
)
door_number: Mapped[str] = mapped_column(
String(24), nullable=True, comment="Door Number"
)
floor_number: Mapped[str] = mapped_column(
String(24), nullable=True, comment="Floor Number"
)
comment_address: Mapped[str] = mapped_column(
String, nullable=False, comment="Address"
)
letter_address: Mapped[str] = mapped_column(
String, nullable=False, comment="Address"
)
short_letter_address: Mapped[str] = mapped_column(
String, nullable=False, comment="Address"
)
latitude: Mapped[float] = mapped_column(Numeric(20, 12), server_default="0")
longitude: Mapped[float] = mapped_column(Numeric(20, 12), server_default="0")
street_id: Mapped[int] = mapped_column(
ForeignKey("address_street.id"), nullable=False
)
street_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Street UUID"
)
__table_args__ = (
# Index("_address_ndx_00", country_code, b_state, city, district),
{"comment": "Address Information"},
)
@classmethod
def list_via_employee(cls, token_dict, filter_expr=None):
with cls.new_session() as db_session:
post_code_list = RelationshipEmployee2PostCode.filter_all(
RelationshipEmployee2PostCode.employee_id
== token_dict.selected_company.employee_id,
db=db_session
).data
post_code_id_list = [post_code.member_id for post_code in post_code_list]
if not post_code_id_list:
raise ValueError(
"User has no post code registered. User can not list addresses."
)
# raise HTTPException(
# status_code=404,
# detail="User has no post code registered. User can not list addresses.",
# )
cls.pre_query = cls.filter_all(cls.post_code_id.in_(post_code_id_list), db=db_session).query
filter_cls = cls.filter_all(*filter_expr or [], db=db_session)
cls.pre_query = None
return filter_cls.data
# buildings: Mapped["Build"] = relationship(
# "Build", back_populates="addresses", foreign_keys="Build.address_id"
# )
# site: Mapped["BuildSites"] = relationship(
# "BuildSites", back_populates="addresses", foreign_keys="BuildSites.address_id"
# )
# official_companies: Mapped["Companies"] = relationship(
# "Company",
# back_populates="official_address",
# foreign_keys="Company.official_address_id",
# )
# @classmethod
# def create_action(cls, request, create_address: InsertAddress):
# from services.redis.auth_actions.token import parse_token_object_to_dict
#
# token_dict = parse_token_object_to_dict(request=request)
# data_dict = create_address.model_dump()
# post_code = AddressPostcode.find_one(uu_id=create_address.post_code_uu_id)
# if not post_code:
# raise HTTPException(
# status_code=404,
# detail="Post code not found.",
# )
# if Employee2AddressRelationship.post_code_id.find_one(
# employee_id=token_dict.selected_company.employee_id,
# post_code_id=post_code.id,
# ):
# data_dict["post_code_id"] = post_code.id
# del data_dict["post_code_uu_id"]
# return cls.find_or_create(**create_address.model_dump())
# raise HTTPException(
# status_code=401,
# detail=f"User is not qualified to create address at this post code {post_code.postcode}",
# )
# __table_args__ = (
# Index("_address_ndx_00", country_code, b_state, city, district),
# {"comment": "Address Information"},
# )
class AddressGeographicLocations(CrudCollection):
"""
Country class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_geographic_locations"
__exclude__fields__ = []
geo_table: Mapped[str] = mapped_column(
String, nullable=False, comment="Address Table Name"
)
geo_id: Mapped[int] = mapped_column(
Integer, nullable=False, comment="Address Table ID"
)
geo_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Geographic Location Name"
)
geo_latitude: Mapped[float] = mapped_column(
Numeric(20, 6), server_default="0", comment="Geographic Location Name"
)
geo_longitude: Mapped[float] = mapped_column(
Numeric(20, 6), server_default="0", comment="Geographic Location Latitude"
)
geo_altitude: Mapped[float] = mapped_column(
Numeric(20, 6), server_default="0", comment="Geographic Location Longitude"
)
geo_description: Mapped[str] = mapped_column(
Text, nullable=False, comment="Geographic Location Description"
)
geo_area_size: Mapped[float] = mapped_column(
Numeric(20, 2),
nullable=True,
server_default="0",
comment="Geographic Location Area Size",
)
geo_population: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Geographic Location Population"
)
# geo_geom_point = mapped_column(Geometry('POINT', srid=4326), nullable=True, comment="Geographic Location Points")
# geo_geom_polygon = mapped_column(Geometry('POLYGON', srid=4326), nullable=True,
# comment="Geographic Location Vector geographic information (polygon)")
# geo_centroid = mapped_column( GEOMETRY(POINT, 4326), nullable=True,
# comment="Geographic Location center of gravity of the region(points)")
__table_args__ = (
Index("_address_geographic_locations_ndx_00", geo_table, geo_id),
Index("_address_geographic_locations_ndx_01", geo_latitude, geo_longitude),
{"comment": "Geographic Location Information"},
)
class AddressCountry(CrudCollection):
"""
Country class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_country"
__exclude__fields__ = []
country_code: Mapped[str] = mapped_column(
String(16), nullable=False, comment="Country Code"
)
country_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Country Name"
)
money_code: Mapped[str] = mapped_column(
String(12), nullable=True, comment="Money Code"
)
language: Mapped[str] = mapped_column(
String, nullable=True, comment="Language Code"
)
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
__table_args__ = (
Index("_address_country_ndx_00", money_code),
Index("_address_country_ndx_01", country_code, unique=True),
{"comment": "Country Information"},
)
class AddressState(CrudCollection):
"""
State class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_state"
__exclude__fields__ = []
state_code: Mapped[str] = mapped_column(
String(16), nullable=False, comment="State Code"
)
state_name: Mapped[str] = mapped_column(
String, nullable=False, comment="State Name"
)
licence_plate: Mapped[str] = mapped_column(
String(24), nullable=True, comment="Sign Code"
)
phone_code: Mapped[str] = mapped_column(
String(36), nullable=True, comment="Phone Code"
)
gov_code: Mapped[str] = mapped_column(
String(128), nullable=True, comment="Government Code"
)
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
country_id: Mapped[int] = mapped_column(ForeignKey("address_country.id"))
country_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Country UUID"
)
__table_args__ = (
Index(
"_address_state_ndx_01",
country_id,
state_code,
unique=True,
),
{"comment": "State Information"},
)
class AddressCity(CrudCollection):
"""
City class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_city"
__exclude__fields__ = []
city_code: Mapped[str] = mapped_column(
String(24), nullable=False, comment="City Code"
)
city_name: Mapped[str] = mapped_column(String, nullable=False, comment="City Name")
licence_plate: Mapped[str] = mapped_column(
String(24), nullable=True, comment="Sign Code"
)
phone_code: Mapped[str] = mapped_column(
String(36), nullable=True, comment="Phone Code"
)
gov_code: Mapped[str] = mapped_column(
String(128), nullable=True, comment="Government Code"
)
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
state_id: Mapped[int] = mapped_column(ForeignKey("address_state.id"))
state_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="State UUID"
)
__table_args__ = (
Index(
"_address_city_ndx_01",
state_id,
city_code,
unique=True,
),
{"comment": "City Information"},
)
class AddressDistrict(CrudCollection):
"""
District class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_district"
__exclude__fields__ = []
district_code: Mapped[str] = mapped_column(
String(16), nullable=False, comment="District Code"
)
district_name: Mapped[str] = mapped_column(
String, nullable=False, comment="District Name"
)
phone_code: Mapped[str] = mapped_column(
String(36), nullable=True, comment="Phone Code"
)
gov_code: Mapped[str] = mapped_column(
String(128), nullable=True, comment="Government Code"
)
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
city_id: Mapped[int] = mapped_column(
ForeignKey("address_city.id"), nullable=False, comment="City ID"
)
city_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="City UUID"
)
__table_args__ = (
Index(
"_address_district_ndx_01",
city_id,
district_code,
unique=True,
),
{"comment": "District Information"},
)
class AddressLocality(CrudCollection):
"""
Locality class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_locality"
__exclude__fields__ = []
locality_code: Mapped[str] = mapped_column(
String(16), nullable=False, comment="Locality Code"
)
locality_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Locality Name"
)
type_code: Mapped[str] = mapped_column(String, nullable=True, comment="Type Name")
type_description: Mapped[str] = mapped_column(
String, nullable=True, comment="Type Name"
)
gov_code: Mapped[str] = mapped_column(
String(128), nullable=True, comment="Government Code"
)
address_show: Mapped[bool] = mapped_column(Boolean, server_default="1")
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
district_id: Mapped[int] = mapped_column(
ForeignKey("address_district.id"), nullable=False, comment="District ID"
)
district_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="District UUID"
)
__table_args__ = (
Index(
"_address_locality_ndx_01",
district_id,
locality_code,
unique=True,
),
{"comment": "Locality Information"},
)
class AddressNeighborhood(CrudCollection):
"""
Neighborhood class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_neighborhood"
__exclude__fields__ = []
neighborhood_code: Mapped[str] = mapped_column(
String(16), nullable=False, comment="Neighborhood Code"
)
neighborhood_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Neighborhood Name"
)
type_code: Mapped[str] = mapped_column(String, nullable=True, comment="Type Name")
type_description: Mapped[str] = mapped_column(
String, nullable=True, comment="Type Name"
)
gov_code: Mapped[str] = mapped_column(
String(128), nullable=True, comment="Government Code"
)
address_show: Mapped[bool] = mapped_column(Boolean, server_default="1")
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
district_id: Mapped[int] = mapped_column(
ForeignKey("address_district.id"), nullable=True, comment="District ID"
)
district_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="District UUID"
)
locality_id: Mapped[int] = mapped_column(
ForeignKey("address_locality.id"), nullable=True, comment="Locality ID"
)
locality_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Locality UUID"
)
__table_args__ = (
Index(
"_address_neighborhood_ndx_01",
locality_id,
neighborhood_code,
unique=True,
),
{"comment": "Neighborhood Information"},
)
class AddressStreet(CrudCollection):
"""
Street class based on declarative_base and BaseMixin via session
"""
__tablename__ = "address_street"
__exclude__fields__ = []
street_code: Mapped[str] = mapped_column(
String(16), nullable=False, comment="Street Code"
)
street_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Street Name"
)
type_code: Mapped[str] = mapped_column(String, nullable=True, comment="Type Name")
type_description: Mapped[str] = mapped_column(
String, nullable=True, comment="Type Name"
)
gov_code: Mapped[str] = mapped_column(
String(128), nullable=True, comment="Government Code"
)
address_geographic_id: Mapped[int] = mapped_column(
BigInteger, nullable=True, comment="Address Geographic Id"
)
neighborhood_id: Mapped[int] = mapped_column(
ForeignKey("address_neighborhood.id"), nullable=False, comment="Neighborhood ID"
)
neighborhood_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Neighborhood UUID"
)
__table_args__ = (
Index("_address_street_ndx_01", neighborhood_id, street_code, unique=True),
{"comment": "Street Information"},
)
@classmethod
def search_address_text(cls, search_text, token_dict=None):
field_dict = {
"AddressStreet.uu_id": cls.uu_id,
"AddressCountry.uu_id": AddressCountry.uu_id,
"AddressState.uu_id": AddressState.uu_id,
"AddressCity.uu_id": AddressCity.uu_id,
"AddressDistrict.uu_id": AddressDistrict.uu_id,
"AddressLocality.uu_id": AddressLocality.uu_id,
"AddressNeighborhood.uu_id": AddressNeighborhood.uu_id,
"AddressCountry.country_name": AddressCountry.country_name,
"AddressState.state_name": AddressState.state_name,
"AddressCity.city_name": AddressCity.city_name,
"AddressDistrict.district_name": AddressDistrict.district_name,
"AddressLocality.locality_name": AddressLocality.locality_name,
"AddressNeighborhood.neighborhood_name": AddressNeighborhood.neighborhood_name,
"AddressStreet.street_name": cls.street_name,
}
joined_data = (
cls.session.query(*list(field_dict.values()))
.select_from(cls)
.join(AddressNeighborhood, AddressNeighborhood.id == cls.neighborhood_id)
.join(
AddressLocality, AddressLocality.id == AddressNeighborhood.locality_id
)
.join(AddressDistrict, AddressDistrict.id == AddressLocality.district_id)
.join(AddressCity, AddressCity.id == AddressDistrict.city_id)
.join(AddressState, AddressState.id == AddressCity.state_id)
.join(AddressCountry, AddressCountry.id == AddressState.country_id)
.filter(
or_(
AddressNeighborhood.neighborhood_name.ilike(
f"%{str(search_text).upper()}%"
),
AddressLocality.locality_name.ilike(
f"%{str(search_text).upper()}%"
),
AddressDistrict.district_name.ilike(
f"%{str(search_text).upper()}%"
),
# AddressCity.city_name.ilike(f"%{str(search_text).upper()}%"),
# AddressState.state_name.ilike(f"%{str(search_text).upper()}%"),
# AddressCountry.country_name.ilike(f"%{str(search_text).upper()}%"),
cls.street_name.ilike(f"%{str(search_text).upper()}%"),
),
)
)
# select([mytable.c.id]).where(
# func.to_tsvector('english', mytable.c.title) \
# .match('somestring', postgresql_regconfig='english')
# )
joined_statement = joined_data
joined_data = joined_data.first()
if not joined_data:
raise ValueError(
"No address found with the given search text.",
)
# raise HTTPException(
# status_code=404,
# detail="No address found with the given search text.",
# )
return dict(
query=joined_statement,
schema=list(field_dict.keys()),
)

View File

@ -625,3 +625,4 @@ class BuildPersonProviding(CrudCollection):
),
{"comment": "People providing services for building"},
)

239
Schemas/company/company.py Normal file
View File

@ -0,0 +1,239 @@
from typing import Any
from sqlalchemy import (
String,
Integer,
Boolean,
ForeignKey,
Index,
Identity,
TIMESTAMP,
func,
)
from sqlalchemy.orm import mapped_column, relationship, Mapped
from Controllers.Postgres.mixin import CrudCollection
from Schemas import Duties, Addresses
class RelationshipDutyCompany(CrudCollection):
"""
CompanyRelationship class based on declarative_base and CrudCollection via session
Company -> Sub Company -> Sub-Sub Company
if owner_id == parent_id: can manipulate data of any record
else: Read-Only
duty_id = if relationship_type == base An organization / not operational / no responsible person
relationship = company_id filter -> Action filter(company_id) relationship_type = Organization
relationship = company_id filter -> Action filter(company_id) relationship_type = Commercial
"""
__tablename__ = "relationship_duty_company"
__exclude__fields__ = []
owner_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=False
) # 1
duties_id: Mapped[int] = mapped_column(
ForeignKey("duties.id"), nullable=False
) # duty -> (n)employee Evyos LTD
member_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=False
) # 2, 3, 4
parent_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=True
) # None
relationship_type: Mapped[str] = mapped_column(
String, nullable=True, server_default="Commercial"
) # Commercial, Organization # Bulk
child_count: Mapped[int] = mapped_column(Integer) # 0
show_only: Mapped[bool] = mapped_column(Boolean, server_default="0")
# related_company: Mapped[List["Companies"]] = relationship(
# "Companies",
# back_populates="related_companies",
# foreign_keys=[related_company_id],
# )
@classmethod
def match_company_to_company_commercial(cls, data: Any, token):
with cls.new_session() as db_session:
token_duties_id, token_company_id = token.get("duty_id"), token.get(
"company_id"
)
list_match_company_id = []
send_duties = Duties.filter_one(
Duties.uu_id == data.duty_uu_id,
db=db_session
)
send_user_duties = Duties.filter_one(
Duties.duties_id == send_duties.id,
Duties.company_id == token_duties_id,
db=db_session
)
if not send_user_duties:
raise Exception(
"Send Duty is not found in company. Please check duty uuid and try again."
)
for company_uu_id in list(data.match_company_uu_id):
company = Companies.filter_one(
Companies.uu_id == company_uu_id,
db=db_session
)
bulk_company = RelationshipDutyCompany.filter_one(
RelationshipDutyCompany.owner_id == token_company_id,
RelationshipDutyCompany.relationship_type == "Bulk",
RelationshipDutyCompany.member_id == company.id,
db=db_session
)
if not bulk_company:
raise Exception(
f"Bulk Company is not found in company. "
f"Please check company uuid {bulk_company.uu_id} and try again."
)
list_match_company_id.append(bulk_company)
for match_company_id in list_match_company_id:
RelationshipDutyCompany.find_or_create(
owner_id=token_company_id,
duties_id=send_user_duties.id,
member_id=match_company_id.id,
parent_id=match_company_id.parent_id,
relationship_type="Commercial",
show_only=False,
db=db_session
)
@classmethod
def match_company_to_company_organization(cls, data: Any, token):
with cls.new_session() as db_session:
token_duties_id, token_company_id = token.get("duty_id"), token.get(
"company_id"
)
list_match_company_id = []
send_duties = Duties.filter_one(
Duties.uu_id == data.duty_uu_id,
db=db_session
)
send_user_duties = Duties.filter_one(
Duties.duties_id == send_duties.id,
Duties.company_id == token_duties_id,
db=db_session
)
if not send_user_duties:
raise Exception(
"Send Duty is not found in company. Please check duty uuid and try again."
)
for company_uu_id in list(data.match_company_uu_id):
company = Companies.filter_one(
Companies.uu_id == company_uu_id,
db=db_session
)
bulk_company = RelationshipDutyCompany.filter_one(
RelationshipDutyCompany.owner_id == token_company_id,
RelationshipDutyCompany.relationship_type == "Bulk",
RelationshipDutyCompany.member_id == company.id,
db=db_session
)
if not bulk_company:
raise Exception(
f"Bulk Company is not found in company. "
f"Please check company uuid {bulk_company.uu_id} and try again."
)
list_match_company_id.append(bulk_company)
for match_company_id in list_match_company_id:
Duties.init_a_company_default_duties(
company_id=match_company_id.id,
company_uu_id=str(match_company_id.uu_id),
db=db_session
)
RelationshipDutyCompany.find_or_create(
owner_id=token_company_id,
duties_id=send_user_duties.id,
member_id=match_company_id.id,
parent_id=match_company_id.parent_id,
relationship_type="Organization",
show_only=False,
db=db_session
)
__table_args__ = (
Index(
"_company_relationship_ndx_01",
duties_id,
owner_id,
member_id,
relationship_type,
unique=True,
),
{"comment": "Company Relationship Information"},
)
class Companies(CrudCollection):
"""
Company class based on declarative_base and CrudCollection via session
formal_name = Government register name by offical
public_name = Public registered name by User
nick_name = Search by nickname, commercial_type = Tüzel veya birey
"""
__tablename__ = "companies"
__exclude__fields__ = ["is_blacklist", "is_commercial"]
__access_by__ = []
__many__table__ = RelationshipDutyCompany
formal_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Formal Name"
)
company_type: Mapped[str] = mapped_column(
String, nullable=False, comment="Company Type"
)
commercial_type: Mapped[str] = mapped_column(
String, nullable=False, comment="Commercial Type"
)
tax_no: Mapped[str] = mapped_column(
String, index=True, unique=True, nullable=False, comment="Tax No"
)
public_name: Mapped[str] = mapped_column(String, comment="Public Name of a company")
company_tag: Mapped[str] = mapped_column(String, comment="Company Tag")
default_lang_type: Mapped[str] = mapped_column(String, server_default="TR")
default_money_type: Mapped[str] = mapped_column(String, server_default="TL")
is_commercial: Mapped[bool] = mapped_column(Boolean, server_default="False")
is_blacklist: Mapped[bool] = mapped_column(Boolean, server_default="False")
parent_id = mapped_column(Integer, nullable=True)
workplace_no: Mapped[str] = mapped_column(String, nullable=True)
official_address_id: Mapped[int] = mapped_column(
ForeignKey("addresses.id"), nullable=True
)
official_address_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Official Address UUID"
)
top_responsible_company_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=True
)
top_responsible_company_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Top Responsible Company UUID"
)
# buildings: Mapped[List["Build"]] = relationship(
# "Build",
# back_populates="companies",
# foreign_keys="Build.company_id",
# )
__table_args__ = (
Index("_company_ndx_01", tax_no, unique=True),
Index("_company_ndx_02", formal_name, public_name),
{"comment": "Company Information"},
)

View File

@ -0,0 +1,73 @@
from sqlalchemy import String, Integer, ForeignKey, Index, Boolean, Identity
from sqlalchemy.orm import mapped_column, Mapped
from Controllers.Postgres.mixin import CrudCollection
class Departments(CrudCollection):
__tablename__ = "departments"
__exclude__fields__ = []
parent_department_id = mapped_column(Integer, server_default="0")
department_code = mapped_column(
String(16), nullable=False, index=True, comment="Department Code"
)
department_name: Mapped[str] = mapped_column(
String(128), nullable=False, comment="Department Name"
)
department_description: Mapped[str] = mapped_column(String, server_default="")
company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"), nullable=False)
company_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Company UUID"
)
__table_args__ = {"comment": "Departments Information"}
class Duty(CrudCollection):
__tablename__ = "duty"
__exclude__fields__ = []
duty_name: Mapped[str] = mapped_column(
String, unique=True, nullable=False, comment="Duty Name"
)
duty_code: Mapped[str] = mapped_column(String, nullable=False, comment="Duty Code")
duty_description: Mapped[str] = mapped_column(String, comment="Duty Description")
__table_args__ = ({"comment": "Duty Information"},)
class Duties(CrudCollection):
__tablename__ = "duties"
__exclude__fields__ = []
users_default_duty = mapped_column(
ForeignKey("duty.id"), nullable=True, comment="Default Duty for Users"
)
company_id: Mapped[int] = mapped_column(Integer)
company_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Company UUID"
)
duties_id: Mapped[int] = mapped_column(ForeignKey("duty.id"), nullable=False)
duties_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Duty UUID"
)
department_id = mapped_column(
ForeignKey("departments.id"), nullable=False, comment="Department ID"
)
department_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Department UUID"
)
# priority_id: Mapped[int] = mapped_column(ForeignKey("priority.id"), nullable=True)
management_duty = mapped_column(
Boolean, server_default="0"
) # is this a prime Company Duty ???
__table_args__ = (
Index("duty_ndx_00", company_id, duties_id, department_id, unique=True),
{"comment": "Duty & Company & Department Information"},
)

View File

@ -0,0 +1,75 @@
from sqlalchemy import (
String,
ForeignKey,
Index,
Numeric,
)
from sqlalchemy.orm import mapped_column, Mapped
from Controllers.Postgres.mixin import CrudCollection
class Staff(CrudCollection):
__tablename__ = "staff"
__exclude__fields__ = []
staff_description: Mapped[str] = mapped_column(String, server_default="", comment="Staff Description")
staff_name: Mapped[str] = mapped_column(String, nullable=False, comment="Staff Name")
staff_code: Mapped[str] = mapped_column(String, nullable=False, comment="Staff Code")
duties_id: Mapped[int] = mapped_column(ForeignKey("duties.id"), nullable=False)
duties_uu_id: Mapped[str] = mapped_column(String, nullable=False, comment="Duty UUID")
__table_args__ = ({"comment": "Staff Information"},)
class Employees(CrudCollection):
__tablename__ = "employees"
__exclude__fields__ = []
staff_id: Mapped[int] = mapped_column(ForeignKey("staff.id"))
staff_uu_id: Mapped[str] = mapped_column(String, nullable=False, comment="Staff UUID")
people_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=True)
people_uu_id: Mapped[str] = mapped_column(String, nullable=True, comment="People UUID")
__table_args__ = (
Index("employees_ndx_00", people_id, staff_id, unique=True),
{"comment": "Employee Person Information"},
)
class EmployeeHistory(CrudCollection):
__tablename__ = "employee_history"
__exclude__fields__ = []
staff_id: Mapped[int] = mapped_column(ForeignKey("staff.id"), nullable=False, comment="Staff ID")
staff_uu_id: Mapped[str] = mapped_column(String, nullable=False, comment="Staff UUID")
people_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=False, comment="People ID")
people_uu_id: Mapped[str] = mapped_column(String, nullable=False, comment="People UUID")
__table_args__ = (
Index("_employee_history_ndx_00", people_id, staff_id),
{"comment": "Employee History Information"},
)
class EmployeesSalaries(CrudCollection):
__tablename__ = "employee_salaries"
__exclude__fields__ = []
gross_salary: Mapped[float] = mapped_column(
Numeric(20, 6), nullable=False, comment="Gross Salary"
)
net_salary: Mapped[float] = mapped_column(
Numeric(20, 6), nullable=False, comment="Net Salary"
)
people_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=False)
people_uu_id: Mapped[str] = mapped_column(String, nullable=False, comment="People UUID")
__table_args__ = (
Index("_employee_salaries_ndx_00", people_id, "expiry_starts"),
{"comment": "Employee Salaries Information"},
)

430
Schemas/event/event.py Normal file
View File

@ -0,0 +1,430 @@
from sqlalchemy import (
String,
ForeignKey,
Numeric,
SmallInteger,
Boolean,
Integer,
Index,
)
from sqlalchemy.orm import mapped_column, Mapped
from Controllers.Postgres.mixin import CrudCollection
from Schemas import OccupantTypes
class Events(CrudCollection):
"""
Events class based on declarative_base and BaseMixin via session
If Events2Occupants and Events2Employees are not found for user request, response 401 Unauthorized
"""
__tablename__ = "events"
__exclude__fields__ = []
event_type: Mapped[str] = mapped_column(
String, nullable=False, comment="Event Type"
)
function_code: Mapped[str] = mapped_column(
String, nullable=False, comment="function code"
)
function_class: Mapped[str] = mapped_column(
String, nullable=False, comment="class name"
)
# name: Mapped[str] = mapped_column(String, nullable=True) # form or page title
description: Mapped[str] = mapped_column(
String, server_default=""
) # form or page description
property_description: Mapped[str] = mapped_column(String, server_default="")
marketing_layer = mapped_column(SmallInteger, server_default="3")
cost: Mapped[float] = mapped_column(Numeric(20, 2), server_default="0.00")
unit_price: Mapped[float] = mapped_column(Numeric(20, 2), server_default="0.00")
endpoint_id: Mapped[int] = mapped_column(
ForeignKey("endpoint_restriction.id"), nullable=True
)
endpoint_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Endpoint UUID"
)
__table_args__ = ({"comment": "Events Information"},)
class Modules(CrudCollection):
"""
Modules class based on declarative_base and BaseMixin via session
"""
__tablename__ = "modules"
__exclude__fields__ = []
module_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Module Name"
)
module_description: Mapped[str] = mapped_column(String, server_default="")
module_code: Mapped[str] = mapped_column(
String, nullable=False, comment="Module Code"
)
module_layer = mapped_column(Integer, nullable=False, comment="Module Layer")
is_default_module = mapped_column(Boolean, server_default="0")
def retrieve_services(self):
services = Services.filter_all(Services.module_id == self.id).data
if not services:
self.raise_http_exception(
status_code="HTTP_404_NOT_FOUND",
error_case="RECORD_NOT_FOUND",
message=f"No services found for this module : {str(self.uu_id)}",
data={
"module_uu_id": str(self.uu_id),
},
)
return services
__table_args__ = ({"comment": "Modules Information"},)
class Services(CrudCollection):
"""
Services class based on declarative_base and BaseMixin via session
"""
__tablename__ = "services"
__exclude__fields__ = []
module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
module_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Module UUID"
)
service_name: Mapped[str] = mapped_column(
String, nullable=False, comment="Service Name"
)
service_description: Mapped[str] = mapped_column(String, server_default="")
service_code: Mapped[str] = mapped_column(
String, nullable=True, comment="Service Code"
)
related_responsibility: Mapped[str] = mapped_column(String, server_default="")
@classmethod
def retrieve_service_via_occupant_code(cls, occupant_code):
with cls.new_session() as db_session:
occupant_type = OccupantTypes.filter_by_one(
system=True,
occupant_code=occupant_code,
db=db_session
).data
if not occupant_type:
cls.raise_http_exception(
status_code="HTTP_404_NOT_FOUND",
error_case="RECORD_NOT_FOUND",
message=f"No occupant type found for this code : {occupant_code}",
data={
"occupant_code": occupant_code,
},
)
return cls.filter_one(
cls.related_responsibility == occupant_type.occupant_code,
db=db_session
).data
__table_args__ = ({"comment": "Services Information"},)
class Service2Events(CrudCollection):
"""
Service2Actions class based on declarative_base and BaseMixin via session
"""
__tablename__ = "services2events"
__exclude__fields__ = []
service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
service_uu_id = mapped_column(String, nullable=False, comment="Service UUID")
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")
__table_args__ = ({"comment": "Service2Events Information"},)
class Event2OccupantExtra(CrudCollection):
__tablename__ = "event2occupant_extra"
__exclude__fields__ = []
build_living_space_id: Mapped[int] = mapped_column(
ForeignKey("build_living_space.id"), nullable=False
)
build_living_space_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Build Living Space UUID"
)
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
event_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Event UUID"
)
__table_args__ = (
Index(
"event2occupant_extra_bind_event_to_occupant",
build_living_space_id,
event_id,
unique=True,
),
{"comment": "Occupant2Event Information"},
)
class Event2EmployeeExtra(CrudCollection):
"""
Employee2Event class based on declarative_base and BaseMixin via session
"""
__tablename__ = "event2employee_extra"
__exclude__fields__ = []
employee_id: Mapped[int] = mapped_column(ForeignKey("employees.id"), nullable=False)
employee_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Employee UUID"
)
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
event_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Event UUID"
)
__table_args__ = (
Index(
"event2employee_extra_employee_to_event",
employee_id,
event_id,
unique=True,
),
{"comment": "Employee to Event Information"},
)
class Event2Employee(CrudCollection):
"""
Employee2Event class based on declarative_base and BaseMixin via session
"""
__tablename__ = "event2employee"
__exclude__fields__ = []
employee_id: Mapped[int] = mapped_column(ForeignKey("employees.id"), nullable=False)
employee_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Employee UUID"
)
event_service_id: Mapped[int] = mapped_column(
ForeignKey("services.id"), nullable=False
)
event_service_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Event Cluster UUID"
)
__table_args__ = (
Index(
"event2employee_employee_to_event",
employee_id,
event_service_id,
unique=True,
),
{"comment": "Employee to Event Information"},
)
@classmethod
def get_event_codes(cls, employee_id: int) -> list:
db = cls.new_session()
employee_events = cls.filter_all(
cls.employee_id == employee_id,
db=db,
).data
active_event_ids = Service2Events.filter_all_system(
Service2Events.service_id.in_(
[event.event_service_id for event in employee_events]
),
db=db,
).data
active_events = Events.filter_all(
Events.id.in_([event.event_id for event in active_event_ids]),
db=db,
).data
if extra_events := Event2EmployeeExtra.filter_all(
Event2EmployeeExtra.employee_id == employee_id,
db=db,
).data:
events_extra = Events.filter_all(
Events.id.in_([event.event_id for event in extra_events]),
db=db,
).data
active_events.extend(events_extra)
return [event.function_code for event in active_events]
# @classmethod
# def get_event_endpoints(cls, employee_id: int) -> list:
# from Schemas import EndpointRestriction
#
# db = cls.new_session()
# employee_events = cls.filter_all(
# cls.employee_id == employee_id,
# db=db,
# ).data
# active_event_ids = Service2Events.filter_all(
# Service2Events.service_id.in_(
# [event.event_service_id for event in employee_events]
# ),
# db=db,
# system=True,
# ).data
# active_events = Events.filter_all(
# Events.id.in_([event.event_id for event in active_event_ids]),
# db=db,
# ).data
# if extra_events := Event2EmployeeExtra.filter_all(
# Event2EmployeeExtra.employee_id == employee_id,
# db=db,
# ).data:
# events_extra = Events.filter_all(
# Events.id.in_([event.event_id for event in extra_events]),
# db=db,
# ).data
# active_events.extend(events_extra)
# endpoint_restrictions = EndpointRestriction.filter_all(
# EndpointRestriction.id.in_([event.endpoint_id for event in active_events]),
# db=db,
# ).data
# return [event.endpoint_name for event in endpoint_restrictions]
#
class Event2Occupant(CrudCollection):
"""
Occupant2Event class based on declarative_base and BaseMixin via session
"""
__tablename__ = "event2occupant"
__exclude__fields__ = []
build_living_space_id: Mapped[str] = mapped_column(
ForeignKey("build_living_space.id"), nullable=False
)
build_living_space_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Build Living Space UUID"
)
event_service_id: Mapped[int] = mapped_column(
ForeignKey("services.id"), nullable=False
)
event_service_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Event Cluster UUID"
)
# event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
# event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")
__table_args__ = (
Index(
"event2occupant_bind_event_to_occupant",
build_living_space_id,
event_service_id,
unique=True,
),
{"comment": "Occupant2Event Information"},
)
@classmethod
def get_event_codes(cls, build_living_space_id) -> list:
db = cls.new_session()
occupant_events = cls.filter_all(
cls.build_living_space_id == build_living_space_id,
db=db,
).data
active_event_ids = Service2Events.filter_all_system(
Service2Events.service_id.in_(
[event.event_service_id for event in occupant_events]
),
db=db,
).data
active_events = Events.filter_all(
Events.id.in_([event.event_id for event in active_event_ids]),
db=db,
).data
if extra_events := Event2OccupantExtra.filter_all(
Event2OccupantExtra.build_living_space_id == build_living_space_id,
db=db,
).data:
events_extra = Events.filter_all(
Events.id.in_([event.event_id for event in extra_events]),
db=db,
).data
active_events.extend(events_extra)
return [event.function_code for event in active_events]
# @classmethod
# def get_event_endpoints(cls, build_living_space_id) -> list:
# from Schemas import EndpointRestriction
#
# db = cls.new_session()
# occupant_events = cls.filter_all(
# cls.build_living_space_id == build_living_space_id,
# db=db,
# ).data
# active_event_ids = Service2Events.filter_all(
# Service2Events.service_id.in_(
# [event.event_service_id for event in occupant_events]
# ),
# db=db,
# system=True,
# ).data
# active_events = Events.filter_all(
# Events.id.in_([event.event_id for event in active_event_ids]),
# db=db,
# ).data
# if extra_events := Event2OccupantExtra.filter_all(
# Event2OccupantExtra.build_living_space_id == build_living_space_id,
# db=db,
# ).data:
# events_extra = Events.filter_all(
# Events.id.in_([event.event_id for event in extra_events]),
# db=db,
# ).data
# active_events.extend(events_extra)
# endpoint_restrictions = EndpointRestriction.filter_all(
# EndpointRestriction.id.in_([event.endpoint_id for event in active_events]),
# db=db,
# ).data
# return [event.endpoint_name for event in endpoint_restrictions]
class ModulePrice(CrudCollection):
"""
ModulePrice class based on declarative_base and BaseMixin via session
"""
__tablename__ = "module_price"
__exclude__fields__ = []
campaign_code: Mapped[str] = mapped_column(
String, nullable=False, comment="Campaign Code"
)
module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
module_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Module UUID"
)
service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
service_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Service UUID"
)
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
event_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Event UUID"
)
is_counted_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
__table_args__ = ({"comment": "ModulePrice Information"},)

View File

@ -0,0 +1,434 @@
import arrow
from sqlalchemy import (
String,
Integer,
Boolean,
ForeignKey,
Index,
TIMESTAMP,
Text,
func,
BigInteger,
Numeric,
or_,
)
from sqlalchemy.orm import mapped_column, relationship, Mapped
from Controllers.Postgres.mixin import CrudCollection
class UsersTokens(CrudCollection):
__tablename__ = "users_tokens"
__exclude__fields__ = []
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False)
token_type: Mapped[str] = mapped_column(String(16), server_default="RememberMe")
token: Mapped[str] = mapped_column(String, server_default="")
domain: Mapped[str] = mapped_column(String, server_default="")
expires_at: Mapped[TIMESTAMP] = mapped_column(
TIMESTAMP(timezone=True),
default=str(arrow.now().shift(date=arrow.now(), days=3)),
)
# users = relationship("Users", back_populates="tokens", foreign_keys=[user_id])
class Users(CrudCollection):
"""
Application User frame to connect to API with assigned token-based HTTP connection
"""
__tablename__ = "users"
__exclude__fields__ = [
"hash_password",
"password_token",
"expiry_begins",
"related_company",
]
user_tag: Mapped[str] = mapped_column(
String(64), server_default="", comment="Unique tag for the user", index=True
)
email: Mapped[str] = mapped_column(
String(128), server_default="", comment="Email address of the user", index=True
)
phone_number: Mapped[str] = mapped_column(
String, server_default="", comment="Phone number of the user", index=True
)
via: Mapped[str] = mapped_column(
String,
server_default="111",
comment="Email 1/ Phone 2/ User Tag 3 All 111 Only 100",
)
avatar: Mapped[str] = mapped_column(
String, server_default="", comment="Avatar URL for the user"
)
hash_password: Mapped[str] = mapped_column(
String(256), server_default="", comment="Hashed password for security"
)
password_token: Mapped[str] = mapped_column(
String(256), server_default="", comment="Token for password reset"
)
remember_me: Mapped[bool] = mapped_column(
Boolean, server_default="0", comment="Flag to remember user login"
)
password_expires_day: Mapped[int] = mapped_column(
Integer,
server_default=str(30),
comment="Password expires in days",
)
password_expiry_begins: Mapped[TIMESTAMP] = mapped_column(
TIMESTAMP(timezone=True),
server_default=func.now(),
comment="Timestamp when password expiry begins",
)
related_company: Mapped[str] = mapped_column(String, comment="Related Company UUID")
person_id: Mapped[int] = mapped_column(
ForeignKey("people.id"), nullable=False, comment="Foreign key to person table"
)
person_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Person UUID", index=True
)
local_timezone = mapped_column(
String, server_default="GMT+3", comment="Local timezone of user"
)
person = relationship("People", back_populates="user", foreign_keys=[person_id])
#
# @property
# def is_occupant(self):
# return not str(self.email).split("@")[1] == Auth.ACCESS_EMAIL_EXT
#
# @property
# def is_employee(self):
# return str(self.email).split("@")[1] == Auth.ACCESS_EMAIL_EXT
#
# @property
# def user_type(self):
# return "Occupant" if self.is_occupant else "Employee"
#
# @classmethod
# def credentials(cls):
# db_session = cls.new_session()
# person_object: People = People.filter_by_one(
# db=db_session, system=True, id=cls.person_id
# ).data
# if person_object:
# return {
# "person_id": person_object.id,
# "person_uu_id": str(person_object.uu_id),
# }
# return {
# "person_id": None,
# "person_uu_id": None,
# }
#
# @property
# def password_expiry_ends(self):
# """Calculates the expiry end date based on expiry begins and expires day"""
# return self.password_expiry_begins + timedelta(
# days=int(
# "".join(
# [
# _
# for _ in str(self.password_expires_day).split(",")[0]
# if _.isdigit()
# ]
# )
# )
# )
#
# @classmethod
# def create_action(cls, create_user: InsertUsers, token_dict):
# db_session = cls.new_session()
# found_person = People.filter_one(
# People.uu_id == create_user.people_uu_id,
# db=db_session,
# ).data
#
# if not found_person:
# raise HTTPException(status_code=400, detail="Person not found.")
# if (
# not any(i in str(create_user.email) for i in ["@", "."])
# and not len(str(create_user.phone_number)) >= 10
# ):
# raise HTTPException(
# status_code=400,
# detail="Please enter at least one valid email or phone number.",
# )
# if not create_user.avatar:
# create_user.avatar = ApiStatic.PLACEHOLDER
# create_dict = create_user.model_dump()
# del create_dict["people_uu_id"]
# create_dict["person_id"] = found_person.id
# create_dict["person_uu_id"] = str(found_person.uu_id)
# create_dict["related_company"] = token_dict.selected_company.company_uu_id
# created_user = cls.find_or_create(**create_dict)
# created_user.reset_password_token(found_user=created_user)
# return created_user
#
# def get_employee_and_duty_details(self):
# from ApiLayers.Schemas import Employees, Duties
#
# db_session = self.new_session()
# found_person = People.filter_one(
# People.id == self.person_id,
# db=db_session,
# )
# found_employees = Employees.filter_by_active(
# people_id=found_person.id, is_confirmed=True, db=db_session
# )
# found_duties = Duties.filter_all(
# Duties.is_confirmed == True,
# Duties.id.in_(
# list(found_employee.duty_id for found_employee in found_employees.data)
# ),
# db=db_session,
# )
# if not found_employees.count:
# raise HTTPException(
# status_code=401,
# detail={
# "message": "Person has no confirmed duty. No employee match please register "
# "your super admin",
# "completed": False,
# },
# )
# return {
# "duty_list": [
# {
# "duty_id": duty.id,
# "duty_uu_id": duty.uu_id.__str__(),
# "duty_code": duty.duty_code,
# "duty_name": duty.duty_name,
# "duty_description": duty.duty_description,
# }
# for duty in found_duties.data
# ],
# }
#
# def get_main_domain_and_other_domains(self, get_main_domain: bool = True):
# from ApiLayers.Schemas import MongoQueryIdentity
#
# query_engine = MongoQueryIdentity(company_uuid=self.related_company)
# domain_via_user = query_engine.get_domain_via_user(user_uu_id=str(self.uu_id))
# if not domain_via_user:
# raise HTTPException(
# status_code=401,
# detail="Domain not found. Please contact the admin.",
# )
# domain_via_user = domain_via_user[0]
# if get_main_domain:
# return domain_via_user.get("main_domain", None)
# return domain_via_user.get("other_domains_list", None)
class RelationshipDutyPeople(CrudCollection):
__tablename__ = "relationship_duty_people"
__exclude__fields__ = []
company_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=False
) # 1, 2, 3
duties_id: Mapped[int] = mapped_column(
ForeignKey("duties.id"), nullable=False
) # duty -> (n)person Evyos LTD
member_id: Mapped[int] = mapped_column(
ForeignKey("people.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="0")
# related_company: Mapped[List["Company"]] = relationship(
# "Company",
# back_populates="related_companies",
# foreign_keys=[related_company_id],
# )
__table_args__ = (
Index(
"person_relationship_ndx_01",
company_id,
duties_id,
member_id,
relationship_type,
unique=True,
),
{"comment": "Person Relationship Information"},
)
class People(CrudCollection):
"""
People that are related to users in the application
"""
__tablename__ = "people"
__exclude__fields__ = []
__many__table__ = RelationshipDutyPeople
__encrypt_list__ = [
"father_name",
"mother_name",
"country_code",
"national_identity_id",
"birth_place",
"birth_date",
"tax_no",
]
firstname: Mapped[str] = mapped_column(
String, nullable=False, comment="First name of the person"
)
surname: Mapped[str] = mapped_column(
String(24), nullable=False, comment="Surname of the person"
)
middle_name: Mapped[str] = mapped_column(
String, server_default="", comment="Middle name of the person"
)
sex_code: Mapped[str] = mapped_column(
String(1), nullable=False, comment="Sex code of the person (e.g., M/F)"
)
person_ref: Mapped[str] = mapped_column(
String, server_default="", comment="Reference ID for the person"
)
person_tag: Mapped[str] = mapped_column(
String, server_default="", comment="Unique tag for the person"
)
# ENCRYPT DATA
father_name: Mapped[str] = mapped_column(
String, server_default="", comment="Father's name of the person"
)
mother_name: Mapped[str] = mapped_column(
String, server_default="", comment="Mother's name of the person"
)
country_code: Mapped[str] = mapped_column(
String(4), server_default="TR", comment="Country code of the person"
)
national_identity_id: Mapped[str] = mapped_column(
String, server_default="", comment="National identity ID of the person"
)
birth_place: Mapped[str] = mapped_column(
String, server_default="", comment="Birth place of the person"
)
birth_date: Mapped[TIMESTAMP] = mapped_column(
TIMESTAMP(timezone=True),
server_default="1900-01-01",
comment="Birth date of the person",
)
tax_no: Mapped[str] = mapped_column(
String, server_default="", comment="Tax number of the person"
)
# Receive at Create person
# language = mapped_column(
# String, comment="Language code of the person"
# )
# currency = mapped_column(
# String, comment="Currency code of the person"
# )
# ENCRYPT DATA
user = relationship(
"Users", back_populates="person", foreign_keys="Users.person_id"
)
__table_args__ = (
Index(
"person_ndx_001",
national_identity_id,
unique=True,
),
{"comment": "Person Information"},
)
@property
def full_name(self):
if self.middle_name:
return f"{self.firstname} {self.middle_name} {self.surname}"
return f"{self.firstname} {self.surname}"
class OccupantTypes(CrudCollection):
"""
Occupant Types class based on declarative_base and BaseMixin via session
"""
__tablename__ = "occupant_types"
__exclude__fields__ = []
occupant_type: Mapped[str] = mapped_column(
String, nullable=False, comment="Occupant Type"
)
occupant_description: Mapped[str] = mapped_column(String, server_default="")
occupant_code: Mapped[str] = mapped_column(String, server_default="")
occupant_category: Mapped[str] = mapped_column(String, server_default="")
occupant_category_type: Mapped[str] = mapped_column(String, server_default="")
occupant_is_unique: Mapped[bool] = mapped_column(Boolean, server_default="0")
__table_args__ = ({"comment": "Occupant Types Information"},)
class Contracts(CrudCollection):
"""
Contract class based on declarative_base and BaseMixin via session
"""
__tablename__ = "contracts"
__exclude__fields__ = []
contract_type: Mapped[str] = mapped_column(
String(5),
nullable=False,
comment="The code for personnel is P and the code for companies is C.",
)
contract_title: Mapped[str] = mapped_column(String(255))
contract_details: Mapped[str] = mapped_column(Text)
contract_terms: Mapped[str] = mapped_column(Text)
contract_code: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="contract_code is the unique code given by the system.",
)
contract_date: Mapped[TIMESTAMP] = mapped_column(
TIMESTAMP(timezone=True),
server_default="2099-12-31 23:59:59",
comment="contract date is the date the contract is made. "
"expire start is the start date of the contract, expire en is the end date of the contract.",
)
company_id: Mapped[int] = mapped_column(
Integer, ForeignKey("companies.id"), nullable=True
)
company_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Company UUID"
)
person_id: Mapped[int] = mapped_column(
Integer, ForeignKey("people.id"), nullable=True
)
person_uu_id: Mapped[str] = mapped_column(
String, server_default="", comment="Person UUID"
)
@classmethod
def retrieve_contact_no(cls):
# todo When create record contract_code == below string
related_date, counter = Contracts.client_arrow.now(), 1
return (
f"{related_date.date().year}{str(cls.contract_type)}{str(counter).zfill(6)}"
)
__table_args__ = (
Index("_contract_ndx_01", contract_code, unique=True),
{"comment": "Contract Information"},
)

106
Schemas/others/enums.py Normal file
View File

@ -0,0 +1,106 @@
from sqlalchemy import (
UUID,
String,
text,
)
from sqlalchemy.orm import (
Mapped,
mapped_column,
)
from Controllers.Postgres.mixin import CrudCollection
class ApiEnumDropdown(CrudCollection):
__tablename__ = "api_enum_dropdown"
__exclude__fields__ = ["enum_class"]
__language_model__ = None
id: Mapped[int] = mapped_column(primary_key=True)
uu_id: Mapped[str] = mapped_column(
UUID, server_default=text("gen_random_uuid()"), index=True, unique=True
)
enum_class: Mapped[str] = mapped_column(
String, nullable=False, comment="Enum Constant Name"
)
key: Mapped[str] = mapped_column(String, nullable=False, comment="Enum Key")
value: Mapped[str] = mapped_column(String, nullable=False, comment="Enum Value")
description: Mapped[str] = mapped_column(String, nullable=True)
__table_args__ = ({"comment": "Enum objets that are linked to tables"},)
@classmethod
def get_by_uuid(cls, uuid: str):
with cls.new_session() as db_session:
return cls.filter_by_one(uu_id=str(uuid), db=db_session).data
@classmethod
def get_debit_search(cls, search_debit: str = None, search_uu_id: str = None):
with cls.new_session() as db_session:
if search_uu_id:
if search := cls.filter_one_system(
cls.enum_class.in_(["DebitTypes"]),
cls.uu_id == search_uu_id,
db=db_session
).data:
return search
elif search_debit:
if search := cls.filter_one(
cls.enum_class.in_(["DebitTypes"]), cls.key == search_debit, db=db_session
).data:
return search
return cls.filter_all_system(cls.enum_class.in_(["DebitTypes"]), db=db_session).data
@classmethod
def get_due_types(cls):
with cls.new_session() as db_session:
if due_list := cls.filter_all_system(
cls.enum_class == "BuildDuesTypes",
cls.key.in_(["BDT-A", "BDT-D"]),
db=db_session
).data:
return [due.uu_id.__str__() for due in due_list]
# raise HTTPException(
# status_code=404,
# detail="No dues types found",
# )
@classmethod
def due_type_search(cls, search_management: str = None, search_uu_id: str = None):
with cls.new_session() as db_session:
if search_uu_id:
if search := cls.filter_one_system(
cls.enum_class.in_(["BuildDuesTypes"]),
cls.uu_id == search_uu_id,
db=db_session
).data:
return search
elif search_management:
if search := cls.filter_one_system(
cls.enum_class.in_(["BuildDuesTypes"]),
cls.key == search_management,
db=db_session
).data:
return search
return cls.filter_all_system(cls.enum_class.in_(["BuildDuesTypes"]), db=db_session).data
def get_enum_dict(self):
return {
"uu_id": str(self.uu_id),
"enum_class": self.enum_class,
"key": self.key,
"value": self.value,
"description": self.description,
}
@classmethod
def uuid_of_enum(cls, enum_class: str, key: str):
with cls.new_session() as db_session:
return str(
getattr(
cls.filter_one_system(
cls.enum_class == enum_class, cls.key == key, db=db_session
).data,
"uu_id",
None,
)
)

35
Schemas/rules/rules.py Normal file
View File

@ -0,0 +1,35 @@
from sqlalchemy import (
UUID,
String,
text,
)
from sqlalchemy.orm import (
Mapped,
mapped_column,
)
from Controllers.Postgres.mixin import CrudCollection
class EndpointRestriction(CrudCollection):
"""
Initialize Endpoint Restriction with default values
"""
__tablename__ = "endpoint_restriction"
__exclude__fields__ = []
endpoint_function: Mapped[str] = mapped_column(
String, server_default="", comment="Function name of the API endpoint"
)
endpoint_name: Mapped[str] = mapped_column(
String, server_default="", comment="Name of the API endpoint"
)
endpoint_method: Mapped[str] = mapped_column(
String, server_default="", comment="HTTP method used by the endpoint"
)
endpoint_desc: Mapped[str] = mapped_column(
String, server_default="", comment="Description of the endpoint"
)
endpoint_code: Mapped[str] = mapped_column(
String, server_default="", unique=True, comment="Unique code for the endpoint"
)

View File

@ -28,3 +28,4 @@ API_REFRESHER_TOKEN_LENGTH=144
API_EMAIL_HOST=10.10.2.36
API_DATETIME_FORMAT=YYYY-MM-DD HH:mm:ss Z
API_FORGOT_LINK=https://www.evyos.com.tr/password/create?tokenUrl=
API_VERSION=0.1.001

View File

@ -1,4 +1,5 @@
services:
mongo_service:
container_name: mongo_service
image: "bitnami/mongodb:latest"