Compare commits

...

35 Commits

Author SHA1 Message Date
4d7a6e6ec0 web service tenant first try 2025-05-07 11:41:08 +03:00
aee9d59750 updated all systems 2025-05-06 17:50:24 +03:00
bc43471259 updated client-frontend additions 2025-05-06 17:48:13 +03:00
e0ae1ee80a appender events and applications are updated 2025-05-06 12:03:58 +03:00
dd707b2463 tested appender service to events 2025-05-04 21:24:29 +03:00
0cde34a9bc updated appenders service 2025-05-04 00:21:38 +03:00
01f3e82a54 updated service binders updated 2025-05-03 23:35:03 +03:00
ac8c3fe1c3 updated management service bind 2025-05-03 18:38:50 +03:00
c6b1a2b1e8 updated managment index 2025-05-03 15:24:41 +03:00
734dc59e38 updated mdenu 2025-05-03 15:13:44 +03:00
71c808a5c3 updated components common header layouts 2025-05-03 13:51:02 +03:00
1ce28ec5f0 updated Api Defaults 2025-05-02 20:46:04 +03:00
1920c2a25d updated Identity and managment service 2025-05-01 15:25:15 +03:00
e815251123 event and service sendpoints added 2025-04-30 18:19:31 +03:00
36e63960f8 updated lang change and FormDisplay Components 2025-04-30 14:30:22 +03:00
f2cc7a69b5 components stablized 2025-04-30 00:44:13 +03:00
0052c92974 Card Component implemented 2025-04-29 20:44:39 +03:00
113e43c7d7 updated initilazer 2025-04-29 16:36:42 +03:00
2d418644bb updated pagination commit to carry 2025-04-28 13:19:01 +03:00
ac344773c5 added application page 2025-04-28 02:30:06 +03:00
346b132f4c updated Bank service routine email sender and wag managment application page completed 2025-04-27 21:01:06 +03:00
090567ade8 managment frontend initiated 2025-04-27 14:12:49 +03:00
ba784c40e4 routine crontab service tested and completed added to Readme.md 2025-04-25 16:07:17 +03:00
a886c2f28c updated Dockerfile 2025-04-25 16:01:46 +03:00
f4e43306c1 updated Dockerfile 2025-04-25 15:52:06 +03:00
c553975e82 updated Dockerfile 2025-04-25 15:46:14 +03:00
0bdc0d287e updated Dockerfile 2025-04-25 15:31:22 +03:00
7efd6f8941 updated Dockerfile 2025-04-25 15:22:20 +03:00
9f0c42e57a updated mail Dockerfile with env variables 2025-04-25 15:03:47 +03:00
b9825bb8e8 updated mail config 2025-04-25 14:49:20 +03:00
0bd8ddce4d updated email service 2025-04-24 17:41:14 +03:00
9511f81bc0 created design pattern 2025-04-23 12:26:15 +03:00
e5f88f2eb4 black shift 2025-04-22 11:10:29 +03:00
d7f1da8de8 identity service completed 2025-04-22 01:20:15 +03:00
9069ba0754 updated event and router stacks 2025-04-22 00:57:06 +03:00
462 changed files with 25210 additions and 2599 deletions

View File

@@ -0,0 +1,56 @@
from fastapi import Header, Request, Response
from pydantic import BaseModel
from ApiDefaults.config import api_config
class CommonHeaders(BaseModel):
language: str | None = None
domain: str | None = None
timezone: str | None = None
token: str | None = None
request: Request | None = None
response: Response | None = None
operation_id: str | None = None
model_config = {
"arbitrary_types_allowed": True
}
@classmethod
def as_dependency(
cls,
request: Request,
response: Response,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),
tz: str = Header(None, alias="timezone"),
):
token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None)
# Extract operation_id from the route
operation_id = None
if hasattr(request.scope.get("route"), "operation_id"):
operation_id = request.scope.get("route").operation_id
return cls(
language=language,
domain=domain,
timezone=tz,
token=token,
request=request,
response=response,
operation_id=operation_id,
)
def get_headers_dict(self):
"""Convert the headers to a dictionary format used in the application"""
import uuid
return {
"language": self.language or "",
"domain": self.domain or "",
"eys-ext": f"{str(uuid.uuid4())}",
"tz": self.timezone or "GMT+3",
"token": self.token,
}

View File

@@ -0,0 +1,133 @@
from typing import Optional, Type
from pydantic import BaseModel
class EventCluster:
"""
EventCluster
"""
def __repr__(self):
return f"EventCluster(name={self.name})"
def __init__(self, endpoint_uu_id: str, name: str):
self.endpoint_uu_id = endpoint_uu_id
self.name = name
self.events: list["Event"] = []
def add_event(self, event: "Event"):
"""
Add an event to the cluster
"""
if event.key not in [e.key for e in self.events]:
self.events.append(event)
def get_event(self, event_key: str):
"""
Get an event by its key
"""
for event in self.events:
if event.key == event_key:
return event
return None
def set_events_to_database(self):
from Schemas import Events, EndpointRestriction
with Events.new_session() as db_session:
if to_save_endpoint := EndpointRestriction.filter_one(
EndpointRestriction.operation_uu_id == self.endpoint_uu_id,
db=db_session,
).data:
for event in self.events:
event_dict_to_save = dict(
function_code=event.key,
function_class=event.name,
description=event.description,
endpoint_code=self.endpoint_uu_id,
endpoint_id=to_save_endpoint.id,
endpoint_uu_id=str(to_save_endpoint.uu_id),
is_confirmed=True,
db=db_session,
)
event_found = Events.filter_one(
Events.function_code == event_dict_to_save["function_code"],
db=db_session,
).data
if event_found:
event_found.update(**event_dict_to_save)
event_found.save(db=db_session)
else:
event_to_save_database = Events.find_or_create(
**event_dict_to_save,
include_args=[
Events.function_code,
Events.function_class,
Events.endpoint_code,
Events.endpoint_uu_id,
]
)
if event_to_save_database.meta_data.created:
print(f"UUID: {event_to_save_database.uu_id} event is saved to {to_save_endpoint.uu_id}")
event_to_save_database.save(db=db_session)
def match_event(self, event_key: str) -> "Event":
"""
Match an event by its key
"""
if event := self.get_event(event_key=event_key):
return event
raise ValueError("Event key not found")
class Event:
def __init__(
self,
name: str,
key: str,
request_validator: Optional[Type[BaseModel]] = None,
response_validator: Optional[Type[BaseModel]] = None,
description: str = "",
):
self.name = name
self.key = key
self.request_validator = request_validator
self.response_validator = response_validator
self.description = description
def event_callable(self):
"""
Example callable method
"""
print(self.name)
return {}
class RouterCluster:
"""
RouterCluster
"""
def __repr__(self):
return f"RouterCluster(name={self.name})"
def __init__(self, name: str):
self.name = name
self.event_clusters: dict[str, EventCluster] = {}
def set_event_cluster(self, event_cluster: EventCluster):
"""
Add an event cluster to the set
"""
print("Setting event cluster:", event_cluster.name)
if event_cluster.name not in self.event_clusters:
self.event_clusters[event_cluster.name] = event_cluster
def get_event_cluster(self, event_cluster_name: str) -> EventCluster:
"""
Get an event cluster by its name
"""
if event_cluster_name not in self.event_clusters:
raise ValueError("Event cluster not found")
return self.event_clusters[event_cluster_name]

View File

@@ -23,17 +23,24 @@ class RouteRegisterController:
for route_method in [
method.lower() for method in getattr(route, "methods")
]:
restriction = EndpointRestriction.find_or_create(
add_or_update_dict = dict(
endpoint_method=route_method,
endpoint_name=route_path,
endpoint_desc=route_summary.replace("_", " "),
endpoint_function=route_summary,
operation_uu_id=operation_id, # UUID of the endpoint
operation_uu_id=operation_id,
is_confirmed=True,
db=db_session,
)
if restriction.meta_data.created:
restriction.save(db=db_session)
endpoint_restriction_found = EndpointRestriction.filter_one_system(
EndpointRestriction.operation_uu_id == operation_id, db=db_session,
).data
if endpoint_restriction_found:
endpoint_restriction_found.update(**add_or_update_dict, db=db_session)
endpoint_restriction_found.save(db=db_session)
else:
restriction = EndpointRestriction.find_or_create(**add_or_update_dict, db=db_session)
if restriction.meta_data.created:
restriction.save(db=db_session)
def register_routes(self):
for router in self.router_list:

View File

@@ -1,11 +1,11 @@
from fastapi import Request, status
from fastapi.responses import JSONResponse
from ApiServices.IdentityService.endpoints.routes import get_safe_endpoint_urls
from ApiServices.IdentityService.config import api_config
from ApiDefaults.config import api_config
from Endpoints.routes import get_safe_endpoint_urls
async def token_middleware(request: Request, call_next):
base_url = request.url.path
safe_endpoints = [_[0] for _ in get_safe_endpoint_urls()]
if base_url in safe_endpoints:

View File

@@ -1,7 +1,7 @@
import uvicorn
from config import api_config
from create_app import create_app
from ApiDefaults.config import api_config
from ApiDefaults.create_app import create_app
# from prometheus_fastapi_instrumentator import Instrumentator

View File

@@ -22,7 +22,7 @@ class Configs(BaseSettings):
EMAIL_HOST: str = ""
DATETIME_FORMAT: str = ""
FORGOT_LINK: str = ""
ALLOW_ORIGINS: list = ["http://localhost:3000"]
ALLOW_ORIGINS: list = ["http://localhost:3000", "http://localhost:3001"]
VERSION: str = "0.1.001"
DESCRIPTION: str = ""

View File

@@ -1,24 +1,42 @@
from ApiControllers.abstracts.event_clusters import RouterCluster, EventCluster
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import RedirectResponse
from endpoints.routes import get_routes
from open_api_creator import create_openapi_schema
from middlewares.token_middleware import token_middleware
from initializer.create_route import RouteRegisterController
from config import api_config
cluster_is_set = False
def create_events_if_any_cluster_set():
import events
import Events
for event_str in events.__all__:
if to_set_events := getattr(events, event_str, None):
to_set_events.set_events_to_database()
global cluster_is_set
if not Events.__all__ or cluster_is_set:
return
router_cluster_stack: list[RouterCluster] = [
getattr(Events, e, None) for e in Events.__all__
]
for router_cluster in router_cluster_stack:
event_cluster_stack: list[EventCluster] = list(
router_cluster.event_clusters.values()
)
for event_cluster in event_cluster_stack:
try:
event_cluster.set_events_to_database()
except Exception as e:
print(f"Error creating event cluster: {e}")
cluster_is_set = True
def create_app():
from ApiDefaults.open_api_creator import create_openapi_schema
from ApiDefaults.config import api_config
from ApiControllers.middlewares.token_middleware import token_middleware
from ApiControllers.initializer.create_route import RouteRegisterController
from Endpoints.routes import get_routes
application = FastAPI(**api_config.api_info)
# application.mount(
@@ -44,6 +62,7 @@ def create_app():
route_register = RouteRegisterController(app=application, router_list=get_routes())
application = route_register.register_routes()
create_events_if_any_cluster_set()
application.openapi = lambda _=application: create_openapi_schema(_)
return application

View File

@@ -3,8 +3,8 @@ from fastapi import FastAPI
from fastapi.routing import APIRoute
from fastapi.openapi.utils import get_openapi
from config import api_config as template_api_config
from endpoints.routes import get_safe_endpoint_urls
from ApiDefaults.config import api_config as template_api_config
from Endpoints.routes import get_safe_endpoint_urls
class OpenAPISchemaCreator:

View File

@@ -22,7 +22,7 @@ class Configs(BaseSettings):
EMAIL_HOST: str = ""
DATETIME_FORMAT: str = ""
FORGOT_LINK: str = ""
ALLOW_ORIGINS: list = ["http://localhost:3000"]
ALLOW_ORIGINS: list = ["http://localhost:3000", "http://localhost:3001"]
VERSION: str = "0.1.001"
DESCRIPTION: str = ""

View File

@@ -304,7 +304,9 @@ def authentication_token_check_post(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
headers=headers,
)
if AuthHandlers.LoginHandler.authentication_check_token_valid(access_token=token):
if AuthHandlers.LoginHandler.authentication_check_token_valid(
domain=domain, access_token=token
):
return JSONResponse(
content={"message": "MSG_0001"},
status_code=status.HTTP_202_ACCEPTED,
@@ -438,7 +440,7 @@ def authentication_page_valid(
summary="Lists all sites that are available for user",
description="Lists all sites that are available for user",
)
def authentication_page_valid(
def authentication_get_all_sites_list(
request: Request,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),

View File

@@ -171,8 +171,20 @@ class LoginHandler:
access_key=data.access_key, db_session=db_session
)
other_domains_list, main_domain = [], ""
with mongo_handler.collection(
f"{str(found_user.related_company)}*Domain"
) as collection:
result = collection.find_one({"user_uu_id": str(found_user.uu_id)})
if not result:
raise ValueError("EYS_00087")
other_domains_list = result.get("other_domains_list", [])
main_domain = result.get("main_domain", None)
if domain not in other_domains_list or not main_domain:
raise ValueError("EYS_00088")
if not user_handler.check_password_valid(
domain=domain or "",
domain=main_domain,
id_=str(found_user.uu_id),
password=data.password,
password_hashed=found_user.hash_password,
@@ -233,6 +245,7 @@ class LoginHandler:
person_id=found_user.person_id,
person_uu_id=str(person.uu_id),
request=dict(request.headers),
domain_list=other_domains_list,
companies_uu_id_list=companies_uu_id_list,
companies_id_list=companies_id_list,
duty_uu_id_list=duty_uu_id_list,
@@ -286,8 +299,20 @@ class LoginHandler:
found_user = user_handler.check_user_exists(
access_key=data.access_key, db_session=db_session
)
other_domains_list, main_domain = [], ""
with mongo_handler.collection(
f"{str(found_user.related_company)}*Domain"
) as collection:
result = collection.find_one({"user_uu_id": str(found_user.uu_id)})
if not result:
raise ValueError("EYS_00087")
other_domains_list = result.get("other_domains_list", [])
main_domain = result.get("main_domain", None)
if domain not in other_domains_list or not main_domain:
raise ValueError("EYS_00088")
if not user_handler.check_password_valid(
domain=domain,
domain=main_domain,
id_=str(found_user.uu_id),
password=data.password,
password_hashed=found_user.hash_password,
@@ -343,6 +368,7 @@ class LoginHandler:
user_id=found_user.id,
person_id=person.id,
person_uu_id=str(person.uu_id),
domain_list=other_domains_list,
request=dict(request.headers),
available_occupants=occupants_selection_dict,
).model_dump()
@@ -606,10 +632,17 @@ class LoginHandler:
)
@classmethod
def authentication_check_token_valid(cls, access_token: str) -> bool:
def authentication_check_token_valid(cls, domain, access_token: str) -> bool:
redis_handler = RedisHandlers()
if redis_handler.get_object_from_redis(access_token=access_token):
return True
if auth_token := redis_handler.get_object_from_redis(access_token=access_token):
if auth_token.is_employee:
if domain not in auth_token.domain_list:
raise ValueError("EYS_00112")
return True
elif auth_token.is_occupant:
if domain not in auth_token.domain_list:
raise ValueError("EYS_00113")
return True
return False

View File

@@ -5,6 +5,7 @@ from ..config import api_config
async def token_middleware(request: Request, call_next):
print("Token Middleware", dict(request.headers))
base_url = request.url.path
safe_endpoints = [_[0] for _ in get_safe_endpoint_urls()]
if base_url in safe_endpoints:

View File

@@ -35,6 +35,7 @@ class ApplicationToken(BaseModel):
person_uu_id: str
request: Optional[dict] = None # Request Info of Client
domain_list: Optional[list[str]] = None
expires_at: Optional[float] = None # Expiry timestamp

View File

@@ -0,0 +1,29 @@
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 /ApiControllers /ApiControllers
COPY /ApiDefaults /ApiDefaults
COPY /Controllers /Controllers
COPY /Schemas /Schemas
COPY /ApiServices/BuildingService/Endpoints /ApiDefaults/Endpoints
COPY /ApiServices/BuildingService/Events /ApiDefaults/Events
COPY /ApiServices/BuildingService/Validations /ApiDefaults/Validations
# 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", "ApiDefaults/app.py"]

View File

@@ -0,0 +1,70 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
from Events.area.cluster import BuildAreaRouterCluster
area_route = APIRouter(prefix="/building/area", tags=["Building Area"])
@area_route.post(
path="/list",
description="List building area endpoint",
operation_id="f2831efc-5493-448c-bcf6-4d52d744ba7e",
)
def area_list_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List building area endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildAreaRouterCluster.get_event_cluster("BuildAreaList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@area_route.post(
path="/create",
description="Create building area endpoint",
operation_id="66e8b310-7a5d-41f4-977c-ee5f3b0603da",
)
def area_create_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create building area endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildAreaRouterCluster.get_event_cluster("BuildAreaCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@area_route.post(
path="/update",
description="Update building area endpoint",
operation_id="d7769899-156d-49ff-85f4-06e3faa23e30",
)
def area_update_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update building area endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildAreaRouterCluster.get_event_cluster("BuildAreaUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,70 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
from Events.building.cluster import BuildRouterCluster
building_route = APIRouter(prefix="/building", tags=["Building"])
@building_route.post(
path="/list",
description="List buildings endpoint",
operation_id="72003d1f-79cc-43c3-9150-3a94f318186e",
)
def building_list_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List buildings endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildRouterCluster.get_event_cluster("BuildList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@building_route.post(
path="/create",
description="Create buildings endpoint",
operation_id="13b86c9c-702b-411f-acb9-9ff50ef86507",
)
def building_create_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create buildings endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildRouterCluster.get_event_cluster("BuildCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@building_route.post(
path="/update",
description="Update buildings endpoint",
operation_id="b09fb6fd-a6c9-4c03-8637-9af0570a84e8",
)
def building_update_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update buildings endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildRouterCluster.get_event_cluster("BuildUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,29 @@
from fastapi import APIRouter
def get_routes() -> list[APIRouter]:
from .building.route import building_route
from .area.route import area_route
from .sites.route import sites_route
from .parts.route import parts_route
from .spaces.route import spaces_route
from .type.route import build_types_route
return [
building_route,
area_route,
sites_route,
parts_route,
spaces_route,
build_types_route,
]
def get_safe_endpoint_urls() -> list[tuple[str, str]]:
return [
("/", "GET"),
("/docs", "GET"),
("/redoc", "GET"),
("/openapi.json", "GET"),
("/metrics", "GET"),
]

View File

@@ -0,0 +1,70 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
from Events.sites.cluster import BuildSitesRouterCluster
sites_route = APIRouter(prefix="/building/sites", tags=["Build Sites"])
@sites_route.post(
path="/list",
description="List build sites endpoint",
operation_id="b64a2479-4160-43bf-9676-cd762a48bf62",
)
def sites_list_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List build sites endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildSitesRouterCluster.get_event_cluster("BuildSitesList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@sites_route.post(
path="/create",
description="Create build sites endpoint",
operation_id="e63dab4b-d446-430c-ac7d-0cb47a66390c",
)
def sites_create_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create build sites endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildSitesRouterCluster.get_event_cluster("BuildSitesCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@sites_route.post(
path="/update",
description="Update build sites endpoint",
operation_id="34ec902c-5ebe-41f6-8294-dfe634d47d98",
)
def sites_update_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update build sites endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildSitesRouterCluster.get_event_cluster("BuildSitesUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,76 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
from Events.spaces.cluster import BuildLivingSpaceRouterCluster
spaces_route = APIRouter(prefix="/building/spaces", tags=["Build Spaces"])
@spaces_route.post(
path="/list",
description="List build spaces endpoint",
operation_id="9d072fd3-d727-4f71-bf0c-fd74e25ba507",
)
def spaces_list_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List build spaces endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildLivingSpaceRouterCluster.get_event_cluster(
"BuildLivingSpaceList"
)
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@spaces_route.post(
path="/create",
description="Create build spaces endpoint",
operation_id="4520cfb7-ed45-44d2-a706-e2a8be777419",
)
def spaces_create_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create build spaces endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildLivingSpaceRouterCluster.get_event_cluster(
"BuildLivingSpaceCreate"
)
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@spaces_route.post(
path="/update",
description="Update build spaces endpoint",
operation_id="d8c90f64-0a4c-4a7c-a685-0e1894cbe1c4",
)
def spaces_update_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update build spaces endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildLivingSpaceRouterCluster.get_event_cluster(
"BuildLivingSpaceUpdate"
)
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,70 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
from Events.type.cluster import BuildTypeRouterCluster
build_types_route = APIRouter(prefix="/building/types", tags=["Build Types"])
@build_types_route.post(
path="/list",
description="List build types endpoint",
operation_id="916d2e02-ee83-4099-ba02-63e2a3f83ec4",
)
def build_types_list_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List build types endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildTypeRouterCluster.get_event_cluster("BuildTypeList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@build_types_route.post(
path="/create",
description="Create build types endpoint",
operation_id="ae7d9e5d-3933-4613-a686-c887d74b85b3",
)
def build_types_create_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create build types endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildTypeRouterCluster.get_event_cluster("BuildTypeCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@build_types_route.post(
path="/update",
description="Update build types endpoint",
operation_id="0f304075-efb0-4f9d-a3b2-e60eeb4d9a87",
)
def build_types_update_route(
data: dict,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update build types endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = BuildTypeRouterCluster.get_event_cluster("BuildTypeUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,15 @@
from .building.cluster import BuildRouterCluster
from .area.cluster import BuildAreaRouterCluster
from .parts.cluster import BuildPartsRouterCluster
from .spaces.cluster import BuildLivingSpaceRouterCluster
from .type.cluster import BuildTypeRouterCluster
from .sites.cluster import BuildSitesRouterCluster
__all__ = [
"BuildRouterCluster",
"BuildAreaRouterCluster",
"BuildPartsRouterCluster",
"BuildLivingSpaceRouterCluster",
"BuildTypeRouterCluster",
"BuildSitesRouterCluster",
]

View File

@@ -0,0 +1,26 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
BuildAreaListEvent,
BuildAreaCreateEvent,
BuildAreaUpdateEvent,
)
BuildAreaRouterCluster = RouterCluster(name="BuildAreaRouterCluster")
BuildAreaEventClusterList = EventCluster(
name="BuildAreaList", endpoint_uu_id="cc487a4f-9a45-4072-89c1-a1ad504c79ad"
)
BuildAreaEventClusterCreate = EventCluster(
name="BuildAreaCreate", endpoint_uu_id="bdd58d68-3a7c-4150-9f5b-e322db35b804"
)
BuildAreaEventClusterUpdate = EventCluster(
name="BuildAreaUpdate", endpoint_uu_id="cad0c4e2-36e3-4f80-9ad2-b06bf8cd8d1c"
)
BuildAreaEventClusterList.add_event(BuildAreaListEvent)
BuildAreaEventClusterCreate.add_event(BuildAreaCreateEvent)
BuildAreaEventClusterUpdate.add_event(BuildAreaUpdateEvent)
BuildAreaRouterCluster.set_event_cluster(BuildAreaEventClusterList)
BuildAreaRouterCluster.set_event_cluster(BuildAreaEventClusterCreate)
BuildAreaRouterCluster.set_event_cluster(BuildAreaEventClusterUpdate)

View File

@@ -0,0 +1,96 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import BuildArea
# List endpoint
BuildAreaListEvent = Event(
name="build_area_list",
key="306e6e11-21da-4fbb-b3d6-3a5179ecfe71",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="List events of build area endpoint",
)
# Create endpoint
BuildAreaCreateEvent = Event(
name="build_area_create",
key="aa173f0f-7a97-4e91-97da-173626dd3257",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Create events of build area endpoint",
)
# Update endpoint
BuildAreaUpdateEvent = Event(
name="build_area_update",
key="358404d0-fb80-4d58-8907-0c04948b364e",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Update events of build area endpoint",
)
def build_area_list_callable(list_options: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
with BuildArea.new_session() as db_session:
if list_options.query:
buildings_list = BuildArea.filter_all(
*BuildArea.convert(list_options.query), db=db_session
)
else:
buildings_list = BuildArea.filter_all(db=db_session)
pagination = Pagination(data=buildings_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(
data=buildings_list,
pagination=pagination,
# response_model="",
).pagination.as_dict
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
BuildAreaListEvent.event_callable = build_area_list_callable
def build_area_create_callable(data: dict):
"""
Example callable method
"""
with BuildArea.new_session() as db_session:
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildAreaCreateEvent.event_callable = build_area_create_callable
def build_area_update_callable(data: dict):
"""
Example callable method
"""
with BuildArea.new_session() as db_session:
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildAreaUpdateEvent.event_callable = build_area_update_callable

View File

@@ -0,0 +1,27 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
BuildingListEvent,
BuildingCreateEvent,
BuildingUpdateEvent,
)
BuildRouterCluster = RouterCluster(name="BuildRouterCluster")
BuildEventClusterList = EventCluster(
name="BuildList", endpoint_uu_id="1a186985-ed2a-434b-af28-22d6773382e9"
)
BuildEventClusterList.add_event(BuildingListEvent)
BuildEventClusterCreate = EventCluster(
name="BuildCreate", endpoint_uu_id="d545c5a9-bbbf-4795-a4de-467db0809a04"
)
BuildEventClusterCreate.add_event(BuildingCreateEvent)
BuildEventClusterUpdate = EventCluster(
name="BuildUpdate", endpoint_uu_id="6166a28e-8da8-4a2c-96c8-0a1651739cf3"
)
BuildEventClusterUpdate.add_event(BuildingUpdateEvent)
BuildRouterCluster.set_event_cluster(BuildEventClusterList)
BuildRouterCluster.set_event_cluster(BuildEventClusterCreate)
BuildRouterCluster.set_event_cluster(BuildEventClusterUpdate)

View File

@@ -0,0 +1,98 @@
from ApiControllers.abstracts.event_clusters import Event
from Validations.building.building.validations import (
REQUESTEWFAZCDMPVZHIWOKZEJBIEUDAFBNXFEEAEGSELVGGCDMWLQPYMRAEEABSRQJUFBIMFEEADXK,
)
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import Build
# List endpoint
BuildingListEvent = Event(
name="building_list",
key="e675d36a-6772-44a8-b153-9a8d55e0f560",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="List events of buildings endpoint",
)
# Create endpoint
BuildingCreateEvent = Event(
name="building_create",
key="d79e3bdc-8f75-41d0-8eeb-dd9893d7ea0d",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Create events of buildings endpoint",
)
# Update endpoint
BuildingUpdateEvent = Event(
name="building_update",
key="45e1bb8c-c521-4013-9e99-d3a58204bc5f",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Update events of buildings endpoint",
)
def building_list_callable(list_options: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
with Build.new_session() as db_session:
if list_options.query:
buildings_list = Build.filter_all(
*Build.convert(list_options.query), db=db_session
)
else:
buildings_list = Build.filter_all(db=db_session)
pagination = Pagination(data=buildings_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(
data=buildings_list,
pagination=pagination,
# response_model="",
).pagination.as_dict
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
request=REQUESTEWFAZCDMPVZHIWOKZEJBIEUDAFBNXFEEAEGSELVGGCDMWLQPYMRAEEABSRQJUFBIMFEEADXK,
).response
BuildingListEvent.event_callable = building_list_callable
def building_create_callable():
"""
Example callable method
"""
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildingCreateEvent.event_callable = building_create_callable
def building_update_callable():
"""
Example callable method
"""
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildingUpdateEvent.event_callable = building_update_callable

View File

@@ -0,0 +1,27 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
BuildSitesListEvent,
BuildSitesCreateEvent,
BuildSitesUpdateEvent,
)
BuildSitesRouterCluster = RouterCluster(name="BuildSitesRouterCluster")
BuildSitesEventClusterList = EventCluster(
name="BuildSitesList", endpoint_uu_id="1159fb39-ad5d-46fb-8b6b-461021a39da3"
)
BuildSitesEventClusterList.add_event(BuildSitesListEvent)
BuildSitesEventClusterCreate = EventCluster(
name="BuildCreate", endpoint_uu_id="bc71d276-fd51-43bb-90f2-6f4245b59d72"
)
BuildSitesEventClusterCreate.add_event(BuildSitesCreateEvent)
BuildSitesEventClusterUpdate = EventCluster(
name="BuildUpdate", endpoint_uu_id="eca87985-3074-44cb-a947-f01e30769019"
)
BuildSitesEventClusterUpdate.add_event(BuildSitesUpdateEvent)
BuildSitesRouterCluster.set_event_cluster(BuildSitesEventClusterList)
BuildSitesRouterCluster.set_event_cluster(BuildSitesEventClusterCreate)
BuildSitesRouterCluster.set_event_cluster(BuildSitesEventClusterUpdate)

View File

@@ -0,0 +1,96 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import BuildSites
# List endpoint
BuildSitesListEvent = Event(
name="build_sites_list",
key="d16c692f-5597-493a-90fe-b2bfe0d1c163",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="List events of build sites endpoint",
)
# Create endpoint
BuildSitesCreateEvent = Event(
name="build_sites_create",
key="8ed0929e-9c96-4e81-b073-e3578ca13f37",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Create events of build sites endpoint",
)
# Update endpoint
BuildSitesUpdateEvent = Event(
name="build_sites_update",
key="ece55fa6-afba-4c34-bd2e-f39a4cdd6b5c",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Update events of build sites endpoint",
)
def build_sites_list_callable(list_options: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
with BuildSites.new_session() as db_session:
if list_options.query:
buildings_list = BuildSites.filter_all(
*BuildSites.convert(list_options.query), db=db_session
)
else:
buildings_list = BuildSites.filter_all(db=db_session)
pagination = Pagination(data=buildings_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(
data=buildings_list,
pagination=pagination,
# response_model="",
).pagination.as_dict
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
BuildSitesListEvent.event_callable = build_sites_list_callable
def build_sites_create_callable(data: dict):
"""
Example callable method
"""
with BuildSites.new_session() as db_session:
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildSitesCreateEvent.event_callable = build_sites_create_callable
def build_sites_update_callable(data: dict):
"""
Example callable method
"""
with BuildSites.new_session() as db_session:
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildSitesUpdateEvent.event_callable = build_sites_update_callable

View File

@@ -0,0 +1,27 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
BuildLivingSpaceListEvent,
BuildLivingSpaceCreateEvent,
BuildLivingSpaceUpdateEvent,
)
BuildLivingSpaceRouterCluster = RouterCluster(name="BuildLivingSpaceRouterCluster")
BuildLivingSpaceEventClusterList = EventCluster(
name="BuildLivingSpaceList", endpoint_uu_id="ad17c019-3050-4c41-ab6f-9ce43290e81a"
)
BuildLivingSpaceEventClusterList.add_event(BuildLivingSpaceListEvent)
BuildLivingSpaceEventClusterCreate = EventCluster(
name="BuildCreate", endpoint_uu_id="ed9a0303-14e2-46fe-bec0-d395c29801ff"
)
BuildLivingSpaceEventClusterCreate.add_event(BuildLivingSpaceCreateEvent)
BuildLivingSpaceEventClusterUpdate = EventCluster(
name="BuildUpdate", endpoint_uu_id="c62bb3dc-03c0-406c-8bbc-0e1f75a6420c"
)
BuildLivingSpaceEventClusterUpdate.add_event(BuildLivingSpaceUpdateEvent)
BuildLivingSpaceRouterCluster.set_event_cluster(BuildLivingSpaceEventClusterList)
BuildLivingSpaceRouterCluster.set_event_cluster(BuildLivingSpaceEventClusterCreate)
BuildLivingSpaceRouterCluster.set_event_cluster(BuildLivingSpaceEventClusterUpdate)

View File

@@ -0,0 +1,96 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import BuildLivingSpace
# List endpoint
BuildLivingSpaceListEvent = Event(
name="build_living_space_list",
key="d16c692f-5597-493a-90fe-b2bfe0d1c163",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="List events of build living spaces endpoint",
)
# Create endpoint
BuildLivingSpaceCreateEvent = Event(
name="build_living_space_create",
key="8ed0929e-9c96-4e81-b073-e3578ca13f37",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Create events of build living spaces endpoint",
)
# Update endpoint
BuildLivingSpaceUpdateEvent = Event(
name="build_living_space_update",
key="ece55fa6-afba-4c34-bd2e-f39a4cdd6b5c",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Update events of build living spaces endpoint",
)
def build_living_space_list_callable(list_options: PaginateOnly):
"""
List callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
with BuildLivingSpace.new_session() as db_session:
if list_options.query:
buildings_list = BuildLivingSpace.filter_all(
*BuildLivingSpace.convert(list_options.query), db=db_session
)
else:
buildings_list = BuildLivingSpace.filter_all(db=db_session)
pagination = Pagination(data=buildings_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(
data=buildings_list,
pagination=pagination,
# response_model="",
).pagination.as_dict
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
BuildLivingSpaceListEvent.event_callable = build_living_space_list_callable
def build_living_space_create_callable(data: dict):
"""
Create callable method
"""
with BuildLivingSpace.new_session() as db_session:
return {
"completed": True,
"message": "Build living space created",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildLivingSpaceCreateEvent.event_callable = build_living_space_create_callable
def build_living_space_update_callable(data: dict):
"""
Update callable method
"""
with BuildLivingSpace.new_session() as db_session:
return {
"completed": True,
"message": "Build living space updated",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildLivingSpaceUpdateEvent.event_callable = build_living_space_update_callable

View File

@@ -0,0 +1,27 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
BuildTypeListEvent,
BuildTypeCreateEvent,
BuildTypeUpdateEvent,
)
BuildTypeRouterCluster = RouterCluster(name="BuildTypeRouterCluster")
BuildTypeEventClusterList = EventCluster(
name="BuildTypeList", endpoint_uu_id="14f076c2-b118-4cfb-b679-9f2168a2658c"
)
BuildTypeEventClusterList.add_event(BuildTypeListEvent)
BuildTypeEventClusterCreate = EventCluster(
name="BuildCreate", endpoint_uu_id="4c90c4cf-8873-479a-a56b-d12f276efa9d"
)
BuildTypeEventClusterCreate.add_event(BuildTypeCreateEvent)
BuildTypeEventClusterUpdate = EventCluster(
name="BuildUpdate", endpoint_uu_id="cde9db69-6795-4562-802d-540d0b03ceaa"
)
BuildTypeEventClusterUpdate.add_event(BuildTypeUpdateEvent)
BuildTypeRouterCluster.set_event_cluster(BuildTypeEventClusterList)
BuildTypeRouterCluster.set_event_cluster(BuildTypeEventClusterCreate)
BuildTypeRouterCluster.set_event_cluster(BuildTypeEventClusterUpdate)

View File

@@ -0,0 +1,96 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import BuildTypes
# List endpoint
BuildTypeListEvent = Event(
name="build_type_list",
key="e013b43e-3845-4a95-b5b0-409343659c5f",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="List events of build types endpoint",
)
# Create endpoint
BuildTypeCreateEvent = Event(
name="build_type_create",
key="8119a07e-bbb2-4d4c-b529-f923e8cdcc60",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Create events of build types endpoint",
)
# Update endpoint
BuildTypeUpdateEvent = Event(
name="build_type_update",
key="6b7b89d5-6406-4614-aba4-c942f0c081ac",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Update events of build types endpoint",
)
def build_type_list_callable(list_options: PaginateOnly):
"""
List callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
with BuildTypes.new_session() as db_session:
if list_options.query:
buildings_list = BuildTypes.filter_all(
*BuildTypes.convert(list_options.query), db=db_session
)
else:
buildings_list = BuildTypes.filter_all(db=db_session)
pagination = Pagination(data=buildings_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(
data=buildings_list,
pagination=pagination,
# response_model="",
).pagination.as_dict
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
BuildTypeListEvent.event_callable = build_type_list_callable
def build_type_create_callable(data: dict):
"""
Create callable method
"""
with BuildTypes.new_session() as db_session:
return {
"completed": True,
"message": "Build type created",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildTypeCreateEvent.event_callable = build_type_create_callable
def build_type_update_callable(data: dict):
"""
Update callable method
"""
with BuildTypes.new_session() as db_session:
return {
"completed": True,
"message": "Build type updated",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
BuildTypeUpdateEvent.event_callable = build_type_update_callable

View File

@@ -0,0 +1,37 @@
from pydantic import BaseModel
from typing import Optional
class REQUESTEWFAZCDMPVZHIWOKZEJBIEUDAFBNXFEEAEGSELVGGCDMWLQPYMRAEEABSRQJUFBIMFEEADXK(
BaseModel
):
gov_address_code: str
build_name: str
build_no: str
max_floor: int
underground_floor: int
build_date: str
decision_period_date: str
tax_no: str
lift_count: int
heating_system: bool
cooling_system: bool
hot_water_system: bool
block_service_man_count: int
security_service_man_count: int
garage_count: int
management_room_id: int
site_uu_id: str
address_uu_id: str
class REQUESTOCARDAJXLDANCXQAJWDBDIWXHUAEKQNUOSBZOCWXDAFGLAAVRBSADHUBDXAREUSESYGNGKBR(
BaseModel
):
pass
class REQUESTAEKUDAILSFMCCLOERBHBFRCIKFCSNCBOSENCAEOIDACPRFZCCWGEDBHBFBMZBFCJHCBVKEFC(
BaseModel
):
pass

View File

@@ -1,12 +1,12 @@
from Controllers.Postgres.database import get_db
from Schemas import Users, Employees, BuildLivingSpace
from Schemas import Users, Employees, BuildLivingSpace, Services
from init_service_to_events import init_service_to_event_matches_for_super_user
from init_applications import (
init_applications_for_super_user,
init_applications_for_general_manager,
init_applications_for_build_manager,
init_applications_for_owner,
init_applications_for_tenant,
# init_applications_for_general_manager,
# init_applications_for_build_manager,
# init_applications_for_owner,
# init_applications_for_tenant,
)
@@ -16,62 +16,59 @@ if __name__ == "__main__":
Set Events to service | Set Service to employee
"""
with get_db() as db_session:
if super_man := Users.filter_one(
Users.email == "karatay.berkay.sup@evyos.com.tr", db=db_session
).data:
super_employee = Employees.filter_one(
Employees.people_id == super_man.person_id, db=db_session
).data
service_super_user = Services.filter_one(Services.service_code == "SRE-SUE", db=db_session).data
user_super_user = Users.filter_one(Users.email == "karatay.berkay.sup@evyos.com.tr", db=db_session).data
employee_super_user = Employees.filter_one(Employees.people_id == user_super_user.person_id, db=db_session).data
if service_super_user and user_super_user and employee_super_user:
init_service_to_event_matches_for_super_user(
super_user=super_employee, db_session=db_session
service_match=service_super_user, employee_match=employee_super_user, db_session=db_session
)
init_applications_for_super_user(
super_user=super_employee, db_session=db_session
service_match=service_super_user, employee_match=employee_super_user, db_session=db_session
)
with get_db() as db_session:
print("Createing GM")
if gen_man := Users.filter_one(
Users.email == "example.general@evyos.com.tr", db=db_session
).data:
gen_man_employee = Employees.filter_one(
Employees.people_id == gen_man.person_id, db=db_session
).data
print("General Manager : ", gen_man_employee)
init_applications_for_general_manager(
super_user=gen_man_employee, db_session=db_session
)
# with get_db() as db_session:
# print("Createing GM")
# if gen_man := Users.filter_one(
# Users.email == "example.general@evyos.com.tr", db=db_session
# ).data:
# gen_man_employee = Employees.filter_one(
# Employees.people_id == gen_man.person_id, db=db_session
# ).data
# print("General Manager : ", gen_man_employee)
# init_applications_for_general_manager(
# super_user=gen_man_employee, db_session=db_session
# )
with get_db() as db_session:
if build_man := Users.filter_one(
Users.email == "example.build.manager@gmail.com", db=db_session
).data:
build_man_employee = BuildLivingSpace.filter_one(
BuildLivingSpace.person_id == build_man.person_id, db=db_session
).data
init_applications_for_build_manager(
super_user=build_man_employee, db_session=db_session
)
# with get_db() as db_session:
# if build_man := Users.filter_one(
# Users.email == "example.build.manager@gmail.com", db=db_session
# ).data:
# build_man_employee = BuildLivingSpace.filter_one(
# BuildLivingSpace.person_id == build_man.person_id, db=db_session
# ).data
# init_applications_for_build_manager(
# super_user=build_man_employee, db_session=db_session
# )
with get_db() as db_session:
if own_flt := Users.filter_one(
Users.email == "example.owner@gmail.com", db=db_session
).data:
own_flt_employee = BuildLivingSpace.filter_one(
BuildLivingSpace.person_id == own_flt.person_id, db=db_session
).data
init_applications_for_owner(
super_user=own_flt_employee, db_session=db_session
)
# with get_db() as db_session:
# if own_flt := Users.filter_one(
# Users.email == "example.owner@gmail.com", db=db_session
# ).data:
# own_flt_employee = BuildLivingSpace.filter_one(
# BuildLivingSpace.person_id == own_flt.person_id, db=db_session
# ).data
# init_applications_for_owner(
# super_user=own_flt_employee, db_session=db_session
# )
with get_db() as db_session:
if ten_flt := Users.filter_one(
Users.email == "example.tenant@gmail.com", db=db_session
).data:
ten_flt_employee = BuildLivingSpace.filter_one(
BuildLivingSpace.person_id == ten_flt.person_id, db=db_session
).data
init_applications_for_tenant(
super_user=ten_flt_employee, db_session=db_session
)
# with get_db() as db_session:
# if ten_flt := Users.filter_one(
# Users.email == "example.tenant@gmail.com", db=db_session
# ).data:
# ten_flt_employee = BuildLivingSpace.filter_one(
# BuildLivingSpace.person_id == ten_flt.person_id, db=db_session
# ).data
# init_applications_for_tenant(
# super_user=ten_flt_employee, db_session=db_session
# )

View File

@@ -4,223 +4,193 @@ from Schemas import (
Application2Occupant,
Employees,
BuildLivingSpace,
Services,
Service2Application,
)
def init_applications_for_super_user(super_user: Employees, db_session=None) -> None:
list_of_created_apps = [
dict(
name="Dashboard1",
application_code="app000001",
site_url="/dashboard",
application_type="info",
description="Dashboard Page",
),
dict(
name="Individual",
application_code="app000003",
site_url="/individual",
application_type="Dash",
description="Individual Page for people",
),
dict(
name="User",
application_code="app000004",
site_url="/user",
application_type="Dash",
description="Individual Page for user",
),
dict(
name="Build",
application_code="app000005",
site_url="/build",
application_type="Dash",
description="Individual Page for build",
),
dict(
name="BuildParts",
application_code="app000006",
site_url="/build/parts",
application_type="Dash",
description="Individual Page for build parts",
),
dict(
name="BuildArea",
application_code="app000007",
site_url="/build/area",
application_type="Dash",
description="Individual Page for build area",
),
dict(
name="ManagementAccounting",
application_code="app000008",
site_url="/management/accounting",
application_type="Dash",
description="Individual Page for management accounting",
),
dict(
name="ManagementBudget",
application_code="app000009",
site_url="/management/budget",
application_type="Dash",
description="Individual Page for management accounting2",
),
dict(
name="ManagementMeetingClose",
application_code="app000010",
site_url="/annual/meeting/close",
application_type="Dash",
description="Individual Page for management accounting3",
),
dict(
name="EmergencyMeeting",
application_code="app000011",
site_url="/emergency/meeting",
application_type="Dash",
description="Individual Page for management accounting4",
),
dict(
name="EmergencyMeetingClose",
application_code="app000012",
site_url="/emergency/meeting/close",
application_type="Dash",
description="Individual Page for management accounting5",
),
dict(
name="MeetingParticipation",
application_code="app000013",
site_url="/meeting/participation",
application_type="Dash",
description="Individual Page for management accounting6",
),
]
for list_of_created_app in list_of_created_apps:
created_page = Applications.find_or_create(
**list_of_created_app,
def init_applications_for_super_user(service_match: Services, employee_match: Employees, db_session=None) -> None:
list_of_all_events = Applications.filter_all(db=db_session).data
Service2Application.filter_all(db=db_session).query.delete()
Service2Application.save(db=db_session)
for list_of_event_code in list_of_all_events:
service_to_event_found = Service2Application.filter_one_system(
Service2Application.application_id == list_of_event_code.id,
Service2Application.service_id == service_match.id,
db=db_session,
)
if service_to_event_found.data:
service_to_event_found.destroy(db=db_session)
print(
f"UUID: {service_to_event_found.uu_id} application is deleted from {service_match.service_description}"
)
employee_added_application = Service2Application.find_or_create(
service_id=service_match.id,
service_uu_id=str(service_match.uu_id),
application_id=list_of_event_code.id,
application_uu_id=str(list_of_event_code.uu_id),
application_code=list_of_event_code.application_code,
site_url=list_of_event_code.site_url,
is_confirmed=True,
)
if created_page.meta_data.created:
created_page.save(db=db_session)
application_employee_created = Application2Employee.find_or_create(
employee_id=super_user.id,
employee_uu_id=str(super_user.uu_id),
site_url=created_page.site_url,
application_code=created_page.application_code,
application_id=created_page.id,
application_uu_id=str(created_page.uu_id),
is_confirmed=True,
active=True,
db=db_session,
)
if application_employee_created.meta_data.created:
application_employee_created.save(db=db_session)
if employee_added_application.meta_data.created:
employee_added_application.save(db=db_session)
print(
f"UUID: {employee_added_application.uu_id} application is saved to {service_match.service_description}"
)
def init_applications_for_general_manager(
super_user: Employees, db_session=None
) -> None:
list_of_created_apps = [
dict(
name="Dashboard1",
application_code="app000001",
site_url="/dashboard",
application_type="info",
description="Dashboard Page",
),
dict(
name="ManagementAccounting",
application_code="app000008",
site_url="/management/accounting",
application_type="Dash",
description="Individual Page for management accounting",
),
]
for list_of_created_app in list_of_created_apps:
created_page = Applications.find_or_create(
**list_of_created_app,
db=db_session,
employee_added_service = Application2Employee.find_or_create(
service_id=service_match.id,
service_uu_id=str(service_match.uu_id),
employee_id=employee_match.id,
employee_uu_id=str(employee_match.uu_id),
is_confirmed=True,
db=db_session,
)
if employee_added_service.meta_data.created:
employee_added_service.save(db=db_session)
print(
f"UUID: {employee_added_service.uu_id} service is saved to {employee_match.uu_id}"
)
print("Application : ", created_page)
if created_page.meta_data.created:
created_page.save(db=db_session)
application_employee_created = Application2Employee.find_or_create(
employee_id=super_user.id,
employee_uu_id=str(super_user.uu_id),
site_url=created_page.site_url,
application_code=created_page.application_code,
application_id=created_page.id,
application_uu_id=str(created_page.uu_id),
is_confirmed=True,
db=db_session,
)
print("Application Employee : ", application_employee_created)
if application_employee_created.meta_data.created:
application_employee_created.save(db=db_session)
def init_applications_for_build_manager(
super_user: BuildLivingSpace, db_session=None
) -> None:
list_of_created_apps = []
# def init_applications_for_general_manager(
# super_user: Employees, db_session=None
# ) -> None:
# list_of_created_apps = Applications.filter_all_system(db=db_session).data
# if not list_of_created_apps:
# raise Exception("No applications found")
# for list_of_created_app in list_of_created_apps:
# application_employee_created = Application2Employee.find_or_create(
# employee_id=super_user.id,
# employee_uu_id=str(super_user.uu_id),
# site_url=list_of_created_app.site_url,
# application_code=list_of_created_app.application_code,
# application_id=list_of_created_app.id,
# application_uu_id=str(list_of_created_app.uu_id),
# is_confirmed=True,
# db=db_session,
# )
# if application_employee_created.meta_data.created:
# application_employee_created.save(db=db_session)
def init_applications_for_owner(super_user: BuildLivingSpace, db_session=None) -> None:
pass
# def init_applications_for_build_manager(
# super_user: BuildLivingSpace, db_session=None
# ) -> None:
# list_of_created_apps = Applications.filter_all_system(db=db_session).data
# if not list_of_created_apps:
# raise Exception("No applications found")
# for list_of_created_app in list_of_created_apps:
# application_employee_created = Application2Employee.find_or_create(
# employee_id=super_user.id,
# employee_uu_id=str(super_user.uu_id),
# site_url=list_of_created_app.site_url,
# application_code=list_of_created_app.application_code,
# application_id=list_of_created_app.id,
# application_uu_id=str(list_of_created_app.uu_id),
# is_confirmed=True,
# db=db_session,
# )
# if application_employee_created.meta_data.created:
# application_employee_created.save(db=db_session)
def init_applications_for_tenant(super_user: BuildLivingSpace, db_session=None) -> None:
list_of_created_apps = [
dict(
name="Dashboard1",
application_code="app000001",
site_url="/dashboard",
application_type="info",
description="Dashboard Page",
),
dict(
name="TenantSendMessageToBuildManager",
application_code="app000022",
site_url="/tenant/messageToBM",
application_type="Dash",
description="Individual Page for tenant send message to build manager",
),
dict(
name="TenantSendMessageToOwner",
application_code="app000018",
site_url="/tenant/messageToOwner",
application_type="Dash",
description="Individual Page for tenant send message to owner",
),
dict(
name="TenantAccountView",
application_code="app000019",
site_url="/tenant/accounting",
application_type="Dash",
description="Individual Page for tenant account view",
),
# def init_applications_for_owner(super_user: BuildLivingSpace, db_session=None) -> None:
# list_of_created_apps = Applications.filter_all_system(db=db_session).data
# if not list_of_created_apps:
# raise Exception("No applications found")
]
# for list_of_created_app in list_of_created_apps:
# application_employee_created = Application2Employee.find_or_create(
# employee_id=super_user.id,
# employee_uu_id=str(super_user.uu_id),
# site_url=list_of_created_app.site_url,
# application_code=list_of_created_app.application_code,
# application_id=list_of_created_app.id,
# application_uu_id=str(list_of_created_app.uu_id),
# is_confirmed=True,
# db=db_session,
# )
# if application_employee_created.meta_data.created:
# application_employee_created.save(db=db_session)
for list_of_created_app in list_of_created_apps:
created_page = Applications.find_or_create(
**list_of_created_app,
db=db_session,
is_confirmed=True,
)
if created_page.meta_data.created:
created_page.save(db=db_session)
application_occupant_created = Application2Occupant.find_or_create(
build_living_space_id=super_user.id,
build_living_space_uu_id=str(super_user.uu_id),
site_url=created_page.site_url,
application_code=created_page.application_code,
application_id=created_page.id,
application_uu_id=str(created_page.uu_id),
is_confirmed=True,
db=db_session,
)
if application_occupant_created.meta_data.created:
application_occupant_created.save(db=db_session)
# def init_applications_for_tenant(super_user: BuildLivingSpace, db_session=None) -> None:
# list_of_created_apps = Applications.filter_all_system(db=db_session).data
# if not list_of_created_apps:
# raise Exception("No applications found")
# for list_of_created_app in list_of_created_apps:
# application_employee_created = Application2Employee.find_or_create(
# employee_id=super_user.id,
# employee_uu_id=str(super_user.uu_id),
# site_url=list_of_created_app.site_url,
# application_code=list_of_created_app.application_code,
# application_id=list_of_created_app.id,
# application_uu_id=str(list_of_created_app.uu_id),
# is_confirmed=True,
# db=db_session,
# )
# if application_employee_created.meta_data.created:
# application_employee_created.save(db=db_session)
# list_of_created_apps = [
# dict(
# name="Dashboard1",
# application_code="app000001",
# site_url="/dashboard",
# application_type="info",
# description="Dashboard Page",
# ),
# dict(
# name="TenantSendMessageToBuildManager",
# application_code="app000022",
# site_url="/tenant/messageToBM",
# application_type="Dash",
# description="Individual Page for tenant send message to build manager",
# ),
# dict(
# name="TenantSendMessageToOwner",
# application_code="app000018",
# site_url="/tenant/messageToOwner",
# application_type="Dash",
# description="Individual Page for tenant send message to owner",
# ),
# dict(
# name="TenantAccountView",
# application_code="app000019",
# site_url="/tenant/accounting",
# application_type="Dash",
# description="Individual Page for tenant account view",
# ),
# ]
# for list_of_created_app in list_of_created_apps:
# created_page = Applications.find_or_create(
# **list_of_created_app,
# db=db_session,
# is_confirmed=True,
# )
# if created_page.meta_data.created:
# created_page.save(db=db_session)
# application_occupant_created = Application2Occupant.find_or_create(
# build_living_space_id=super_user.id,
# build_living_space_uu_id=str(super_user.uu_id),
# site_url=created_page.site_url,
# application_code=created_page.application_code,
# application_id=created_page.id,
# application_uu_id=str(created_page.uu_id),
# is_confirmed=True,
# db=db_session,
# )
# if application_occupant_created.meta_data.created:
# application_occupant_created.save(db=db_session)

View File

@@ -11,14 +11,23 @@ from Schemas import (
)
def init_service_to_event_matches_for_super_user(super_user, db_session=None) -> None:
service_match = Services.filter_one(
Services.service_name == "Super User",
db=db_session,
).data
def init_service_to_event_matches_for_super_user(service_match: Services, employee_match: Employees, db_session=None) -> None:
list_of_all_events = Events.filter_all(db=db_session).data
Service2Events.filter_all(db=db_session).query.delete()
Service2Events.save(db=db_session)
for list_of_event_code in list_of_all_events:
created_service = Service2Events.find_or_create(
service_to_event_found = Service2Events.filter_one_system(
Service2Events.event_id == list_of_event_code.id,
Service2Events.service_id == service_match.id,
db=db_session,
)
if service_to_event_found.data:
service_to_event_found.destroy(db=db_session)
print(
f"UUID: {service_to_event_found.uu_id} event is deleted from {service_match.service_description}"
)
added_service = Service2Events.find_or_create(
service_id=service_match.id,
service_uu_id=str(service_match.uu_id),
event_id=list_of_event_code.id,
@@ -27,22 +36,22 @@ def init_service_to_event_matches_for_super_user(super_user, db_session=None) ->
active=True,
db=db_session,
)
if created_service.meta_data.created:
created_service.save(db=db_session)
if added_service.meta_data.created:
added_service.save(db=db_session)
print(
f"UUID: {created_service.uu_id} event is saved to {service_match.uu_id}"
f"UUID: {added_service.uu_id} event is saved to {service_match.service_description}"
)
employee_added_service = Event2Employee.find_or_create(
event_service_id=service_match.id,
event_service_uu_id=str(service_match.uu_id),
employee_id=super_user.id,
employee_uu_id=str(super_user.uu_id),
is_confirmed=True,
db=db_session,
employee_added_service = Event2Employee.find_or_create(
event_service_id=service_match.id,
event_service_uu_id=str(service_match.uu_id),
employee_id=employee_match.id,
employee_uu_id=str(employee_match.uu_id),
is_confirmed=True,
db=db_session,
)
if employee_added_service.meta_data.created:
employee_added_service.save(db=db_session)
print(
f"UUID: {employee_added_service.uu_id} event is saved to employee {employee_match.uu_id}"
)
if employee_added_service.meta_data.created:
employee_added_service.save(db=db_session)
print(
f"UUID: {employee_added_service.uu_id} event is saved to {super_user.uu_id}"
)

View File

@@ -3,24 +3,27 @@ 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
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
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/IdentityService /ApiServices/IdentityService
COPY /ApiControllers /ApiControllers
COPY /ApiDefaults /ApiDefaults
COPY /Controllers /Controllers
COPY /Schemas /Schemas
COPY /ApiServices/IdentityService/Endpoints /ApiDefaults/Endpoints
COPY /ApiServices/IdentityService/Events /ApiDefaults/Events
COPY /ApiServices/IdentityService/Validations /ApiDefaults/Validations
# 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/IdentityService/app.py"]
CMD ["poetry", "run", "python", "ApiDefaults/app.py"]

View File

@@ -0,0 +1,67 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
from Events.people.cluster import PeopleRouterCluster
people_route = APIRouter(prefix="/people", tags=["People"])
@people_route.post(
path="/list",
description="List people endpoint",
operation_id="f102db46-031a-43e4-966a-dae6896f985b",
)
def people_route_list(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List people endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = PeopleRouterCluster.get_event_cluster("PeopleList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@people_route.post(
path="/create",
description="Create people endpoint",
operation_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6",
)
def people_route_create(
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create people endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = PeopleRouterCluster.get_event_cluster("PeopleCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable()
@people_route.post(
path="/update",
description="Update people endpoint",
operation_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89",
)
def people_route_update(
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update people endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = PeopleRouterCluster.get_event_cluster("PeopleUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable()

View File

@@ -1,14 +1,11 @@
from fastapi import APIRouter
# from .user.route import user_route
from .people.route import people_route
def get_routes() -> list[APIRouter]:
return [
# user_route,
people_route
]
from .people.route import people_route
from .user.route import user_route
return [user_route, people_route]
def get_safe_endpoint_urls() -> list[tuple[str, str]]:

View File

@@ -0,0 +1,72 @@
import uuid
from fastapi import APIRouter, Header
from typing import Any
from ApiDefaults.config import api_config
from Events.user.cluster import UserRouterCluster
from ApiControllers.providers.token_provider import TokenProvider
from ApiControllers.abstracts.default_validations import CommonHeaders
from Controllers.Postgres.pagination import PaginateOnly
user_route = APIRouter(prefix="/user", tags=["User"])
@user_route.post(
path="/list",
description="List users endpoint",
operation_id="1aca3094-fe80-4e0f-a460-1a506419082a",
)
def user_list_route(
data: PaginateOnly,
headers: CommonHeaders,
):
"""
List users endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = UserRouterCluster.get_event_cluster("UserList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@user_route.post(
path="/create",
description="Create users endpoint",
operation_id="9686211f-4260-485d-8076-186c22c053aa",
)
def user_create_route(
data: Any,
headers: CommonHeaders,
):
"""
Create users endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = UserRouterCluster.get_event_cluster("UserCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@user_route.post(
path="/update",
description="Update users endpoint",
operation_id="268e887b-5ff5-4f99-b1be-7e127e28a198",
)
def user_update_route(
data: Any,
headers: CommonHeaders,
):
"""
Update users endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = UserRouterCluster.get_event_cluster("UserUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,8 @@
from .people.cluster import PeopleRouterCluster
from .user.cluster import UserRouterCluster
__all__ = [
"PeopleRouterCluster",
"UserRouterCluster",
]

View File

@@ -0,0 +1,25 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
SupersPeopleCreateEvent,
SupersPeopleUpdateEvent,
SupersPeopleListEvent,
)
PeopleRouterCluster = RouterCluster(name="PeopleRouterCluster")
PeopleEventClusterList = EventCluster(
name="PeopleList", endpoint_uu_id="f102db46-031a-43e4-966a-dae6896f985b"
)
PeopleEventClusterList.add_event(SupersPeopleListEvent)
PeopleEventClusterCreate = EventCluster(
name="PeopleCreate", endpoint_uu_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6"
)
PeopleEventClusterCreate.add_event(SupersPeopleCreateEvent)
PeopleEventClusterUpdate = EventCluster(
name="PeopleUpdate", endpoint_uu_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89"
)
PeopleEventClusterUpdate.add_event(SupersPeopleUpdateEvent)
PeopleRouterCluster.set_event_cluster(PeopleEventClusterList)
PeopleRouterCluster.set_event_cluster(PeopleEventClusterCreate)
PeopleRouterCluster.set_event_cluster(PeopleEventClusterUpdate)

View File

@@ -1,23 +1,45 @@
from ApiServices.IdentityService.initializer.event_clusters import EventCluster, Event
from ApiServices.IdentityService.validations.people.validations import (
from ApiControllers.abstracts.event_clusters import Event
from Validations.people.validations import (
REQUESTAWMXNTKMGPPOJWRCTZUBADNFLQDBDYVQAORFAVCSXUUHEBQHCEPCSKFBADBODFDBPYKOVINV,
)
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.pagination import (
ListOptions,
Pagination,
PaginationResult,
PaginateOnly,
)
from Controllers.Postgres.response import EndpointResponse
from Schemas.identity.identity import People
from Schemas import People
# Create endpoint
supers_people_create = Event(
name="supers_people_list",
SupersPeopleCreateEvent = Event(
name="supers_people_create",
key="ec4c2404-a61b-46c7-bbdf-ce3357e6cf41",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Create events of people endpoint",
description="Super Users Create events of people endpoint",
)
# Update endpoint
SupersPeopleUpdateEvent = Event(
name="supers_people_update",
key="91e77de4-9f29-4309-b121-4aad256d440c",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Update events of people endpoint",
)
# List endpoint
SupersPeopleListEvent = Event(
name="supers_people_list",
key="6828d280-e587-400d-a622-c318277386c3",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List events of people endpoint",
)
def supers_people_create_callable(list_options):
def supers_people_create_callable():
"""
Example callable method
"""
@@ -32,21 +54,7 @@ def supers_people_create_callable(list_options):
}
supers_people_create.event_callable = supers_people_create_callable
people_event_cluster_create = EventCluster(
endpoint_uu_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6"
)
people_event_cluster_create.add_event([supers_people_create])
# Update endpoint
supers_people_update = Event(
name="supers_people_update",
key="91e77de4-9f29-4309-b121-4aad256d440c",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Update events of people endpoint",
)
SupersPeopleCreateEvent.event_callable = supers_people_create_callable
def supers_people_update_callable():
@@ -64,33 +72,15 @@ def supers_people_update_callable():
}
supers_people_update.event_callable = supers_people_update_callable
people_event_cluster_update = EventCluster(
endpoint_uu_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89"
)
people_event_cluster_update.add_event([supers_people_update])
SupersPeopleUpdateEvent.event_callable = supers_people_update_callable
# List endpoint
supers_people_list = Event(
name="supers_people_list",
key="6828d280-e587-400d-a622-c318277386c3",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="List events of people endpoint",
)
def supers_people_list_callable(list_options: PaginateOnly):
def supers_people_list_callable(data: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
list_options = PaginateOnly(**data.model_dump())
with People.new_session() as db_session:
People.pre_query = People.filter_all(
People.firstname.ilike("%B%"), db=db_session
).query
if list_options.query:
people_list = People.filter_all(
*People.convert(list_options.query), db=db_session
@@ -110,19 +100,4 @@ def supers_people_list_callable(list_options: PaginateOnly):
).response
supers_people_list.event_callable = supers_people_list_callable
people_event_cluster_list = EventCluster(
endpoint_uu_id="f102db46-031a-43e4-966a-dae6896f985b"
)
people_event_cluster_list.add_event([supers_people_list])
class PeopleCluster:
"""
People Clusters
"""
PeopleListCluster = people_event_cluster_list
PeopleCreateCluster = people_event_cluster_create
PeopleUpdateCluster = people_event_cluster_update
SupersPeopleListEvent.event_callable = supers_people_list_callable

View File

@@ -0,0 +1,27 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
SuperUsersListEvent,
SuperUsersCreateEvent,
SuperUsersUpdateEvent,
)
UserRouterCluster = RouterCluster(name="UserRouterCluster")
UserEventClusterList = EventCluster(
name="UserList", endpoint_uu_id="1aca3094-fe80-4e0f-a460-1a506419082a"
)
UserEventClusterList.add_event(SuperUsersListEvent)
UserEventClusterCreate = EventCluster(
name="UserCreate", endpoint_uu_id="9686211f-4260-485d-8076-186c22c053aa"
)
UserEventClusterCreate.add_event(SuperUsersCreateEvent)
UserEventClusterUpdate = EventCluster(
name="UserUpdate", endpoint_uu_id="268e887b-5ff5-4f99-b1be-7e127e28a198"
)
UserEventClusterUpdate.add_event(SuperUsersUpdateEvent)
UserRouterCluster.set_event_cluster(UserEventClusterList)
UserRouterCluster.set_event_cluster(UserEventClusterCreate)
UserRouterCluster.set_event_cluster(UserEventClusterUpdate)

View File

@@ -0,0 +1,94 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import Users
# List endpoint
SuperUsersListEvent = Event(
name="supers_users_list",
key="341b394f-9f11-4abb-99e7-4b27fa6bf012",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super User List events of users endpoint",
)
# Create endpoint
SuperUsersCreateEvent = Event(
name="supers_users_create",
key="4e7e189e-e015-4ff8-902d-60138cbc77a6",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super User Create events of users endpoint",
)
# Update endpoint
SuperUsersUpdateEvent = Event(
name="supers_users_update",
key="efa4aa4a-d414-4391-91ee-97eb617b7755",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super User Update events of users endpoint",
)
def supers_users_list_callable(list_options: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
with Users.new_session() as db_session:
if list_options.query:
users_list = Users.filter_all(
*Users.convert(list_options.query), db=db_session
)
else:
users_list = Users.filter_all(db=db_session)
pagination = Pagination(data=users_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(
data=users_list,
pagination=pagination,
# response_model="",
).pagination.as_dict
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
SuperUsersListEvent.event_callable = supers_users_list_callable
def supers_users_create_callable():
"""
Example callable method
"""
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
SuperUsersCreateEvent.event_callable = supers_users_create_callable
def supers_users_update_callable():
"""
Example callable method
"""
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
SuperUsersUpdateEvent.event_callable = supers_users_update_callable

View File

@@ -0,0 +1,26 @@
from pydantic import BaseModel
from typing import Optional
class ListOptions(BaseModel):
"""
Query for list option abilities
"""
page: Optional[int] = 1
size: Optional[int] = 10
order_field: Optional[str] = "id"
order_type: Optional[str] = "asc"
# include_joins: Optional[list] = None
query: Optional[dict] = None
class PaginateOnly(BaseModel):
"""
Query for list option abilities
"""
page: Optional[int] = 1
size: Optional[int] = 10
order_field: Optional[str] = "id"
order_type: Optional[str] = "asc"

View File

@@ -0,0 +1,24 @@
from pydantic import BaseModel
class REQUESTAWMXNTKMGPPOJWRCTZUBADNFLQDBDYVQAORFAVCSXUUHEBQHCEPCSKFBADBODFDBPYKOVINV(
BaseModel
):
uu_id: str
created_at: str
updated_at: str
person_tag: str
expiry_starts: str
expiry_ends: str
firstname: str
middle_name: str
surname: str
birth_date: str
birth_place: str
sex_code: str
country_code: str
tax_no: str
active: bool
deleted: bool
is_confirmed: bool
is_notification_send: bool

View File

@@ -1,123 +0,0 @@
import uuid
from fastapi import APIRouter, Request, Response, Header
from ApiServices.IdentityService.config import api_config
from ApiServices.IdentityService.events.people.event import PeopleCluster
from ApiServices.IdentityService.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly
people_route = APIRouter(prefix="/people", tags=["People"])
@people_route.post(
path="/list",
description="Test Template Route",
operation_id="f102db46-031a-43e4-966a-dae6896f985b",
)
def people_route_list(
request: Request,
response: Response,
data: PaginateOnly,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),
tz: str = Header(None, alias="timezone"),
):
"""
Test Template Route
"""
endpoint_code = "f102db46-031a-43e4-966a-dae6896f985b"
token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None)
headers = {
"language": language or "",
"domain": domain or "",
"eys-ext": f"{str(uuid.uuid4())}",
"tz": tz or "GMT+3",
"token": token,
}
token_object = TokenProvider.get_dict_from_redis(token=token)
event_key = TokenProvider.retrieve_event_codes(
endpoint_code=endpoint_code, token=token_object
)
event_cluster_matched = PeopleCluster.PeopleListCluster.match_event(
event_key=event_key
)
response.headers["X-Header"] = "Test Header GET"
if runner_callable := event_cluster_matched.event_callable(list_options=data):
return runner_callable
raise ValueError("Event key not found or multiple matches found")
@people_route.post(
path="/create",
description="Test Template Route with Post Method",
operation_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6",
)
def test_template_post(
request: Request,
response: Response,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),
tz: str = Header(None, alias="timezone"),
):
"""
Test Template Route with Post Method
"""
endpoint_code = "eb465fde-337f-4b81-94cf-28c6d4f2b1b6"
token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None)
headers = {
"language": language or "",
"domain": domain or "",
"eys-ext": f"{str(uuid.uuid4())}",
"tz": tz or "GMT+3",
"token": token,
}
token_object = TokenProvider.get_dict_from_redis(token=token)
event_key = TokenProvider.retrieve_event_codes(
endpoint_code=endpoint_code, token=token_object
)
event_cluster_matched = PeopleCluster.PeopleCreateCluster.match_event(
event_key=event_key
)
response.headers["X-Header"] = "Test Header POST"
if runner_callable := event_cluster_matched.event_callable():
return runner_callable
raise ValueError("Event key not found or multiple matches found")
@people_route.post(
path="/update",
description="Test Template Route with Post Method",
operation_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89",
)
def test_template_post(
request: Request,
response: Response,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),
tz: str = Header(None, alias="timezone"),
):
"""
Test Template Route with Post Method
"""
token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None)
endpoint_code = "c9e5ba69-6915-43f5-8f9c-a5c2aa865b89"
headers = {
"language": language or "",
"domain": domain or "",
"eys-ext": f"{str(uuid.uuid4())}",
"tz": tz or "GMT+3",
"token": token,
}
token_object = TokenProvider.get_dict_from_redis(token=token)
event_key = TokenProvider.retrieve_event_codes(
endpoint_code=endpoint_code, token=token_object
)
event_cluster_matched = PeopleCluster.PeopleUpdateCluster.match_event(
event_key=event_key
)
response.headers["X-Header"] = "Test Header POST"
if runner_callable := event_cluster_matched.event_callable():
return runner_callable
raise ValueError("Event key not found or multiple matches found")

View File

@@ -1,90 +0,0 @@
import uuid
from fastapi import APIRouter, Request, Response, Header
from ApiServices.IdentityService.config import api_config
from ApiServices.IdentityService.events.user.event import supers_users_list
user_route = APIRouter(prefix="/user", tags=["User"])
@user_route.post(
path="/list",
description="Test Template Route",
operation_id="5bc09312-d3f2-4f47-baba-17c928706da8",
)
def test_template(
request: Request,
response: Response,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),
tz: str = Header(None, alias="timezone"),
):
"""
Test Template Route
"""
event_code = "bb20c8c6-a289-4cab-9da7-34ca8a36c8e5"
token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None)
headers = {
"language": language or "",
"domain": domain or "",
"eys-ext": f"{str(uuid.uuid4())}",
"tz": tz or "GMT+3",
"token": token,
}
event_cluster_matched = supers_users_list.match_event(
event_keys=[
"3f510dcf-9f84-4eb9-b919-f582f30adab1",
"9f403034-deba-4e1f-b43e-b25d3c808d39",
"b8ec6e64-286a-4f60-8554-7a3865454944",
]
)
response.headers["X-Header"] = "Test Header GET"
if runner_callable := event_cluster_matched.example_callable():
return runner_callable
raise ValueError("Event key not found or multiple matches found")
@user_route.post(
path="/create",
description="Test Template Route with Post Method",
operation_id="08d4b572-1584-47bb-aa42-8d068e5514e7",
)
def test_template_post(request: Request, response: Response):
"""
Test Template Route with Post Method
"""
event_cluster_matched = supers_users_list.match_event(
event_keys=[
"3f510dcf-9f84-4eb9-b919-f582f30adab1",
"9f403034-deba-4e1f-b43e-b25d3c808d39",
"b8ec6e64-286a-4f60-8554-7a3865454944",
]
)
response.headers["X-Header"] = "Test Header POST"
if runner_callable := event_cluster_matched.example_callable():
return runner_callable
raise ValueError("Event key not found or multiple matches found")
@user_route.post(
path="/update",
description="Test Template Route with Post Method",
operation_id="b641236a-928d-4f19-a1d2-5edf611d1e56",
)
def test_template_post(request: Request, response: Response):
"""
Test Template Route with Post Method
"""
event_cluster_matched = supers_users_list.match_event(
event_keys=[
"3f510dcf-9f84-4eb9-b919-f582f30adab1",
"9f403034-deba-4e1f-b43e-b25d3c808d39",
"b8ec6e64-286a-4f60-8554-7a3865454944",
]
)
response.headers["X-Header"] = "Test Header POST"
if runner_callable := event_cluster_matched.example_callable():
return runner_callable
raise ValueError("Event key not found or multiple matches found")

View File

@@ -1,12 +0,0 @@
from .people.event import (
people_event_cluster_list,
people_event_cluster_update,
people_event_cluster_create,
)
__all__ = [
"people_event_cluster_list",
"people_event_cluster_update",
"people_event_cluster_create",
]

View File

@@ -1,33 +0,0 @@
from ApiServices.IdentityService.initializer.event_clusters import EventCluster, Event
supers_users_list = Event(
name="supers_people_list",
key="341b394f-9f11-4abb-99e7-4b27fa6bf012",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Example event description",
)
def supers_people_list_callable():
"""
Example callable method
"""
return {
"completed": True,
"message": "Example callable method 2",
"info": {
"host": "example_host",
"user_agent": "example_user_agent",
},
}
supers_users_list.event_callable = supers_people_list_callable
people_event_cluster_list = EventCluster(
endpoint_uu_id="f102db46-031a-43e4-966a-dae6896f985b"
)
people_event_cluster_list.add_event([supers_users_list])

View File

@@ -1,53 +0,0 @@
from pydantic import BaseModel
"""
"sex_code": "M",
"country_code": "TR",
"created_at": "2025-04-13 10:03:32 +00:00",
"father_name": "Father",
"birth_place": "Ankara",
"updated_credentials_token": null,
"cryp_uu_id": null,
"mother_name": "Mother",
"expiry_starts": "2025-04-13 10:03:32 +00:00",
"confirmed_credentials_token": null,
"surname": "Karatay",
"firstname": "Berkay Super User",
"birth_date": "1990-01-07 00:00:00 +00:00",
"expiry_ends": "2099-12-31 00:00:00 +00:00",
"is_confirmed": true,
"is_email_send": false,
"tax_no": "1231231232",
"person_ref": "",
"active": true,
"deleted": false,
"updated_at": "2025-04-13 10:03:32 +00:00",
"uu_id": "b5b6e68f-a4d0-4d64-aa18-634671cb1299",
"middle_name": "",
"created_credentials_token": null,
"person_tag": "BSU-System",
"is_notification_send": false
"""
class REQUESTAWMXNTKMGPPOJWRCTZUBADNFLQDBDYVQAORFAVCSXUUHEBQHCEPCSKFBADBODFDBPYKOVINV(
BaseModel
):
uu_id: str
created_at: str
updated_at: str
person_tag: str
expiry_starts: str
expiry_ends: str
firstname: str
middle_name: str
surname: str
birth_date: str
birth_place: str
sex_code: str
country_code: str
tax_no: str
active: bool
deleted: bool
is_confirmed: bool
is_notification_send: bool

View File

@@ -9,17 +9,35 @@ from init_services import create_modules_and_services_and_actions
from init_address import create_one_address
from init_occ_defaults import create_occupant_defaults
set_alembic = bool(os.getenv("set_alembic", 0))
set_alembic = bool(int(os.getenv("SET_ALEMBIC"), 0))
if __name__ == "__main__":
print(f"Set alembic: {set_alembic}")
with get_db() as db_session:
if set_alembic:
generate_alembic(session=db_session)
create_one_address(db_session=db_session)
init_api_enums_build_types(db_session=db_session)
create_application_defaults(db_session=db_session)
create_occupant_types_defaults(db_session=db_session)
create_modules_and_services_and_actions(db_session=db_session)
create_occupant_defaults(db_session=db_session)
try:
create_one_address(db_session=db_session)
except Exception as e:
print(f"Error creating address: {e}")
try:
init_api_enums_build_types(db_session=db_session)
except Exception as e:
print(f"Error creating enums: {e}")
try:
create_application_defaults(db_session=db_session)
except Exception as e:
print(f"Error creating application defaults: {e}")
try:
create_occupant_types_defaults(db_session=db_session)
except Exception as e:
print(f"Error creating occupant types defaults: {e}")
try:
create_modules_and_services_and_actions(db_session=db_session)
except Exception as e:
print(f"Error creating modules and services and actions: {e}")
try:
create_occupant_defaults(db_session=db_session)
except Exception as e:
print(f"Error creating occupant defaults: {e}")

View File

@@ -444,14 +444,29 @@ def create_application_defaults(db_session):
f"{str(company_management.uu_id)}*Domain",
)
with mongo_handler.collection(collection_name) as mongo_engine:
mongo_engine.insert_one(
document={
"user_uu_id": str(gen_manager_user.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
existing_record = mongo_engine.find_one(
{"user_uu_id": str(gen_manager_user.uu_id)}
)
if not existing_record:
mongo_engine.insert_one(
document={
"user_uu_id": str(gen_manager_user.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
else:
mongo_engine.update_one(
{"user_uu_id": str(gen_manager_user.uu_id)},
{
"$set": {
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
},
)
app_manager_user = Users.find_or_create(
person_id=app_manager.id,
@@ -472,14 +487,29 @@ def create_application_defaults(db_session):
app_manager_user.password_token = PasswordModule.generate_refresher_token()
with mongo_handler.collection(collection_name) as mongo_engine:
mongo_engine.insert_one(
document={
"user_uu_id": str(app_manager_user.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
existing_record = mongo_engine.find_one(
{"user_uu_id": str(app_manager_user.uu_id)}
)
if not existing_record:
mongo_engine.insert_one(
document={
"user_uu_id": str(app_manager_user.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
else:
mongo_engine.update_one(
{"user_uu_id": str(app_manager_user.uu_id)},
{
"$set": {
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
},
)
sup_manager_employee = Users.find_or_create(
person_id=sup_manager.id,
@@ -502,14 +532,32 @@ def create_application_defaults(db_session):
sup_manager_employee.password_expiry_begins = str(arrow.now())
sup_manager_employee.password_token = PasswordModule.generate_refresher_token()
with mongo_handler.collection(collection_name) as mongo_engine:
mongo_engine.insert_one(
document={
"user_uu_id": str(sup_manager_employee.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
existing_record = mongo_engine.find_one(
{"user_uu_id": str(sup_manager_employee.uu_id)}
)
if not existing_record:
print("insert sup existing record", existing_record)
mongo_engine.insert_one(
document={
"user_uu_id": str(sup_manager_employee.uu_id),
"other_domains_list": [main_domain, "management.com.tr"],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
else:
print("update sup existing record", existing_record)
# Optionally update the existing record if needed
mongo_engine.update_one(
{"user_uu_id": str(sup_manager_employee.uu_id)},
{
"$set": {
"other_domains_list": [main_domain, "management.com.tr"],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
},
)
db_session.commit()
print("All Defaults Create is now completed")

View File

@@ -239,34 +239,75 @@ def create_occupant_defaults(db_session):
user_tenant.password_token = PasswordModule.generate_refresher_token()
with mongo_handler.collection(collection_name) as mongo_engine:
mongo_engine.insert_one(
document={
"user_uu_id": str(user_build_manager.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
existing_record = mongo_engine.find_one(
{"user_uu_id": str(user_build_manager.uu_id)}
)
if not existing_record:
mongo_engine.insert_one(
document={
"user_uu_id": str(user_build_manager.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
else:
mongo_engine.update_one(
{"user_uu_id": str(user_build_manager.uu_id)},
{
"$set": {
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
},
)
with mongo_handler.collection(collection_name) as mongo_engine:
mongo_engine.insert_one(
document={
"user_uu_id": str(user_owner.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
existing_record = mongo_engine.find_one({"user_uu_id": str(user_owner.uu_id)})
if not existing_record:
mongo_engine.insert_one(
document={
"user_uu_id": str(user_owner.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
else:
mongo_engine.update_one(
{"user_uu_id": str(user_owner.uu_id)},
{
"$set": {
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
},
)
with mongo_handler.collection(collection_name) as mongo_engine:
mongo_engine.insert_one(
document={
"user_uu_id": str(user_tenant.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
existing_record = mongo_engine.find_one({"user_uu_id": str(user_tenant.uu_id)})
if not existing_record:
mongo_engine.insert_one(
document={
"user_uu_id": str(user_tenant.uu_id),
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
)
else:
mongo_engine.update_one(
{"user_uu_id": str(user_tenant.uu_id)},
{
"$set": {
"other_domains_list": [main_domain],
"main_domain": main_domain,
"modified_at": arrow.now().timestamp(),
}
},
)
created_build_living_space_prs = BuildLivingSpace.find_or_create(
build_id=created_build.id,

View File

@@ -0,0 +1,29 @@
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 /ApiControllers /ApiControllers
COPY /ApiDefaults /ApiDefaults
COPY /Controllers /Controllers
COPY /Schemas /Schemas
COPY /ApiServices/ManagementService/Endpoints /ApiDefaults/Endpoints
COPY /ApiServices/ManagementService/Events /ApiDefaults/Events
COPY /ApiServices/ManagementService/Validations /ApiDefaults/Validations
# 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", "ApiDefaults/app.py"]

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,197 @@
from fastapi import APIRouter, Depends
from typing import Any
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly, Pagination, PaginationResult
from Controllers.Postgres.response import EndpointResponse, CreateEndpointResponse
from Schemas import Applications
from Validations.application.validations import RequestApplication
from Events.application.cluster import ApplicationRouterCluster
from Validations.application.validations import AddRemoveService
# Create API router
application_route = APIRouter(prefix="/application", tags=["Application Management"])
@application_route.post(
path="/list/all",
description="List all applications endpoint",
operation_id="fe30481d-802c-4490-897f-a4e95310e6bc",
)
def application_list_all_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List all applications with pagination and filtering options
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationListAll")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(list_options=data)
@application_route.post(
path="/list/available",
description="List available applications endpoint",
operation_id="7492bb02-a074-4320-b58c-4bc7d9fba3a6",
)
def application_list_available_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List available applications with pagination and filtering options
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationListAvailable")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(list_options=data)
@application_route.post(
path="/list/appended",
description="List appended applications endpoint",
operation_id="ea7bbd58-da09-407c-a630-c324e0272385",
)
def application_list_appended_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List appended applications with pagination and filtering options
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationListAppended")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(list_options=data)
@application_route.post(
path="/register/service",
description="Register event to service endpoint",
operation_id="92e0870f-f8bb-4879-ba03-c2901cc70ecc",
)
def application_register_service_route(
data: AddRemoveService,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Register event to service
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationRegisterService")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@application_route.post(
path="/unregister/service",
description="Unregister event from service endpoint",
operation_id="7fa1a183-4c99-4746-b675-148f65ad7ba7",
)
def application_unregister_service_route(
data: AddRemoveService,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Unregister event from service
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationUnRegisterService")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@application_route.post(
path="/create",
description="Create application endpoint",
operation_id="5570be78-030a-438e-8674-7e751447608b",
)
def application_create_route(
data: RequestApplication,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Create a new application
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationCreate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@application_route.post(
path="/update/{application_uuid}",
description="Update application endpoint",
operation_id="87cd4515-73dd-4d11-a01f-562e221d973c",
)
def application_update_route(
data: RequestApplication,
application_uuid: str,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Update an existing application
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationUpdate")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data, uu_id=application_uuid)
@application_route.post(
path="/bind/employee",
description="Bind application to employee endpoint",
operation_id="2bab94fa-becb-4d8e-80f1-f4631119a521",
)
def application_bind_employee_route(
data: Any,
headers: CommonHeaders,
):
"""
Bind application to employee endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationBindEmployee")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@application_route.post(
path="/bind/occupant",
description="Bind application to occupant endpoint",
operation_id="fccf1a59-0650-4e5c-ba8d-f389dadce01c",
)
def application_bind_occupant_route(
data: Any,
headers: CommonHeaders,
):
"""
Bind application to occupant endpoint
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ApplicationRouterCluster.get_event_cluster("ApplicationBindOccupant")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,142 @@
from typing import Any
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly, Pagination, PaginationResult
from Controllers.Postgres.response import EndpointResponse
from Validations.service_endpoints.validations import (
Event2Employee,
Event2Occupant,
AddRemoveService,
)
from Events.event_endpoints.cluster import EventsEndpointRouterCluster
# Create API router
event_endpoint_route = APIRouter(prefix="/events", tags=["Event Actions"])
@event_endpoint_route.post(
path="/list/available",
description="List available events endpoint",
operation_id="0659d5e4-671f-466c-a84f-47a1290a6f0d",
)
def event_list_available_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List available events with pagination and filtering options
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = EventsEndpointRouterCluster.get_event_cluster("EventsListAvailable")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(list_options=data)
@event_endpoint_route.post(
path="/list/appended",
description="List appended events endpoint",
operation_id="4d563973-cdcd-44e1-94e0-4262ffb456a1",
)
def event_list_appended_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List events with pagination and filtering options
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = EventsEndpointRouterCluster.get_event_cluster("EventsListAppended")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(list_options=data)
@event_endpoint_route.post(
path="/register/service",
description="Register event to service endpoint",
operation_id="c89a2150-db4d-4a8f-b6ec-9e0f09625f76",
)
def event_register_service_route(
data: AddRemoveService,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Register event to service
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = EventsEndpointRouterCluster.get_event_cluster("EventRegisterService")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@event_endpoint_route.post(
path="/unregister/service",
description="Unregister event from service endpoint",
operation_id="2f16dc9e-de02-449d-9c3f-1a21f87e8794",
)
def event_unregister_service_route(
data: AddRemoveService,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Unregister event from service
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = EventsEndpointRouterCluster.get_event_cluster(
"EventUnregisterService"
)
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@event_endpoint_route.post(
path="/bind/extra/employee",
description="Bind event to employee extra endpoint",
operation_id="58ef3640-04ec-43f9-8f3e-f86be3ce4a24",
)
def event_bind_employee_extra_route(
data: Any,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Bind event to employee extra
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = EventsEndpointRouterCluster.get_event_cluster(
"EventBindEmployeeExtra"
)
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@event_endpoint_route.post(
path="/bind/extra/occupant",
description="Bind event to occupant extra endpoint",
operation_id="7794a550-3073-43e3-b0c5-80128f8d3e4b",
)
def event_bind_occupant_extra_route(
data: Any,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
Bind event to occupant extra
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = EventsEndpointRouterCluster.get_event_cluster(
"EventBindOccupantExtra"
)
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,25 @@
from fastapi import APIRouter
def get_routes() -> list[APIRouter]:
from .application.route import application_route
from .service_endpoints.route import service_endpoint_route
from .service_managements.route import service_management_route
from .event_endpoints.route import event_endpoint_route
return [
application_route,
service_endpoint_route,
service_management_route,
event_endpoint_route,
]
def get_safe_endpoint_urls() -> list[tuple[str, str]]:
return [
("/", "GET"),
("/docs", "GET"),
("/redoc", "GET"),
("/openapi.json", "GET"),
("/metrics", "GET"),
]

View File

@@ -0,0 +1,52 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly, Pagination, PaginationResult
from Controllers.Postgres.response import EndpointResponse
from Events.service_endpoints.cluster import ServiceEndpointRouterCluster
# Create API router
service_endpoint_route = APIRouter(prefix="/service", tags=["Service Actions"])
@service_endpoint_route.post(
path="/list",
description="List services endpoint",
operation_id="f4e4d332-70b1-4121-9fcc-a08850b72aaa",
)
def service_list_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List services with pagination and filtering options
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ServiceEndpointRouterCluster.get_event_cluster("ServiceList")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)
@service_endpoint_route.post(
path="/to/events",
description="List events of a service endpoint given service UUID",
operation_id="7b6b0c6a-e3db-4353-a7df-ea49d2a67f8a",
)
def service_to_events_route(
data: PaginateOnly,
headers: CommonHeaders = Depends(CommonHeaders.as_dependency),
):
"""
List events of a service given service UUID
"""
token_object = TokenProvider.get_dict_from_redis(token=headers.token)
event_founder_dict = dict(endpoint_code=headers.operation_id, token=token_object)
event_key = TokenProvider.retrieve_event_codes(**event_founder_dict)
FoundCluster = ServiceEndpointRouterCluster.get_event_cluster("ServiceToEvents")
event_cluster_matched = FoundCluster.match_event(event_key=event_key)
return event_cluster_matched.event_callable(data=data)

View File

@@ -0,0 +1,26 @@
from fastapi import APIRouter, Depends
from ApiControllers.abstracts.default_validations import CommonHeaders
from ApiControllers.providers.token_provider import TokenProvider
from Controllers.Postgres.pagination import PaginateOnly, Pagination, PaginationResult
from Controllers.Postgres.response import EndpointResponse
from Schemas import (
Services,
Employees,
Event2Employee,
Users,
Events,
Service2Events,
Applications,
Application2Employee,
Application2Occupant,
)
from Validations.application.validations import (
RequestApplication,
)
# Create API router
service_management_route = APIRouter(
prefix="/managements/service", tags=["Service Management"]
)

View File

@@ -0,0 +1,9 @@
from .service_endpoints.cluster import ServiceEndpointRouterCluster
from .event_endpoints.cluster import EventsEndpointRouterCluster
from .application.cluster import ApplicationRouterCluster
__all__ = [
"ServiceEndpointRouterCluster",
"EventsEndpointRouterCluster",
"ApplicationRouterCluster",
]

View File

@@ -0,0 +1,55 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
ApplicationListAllEvent,
ApplicationListAvailableEvent,
ApplicationListAppendedEvent,
ApplicationRegisterServiceEvent,
ApplicationUnRegisterServiceEvent,
ApplicationCreateEvent,
ApplicationUpdateEvent,
)
ApplicationRouterCluster = RouterCluster(name="ApplicationRouterCluster")
ApplicationEventClusterListAll = EventCluster(
name="ApplicationListAll", endpoint_uu_id="fe30481d-802c-4490-897f-a4e95310e6bc"
)
ApplicationEventClusterListAll.add_event(ApplicationListAllEvent)
ApplicationEventClusterListAvailable = EventCluster(
name="ApplicationListAvailable", endpoint_uu_id="7492bb02-a074-4320-b58c-4bc7d9fba3a6"
)
ApplicationEventClusterListAvailable.add_event(ApplicationListAvailableEvent)
ApplicationEventClusterListAppended = EventCluster(
name="ApplicationListAppended", endpoint_uu_id="ea7bbd58-da09-407c-a630-c324e0272385"
)
ApplicationEventClusterListAppended.add_event(ApplicationListAppendedEvent)
ApplicationEventClusterRegisterService = EventCluster(
name="ApplicationRegisterService", endpoint_uu_id="92e0870f-f8bb-4879-ba03-c2901cc70ecc"
)
ApplicationEventClusterRegisterService.add_event(ApplicationRegisterServiceEvent)
ApplicationEventClusterUnregisterService = EventCluster(
name="ApplicationUnRegisterService", endpoint_uu_id="7fa1a183-4c99-4746-b675-148f65ad7ba7"
)
ApplicationEventClusterUnregisterService.add_event(ApplicationUnRegisterServiceEvent)
ApplicationEventClusterCreate = EventCluster(
name="ApplicationCreate", endpoint_uu_id="5570be78-030a-438e-8674-7e751447608b"
)
ApplicationEventClusterCreate.add_event(ApplicationCreateEvent)
ApplicationEventClusterUpdate = EventCluster(
name="ApplicationUpdate", endpoint_uu_id="87cd4515-73dd-4d11-a01f-562e221d973c"
)
ApplicationEventClusterUpdate.add_event(ApplicationUpdateEvent)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterListAvailable)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterListAppended)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterListAll)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterRegisterService)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterUnregisterService)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterCreate)
ApplicationRouterCluster.set_event_cluster(ApplicationEventClusterUpdate)

View File

@@ -0,0 +1,320 @@
from typing import Any
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import (
Applications,
Application2Employee,
Application2Occupant,
Service2Application,
Services,
)
# List all endpoint
ApplicationListAllEvent = Event(
name="application_list_all",
key="1971ce4d-4f59-4aa8-83e2-ca19d7da6d11",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List all applications endpoint",
)
# List available endpoint
ApplicationListAvailableEvent = Event(
name="application_list_available",
key="d8e733f5-b53a-4c36-9082-12579bf9cc4a",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List available applications endpoint",
)
# List appended endpoint
ApplicationListAppendedEvent = Event(
name="application_list_appended",
key="ea7bbd58-da09-407c-a630-c324e0272385",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List appended applications endpoint",
)
# Register application to service endpoint
ApplicationRegisterServiceEvent = Event(
name="application_register_service",
key="47d7cfc8-6004-4442-8357-16ceac5d9d18",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Register application to service endpoint",
)
# Unregister application to service endpoint
ApplicationUnRegisterServiceEvent = Event(
name="application_unregister_service",
key="d228ab26-0b74-440f-8f1f-8f40be5a22f2",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Unregister application to service endpoint",
)
# Create endpoint
ApplicationCreateEvent = Event(
name="application_create",
key="f53ca9aa-5536-4d77-9129-78d67e61db4a",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Create applications endpoint",
)
# Update endpoint
ApplicationUpdateEvent = Event(
name="application_update",
key="0e9a855e-4e69-44b5-8ac2-825daa32840c",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Update applications endpoint",
)
def application_list_all_callable(list_options: PaginateOnly):
list_options = PaginateOnly(**list_options.model_dump())
with Applications.new_session() as db_session:
if list_options.query:
applications_list = Applications.filter_all(*Applications.convert(list_options.query), db=db_session)
else:
applications_list = Applications.filter_all(db=db_session)
pagination = Pagination(data=applications_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(data=applications_list, pagination=pagination)
return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response
ApplicationListAllEvent.event_callable = application_list_all_callable
def application_list_available_callable(list_options: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
service_uu_id = list_options.query.get("service_uu_id__ilike", None)
if not service_uu_id:
return {
"message": "MSG0003-PARAM-MISSING",
"data": list_options.query,
"completed": False,
}
list_options.query.pop("service_uu_id__ilike", None)
list_options.query.pop("service_uu_id", None)
with Applications.new_session() as db_session:
service2applications = Service2Application.filter_all(
*Service2Application.convert({"service_uu_id__ilike": service_uu_id}),
db=db_session,
)
already_events = [
service_to_application.application_id for service_to_application in service2applications.data
]
if list_options.query:
applications_list = Applications.filter_all(
*Applications.convert(list_options.query), Applications.id.not_in(already_events), db=db_session
)
else:
applications_list = Applications.filter_all(Applications.id.not_in(already_events), db=db_session)
pagination = Pagination(data=applications_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(data=applications_list, pagination=pagination)
return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response
ApplicationListAvailableEvent.event_callable = application_list_available_callable
def application_list_appended_callable(list_options: PaginateOnly):
"""
Example callable method
"""
list_options = PaginateOnly(**list_options.model_dump())
service_uu_id = list_options.query.get("service_uu_id__ilike", None)
if not service_uu_id:
return {
"message": "MSG0003-PARAM-MISSING",
"data": list_options.query,
"completed": False,
}
list_options.query.pop("service_uu_id__ilike", None)
list_options.query.pop("service_uu_id", None)
with Applications.new_session() as db_session:
service2applications = Service2Application.filter_all(
*Service2Application.convert({"service_uu_id__ilike": service_uu_id}),
db=db_session,
)
already_events = [
service_to_application.application_id for service_to_application in service2applications.data
]
if list_options.query:
applications_list = Applications.filter_all(
*Applications.convert(list_options.query), Applications.id.in_(already_events), db=db_session
)
else:
applications_list = Applications.filter_all(Applications.id.in_(already_events), db=db_session)
pagination = Pagination(data=applications_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(data=applications_list, pagination=pagination)
return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response
ApplicationListAppendedEvent.event_callable = application_list_appended_callable
def application_create_callable(data: Any):
"""
Create a new application
"""
with Applications.new_session() as db_session:
created_application_dict = data.model_dump()
created_application = Applications.find_or_create(
db=db_session,
include_args=[Applications.application_for, Applications.application_code, Applications.site_url],
**created_application_dict,
)
if created_application.meta_data.created:
created_application.save(db=db_session)
return {
"completed": True,
"message": "MSG0001-INSERT",
"data": created_application,
}
return {
"completed": False,
"message": "MSG0002-ERROR",
"data": created_application,
}
ApplicationCreateEvent.event_callable = application_create_callable
def application_update_callable(data: Any, uu_id: str):
"""
Update an existing application
"""
with Applications.new_session() as db_session:
updated_application_dict = data.model_dump(
exclude_unset=True, exclude_none=True
)
found_application = Applications.filter_one(
Applications.uu_id == uu_id, db=db_session
).data
if not found_application:
return {
"completed": False,
"message": "MSG0002-FOUND",
"data": found_application,
}
updated_application = found_application.update(
db=db_session, **updated_application_dict
)
updated_application.save(db_session)
if updated_application.meta_data.updated:
return {
"completed": True,
"message": "MSG0003-UPDATE",
"data": updated_application,
}
return {
"completed": False,
"message": "MSG0003-UPDATE",
"data": updated_application,
}
ApplicationUpdateEvent.event_callable = application_update_callable
def application_register_service_callable(data: Any):
"""
Register an application to a service
"""
with Applications.new_session() as db_session:
event = Applications.filter_one_system(Applications.uu_id == data.application_uu_id, db=db_session)
if not event.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service = Services.filter_one_system(Services.uu_id == data.service_uu_id, db=db_session)
if not service.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_application = Service2Application.find_or_create(
db=db_session,
include_args=[Service2Application.service_uu_id, Service2Application.application_uu_id],
service_id=service.data.id,
service_uu_id=str(service.data.uu_id),
application_id=event.data.id,
application_uu_id=str(event.data.uu_id),
application_code=event.data.application_code,
site_url=event.data.site_url,
is_confirmed=True,
)
if not service_to_application.meta_data.created:
return {
"message": "MSG0003-ALREADY-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_application.save(db=db_session)
return {
"message": "MSG0003-REGISTER",
"data": data.model_dump(),
"completed": True,
}
ApplicationRegisterServiceEvent.event_callable = application_register_service_callable
def application_unregister_service_callable(data: Any):
"""
Unregister an application from a service
"""
with Applications.new_session() as db_session:
application = Applications.filter_one_system(Applications.uu_id == data.application_uu_id, db=db_session)
if not application.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service = Services.filter_one_system(Services.uu_id == data.service_uu_id, db=db_session)
if not service.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_application = Service2Application.filter_one_system(
Service2Application.service_id == service.data.id,
Service2Application.application_id == application.data.id,
db=db_session,
)
if not service_to_application.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_application.query.delete()
db_session.commit()
return {
"message": "MSG0003-UNREGISTER",
"data": data.model_dump(),
"completed": True,
}
ApplicationUnRegisterServiceEvent.event_callable = application_unregister_service_callable

View File

@@ -0,0 +1,54 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
EventsListAvailableEvent,
EventsListAppendedEvent,
EventRegisterServiceEvent,
EventUnRegisterServiceEvent,
EventBindEmployeeExtraEvent,
EventBindOccupantExtraEvent,
)
EventsEndpointRouterCluster = RouterCluster(name="EventsEndpointRouterCluster")
EventsEndpointEventClusterListAvailable = EventCluster(
name="EventsListAvailable", endpoint_uu_id="0659d5e4-671f-466c-a84f-47a1290a6f0d"
)
EventsEndpointEventClusterListAvailable.add_event(EventsListAvailableEvent)
EventsEndpointEventClusterListAppended = EventCluster(
name="EventsListAppended", endpoint_uu_id="4d563973-cdcd-44e1-94e0-4262ffb456a1"
)
EventsEndpointEventClusterListAppended.add_event(EventsListAppendedEvent)
EventsEndpointEventClusterRegisterService = EventCluster(
name="EventRegisterService", endpoint_uu_id="c89a2150-db4d-4a8f-b6ec-9e0f09625f76"
)
EventsEndpointEventClusterRegisterService.add_event(EventRegisterServiceEvent)
EventsEndpointEventClusterUnregisterService = EventCluster(
name="EventUnregisterService", endpoint_uu_id="2f16dc9e-de02-449d-9c3f-1a21f87e8794"
)
EventsEndpointEventClusterUnregisterService.add_event(EventUnRegisterServiceEvent)
EventsEndpointEventClusterBindEmployeeExtra = EventCluster(
name="EventBindEmployeeExtra", endpoint_uu_id="58ef3640-04ec-43f9-8f3e-f86be3ce4a24"
)
EventsEndpointEventClusterBindEmployeeExtra.add_event(EventBindEmployeeExtraEvent)
EventsEndpointEventClusterBindOccupantExtra = EventCluster(
name="EventBindOccupantExtra", endpoint_uu_id="7794a550-3073-43e3-b0c5-80128f8d3e4b"
)
EventsEndpointEventClusterBindOccupantExtra.add_event(EventBindOccupantExtraEvent)
EventsEndpointRouterCluster.set_event_cluster(EventsEndpointEventClusterListAvailable)
EventsEndpointRouterCluster.set_event_cluster(EventsEndpointEventClusterListAppended)
EventsEndpointRouterCluster.set_event_cluster(EventsEndpointEventClusterRegisterService)
EventsEndpointRouterCluster.set_event_cluster(
EventsEndpointEventClusterUnregisterService
)
EventsEndpointRouterCluster.set_event_cluster(
EventsEndpointEventClusterBindEmployeeExtra
)
EventsEndpointRouterCluster.set_event_cluster(
EventsEndpointEventClusterBindOccupantExtra
)

View File

@@ -0,0 +1,280 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from typing import Any
from Schemas import (
Events,
Event2Employee,
Event2Occupant,
Event2EmployeeExtra,
Event2OccupantExtra,
Service2Events,
Services,
)
# List available events endpoint
EventsListAvailableEvent = Event(
name="event_endpoint_list_available",
key="d39af512-ec71-4c0f-9b35-e53b0d06d3a4",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List available events endpoint",
)
# List appended events endpoint
EventsListAppendedEvent = Event(
name="event_endpoint_list_appended",
key="bea77d6a-d99f-468b-9002-b3bda6bb6ad0",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List appended events endpoint",
)
# Event Register endpoint
EventRegisterServiceEvent = Event(
name="event_endpoint_register_service",
key="e18e7f89-5708-4a15-9258-99b0903ed43d",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Register service endpoint",
)
# Event Unregister endpoint
EventUnRegisterServiceEvent = Event(
name="service_endpoint_unregister_service",
key="4d693774-4857-435b-a63c-c39baebfe916",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Unregister service endpoint",
)
# Bind employee extra endpoint
EventBindEmployeeExtraEvent = Event(
name="service_endpoint_bind_employee_extra",
key="cd452928-4256-4fb4-b81e-0ca41d723616",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Bind service to employee extra endpoint",
)
# Bind occupant extra endpoint
EventBindOccupantExtraEvent = Event(
name="service_endpoint_bind_occupant_extra",
key="cb11a150-8049-45c9-8cf3-d5290ffd2e4a",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users Bind service to occupant extra endpoint",
)
def events_list_available_callable(list_options: PaginateOnly):
"""
List available events with pagination and filtering options
"""
list_options = PaginateOnly(**list_options.model_dump())
service_uu_id = list_options.query.get("service_uu_id__ilike", None)
if not service_uu_id:
return {
"message": "MSG0003-PARAM-MISSING",
"data": list_options.query,
"completed": False,
}
list_options.query.pop("service_uu_id__ilike", None)
list_options.query.pop("service_uu_id", None)
with Events.new_session() as db_session:
service2events = Service2Events.filter_all(
*Service2Events.convert({"service_uu_id__ilike": service_uu_id}),
db=db_session,
)
already_events = [
service_to_event.event_id for service_to_event in service2events.data
]
if list_options.query:
events_list = Events.filter_all(
*Events.convert(list_options.query),
Events.id.not_in(already_events),
db=db_session,
)
else:
events_list = Events.filter_all(
Events.id.not_in(already_events), db=db_session
)
pagination = Pagination(data=events_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(data=events_list, pagination=pagination)
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
EventsListAvailableEvent.event_callable = events_list_available_callable
def events_list_appended_callable(list_options: PaginateOnly):
"""
List appended events with pagination and filtering options
"""
list_options = PaginateOnly(**list_options.model_dump())
service_uu_id = list_options.query.get("service_uu_id__ilike", None)
if not service_uu_id:
return {
"message": "MSG0003-PARAM-MISSING",
"data": list_options.query,
"completed": False,
}
list_options.query.pop("service_uu_id__ilike", None)
list_options.query.pop("service_uu_id", None)
with Events.new_session() as db_session:
service2events = Service2Events.filter_all(
*Service2Events.convert({"service_uu_id__ilike": service_uu_id}),
db=db_session,
)
already_events = [
service_to_event.event_id for service_to_event in service2events.data
]
if list_options.query:
events_list = Events.filter_all(
*Events.convert(list_options.query),
Events.id.in_(already_events),
db=db_session,
)
else:
events_list = Events.filter_all(
Events.id.in_(already_events), db=db_session
)
pagination = Pagination(data=events_list)
pagination.change(**list_options.model_dump())
pagination_result = PaginationResult(data=events_list, pagination=pagination)
return EndpointResponse(
message="MSG0003-LIST",
pagination_result=pagination_result,
).response
EventsListAppendedEvent.event_callable = events_list_appended_callable
def event_register_service_callable(data: Any):
"""
Register event to service
"""
with Events.new_session() as db_session:
event = Events.filter_one_system(
Events.uu_id == data.event_uu_id, db=db_session
)
if not event.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service = Services.filter_one_system(
Services.uu_id == data.service_uu_id, db=db_session
)
if not service.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_event = Service2Events.find_or_create(
db=db_session,
include_args=[
Service2Events.service_uu_id,
Service2Events.event_uu_id,
],
service_id=service.data.id,
event_id=event.data.id,
is_confirmed=True,
service_uu_id=str(service.data.uu_id),
event_uu_id=str(event.data.uu_id),
)
if not service_to_event.meta_data.created:
return {
"message": "MSG0003-ALREADY-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_event.save(db=db_session)
return {
"message": "MSG0003-REGISTER",
"data": data.model_dump(),
"completed": True,
}
EventRegisterServiceEvent.event_callable = event_register_service_callable
def event_unregister_service_callable(data: Any):
"""
Unregister event from service
"""
with Events.new_session() as db_session:
event = Events.filter_one_system(
Events.uu_id == data.event_uu_id, db=db_session
)
if not event.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service = Services.filter_one_system(
Services.uu_id == data.service_uu_id, db=db_session
)
if not service.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_event = Service2Events.filter_one_system(
Service2Events.service_id == service.data.id,
Service2Events.event_id == event.data.id,
db=db_session,
)
if not service_to_event.data:
return {
"message": "MSG0003-NOT-FOUND",
"data": data.model_dump(),
"completed": False,
}
service_to_event.query.delete()
db_session.commit()
return {
"message": "MSG0003-UNREGISTER",
"data": data.model_dump(),
"completed": True,
}
EventUnRegisterServiceEvent.event_callable = event_unregister_service_callable
def event_bind_employee_extra_callable(data: Any):
"""
Bind event to employee extra
"""
return {
"message": "MSG0003-BIND",
"data": data.model_dump(),
"completed": True,
}
EventBindEmployeeExtraEvent.event_callable = event_bind_employee_extra_callable
def event_bind_occupant_extra_callable(data: Any):
"""
Bind event to occupant extra
"""
return EndpointResponse(
message="MSG0003-BIND",
).response
EventBindOccupantExtraEvent.event_callable = event_bind_occupant_extra_callable

View File

@@ -0,0 +1,19 @@
from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster
from .supers_events import (
ServiceEndpointListEvent,
ServiceEndpointToEventsEvent,
)
ServiceEndpointRouterCluster = RouterCluster(name="ServiceEndpointRouterCluster")
ServiceEndpointEventClusterList = EventCluster(
name="ServiceList", endpoint_uu_id="f4e4d332-70b1-4121-9fcc-a08850b72aaa"
)
ServiceEndpointEventClusterList.add_event(ServiceEndpointListEvent)
ServiceEndpointEventClusterToService = EventCluster(
name="ServiceToEvents", endpoint_uu_id="7b6b0c6a-e3db-4353-a7df-ea49d2a67f8a"
)
ServiceEndpointEventClusterToService.add_event(ServiceEndpointToEventsEvent)
ServiceEndpointRouterCluster.set_event_cluster(ServiceEndpointEventClusterList)
ServiceEndpointRouterCluster.set_event_cluster(ServiceEndpointEventClusterToService)

View File

@@ -0,0 +1,69 @@
from ApiControllers.abstracts.event_clusters import Event
from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly
from Controllers.Postgres.response import EndpointResponse
from Schemas import Services, Service2Events
# List endpoint
ServiceEndpointListEvent = Event(
name="service_endpoint_list",
key="7da6ceac-925a-4faa-9cc5-3f34396b5684",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List services endpoint",
)
def service_endpoint_list_callable(data: PaginateOnly):
"""
List services endpoint callable method
"""
list_options = PaginateOnly(**data.model_dump())
with Services.new_session() as db_session:
if data.query:
services_list = Services.filter_all_system(
*Services.convert(data.query), db=db_session
)
else:
services_list = Services.filter_all_system(db=db_session)
pagination = Pagination(data=services_list)
pagination.change(**data.model_dump())
pagination_result = PaginationResult(data=services_list, pagination=pagination)
return EndpointResponse(
message="MSG0003-LIST", pagination_result=pagination_result
).response
ServiceEndpointListEvent.event_callable = service_endpoint_list_callable
# To events endpoint
ServiceEndpointToEventsEvent = Event(
name="service_endpoint_to_events",
key="7b6b0c6a-e3db-4353-a7df-ea49d2a67f8a",
request_validator=None, # TODO: Add request validator
response_validator=None, # TODO: Add response validator
description="Super Users List events of a service endpoint given service UUID",
)
def service_endpoint_to_events_callable(data: PaginateOnly):
"""
List events of a service given service UUID
"""
list_options = PaginateOnly(**data.model_dump())
with Service2Events.new_session() as db_session:
if data.query:
services_list = Service2Events.filter_all_system(
*Service2Events.convert(data.query), db=db_session
)
else:
services_list = Service2Events.filter_all_system(db=db_session)
pagination = Pagination(data=services_list)
pagination.change(**data.model_dump())
pagination_result = PaginationResult(data=services_list, pagination=pagination)
return EndpointResponse(
message="MSG0003-LIST", pagination_result=pagination_result
).response
ServiceEndpointToEventsEvent.event_callable = service_endpoint_to_events_callable

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,22 @@
from pydantic import BaseModel, Field
from typing import Optional
class RequestApplication(BaseModel):
"""Base model for application data"""
name: str = Field(..., description="Application name")
application_code: str = Field(..., description="Unique application code")
site_url: str = Field(..., description="Application site URL")
application_type: str = Field(
..., description="Application type (info, Dash, Admin)"
)
application_for: str = Field(..., description="Application for (EMP, OCC)")
description: Optional[str] = Field(None, description="Application description")
class AddRemoveService(BaseModel):
"""Base model for add/remove service data"""
application_uu_id: str = Field(..., description="Application UUID")
service_uu_id: str = Field(..., description="Service UUID")

View File

@@ -0,0 +1,14 @@
from pydantic import BaseModel
class Event2Employee(BaseModel):
pass
class Event2Occupant(BaseModel):
pass
class AddRemoveService(BaseModel):
event_uu_id: str
service_uu_id: str

View File

@@ -0,0 +1,13 @@
from fastapi import APIRouter
# Import all routes
from ApiServices.ManagementService.Endpoints.application.route import application_route
# Create main router for ManagementService
management_service_router = APIRouter(prefix="/management", tags=["Management Service"])
# Include all routes
management_service_router.include_router(application_route)
# Export the router
__all__ = ["management_service_router"]

View File

@@ -1,5 +0,0 @@
from .template.event import template_event_cluster
__all__ = [
"template_event_cluster",
]

View File

@@ -1,88 +0,0 @@
class EventCluster:
def __init__(self, endpoint_uu_id: str):
self.endpoint_uu_id = endpoint_uu_id
self.events = []
def add_event(self, list_of_events: list["Event"]):
"""
Add an event to the cluster
"""
for event in list_of_events:
self.events.append(event)
self.events = list(set(self.events))
def get_event(self, event_key: str):
"""
Get an event by its key
"""
for event in self.events:
if event.key == event_key:
return event
return None
def set_events_to_database(self):
from Schemas import Events, EndpointRestriction
with Events.new_session() as db_session:
if to_save_endpoint := EndpointRestriction.filter_one(
EndpointRestriction.operation_uu_id == self.endpoint_uu_id,
db=db_session,
).data:
for event in self.events:
event_to_save_database = Events.find_or_create(
function_code=event.key,
function_class=event.name,
description=event.description,
endpoint_code=self.endpoint_uu_id,
endpoint_id=to_save_endpoint.id,
endpoint_uu_id=str(to_save_endpoint.uu_id),
is_confirmed=True,
active=True,
db=db_session,
)
if event_to_save_database.meta_data.created:
event_to_save_database.save(db=db_session)
print(
f"UUID: {event_to_save_database.uu_id} event is saved to {to_save_endpoint.uu_id}"
)
def match_event(self, event_keys: list[str]) -> "Event":
"""
Match an event by its key
"""
# print('set(event_keys)', set(event_keys))
# print('event.keys', set([event.key for event in self.events]))
intersection_of_key: set[str] = set(event_keys) & set(
[event.key for event in self.events]
)
if not len(intersection_of_key) == 1:
raise ValueError(
f"Event key not found or multiple matches found: {intersection_of_key}"
)
return self.get_event(event_key=list(intersection_of_key)[0])
class Event:
def __init__(
self,
name: str,
key: str,
request_validator: str = None,
response_validator: str = None,
description: str = "",
):
self.name = name
self.key = key
self.request_validator = request_validator
self.response_validator = response_validator
self.description = description
def event_callable(self):
"""
Example callable method
"""
print(self.name)
return {}

View File

@@ -30,46 +30,46 @@ T = TypeVar("T")
class EmailProcessingContext:
"""Context manager for email processing that marks emails as unread if an error occurs."""
def __init__(self, email_message, mark_as_read: bool = True):
self.email_message = email_message
self.mark_as_read = mark_as_read
self.success = False
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None or not self.success:
# If an exception occurred or processing wasn't successful, mark as unread
try:
if hasattr(self.email_message, 'mark_as_unread'):
if hasattr(self.email_message, "mark_as_unread"):
self.email_message.mark_as_unread()
print(f"[EMAIL_SERVICE] Marked email as UNREAD due to processing error: {exc_val if exc_val else 'Unknown error'}")
print(
f"[EMAIL_SERVICE] Marked email as UNREAD due to processing error: {exc_val if exc_val else 'Unknown error'}"
)
except Exception as e:
print(f"[EMAIL_SERVICE] Failed to mark email as unread: {str(e)}")
elif self.mark_as_read:
# If processing was successful and mark_as_read is True, ensure it's marked as read
try:
if hasattr(self.email_message, 'mark_as_read'):
if hasattr(self.email_message, "mark_as_read"):
self.email_message.mark_as_read()
except Exception as e:
print(f"[EMAIL_SERVICE] Failed to mark email as read: {str(e)}")
return False # Don't suppress exceptions
def publish_payload_to_redis(
payload, filename: str, mail_info: dict
) -> bool:
def publish_payload_to_redis(payload, filename: str, mail_info: dict) -> bool:
# Create message document
# Use base64 encoding for binary payloads to ensure proper transmission
if isinstance(payload, bytes):
encoded_payload = base64.b64encode(payload).decode('utf-8')
encoded_payload = base64.b64encode(payload).decode("utf-8")
is_base64 = True
else:
encoded_payload = payload
is_base64 = False
message = {
"filename": filename,
"payload": encoded_payload,
@@ -79,12 +79,14 @@ def publish_payload_to_redis(
"uuid": str(uuid4()), # Use UUID
**mail_info,
}
# Publish to Redis channel
result = redis_pubsub.publisher.publish(REDIS_CHANNEL, message)
if result.status:
print(f"[EMAIL_SERVICE] Published message with filename: {filename} to channel: {REDIS_CHANNEL}")
print(
f"[EMAIL_SERVICE] Published message with filename: {filename} to channel: {REDIS_CHANNEL}"
)
return True
else:
print(f"[EMAIL_SERVICE] Publish error: {result.error}")
@@ -126,7 +128,7 @@ def app():
port = Config.EMAIL_PORT
username = Config.EMAIL_USERNAME
password = Config.EMAIL_PASSWORD
box = EmailBox(host=host, port=port, username=username, password=password)
if not box:
return Exception("Mailbox not found")
@@ -136,41 +138,51 @@ def app():
filter_mail = OR(FROM(Config.MAILBOX), FROM(Config.MAIN_MAIL))
filter_print = f"{Config.MAILBOX} & {Config.MAIN_MAIL}"
# Determine if this is the first run of the day
# Determine if this is the first run of the day
# Store last run date in a file
last_run_file = "/tmp/email_service_last_run.json"
current_date = datetime.now().strftime("%Y-%m-%d")
days_to_check, full_check = 7, 90 # Default to 7 days
try:
if os.path.exists(last_run_file):
with open(last_run_file, 'r') as f:
with open(last_run_file, "r") as f:
last_run_data = json.load(f)
last_run_date = last_run_data.get('last_run_date')
last_run_date = last_run_data.get("last_run_date")
# If this is the first run of a new day, check 90 days
if last_run_date != current_date:
days_to_check = full_check
print(f"[EMAIL_SERVICE] First run of the day. Checking emails from the past {days_to_check} days")
print(
f"[EMAIL_SERVICE] First run of the day. Checking emails from the past {days_to_check} days"
)
else:
print(f"[EMAIL_SERVICE] Subsequent run today. Checking emails from the past {days_to_check} days")
print(
f"[EMAIL_SERVICE] Subsequent run today. Checking emails from the past {days_to_check} days"
)
else:
# If no last run file exists, this is the first run ever - check 90 days
days_to_check = full_check
print(f"[EMAIL_SERVICE] First run detected. Checking emails from the past {days_to_check} days")
print(
f"[EMAIL_SERVICE] First run detected. Checking emails from the past {days_to_check} days"
)
except Exception as e:
print(f"[EMAIL_SERVICE] Error reading last run file: {str(e)}. Using default of {days_to_check} days")
print(
f"[EMAIL_SERVICE] Error reading last run file: {str(e)}. Using default of {days_to_check} days"
)
# Update the last run file
try:
with open(last_run_file, 'w') as f:
json.dump({'last_run_date': current_date}, f)
with open(last_run_file, "w") as f:
json.dump({"last_run_date": current_date}, f)
except Exception as e:
print(f"[EMAIL_SERVICE] Error writing last run file: {str(e)}")
# Calculate the date to check from
check_since_date = (datetime.now() - timedelta(days=days_to_check)).strftime("%d-%b-%Y")
check_since_date = (datetime.now() - timedelta(days=days_to_check)).strftime(
"%d-%b-%Y"
)
for folder in mail_folders:
if folder.name == "INBOX":
# Search for emails since the calculated date
@@ -184,27 +196,33 @@ def app():
# Use context manager to handle errors and mark email as unread if needed
with EmailProcessingContext(banks_mail) as ctx:
try:
headers = {k.lower(): v for k, v in banks_mail.headers.items()}
headers = {
k.lower(): v for k, v in banks_mail.headers.items()
}
mail_info = {
"from": headers["from"],
"to": headers["to"],
"subject": headers["subject"],
"date": str(headers["date"]),
}
# Process the email and publish to Redis
success = read_email_and_publish_to_redis(
email_message=email_message, mail_info=mail_info
)
# Set success flag for the context manager
ctx.success = success
if success:
print(f"[EMAIL_SERVICE] Successfully processed email with subject: {mail_info['subject']}")
print(
f"[EMAIL_SERVICE] Successfully processed email with subject: {mail_info['subject']}"
)
else:
print(f"[EMAIL_SERVICE] No matching attachments found in email with subject: {mail_info['subject']}")
print(
f"[EMAIL_SERVICE] No matching attachments found in email with subject: {mail_info['subject']}"
)
except Exception as e:
print(f"[EMAIL_SERVICE] Error processing email: {str(e)}")
# The context manager will mark the email as unread
@@ -213,8 +231,8 @@ def app():
if __name__ == "__main__":
print("=== Starting Email Service with Redis Pub/Sub ===")
print(f"Publishing to channel: {REDIS_CHANNEL}")
time.sleep(20) # Wait for 20 seconds to other services to kick in
time.sleep(20) # Wait for 20 seconds to other services to kick in
while True:
print("\n[EMAIL_SERVICE] Checking for new emails...")
app()

View File

@@ -18,14 +18,16 @@ REDIS_CHANNEL_OUT = "parser" # Publish to Parser Service channel
delimiter = "|"
def publish_parsed_data_to_redis(data, collected_data_dict: list[dict], filename: str) -> bool:
def publish_parsed_data_to_redis(
data, collected_data_dict: list[dict], filename: str
) -> bool:
"""Publish parsed data to Redis.
Args:
data: Original message data from Redis
collected_data_dict: Parsed data from Excel file
filename: Name of the processed file
Returns:
bool: Success status
"""
@@ -40,16 +42,18 @@ def publish_parsed_data_to_redis(data, collected_data_dict: list[dict], filename
else:
message["parsed"] = None
message["stage"] = "not found" # Mark as 'not found' if parsing failed
# Add processing timestamp
message["parsed_at"] = str(arrow.now())
message["filename"] = filename
# Publish to Redis channel
result = redis_pubsub.publisher.publish(REDIS_CHANNEL_OUT, message)
if result.status:
print(f"[PARSER_SERVICE] Published parsed data for {filename} with stage: {message['stage']}")
print(
f"[PARSER_SERVICE] Published parsed data for {filename} with stage: {message['stage']}"
)
return True
else:
print(f"[PARSER_SERVICE] Publish error: {result.error}")
@@ -58,10 +62,10 @@ def publish_parsed_data_to_redis(data, collected_data_dict: list[dict], filename
def parse_excel_file(excel_frame: DataFrame) -> list[dict]:
"""Parse Excel file data.
Args:
excel_frame: DataFrame containing Excel data
Returns:
list[dict]: List of parsed data dictionaries
"""
@@ -76,13 +80,17 @@ def parse_excel_file(excel_frame: DataFrame) -> list[dict]:
dict(
iban=str(iban),
bank_date=arrow.get(
datetime.datetime.strptime(str(row[1]), "%d/%m/%Y-%H:%M:%S")
datetime.datetime.strptime(
str(row[1]), "%d/%m/%Y-%H:%M:%S"
)
).__str__(),
channel_branch=unidecode(str(row[3])),
currency_value=(
float(str(row[4]).replace(",", "")) if row[4] else 0
),
balance=float(str(row[5]).replace(",", "")) if row[5] else 0,
balance=(
float(str(row[5]).replace(",", "")) if row[5] else 0
),
additional_balance=(
float(str(row[6]).replace(",", "")) if row[6] else 0
),
@@ -92,7 +100,9 @@ def parse_excel_file(excel_frame: DataFrame) -> list[dict]:
bank_reference_code=str(row[15]),
)
)
print(f"[PARSER_SERVICE] Successfully parsed {len(data_list)} records from Excel file")
print(
f"[PARSER_SERVICE] Successfully parsed {len(data_list)} records from Excel file"
)
except Exception as e:
print(f"[PARSER_SERVICE] Error parsing Excel file: {str(e)}")
return data_list
@@ -100,13 +110,13 @@ def parse_excel_file(excel_frame: DataFrame) -> list[dict]:
def process_message(message):
"""Process a message from Redis.
Args:
message: Message data from Redis subscriber
"""
# Extract the message data
data = message["data"]
# If data is a string, parse it as JSON
if isinstance(data, str):
try:
@@ -114,7 +124,7 @@ def process_message(message):
except json.JSONDecodeError as e:
print(f"[PARSER_SERVICE] Error parsing message data: {e}")
return
# Check if stage is 'red' before processing
if data.get("stage") == "red":
try:
@@ -122,91 +132,109 @@ def process_message(message):
payload = data.get("payload")
is_base64 = data.get("is_base64", False)
print(f"[PARSER_SERVICE] Processing file: {filename}")
# Handle base64-encoded payload
if is_base64 and isinstance(payload, str):
try:
# Decode base64 string to bytes
payload = base64.b64decode(payload)
print(f"[PARSER_SERVICE] Successfully decoded base64 payload, size: {len(payload)} bytes")
print(
f"[PARSER_SERVICE] Successfully decoded base64 payload, size: {len(payload)} bytes"
)
except Exception as e:
print(f"[PARSER_SERVICE] Error decoding base64 payload: {str(e)}")
# Convert regular string payload to bytes if needed
elif isinstance(payload, str):
payload = payload.encode('utf-8')
payload = payload.encode("utf-8")
# Create an in-memory file-like object and try multiple approaches
excel_frame = None
errors = []
# Save payload to a temporary file for debugging if needed
temp_file_path = f"/tmp/{filename}"
try:
with open(temp_file_path, 'wb') as f:
with open(temp_file_path, "wb") as f:
f.write(payload)
print(f"[PARSER_SERVICE] Saved payload to {temp_file_path} for debugging")
print(
f"[PARSER_SERVICE] Saved payload to {temp_file_path} for debugging"
)
except Exception as e:
print(f"[PARSER_SERVICE] Could not save debug file: {str(e)}")
# Try different approaches to read the Excel file
approaches = [
# Approach 1: Try xlrd for .xls files
lambda: DataFrame(read_excel(io.BytesIO(payload), engine='xlrd')) if filename.lower().endswith('.xls') else None,
lambda: (
DataFrame(read_excel(io.BytesIO(payload), engine="xlrd"))
if filename.lower().endswith(".xls")
else None
),
# Approach 2: Try openpyxl for .xlsx files
lambda: DataFrame(read_excel(io.BytesIO(payload), engine='openpyxl')) if filename.lower().endswith('.xlsx') else None,
lambda: (
DataFrame(read_excel(io.BytesIO(payload), engine="openpyxl"))
if filename.lower().endswith(".xlsx")
else None
),
# Approach 3: Try xlrd with explicit sheet name
lambda: DataFrame(read_excel(io.BytesIO(payload), engine='xlrd', sheet_name=0)),
lambda: DataFrame(
read_excel(io.BytesIO(payload), engine="xlrd", sheet_name=0)
),
# Approach 4: Try with temporary file
lambda: DataFrame(read_excel(temp_file_path)),
]
# Try each approach until one works
for i, approach in enumerate(approaches):
try:
result = approach()
if result is not None:
excel_frame = result
print(f"[PARSER_SERVICE] Successfully read Excel file using approach {i+1}")
print(
f"[PARSER_SERVICE] Successfully read Excel file using approach {i+1}"
)
break
except Exception as e:
errors.append(f"Approach {i+1}: {str(e)}")
# If all approaches failed, raise an exception
if excel_frame is None:
error_details = "\n".join(errors)
raise Exception(f"Failed to read Excel file using all approaches:\n{error_details}")
raise Exception(
f"Failed to read Excel file using all approaches:\n{error_details}"
)
# Extract data from the Excel file
collected_data_dict = parse_excel_file(excel_frame)
# Publish parsed data to Redis
publish_parsed_data_to_redis(
data=data,
collected_data_dict=collected_data_dict,
filename=filename
data=data, collected_data_dict=collected_data_dict, filename=filename
)
except Exception as e:
print(f"[PARSER_SERVICE] Error processing message: {str(e)}")
else:
print(f"[PARSER_SERVICE] Skipped message with UUID: {data.get('uuid')} (stage is not 'red')")
print(
f"[PARSER_SERVICE] Skipped message with UUID: {data.get('uuid')} (stage is not 'red')"
)
def app():
"""Main application function."""
print("[PARSER_SERVICE] Starting Parser Service")
# Subscribe to the input channel
result = redis_pubsub.subscriber.subscribe(REDIS_CHANNEL_IN, process_message)
if result.status:
print(f"[PARSER_SERVICE] Subscribed to channel: {REDIS_CHANNEL_IN}")
else:
print(f"[PARSER_SERVICE] Subscribe error: {result.error}")
return
# Start listening for messages
listen_result = redis_pubsub.subscriber.start_listening(in_thread=True)
if listen_result.status:
print("[PARSER_SERVICE] Listening for messages")
else:
@@ -217,7 +245,7 @@ def app():
if __name__ == "__main__":
# Initialize the app once
app()
# Keep the main thread alive
try:
while True:

View File

@@ -14,12 +14,12 @@ RUN poetry config virtualenvs.create false && poetry install --no-interaction --
# Install cron for scheduling tasks
RUN apt-get update && apt-get install -y cron
# 11:00 Istanbul Time (UTC+3) system time is 08:00 UTC
RUN echo "0 8 * * * /usr/local/bin/python /app.py >> /var/log/cron.log 2>&1" > /tmp/crontab_list && crontab /tmp/crontab_list
# Copy application code
COPY /BankServices/RoutineEmailService /
# Make run_app.sh executable
RUN chmod +x /run_app.sh
COPY /Schemas /Schemas
COPY /Controllers /Controllers
COPY /BankServices/ServiceDepends /
@@ -30,5 +30,8 @@ ENV PYTHONPATH=/ PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
# Create log file to grab cron logs
RUN touch /var/log/cron.log
# Run cron setup and tail the log file for user to monitor logs
CMD cron && tail -f /var/log/cron.log
# Make entrypoint script executable
RUN chmod +x /entrypoint.sh
# Use entrypoint script to update run_app.sh with environment variables and start cron
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -0,0 +1,69 @@
# Routine Email Service
## Overview
This service sends automated email reports about account records at scheduled times using cron. It retrieves account records from a PostgreSQL database, formats them into an HTML email, and sends them to specified recipients.
## Environment Setup
The service requires the following environment variables:
### Email Configuration
- `EMAIL_HOST`: SMTP server address (e.g., "10.10.2.34")
- `EMAIL_USERNAME`: Email sender address (e.g., "example@domain.com")
- `EMAIL_PASSWORD`: Email password (sensitive)
- `EMAIL_PORT`: SMTP port (e.g., 587)
- `EMAIL_SEND`: Flag to enable/disable email sending (1 = enabled)
### Database Configuration
- `DB_HOST`: PostgreSQL server address (e.g., "10.10.2.14")
- `DB_USER`: Database username (e.g., "postgres")
- `DB_PASSWORD`: Database password (sensitive)
- `DB_PORT`: Database port (e.g., 5432)
- `DB_NAME`: Database name (e.g., "postgres")
## Cron Job Configuration
The service is configured to run daily at 11:00 Istanbul Time (08:00 UTC). This is set up in the entrypoint.sh script.
## Docker Container Setup
### Key Files
1. **Dockerfile**: Defines the container image with Python and cron
2. **entrypoint.sh**: Container entrypoint script that:
- Creates an environment file (/env.sh) with all configuration variables
- Sets up the crontab to run run_app.sh at the scheduled time
- Starts the cron service
- Tails the log file for monitoring
3. **run_app.sh**: Script executed by cron that:
- Sources the environment file to get all configuration
- Exports variables to make them available to the Python script
- Runs the Python application
- Logs environment and execution results
### Environment Variable Handling
Cron jobs run with a minimal environment that doesn't automatically include Docker container environment variables. Our solution:
1. Captures all environment variables from Docker to a file at container startup
2. Has the run_app.sh script source this file before execution
3. Explicitly exports all variables to ensure they're available to the Python script
## Logs
Logs are written to `/var/log/cron.log` and can be viewed with:
```bash
docker exec routine_email_service tail -f /var/log/cron.log
```
## Manual Execution
To run the service manually:
```bash
docker exec routine_email_service /run_app.sh
```
## Docker Compose Configuration
In the docker-compose.yml file, the service needs an explicit entrypoint configuration:
```yaml
entrypoint: ["/entrypoint.sh"]
```
This ensures the entrypoint script runs when the container starts.

View File

@@ -11,13 +11,13 @@ def render_email_template(
) -> str:
"""
Render the HTML email template with the provided data.
Args:
headers: List of column headers for the table
rows: List of data rows for the table
balance_error: Flag indicating if there's a balance discrepancy
bank_balance: Current bank balance formatted as string
Returns:
Rendered HTML template as string
"""
@@ -25,7 +25,7 @@ def render_email_template(
# Look for template in ServiceDepends directory
env = Environment(loader=FileSystemLoader("/"))
template = env.get_template("template_accounts.html")
# Render template with variables
return template.render(
headers=headers,
@@ -35,97 +35,109 @@ def render_email_template(
today=str(arrow.now().date()),
)
except Exception as e:
print('Exception render template:',e)
err = e
print("Exception render template:", e)
raise
def send_email_to_given_address(send_to: str, html_template: str) -> bool:
"""
Send email with the rendered HTML template to the specified address.
Args:
send_to: Email address of the recipient
html_template: Rendered HTML template content
Returns:
Boolean indicating if the email was sent successfully
"""
today = arrow.now()
subject = f"{str(today.date())} Gunes Apt. Cari Durum Bilgilendirme Raporu"
# Create email parameters using EmailSendModel
email_params = EmailSendModel(
subject=subject,
html=html_template,
receivers=[send_to],
text=f"Gunes Apt. Cari Durum Bilgilendirme Raporu - {today.date()}"
text=f"Gunes Apt. Cari Durum Bilgilendirme Raporu - {today.date()}",
)
try:
# Use the context manager to handle connection errors
with EmailService.new_session() as email_session:
# Send email through the service
EmailService.send_email(email_session, email_params)
return True
return EmailService.send_email(email_session, email_params)
except Exception as e:
print(f'Exception send email: {e}')
print(f"Exception send email: {e}")
return False
def set_account_records_to_send_email() -> bool:
"""
Retrieve account records from the database, format them, and send an email report.
Usage:
from app import set_account_records_to_send_email
Returns:
Boolean indicating if the process completed successfully
"""
# Get database session and retrieve records
with AccountRecords.new_session() as db_session:
account_records_query = AccountRecords.filter_all(db=db_session).query
# Get the 3 most recent records
account_records: List[AccountRecords] | [] = (
account_records: List[AccountRecords] = (
account_records_query.order_by(
AccountRecords.bank_date.desc(),
AccountRecords.bank_reference_code.desc()
AccountRecords.bank_date.desc(),
AccountRecords.iban.desc(),
)
.limit(3)
.all()
)
# Check if we have enough records
if len(account_records) < 2:
print(f"Not enough records found: {len(account_records)}")
return False
# Check for balance discrepancy
first_record, second_record = account_records[0], account_records[1]
expected_second_balance = first_record.bank_balance - first_record.currency_value
expected_second_balance = (
first_record.bank_balance - first_record.currency_value
)
balance_error = expected_second_balance != second_record.bank_balance
if balance_error:
return False
print(
f"Balance error detected {expected_second_balance} != {second_record.bank_balance}"
)
# Format rows for the email template
list_of_rows = []
for record in account_records:
list_of_rows.append([
record.bank_date.strftime("%d/%m/%Y %H:%M"),
record.process_comment,
f"{record.currency_value:,.2f}",
f"{record.bank_balance:,.2f}"
])
list_of_rows.append(
[
record.bank_date.strftime("%d/%m/%Y %H:%M"),
record.process_comment,
f"{record.currency_value:,.2f}",
f"{record.bank_balance:,.2f}",
]
)
# Get the most recent bank balance
last_bank_balance = sorted(account_records, key=lambda x: x.bank_date, reverse=True)[0].bank_balance
last_bank_balance = sorted(
account_records, key=lambda x: x.bank_date, reverse=True
)[0].bank_balance
# Define headers for the table
headers = ["Ulaştığı Tarih", "Banka Transaksiyonu Ek Bilgi", "Aktarım Değeri", "Banka Bakiyesi"]
headers = [
"Ulaştığı Tarih",
"Banka Transaksiyonu Ek Bilgi",
"Aktarım Değeri",
"Banka Bakiyesi",
]
# Recipient email address
send_to = "karatay@mehmetkaratay.com.tr"
# Render email template
html_template = render_email_template(
headers=headers,
@@ -133,12 +145,13 @@ def set_account_records_to_send_email() -> bool:
balance_error=balance_error,
bank_balance=f"{last_bank_balance:,.2f}",
)
# Send the email
return send_email_to_given_address(send_to=send_to, html_template=html_template)
if __name__ == "__main__":
success = set_account_records_to_send_email()
print("Email sent successfully" if success else "Failed to send email")
exit_code = 0 if success else 1
exit(exit_code)

View File

@@ -0,0 +1,29 @@
#!/bin/bash
# Create environment file that will be available to cron jobs
echo "# Environment variables for cron jobs" > /env.sh
echo "EMAIL_HOST=\"$EMAIL_HOST\"" >> /env.sh
echo "EMAIL_USERNAME=\"$EMAIL_USERNAME\"" >> /env.sh
echo "EMAIL_PASSWORD=\"$EMAIL_PASSWORD\"" >> /env.sh
echo "EMAIL_PORT=$EMAIL_PORT" >> /env.sh
echo "EMAIL_SEND=$EMAIL_SEND" >> /env.sh
echo "DB_HOST=\"$DB_HOST\"" >> /env.sh
echo "DB_USER=\"$DB_USER\"" >> /env.sh
echo "DB_PASSWORD=\"$DB_PASSWORD\"" >> /env.sh
echo "DB_PORT=$DB_PORT" >> /env.sh
echo "DB_NAME=\"$DB_NAME\"" >> /env.sh
# Add Python environment variables
echo "PYTHONPATH=/" >> /env.sh
echo "PYTHONUNBUFFERED=1" >> /env.sh
echo "PYTHONDONTWRITEBYTECODE=1" >> /env.sh
# Make the environment file available to cron
echo "0 8 * * * /run_app.sh >> /var/log/cron.log 2>&1" > /tmp/crontab_list
crontab /tmp/crontab_list
# Start cron
cron
# Tail the log file
tail -f /var/log/cron.log

View File

@@ -0,0 +1,24 @@
#!/bin/bash
# Source the environment file directly
. /env.sh
# Re-export all variables to ensure they're available to the Python script
export EMAIL_HOST
export EMAIL_USERNAME
export EMAIL_PASSWORD
export EMAIL_PORT
export EMAIL_SEND
export DB_HOST
export DB_USER
export DB_PASSWORD
export DB_PORT
export DB_NAME
# Python environment variables
export PYTHONPATH
export PYTHONUNBUFFERED
export PYTHONDONTWRITEBYTECODE
env >> /var/log/cron.log
/usr/local/bin/python /app.py

View File

@@ -12,13 +12,13 @@ def render_email_template(
) -> str:
"""
Render the HTML email template with the provided data.
Args:
headers: List of column headers for the table
rows: List of data rows for the table
balance_error: Flag indicating if there's a balance discrepancy
bank_balance: Current bank balance formatted as string
Returns:
Rendered HTML template as string
"""
@@ -26,7 +26,7 @@ def render_email_template(
# Look for template in ServiceDepends directory
env = Environment(loader=FileSystemLoader("/"))
template = env.get_template("template_accounts.html")
return template.render(
headers=headers,
rows=rows,
@@ -35,32 +35,34 @@ def render_email_template(
today=str(arrow.now().date()),
)
except Exception as e:
print(f'Template rendering failed: {e}')
print(f"Template rendering failed: {e}")
raise
def send_email_to_given_address(send_to: str, html_template: str, count_of_records: int) -> bool:
def send_email_to_given_address(
send_to: str, html_template: str, count_of_records: int
) -> bool:
"""
Send email with the rendered HTML template to the specified address.
Args:
send_to: Email address of the recipient
html_template: Rendered HTML template content
Returns:
Boolean indicating if the email was sent successfully
"""
today = arrow.now()
subject = f"{str(today.date())} Gunes Apt. Cari Durum Kayıt Giriş Raporu"
# Create email parameters using EmailSendModel
email_params = EmailSendModel(
subject=subject + f" ({count_of_records} kayıt)",
html=html_template,
receivers=[send_to],
text=f"Gunes Apt. Cari Durum Kayıt Giriş Raporu - {today.date()}"
text=f"Gunes Apt. Cari Durum Kayıt Giriş Raporu - {today.date()}",
)
try:
# Use the context manager to handle connection errors
with EmailService.new_session() as email_session:
@@ -69,17 +71,17 @@ def send_email_to_given_address(send_to: str, html_template: str, count_of_recor
print(f"Email successfully sent to: {send_to}")
return True
except Exception as e:
print(f'Failed to send email: {e}')
print(f"Failed to send email: {e}")
return False
def process_unsent_email_records() -> bool:
"""
Process account records that haven't been emailed yet.
Finds records with is_email_send=False, formats them into an email,
sends the email, and updates the records as sent if successful.
Returns:
bool: True if email was sent successfully, False otherwise
"""
@@ -87,43 +89,55 @@ def process_unsent_email_records() -> bool:
# Use the context manager to handle database connections
with AccountRecords.new_session() as db_session:
# Query un-sent mail rows - with limit for display only
account_records_query = AccountRecords.filter_all(
AccountRecords.is_email_send == False,
db=db_session,
).query.order_by(AccountRecords.bank_date.asc()).limit(20)
account_records_query = (
AccountRecords.filter_all(
AccountRecords.is_email_send == False,
db=db_session,
)
.query.order_by(AccountRecords.bank_date.asc())
.limit(20)
)
account_records: List[AccountRecords] = account_records_query.all()
if not account_records:
print("No unsent email records found")
return False
# Get the IDs of the records we're processing
record_ids = [record.id for record in account_records]
print(f"Found {len(account_records)} unsent email records")
# Format rows for the email template
list_of_rows = []
for record in account_records:
list_of_rows.append([
record.bank_date.strftime("%d/%m/%Y %H:%M"),
record.process_comment,
f"{record.currency_value:,.2f}",
f"{record.bank_balance:,.2f}"
])
list_of_rows.append(
[
record.bank_date.strftime("%d/%m/%Y %H:%M"),
record.process_comment,
f"{record.currency_value:,.2f}",
f"{record.bank_balance:,.2f}",
]
)
# Reverse list by date
list_of_rows = list_of_rows[::-1]
# Get the most recent bank balance
last_bank_balance = sorted(account_records, key=lambda x: x.bank_date, reverse=True)[0].bank_balance
last_bank_balance = sorted(
account_records, key=lambda x: x.bank_date, reverse=True
)[0].bank_balance
# Define headers for the table
headers = ["Ulaştığı Tarih", "Banka Transaksiyonu Ek Bilgi", "Aktarım Değeri", "Banka Bakiyesi"]
headers = [
"Ulaştığı Tarih",
"Banka Transaksiyonu Ek Bilgi",
"Aktarım Değeri",
"Banka Bakiyesi",
]
# Recipient email address
send_to = "karatay@mehmetkaratay.com.tr"
# Render email template
html_template = render_email_template(
headers=headers,
@@ -131,32 +145,35 @@ def process_unsent_email_records() -> bool:
balance_error=False,
bank_balance=f"{last_bank_balance:,.2f}",
)
# Send the email
if send_email_to_given_address(send_to=send_to, html_template=html_template, count_of_records=len(list_of_rows)):
if send_email_to_given_address(
send_to=send_to,
html_template=html_template,
count_of_records=len(list_of_rows),
):
# Create a new query without limit for updating
update_query = AccountRecords.filter_all(
AccountRecords.id.in_(record_ids),
db=db_session
AccountRecords.id.in_(record_ids), db=db_session
).query
# Update records as sent
update_query.update({"is_email_send": True}, synchronize_session=False)
AccountRecords.save(db_session)
print(f"Successfully marked {len(account_records)} records as sent")
return True
print("Email sending failed, records not updated")
return False
except Exception as e:
print(f'Error processing unsent email records: {e}')
print(f"Error processing unsent email records: {e}")
return False
if __name__ == "__main__":
print("Starting Email Sender Service")
while True:
try:
result = process_unsent_email_records()
@@ -166,7 +183,7 @@ if __name__ == "__main__":
print("No emails sent in this iteration")
except Exception as e:
print(f"Unexpected error in main loop: {e}")
# Sleep for 60 seconds before next check
print("Sleeping for 60 seconds")
time.sleep(60)

View File

@@ -22,7 +22,7 @@ class Config:
class EmailConfig:
EMAIL_HOST: str = os.getenv("EMAIL_HOST", "10.10.2.34")
EMAIL_HOST: str = os.getenv("EMAIL_HOST", "10.10.2.34")
EMAIL_USERNAME: str = Config.EMAIL_SENDER_USERNAME
EMAIL_PASSWORD: str = Config.EMAIL_PASSWORD
EMAIL_PORT: int = Config.EMAIL_SEND_PORT

View File

@@ -18,28 +18,30 @@ delimiter = "|"
def publish_written_data_to_redis(data: Dict[str, Any], file_name: str) -> bool:
"""Publish written data status to Redis.
Args:
data: Original message data from Redis
file_name: Name of the processed file
Returns:
bool: Success status
"""
# Create a copy of the original message to preserve metadata
message = data.copy() if isinstance(data, dict) else {}
# Update stage to 'written'
message["stage"] = "written"
# Add processing timestamp
message["written_at"] = str(arrow.now())
# Publish to Redis channel
result = redis_pubsub.publisher.publish(REDIS_CHANNEL_OUT, message)
if result.status:
print(f"[WRITER_SERVICE] Published written status for {file_name} with stage: written")
print(
f"[WRITER_SERVICE] Published written status for {file_name} with stage: written"
)
return True
else:
print(f"[WRITER_SERVICE] Publish error: {result.error}")
@@ -48,10 +50,10 @@ def publish_written_data_to_redis(data: Dict[str, Any], file_name: str) -> bool:
def write_parsed_data_to_account_records(data_dict: dict, file_name: str) -> bool:
"""Write parsed data to account records database.
Args:
data_dict: Parsed data dictionary
Returns:
bool: True if record was created or already exists, False on error
"""
@@ -61,8 +63,8 @@ def write_parsed_data_to_account_records(data_dict: dict, file_name: str) -> boo
data_dict["bank_balance"] = data_dict.pop("balance")
data_dict["import_file_name"] = file_name
data_dict = BankReceive(**data_dict).model_dump()
print('data_dict', data_dict)
print("data_dict", data_dict)
# Process date fields
bank_date = arrow.get(str(data_dict["bank_date"]))
data_dict["bank_date_w"] = bank_date.weekday()
@@ -70,7 +72,7 @@ def write_parsed_data_to_account_records(data_dict: dict, file_name: str) -> boo
data_dict["bank_date_d"] = bank_date.day
data_dict["bank_date_y"] = bank_date.year
data_dict["bank_date"] = str(bank_date)
# Add build information if available
if build_iban := BuildIbans.filter_by_one(
iban=data_dict["iban"], db=db_session
@@ -81,7 +83,7 @@ def write_parsed_data_to_account_records(data_dict: dict, file_name: str) -> boo
"build_uu_id": build_iban.build_uu_id,
}
)
# Create new record or find existing one using specific fields for matching
new_account_record = AccountRecords.find_or_create(
db=db_session,
@@ -90,16 +92,20 @@ def write_parsed_data_to_account_records(data_dict: dict, file_name: str) -> boo
AccountRecords.bank_date,
AccountRecords.iban,
AccountRecords.bank_reference_code,
AccountRecords.bank_balance
]
AccountRecords.bank_balance,
],
)
if new_account_record.meta_data.created:
new_account_record.is_confirmed = True
new_account_record.save(db=db_session)
print(f"[WRITER_SERVICE] Created new record in database: {new_account_record.id}")
print(
f"[WRITER_SERVICE] Created new record in database: {new_account_record.id}"
)
return True
else:
print(f"[WRITER_SERVICE] Record already exists in database: {new_account_record.id}")
print(
f"[WRITER_SERVICE] Record already exists in database: {new_account_record.id}"
)
return False
except Exception as e:
print(f"[WRITER_SERVICE] Error writing to database: {str(e)}")
@@ -108,13 +114,13 @@ def write_parsed_data_to_account_records(data_dict: dict, file_name: str) -> boo
def process_message(message):
"""Process a message from Redis.
Args:
message: Message data from Redis subscriber
"""
# Extract the message data
data = message["data"]
# If data is a string, parse it as JSON
if isinstance(data, str):
try:
@@ -122,51 +128,55 @@ def process_message(message):
except json.JSONDecodeError as e:
print(f"[WRITER_SERVICE] Error parsing message data: {e}")
return
# Check if stage is 'parsed' before processing
if data.get("stage") == "parsed":
try:
file_name = data.get("filename")
parsed_data = data.get("parsed")
print(f"[WRITER_SERVICE] Processing file: {file_name}")
if not parsed_data:
print(f"[WRITER_SERVICE] No parsed data found for {file_name}")
return
# Process each parsed data item
success = True
for item in parsed_data:
result = write_parsed_data_to_account_records(data_dict=item, file_name=file_name)
result = write_parsed_data_to_account_records(
data_dict=item, file_name=file_name
)
if not result:
success = False
# Publish status update to Redis if all records were processed
if success:
publish_written_data_to_redis(data=data, file_name=file_name)
except Exception as e:
print(f"[WRITER_SERVICE] Error processing message: {str(e)}")
else:
print(f"[WRITER_SERVICE] Skipped message with UUID: {data.get('uuid')} (stage is not 'parsed')")
print(
f"[WRITER_SERVICE] Skipped message with UUID: {data.get('uuid')} (stage is not 'parsed')"
)
def app():
"""Main application function."""
print("[WRITER_SERVICE] Starting Writer Service")
# Subscribe to the input channel
result = redis_pubsub.subscriber.subscribe(REDIS_CHANNEL_IN, process_message)
if result.status:
print(f"[WRITER_SERVICE] Subscribed to channel: {REDIS_CHANNEL_IN}")
else:
print(f"[WRITER_SERVICE] Subscribe error: {result.error}")
return
# Start listening for messages
listen_result = redis_pubsub.subscriber.start_listening(in_thread=True)
if listen_result.status:
print("[WRITER_SERVICE] Listening for messages")
else:
@@ -177,7 +187,7 @@ def app():
if __name__ == "__main__":
# Initialize the app once
app()
# Keep the main thread alive
try:
while True:

View File

@@ -10,7 +10,7 @@ class Configs(BaseSettings):
USERNAME: str = ""
PASSWORD: str = ""
PORT: int = 0
SEND: bool = 0
SEND: bool = True
@property
def is_send(self):

View File

@@ -27,17 +27,27 @@ class EmailSession:
print("Email sending is disabled", params)
return False
receivers = [email_configs.USERNAME]
self.email_sender.send(
subject=params.subject,
receivers=receivers,
text=params.text + f" : Gonderilen [{str(receivers)}]",
html=params.html,
cc=params.cc,
bcc=params.bcc,
headers=params.headers or {},
attachments=params.attachments or {},
)
return True
# Ensure connection is established before sending
try:
# Check if connection exists, if not establish it
if not hasattr(self.email_sender, '_connected') or not self.email_sender._connected:
self.email_sender.connect()
self.email_sender.send(
subject=params.subject,
receivers=receivers,
text=params.text + f" : Gonderilen [{str(receivers)}]",
html=params.html,
cc=params.cc,
bcc=params.bcc,
headers=params.headers or {},
attachments=params.attachments or {},
)
return True
except Exception as e:
print(f"Error sending email: {e}")
raise
class EmailService:
@@ -54,14 +64,25 @@ class EmailService:
"""Create and yield a new email session with active connection."""
email_sender = EmailSender(**email_configs.as_dict())
session = EmailSession(email_sender)
connection_established = False
try:
# Establish connection and set flag
email_sender.connect()
# Set a flag to track connection state
email_sender._connected = True
connection_established = True
yield session
except Exception as e:
print(f"Error with email connection: {e}")
raise
finally:
email_sender.close()
# Only close if connection was successfully established
if connection_established:
try:
email_sender.close()
email_sender._connected = False
except Exception as e:
print(f"Error closing email connection: {e}")
@classmethod
def send_email(cls, session: EmailSession, params: EmailSendModel) -> bool:

Some files were not shown because too many files have changed in this diff Show More