Schemas updated
This commit is contained in:
parent
27c48bb86a
commit
3583d178e9
|
|
@ -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"]
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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"),
|
||||||
|
]
|
||||||
|
|
@ -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"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from Schemas.building.build import BuildParts, BuildLivingSpace
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
from ApiServices.TemplateService.config import template_api_config
|
from config import api_config
|
||||||
|
|
||||||
from ApiServices.TemplateService.create_app import create_app
|
from ApiServices.TemplateService.create_app import create_app
|
||||||
# from prometheus_fastapi_instrumentator import Instrumentator
|
# from prometheus_fastapi_instrumentator import Instrumentator
|
||||||
|
|
||||||
|
|
||||||
app = create_app() # Create FastAPI application
|
app = create_app() # Create FastAPI application
|
||||||
# Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
# Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Run the application with Uvicorn Server
|
# 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()
|
uvicorn.Server(uvicorn_config).run()
|
||||||
|
|
|
||||||
|
|
@ -61,4 +61,4 @@ class Configs(BaseSettings):
|
||||||
model_config = SettingsConfigDict(env_prefix="API_")
|
model_config = SettingsConfigDict(env_prefix="API_")
|
||||||
|
|
||||||
|
|
||||||
template_api_config = Configs()
|
api_config = Configs()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
from .test_template.route import test_template_route
|
||||||
|
|
||||||
|
|
||||||
def get_routes() -> list[APIRouter]:
|
def get_routes() -> list[APIRouter]:
|
||||||
return []
|
return [test_template_route]
|
||||||
|
|
||||||
|
|
||||||
def get_safe_endpoint_urls() -> list[tuple[str, str]]:
|
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/register", "POST"),
|
||||||
("/auth/login", "POST"),
|
("/auth/login", "POST"),
|
||||||
("/metrics", "GET"),
|
("/metrics", "GET"),
|
||||||
|
("/test/template", "GET"),
|
||||||
|
("/test/template", "POST"),
|
||||||
]
|
]
|
||||||
|
|
@ -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"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
from fastapi import Request, Response
|
from fastapi import Request, Response
|
||||||
|
from ApiServices.TemplateService.endpoints.routes import get_safe_endpoint_urls
|
||||||
|
|
||||||
def get_safe_endpoint_urls() -> list:
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
async def token_middleware(request: Request, call_next):
|
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])
|
base_url = "/".join(request.url.path.split("/")[:3])
|
||||||
safe_endpoints = [_[0] for _ in get_safe_endpoint_urls()]
|
safe_endpoints = [_[0] for _ in get_safe_endpoint_urls()]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ from typing import Any, Dict
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.routing import APIRoute
|
from fastapi.routing import APIRoute
|
||||||
from fastapi.openapi.utils import get_openapi
|
from fastapi.openapi.utils import get_openapi
|
||||||
|
|
||||||
from ApiServices.TemplateService.config import template_api_config
|
from ApiServices.TemplateService.config import template_api_config
|
||||||
|
from ApiServices.TemplateService.endpoints.routes import get_safe_endpoint_urls
|
||||||
|
|
||||||
|
|
||||||
class OpenAPISchemaCreator:
|
class OpenAPISchemaCreator:
|
||||||
|
|
@ -18,8 +20,11 @@ class OpenAPISchemaCreator:
|
||||||
app: FastAPI application instance
|
app: FastAPI application instance
|
||||||
"""
|
"""
|
||||||
self.app = app
|
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.
|
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]:
|
def create_schema(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Create the complete OpenAPI schema.
|
Create the complete OpenAPI schema.
|
||||||
|
|
@ -46,7 +75,7 @@ class OpenAPISchemaCreator:
|
||||||
openapi_schema = get_openapi(
|
openapi_schema = get_openapi(
|
||||||
title=template_api_config.TITLE,
|
title=template_api_config.TITLE,
|
||||||
description=template_api_config.DESCRIPTION,
|
description=template_api_config.DESCRIPTION,
|
||||||
version=template_api_config,
|
version=template_api_config.VERSION,
|
||||||
routes=self.app.routes,
|
routes=self.app.routes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -56,7 +85,7 @@ class OpenAPISchemaCreator:
|
||||||
|
|
||||||
openapi_schema["components"][
|
openapi_schema["components"][
|
||||||
"securitySchemes"
|
"securitySchemes"
|
||||||
] = self._create_security_schemes()
|
] = self.create_security_schemes()
|
||||||
|
|
||||||
# Configure route security and responses
|
# Configure route security and responses
|
||||||
for route in self.app.routes:
|
for route in self.app.routes:
|
||||||
|
|
|
||||||
|
|
@ -29,19 +29,19 @@ def example_get_json_iterator() -> None:
|
||||||
"""Example of using the JSON iterator for large datasets."""
|
"""Example of using the JSON iterator for large datasets."""
|
||||||
keys = ["user", "profile", "*"]
|
keys = ["user", "profile", "*"]
|
||||||
for row in RedisActions.get_json_iterator(list_keys=keys):
|
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:
|
def example_delete_key() -> None:
|
||||||
# """Example of deleting a specific key."""
|
"""Example of deleting a specific key."""
|
||||||
# key = "user:profile:123"
|
key = "user:profile:123"
|
||||||
# result = RedisActions.delete_key(key)
|
result = RedisActions.delete_key(key)
|
||||||
# print("Delete specific key:", result)
|
print("Delete specific key:", result)
|
||||||
#
|
|
||||||
# def example_delete() -> None:
|
def example_delete() -> None:
|
||||||
# """Example of deleting multiple keys matching a pattern."""
|
"""Example of deleting multiple keys matching a pattern."""
|
||||||
# keys = ["user", "profile", "*"]
|
keys = ["user", "profile", "*"]
|
||||||
# result = RedisActions.delete(list_keys=keys)
|
result = RedisActions.delete(list_keys=keys)
|
||||||
# print("Delete multiple keys:", result)
|
print("Delete multiple keys:", result)
|
||||||
|
|
||||||
def example_refresh_ttl() -> None:
|
def example_refresh_ttl() -> None:
|
||||||
"""Example of refreshing TTL for a key."""
|
"""Example of refreshing TTL for a key."""
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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",
|
||||||
|
# ------------------------------------------------
|
||||||
|
]
|
||||||
|
|
@ -574,5 +574,3 @@ class AccountRecords(CrudCollection):
|
||||||
# )
|
# )
|
||||||
# print("is all dues_type", payment_dict["dues_type"], paid_value)
|
# print("is all dues_type", payment_dict["dues_type"], paid_value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()),
|
||||||
|
)
|
||||||
|
|
@ -625,3 +625,4 @@ class BuildPersonProviding(CrudCollection):
|
||||||
),
|
),
|
||||||
{"comment": "People providing services for building"},
|
{"comment": "People providing services for building"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -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"},
|
||||||
|
)
|
||||||
|
|
@ -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"},
|
||||||
|
)
|
||||||
|
|
@ -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"},)
|
||||||
|
|
@ -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"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -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,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -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"
|
||||||
|
)
|
||||||
|
|
@ -28,3 +28,4 @@ API_REFRESHER_TOKEN_LENGTH=144
|
||||||
API_EMAIL_HOST=10.10.2.36
|
API_EMAIL_HOST=10.10.2.36
|
||||||
API_DATETIME_FORMAT=YYYY-MM-DD HH:mm:ss Z
|
API_DATETIME_FORMAT=YYYY-MM-DD HH:mm:ss Z
|
||||||
API_FORGOT_LINK=https://www.evyos.com.tr/password/create?tokenUrl=
|
API_FORGOT_LINK=https://www.evyos.com.tr/password/create?tokenUrl=
|
||||||
|
API_VERSION=0.1.001
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
services:
|
services:
|
||||||
|
|
||||||
mongo_service:
|
mongo_service:
|
||||||
container_name: mongo_service
|
container_name: mongo_service
|
||||||
image: "bitnami/mongodb:latest"
|
image: "bitnami/mongodb:latest"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue