alcehmy and event functions updated

This commit is contained in:
berkay 2024-11-09 22:31:12 +03:00
parent e7a9b8c313
commit 1f75e49a07
23 changed files with 709 additions and 505 deletions

View File

@ -1,3 +1,5 @@
from typing import Union
from fastapi.exceptions import HTTPException from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
@ -31,7 +33,11 @@ class AddressListEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def address_list_super_user(cls, list_options: ListOptions, token_dict): def address_list_super_user(
cls,
list_options: ListOptions,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
from sqlalchemy import select from sqlalchemy import select
post_code_list = RelationshipEmployee2PostCode.filter_all( post_code_list = RelationshipEmployee2PostCode.filter_all(
@ -45,17 +51,29 @@ class AddressListEventMethods(MethodToEvent):
detail="User has no post code registered. User can not list addresses.", detail="User has no post code registered. User can not list addresses.",
) )
get_street_ids = AddressPostcode.session.execute( get_street_ids = [
select(AddressPostcode.street_id).where( street_id[0]
AddressPostcode.id.in_(post_code_id_list) for street_id in AddressPostcode.select_only(
AddressPostcode.id.in_(post_code_id_list),
AddressPostcode.active == True,
select_args=[AddressPostcode.street_id],
order_by=AddressPostcode.street_id.desc(),
).data
]
if not get_street_ids:
raise HTTPException(
status_code=404,
detail="User has no street registered. User can not list addresses.",
) )
).all()
Addresses.pre_query = Addresses.filter_active( Addresses.pre_query = Addresses.filter_all(
Addresses.street_id.in_(*get_street_ids) if get_street_ids else None Addresses.street_id.in_(*get_street_ids),
Addresses.active == True,
).query ).query
Addresses.filter_attr = list_options Addresses.filter_attr = list_options
records = Addresses.filter_active( records = Addresses.filter_all(
*Addresses.get_smart_query(list_options.query) *Addresses.get_smart_query(list_options.query),
Addresses.active == True,
) )
return AlchemyJsonResponse( return AlchemyJsonResponse(
completed=True, completed=True,
@ -64,7 +82,11 @@ class AddressListEventMethods(MethodToEvent):
) )
@classmethod @classmethod
def address_list_employee(cls, list_options: ListOptions, token_dict): def address_list_employee(
cls,
list_options: ListOptions,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
Addresses.filter_attr = list_options Addresses.filter_attr = list_options
records = Addresses.list_via_employee( records = Addresses.list_via_employee(
token_dict=token_dict, token_dict=token_dict,
@ -76,6 +98,7 @@ class AddressListEventMethods(MethodToEvent):
result=records, result=records,
) )
class AddressCreateEventMethods(MethodToEvent): class AddressCreateEventMethods(MethodToEvent):
event_type = "CREATE" event_type = "CREATE"
@ -84,8 +107,15 @@ class AddressCreateEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def create_address(cls, data: InsertAddress, token_dict): def create_address(
post_code = AddressPostcode.find_one(uu_id=data.post_code_uu_id) cls,
data: InsertAddress,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
post_code = AddressPostcode.filter_one(
AddressPostcode.uu_id==data.post_code_uu_id,
AddressPostcode.active == True,
).data
if not post_code: if not post_code:
raise HTTPException( raise HTTPException(
status_code=404, status_code=404,
@ -95,15 +125,14 @@ class AddressCreateEventMethods(MethodToEvent):
data_dict = data.excluded_dump() data_dict = data.excluded_dump()
data_dict["street_id"] = post_code.street_id data_dict["street_id"] = post_code.street_id
del data_dict["post_code_uu_id"] del data_dict["post_code_uu_id"]
data_dict["is_confirmed"] = True
address = Addresses.find_or_create(**data_dict) address = Addresses.find_or_create(**data_dict)
if not address.is_found: RelationshipEmployee2PostCode.find_or_create(
RelationshipEmployee2PostCode.find_or_create( employee_id=token_dict.selected_company.employee_id,
employee_id=token_dict.selected_company.employee_id, member_id=post_code.id,
member_id=post_code.id, company_id=token_dict.selected_company.company_id,
company_id=token_dict.selected_company.company_id, is_confirmed=True,
is_confirmed=True, )
)
Addresses.save() Addresses.save()
return JSONResponse( return JSONResponse(
content={ content={
@ -123,7 +152,11 @@ class AddressSearchEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def search_address(cls, data: SearchAddress, token_dict): def search_address(
cls,
data: SearchAddress,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
import databases as database_sql_models import databases as database_sql_models
from time import perf_counter from time import perf_counter
@ -191,11 +224,16 @@ class AddressUpdateEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def update_address(cls, address_uu_id: str, data: InsertAddress, token_dict): def update_address(
cls,
address_uu_id: str,
data: InsertAddress,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
address = Addresses.find_one_or_abort(uu_id=address_uu_id) address = Addresses.find_one_or_abort(uu_id=address_uu_id)
post_code = RelationshipEmployee2PostCode.postcode.find_one( post_code = RelationshipEmployee2PostCode.filter_one(
member_id=address.post_code_id RelationshipEmployee2PostCode.member_id==address.post_code_id
) ).data
if not post_code: if not post_code:
raise HTTPException( raise HTTPException(
status_code=404, status_code=404,
@ -205,7 +243,7 @@ class AddressUpdateEventMethods(MethodToEvent):
data_dict = data.excluded_dump() data_dict = data.excluded_dump()
data_dict["post_code_id"] = post_code.id data_dict["post_code_id"] = post_code.id
del data_dict["post_code_uu_id"] del data_dict["post_code_uu_id"]
data_dict["is_confirmed"] = True
updated_address = address.update(**data_dict) updated_address = address.update(**data_dict)
updated_address.save() updated_address.save()
return JSONResponse( return JSONResponse(
@ -226,7 +264,12 @@ class AddressPatchEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def patch_address(cls, address_uu_id: str, data: InsertAddress, token_dict): def patch_address(
cls,
address_uu_id: str,
data: InsertAddress,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
address = Addresses.find_one_or_abort(uu_id=address_uu_id) address = Addresses.find_one_or_abort(uu_id=address_uu_id)
post_code = RelationshipEmployee2PostCode.filter_one( post_code = RelationshipEmployee2PostCode.filter_one(
RelationshipEmployee2PostCode.member_id == address.post_code_id RelationshipEmployee2PostCode.member_id == address.post_code_id
@ -260,9 +303,13 @@ class AddressPostCodeCreateEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def create_post_code_address(cls, data: InsertPostCode, token_dict): def create_post_code_address(
cls,
data: InsertPostCode,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
data_dump = data.excluded_dump() data_dump = data.excluded_dump()
street = AddressStreet.find_one(uu_id=data.street_uu_id) street = AddressStreet.filter_one(AddressStreet.uu_id==data.street_uu_id).data
if not street: if not street:
raise HTTPException( raise HTTPException(
status_code=404, status_code=404,
@ -273,13 +320,12 @@ class AddressPostCodeCreateEventMethods(MethodToEvent):
del data_dump["street_uu_id"], data_dump["post_code"] del data_dump["street_uu_id"], data_dump["post_code"]
post_code = AddressPostcode.find_or_create(**data_dump) post_code = AddressPostcode.find_or_create(**data_dump)
if not post_code.is_found: AddressPostcode.__many__table__.find_or_create(
AddressPostcode.__many__table__.find_or_create( member_id=post_code.id,
member_id=post_code.id, employee_id=token_dict.selected_company.employee_id,
employee_id=token_dict.selected_company.employee_id, company_id=token_dict.selected_company.company_id,
company_id=token_dict.selected_company.company_id, is_confirmed=True,
is_confirmed=True, )
)
AddressStreet.save() AddressStreet.save()
return JSONResponse( return JSONResponse(
content={ content={
@ -300,10 +346,13 @@ class AddressPostCodeUpdateEventMethods(MethodToEvent):
@classmethod @classmethod
def update_post_code_address( def update_post_code_address(
cls, post_code_uu_id: str, data: InsertPostCode, token_dict cls,
post_code_uu_id: str,
data: InsertPostCode,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
): ):
post_code = AddressPostcode.find_one_or_abort(uu_id=post_code_uu_id) post_code = AddressPostcode.filter_one(AddressPostcode.uu_id==post_code_uu_id).data
street = AddressStreet.find_one(uu_id=data.street_uu_id) street = AddressStreet.filter_one(AddressPostcode.uu_id==data.street_uu_id).data
if not street: if not street:
raise HTTPException( raise HTTPException(
status_code=404, status_code=404,
@ -330,8 +379,12 @@ class AddressPostCodeListEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def list_post_code_address(cls, list_options: ListOptions, token_dict): def list_post_code_address(
post_code_list = AddressPostcode.__many__table__.filter_active( cls,
list_options: ListOptions,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
post_code_list = AddressPostcode.__many__table__.filter_all(
AddressPostcode.__many__table__.company_id AddressPostcode.__many__table__.company_id
== token_dict.selected_company.company_id == token_dict.selected_company.company_id
).data ).data
@ -341,13 +394,14 @@ class AddressPostCodeListEventMethods(MethodToEvent):
detail="User has no post code registered or not yet any post code created.", detail="User has no post code registered or not yet any post code created.",
) )
AddressPostcode.pre_query = AddressPostcode.filter_active( AddressPostcode.pre_query = AddressPostcode.filter_all(
AddressPostcode.id.in_( AddressPostcode.id.in_(
[post_code.member_id for post_code in post_code_list] [post_code.member_id for post_code in post_code_list]
) ),
AddressPostcode.active == True,
).query ).query
AddressPostcode.filter_attr = list_options AddressPostcode.filter_attr = list_options
records = AddressPostcode.filter_active( records = AddressPostcode.filter_all(
*Addresses.get_smart_query(list_options.query) *Addresses.get_smart_query(list_options.query)
) )
return AlchemyJsonResponse( return AlchemyJsonResponse(

View File

@ -37,7 +37,7 @@ from api_services import (
from api_events.events.abstract_class import MethodToEvent, ActionsSchema from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_library.date_time_actions.date_functions import DateTimeLocal from api_library.date_time_actions.date_functions import DateTimeLocal, system_arrow
from api_configs import ApiStatic, Auth from api_configs import ApiStatic, Auth
from databases.no_sql_models.login_handlers import load_user_with_erp_details from databases.no_sql_models.login_handlers import load_user_with_erp_details
@ -51,6 +51,7 @@ from api_validations.validations_request import (
OccupantSelection, OccupantSelection,
EmployeeSelection, EmployeeSelection,
) )
from databases.sql_models.building.build import RelationshipEmployee2Build
class AuthenticationLoginEventMethods(MethodToEvent): class AuthenticationLoginEventMethods(MethodToEvent):
@ -98,8 +99,8 @@ class AuthenticationSelectEventMethods(MethodToEvent):
def authentication_select_company_or_occupant_type( def authentication_select_company_or_occupant_type(
cls, cls,
request: Request, request: Request,
data: typing.Union[EmployeeSelection, OccupantSelection], data,
token_dict: dict = None, token_dict: typing.Union[EmployeeSelection, OccupantSelection],
): ):
from api_objects import OccupantToken, CompanyToken from api_objects import OccupantToken, CompanyToken
@ -116,38 +117,39 @@ class AuthenticationSelectEventMethods(MethodToEvent):
if selected_company := Companies.find_one(uu_id=data.company_uu_id): if selected_company := Companies.find_one(uu_id=data.company_uu_id):
department_ids = [ department_ids = [
department.id department.id
for department in Departments.filter_by_active( for department in Departments.filter_all(
company_id=selected_company.id Departments.company_id==selected_company.id
).data ).data
] ]
duties_ids = [ duties_ids = [
duties.id duties.id
for duties in Duties.filter_active( for duties in Duties.filter_all(
Duties.company_id == selected_company.id, Duties.company_id == selected_company.id,
Duties.department_id.in_(department_ids), Duties.department_id.in_(department_ids),
).data ).data
] ]
staff_ids = [ staff_ids = [
staff.id staff.id
for staff in Staff.filter_active( for staff in Staff.filter_all(
Staff.duties_id.in_(duties_ids) Staff.duties_id.in_(duties_ids)
).data ).data
] ]
employee = Employees.filter_active( employee = Employees.filter_one(
Employees.people_id == token_user.person_id, Employees.people_id == token_user.person_id,
Employees.staff_id.in_(staff_ids), Employees.staff_id.in_(staff_ids),
).data[0] ).data
reachable_event_list_id, reachable_event_list_uu_id = ( reachable_event_list_id, reachable_event_list_uu_id = (
Event2Employee.get_event_id_by_employee_id(employee_id=employee.id) Event2Employee.get_event_id_by_employee_id(employee_id=employee.id)
) )
staff = Staff.find_one(id=employee.staff_id) staff = Staff.filter_one(Staff.id==employee.staff_id).data
duties = Duties.find_one(id=staff.duties_id) duties = Duties.find_one(Duties.id==staff.duties_id).data
department = Departments.find_one(id=duties.department_id) department = Departments.find_one(Departments.id==duties.department_id).data
bulk_id = Duty.find_one(duty_code="BULK") bulk_id = Duty.filter_one(Duty.duty_code=="BULK").data
bulk_duty_id = Duties.find_one( bulk_duty_id = Duties.filter_one(
company_id=selected_company.id, duties_id=bulk_id.id Duties.company_id==selected_company.id,
) Duties.duties_id==bulk_id.id
).data
update_selected_to_redis( update_selected_to_redis(
request=request, request=request,
add_payload=CompanyToken( add_payload=CompanyToken(
@ -174,30 +176,36 @@ class AuthenticationSelectEventMethods(MethodToEvent):
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
) )
elif token_user.user_type == 2: elif token_user.user_type == 2:
occupant_type = OccupantTypes.find_one(uu_id=data.occupant_uu_id) occupant_type = OccupantTypes.filter_one(OccupantTypes.uu_id==data.occupant_uu_id).data
if not occupant_type: if not occupant_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail="Occupant Type is not found", detail="Occupant Type is not found",
) )
build_part = BuildParts.find_one(uu_id=data.build_part_uu_id) build_part = BuildParts.filter_one(BuildParts.uu_id==data.build_part_uu_id).data
if not build_part: if not build_part:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail="Build Part is not found", detail="Build Part is not found",
) )
build = Build.find_one(id=build_part.build_id) build = Build.filter_one(Build.id==build_part.build_id).data
related_company = RelationshipEmployee2Build.find_one(member_id=build.id) related_company = RelationshipEmployee2Build.filter_one(
company_related = Companies.find_one(id=related_company.company_id) RelationshipEmployee2Build.member_id==build.id
responsible_employee = Employees.find_one(id=related_company.employee_id) ).data
if selected_occupant_type := BuildLivingSpace.find_one( company_related = Companies.filter_one(
occupant_type=occupant_type.id, Companies.id==related_company.company_id
person_id=token_user.person_id, ).data
build_parts_id=build_part.id, responsible_employee = Employees.filter_one(
): Employees.id==related_company.employee_id
).data
if selected_occupant_type := BuildLivingSpace.filter_one(
BuildLivingSpace.occupant_type==occupant_type.id,
BuildLivingSpace.person_id==token_user.person_id,
BuildLivingSpace.build_parts_id==build_part.id,
).data:
reachable_event_list_id, reachable_event_list_uu_id = ( reachable_event_list_id, reachable_event_list_uu_id = (
Event2Occupant.get_event_id_by_build_living_space_id( Event2Occupant.get_event_id_by_build_living_space_id(
build_living_space_id=selected_occupant_type.id Event2Occupant.build_living_space_id==selected_occupant_type.id
) )
) )
update_selected_to_redis( update_selected_to_redis(
@ -242,7 +250,7 @@ class AuthenticationCheckTokenEventMethods(MethodToEvent):
@classmethod @classmethod
def authentication_login_with_domain_and_creds( def authentication_login_with_domain_and_creds(
cls, request, token_dict: dict = None cls, request, token_dict: typing.Union[EmployeeSelection, OccupantSelection],
): ):
if get_object_via_access_key(request=request): if get_object_via_access_key(request=request):
return JSONResponse( return JSONResponse(
@ -263,15 +271,17 @@ class AuthenticationRefreshEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def authentication_refresh_user_info(cls, request, token_dict: dict = None): def authentication_refresh_user_info(
cls, request, token_dict: typing.Union[EmployeeSelection, OccupantSelection],
):
access_token = str(request.headers.get(Auth.ACCESS_TOKEN_TAG)) access_token = str(request.headers.get(Auth.ACCESS_TOKEN_TAG))
if token_user := get_object_via_access_key(request=request): if token_user := get_object_via_access_key(request=request):
if found_user := Users.find_one(uu_id=token_user.get("uu_id")): if found_user := Users.filter_one(Users.uu_id==token_user.get("uu_id")).data:
user_token = UsersTokens.find_one( user_token = UsersTokens.filter_one(
domain=found_user.domain_name, UsersTokens.domain==found_user.domain_name,
user_id=found_user.id, UsersTokens.user_id==found_user.id,
token_type="RememberMe", UsersTokens.token_type=="RememberMe",
) ).data
access_dict = { access_dict = {
"access_token": access_token, "access_token": access_token,
"refresh_token": getattr(user_token, "token", None), "refresh_token": getattr(user_token, "token", None),
@ -299,11 +309,11 @@ class AuthenticationChangePasswordEventMethods(MethodToEvent):
@classmethod @classmethod
def authentication_change_password( def authentication_change_password(
cls, request, data: ChangePassword, token_dict: dict = None cls, request, data: ChangePassword, token_dict: typing.Union[EmployeeSelection, OccupantSelection],
): ):
token_user = get_object_via_access_key(request=request) token_user = get_object_via_access_key(request=request)
if token_user.user_type == 1: if token_user.user_type == 1:
if found_user := Users.find_one(uu_id=token_user.uu_id): if found_user := Users.filter_one(Users.uu_id==token_user.uu_id).data:
if found_user.check_password(data.old_password): if found_user.check_password(data.old_password):
found_user.set_password(data.new_password) found_user.set_password(data.new_password)
return JSONResponse( return JSONResponse(
@ -342,10 +352,12 @@ class AuthenticationCreatePasswordEventMethods(MethodToEvent):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match" status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match"
) )
if found_user := Users.find_one(password_token=data.password_token): if found_user := Users.filter_one(
Users.password_token==data.password_token
).data:
found_user.create_password(password=data.password) found_user.create_password(password=data.password)
found_user.password_token = None found_user.password_token = None
found_user.save() Users.save()
send_email_completed = send_email( send_email_completed = send_email(
subject=f"Dear {found_user.user_tag}, your password has been changed.", subject=f"Dear {found_user.user_tag}, your password has been changed.",
receivers=[str(found_user.email)], receivers=[str(found_user.email)],
@ -386,7 +398,9 @@ class AuthenticationDisconnectUserEventMethods(MethodToEvent):
): ):
if token_user := get_object_via_access_key(request=request): if token_user := get_object_via_access_key(request=request):
found_user = Users.find_one(uu_id=token_user.get("uu_id")) found_user = Users.filter_one(
Users.uu_id==token_user.get("uu_id")
).data
if not found_user: if not found_user:
return JSONResponse( return JSONResponse(
content={ content={
@ -400,7 +414,9 @@ class AuthenticationDisconnectUserEventMethods(MethodToEvent):
for key in already_tokens: for key in already_tokens:
token_user = json.loads(redis_cli.get(key) or {}) token_user = json.loads(redis_cli.get(key) or {})
redis_cli.delete(key) redis_cli.delete(key)
selected_user = Users.find_one(uu_id=token_user.get("uu_id")) selected_user = Users.filter_one(
Users.uu_id==token_user.get("uu_id")
).data
selected_user.remove_refresher_token( selected_user.remove_refresher_token(
domain=data.domain, disconnect=True domain=data.domain, disconnect=True
) )
@ -449,7 +465,9 @@ class AuthenticationLogoutEventMethods(MethodToEvent):
token_user = json.loads(redis_cli.get(key) or {}) token_user = json.loads(redis_cli.get(key) or {})
if token_user.get("domain") == data.domain: if token_user.get("domain") == data.domain:
redis_cli.delete(key) redis_cli.delete(key)
selected_user = Users.find_one(uu_id=token_user.get("uu_id")) selected_user = Users.filter_one(
Users.uu_id==token_user.get("uu_id")
).data
selected_user.remove_refresher_token(domain=data.domain) selected_user.remove_refresher_token(domain=data.domain)
# UserLogger.log_error( # UserLogger.log_error(
# str( # str(
@ -503,7 +521,9 @@ class AuthenticationRefreshTokenEventMethods(MethodToEvent):
content={"completed": False, "message": "Invalid data", "data": {}}, content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_202_ACCEPTED, status_code=status.HTTP_202_ACCEPTED,
) )
if found_user := Users.find_one(id=token_refresher.user_id): if found_user := Users.filter_one(
Users.id==token_refresher.user_id
).data:
found_user: Users = found_user found_user: Users = found_user
access_key = save_access_token_to_redis( access_key = save_access_token_to_redis(
request=request, found_user=found_user, domain=data.domain request=request, found_user=found_user, domain=data.domain
@ -513,7 +533,7 @@ class AuthenticationRefreshTokenEventMethods(MethodToEvent):
found_user.last_remote_addr = getattr( found_user.last_remote_addr = getattr(
request, "remote_addr", None request, "remote_addr", None
) or request.headers.get("X-Forwarded-For", None) ) or request.headers.get("X-Forwarded-For", None)
found_user.last_seen = str(DateTimeLocal.now()) found_user.last_seen = str(system_arrow.now())
# UserLogger.log_error( # UserLogger.log_error(
# str( # str(
# dict( # dict(
@ -595,7 +615,7 @@ class AuthenticationForgotPasswordEventMethods(MethodToEvent):
) )
found_user.password_token = forgot_key found_user.password_token = forgot_key
found_user.password_token_is_valid = str(DateTimeLocal.shift(days=1)) found_user.password_token_is_valid = str(system_arrow.shift(days=1))
found_user.save() found_user.save()
return JSONResponse( return JSONResponse(
@ -632,13 +652,13 @@ class AuthenticationDownloadAvatarEventMethods(MethodToEvent):
"remember_me": found_user.remember_me, "remember_me": found_user.remember_me,
"expiry_ends": str(found_user.expiry_ends), "expiry_ends": str(found_user.expiry_ends),
"expired_str": str( "expired_str": str(
DateTimeLocal.now() system_arrow.now()
- DateTimeLocal.get(str(found_user.expiry_ends)) - system_arrow.get(str(found_user.expiry_ends))
), ),
"expired_int": int( "expired_int": int(
( (
DateTimeLocal.now() system_arrow.now()
- DateTimeLocal.get(str(found_user.expiry_ends)) - system_arrow.get(str(found_user.expiry_ends))
).days ).days
), ),
}, },

View File

@ -39,16 +39,18 @@ class BuildListEventMethods(MethodToEvent):
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject], token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
): ):
if isinstance(token_dict, OccupantTokenObject): if isinstance(token_dict, OccupantTokenObject):
Build.pre_query = Build.filter_active( Build.pre_query = Build.filter_all(
Build.id == token_dict.selected_occupant.build_id Build.id == token_dict.selected_occupant.build_id,
Build.active == True,
).query ).query
elif isinstance(token_dict, EmployeeTokenObject): elif isinstance(token_dict, EmployeeTokenObject):
Build.pre_query = Build.select_action( Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id employee_id=token_dict.selected_company.employee_id
) )
Build.filter_attr = list_options Build.filter_attr = list_options
records = Build.filter_active( records = Build.filter_all(
*Build.get_smart_query(smart_query=list_options.query) *Build.get_smart_query(smart_query=list_options.query),
Build.active == True,
) )
return AlchemyJsonResponse( return AlchemyJsonResponse(
completed=True, completed=True,
@ -81,13 +83,13 @@ class BuildCreateEventMethods(MethodToEvent):
created_build = Build.create_action(data=data, token=token_dict) created_build = Build.create_action(data=data, token=token_dict)
if not created_build.is_found: if not created_build.is_found:
build_type = BuildTypes.find_one(type_code="APT_YNT") build_type = BuildTypes.filter_by_one(type_code="APT_YNT").data
if not build_type: if not build_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail="Build type APT_YNT is not found. Please contact with your system administrator.", detail="Build type APT_YNT is not found. Please contact with your system administrator.",
) )
api_enum = ApiEnumDropdown.find_one(enum_class="Directions", key="NN") api_enum = ApiEnumDropdown.filter_by_one(enum_class="Directions", key="NN").data
if not api_enum: if not api_enum:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -107,8 +109,8 @@ class BuildCreateEventMethods(MethodToEvent):
is_confirmed=True, is_confirmed=True,
) )
man_build_part = BuildParts.find_or_create(**build_parts) man_build_part = BuildParts.find_or_create(**build_parts)
if not man_build_part.is_found: created_build.update(management_room_id=man_build_part.id)
created_build.update(management_room_id=man_build_part.id) BuildParts.save()
return JSONResponse( return JSONResponse(
content={ content={
"completed": True, "completed": True,
@ -148,24 +150,19 @@ class BuildCreateEventMethods(MethodToEvent):
) )
created_build = Build.create_action(data=data, token=token_dict) created_build = Build.create_action(data=data, token=token_dict)
if not created_build.is_found: RelationshipEmployee2Build.find_or_create(
RelationshipEmployee2Build.find_or_create( company_id=token_dict.selected_company.company_id,
company_id=token_dict.selected_company.company_id, member_id=created_build.id,
member_id=created_build.id, employee_id=token_dict.selected_company.employee_id,
employee_id=token_dict.selected_company.employee_id, is_confirmed=True,
is_confirmed=True, )
) return JSONResponse(
return JSONResponse( content={
content={ "completed": True,
"completed": True, "message": "Create Build record completed. This build is assigned to you.",
"message": "Create Build record completed. This build is assigned to you.", "data": created_build.get_dict(),
"data": created_build.get_dict(), },
}, status_code=status.HTTP_200_OK,
status_code=status.HTTP_200_OK,
)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Build record create not successful for {token_dict.selected_company.employee_uu_id}",
) )
@ -181,10 +178,12 @@ class BuildUpdateEventMethods(MethodToEvent):
Build.pre_query = Build.select_action( Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id employee_id=token_dict.selected_company.employee_id
) )
if Build.filter_active(Build.person_id == token_dict.person_id): if Build.filter_all(Build.person_id == token_dict.person_id):
Build.pre_query = None
if updated_build := Build.update_action( if updated_build := Build.update_action(
data=data, token=token_dict, build_uu_id=build_uu_id data=data, token=token_dict, build_uu_id=build_uu_id
): ):
Build.save()
return JSONResponse( return JSONResponse(
content={ content={
"completed": True, "completed": True,

View File

@ -1,3 +1,5 @@
from typing import Union
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from fastapi import status from fastapi import status
@ -23,7 +25,9 @@ class BuildingBuildPartsListEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def building_build_parts_list(cls, list_options: ListOptions, token_dict): def building_build_parts_list(
cls, list_options: ListOptions, token_dict: Union[EmployeeTokenObject, OccupantTokenObject]
):
build_list_query = Build.select_action( build_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id, employee_id=token_dict.selected_company.employee_id,
) )
@ -49,7 +53,9 @@ class BuildingBuildPartsCreateEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def building_build_parts_create(cls, data: InsertBuildParts, token_dict: dict): def building_build_parts_create(
cls, data: InsertBuildParts, token_dict: Union[EmployeeTokenObject, OccupantTokenObject]
):
created_build = BuildParts.create_action(data=data, token=token_dict) created_build = BuildParts.create_action(data=data, token=token_dict)
if not created_build: if not created_build:
return JSONResponse( return JSONResponse(
@ -79,7 +85,9 @@ class BuildingBuildPartsUpdateEventMethods(MethodToEvent):
} }
@classmethod @classmethod
def building_build_parts_update(cls, data: InsertBuildParts, token_dict: dict): def building_build_parts_update(
cls, data: InsertBuildParts, token_dict: Union[EmployeeTokenObject, OccupantTokenObject]
):
if updated_build := BuildParts.update_action(data=data, token=token_dict): if updated_build := BuildParts.update_action(data=data, token=token_dict):
updated_build.save() updated_build.save()
return JSONResponse( return JSONResponse(
@ -109,7 +117,7 @@ class BuildingBuildPartsPatchEventMethods(MethodToEvent):
@classmethod @classmethod
def building_build_parts_patch(cls, data, token_dict): def building_build_parts_patch(cls, data, token_dict):
find_one_build = BuildParts.find_one(uu_id=data.uu_id) find_one_build = BuildParts.filter_one(BuildParts.uu_id==data.uu_id).data
access_authorized_build = BuildParts.select_action( access_authorized_build = BuildParts.select_action(
duty_id=token_dict.selected_company.duty_id, duty_id=token_dict.selected_company.duty_id,
filter_expr=[BuildParts.id == find_one_build.id], filter_expr=[BuildParts.id == find_one_build.id],

View File

@ -35,17 +35,19 @@ class BuildingLivingSpacesPartsListEventMethods(MethodToEvent):
employee_id=token_dict.selected_company.employee_id employee_id=token_dict.selected_company.employee_id
) )
Build.filter_attr = list_options Build.filter_attr = list_options
build_part_id_list_query = BuildParts.filter_active( build_part_id_list_query = BuildParts.filter_all(
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]), BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
) BuildParts.active == True,
).data
list_options.query.pop("expiry_starts", None) list_options.query.pop("expiry_starts", None)
list_options.query.pop("expiry_ends", None) list_options.query.pop("expiry_ends", None)
records = BuildLivingSpace.filter_active( records = BuildLivingSpace.filter_all(
BuildLivingSpace.build_parts_id.in_( BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_part_id_list_query.data] [build_part.id for build_part in build_part_id_list_query]
), ),
BuildLivingSpace.active == True,
*BuildLivingSpace.get_smart_query(smart_query=list_options.query), *BuildLivingSpace.get_smart_query(smart_query=list_options.query),
) )
return AlchemyJsonResponse( return AlchemyJsonResponse(
@ -62,17 +64,17 @@ class BuildingLivingSpacesPartsListEventMethods(MethodToEvent):
employee_id=token_dict.selected_company.employee_id employee_id=token_dict.selected_company.employee_id
) )
Build.filter_attr = list_options Build.filter_attr = list_options
build_part_id_list_query = BuildParts.filter_active( build_part_id_list_query = BuildParts.filter_all(
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]), BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
) BuildParts.active == True,
).data
records = BuildLivingSpace.filter_active( records = BuildLivingSpace.filter_all(
BuildLivingSpace.build_parts_id.in_( BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_part_id_list_query.data] [build_part.id for build_part in build_part_id_list_query]
), ),
*BuildLivingSpace.get_smart_query(smart_query=list_options.query), *BuildLivingSpace.get_smart_query(smart_query=list_options.query),
expired=False, ).data
)
return AlchemyJsonResponse( return AlchemyJsonResponse(
completed=True, completed=True,
message="Building Living Spaces are listed successfully", message="Building Living Spaces are listed successfully",
@ -103,15 +105,14 @@ class BuildingLivingSpacesPartsCreateEventMethods(MethodToEvent):
build_part = BuildParts.filter_one( build_part = BuildParts.filter_one(
BuildParts.uu_id == data.build_parts_uu_id, BuildParts.uu_id == data.build_parts_uu_id,
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]), BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
) ).data
if not build_part.data: if not build_part:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id", detail=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id",
) )
build_part = build_part.data
life_person = People.find_one(uu_id=data.person_uu_id or "") life_person = People.filter_one(People.uu_id==data.person_uu_id or "").data
if not life_person: if not life_person:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_418_IM_A_TEAPOT,
@ -119,7 +120,7 @@ class BuildingLivingSpacesPartsCreateEventMethods(MethodToEvent):
f"Check build live person uu_id", f"Check build live person uu_id",
) )
occupant_type = OccupantTypes.find_one(uu_id=data.occupant_type_uu_id) occupant_type = OccupantTypes.filter_by_one(uu_id=data.occupant_type_uu_id).data
if not occupant_type: if not occupant_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_418_IM_A_TEAPOT,
@ -134,21 +135,18 @@ class BuildingLivingSpacesPartsCreateEventMethods(MethodToEvent):
data_dict["person_id"] = life_person.id data_dict["person_id"] = life_person.id
data_dict["person_uu_id"] = str(life_person.uu_id) data_dict["person_uu_id"] = str(life_person.uu_id)
living_space_id = BuildLivingSpace.session.execute( living_space_id = BuildLivingSpace.select_only(
select(BuildLivingSpace.id) BuildLivingSpace.build_parts_id == build_part.id,
.where( BuildLivingSpace.person_id == life_person.id,
*[ BuildLivingSpace.occupant_type == occupant_type.id,
BuildLivingSpace.build_parts_id == build_part.id, BuildLivingSpace.active == True,
BuildLivingSpace.person_id == life_person.id, BuildLivingSpace.is_confirmed == True,
BuildLivingSpace.occupant_type == occupant_type.id, str(system_arrow.now()) < BuildLivingSpace.expiry_ends,
BuildLivingSpace.active == True, str(system_arrow.now()) >= BuildLivingSpace.expiry_starts,
BuildLivingSpace.is_confirmed == True, select_args=[BuildLivingSpace.id],
str(system_arrow.now()) < BuildLivingSpace.expiry_ends, order_by=BuildLivingSpace.expiry_starts.desc(),
str(system_arrow.now()) >= BuildLivingSpace.expiry_starts, limit=1
] ).data
)
.order_by(BuildLivingSpace.expiry_starts.desc())
).first()
last_living_space = BuildLivingSpace.filter_one( last_living_space = BuildLivingSpace.filter_one(
BuildLivingSpace.id == living_space_id[0] if living_space_id else None BuildLivingSpace.id == living_space_id[0] if living_space_id else None
@ -160,11 +158,11 @@ class BuildingLivingSpacesPartsCreateEventMethods(MethodToEvent):
) )
if last_living_space: if last_living_space:
if last_living_space.expiry_ends > system_arrow.now(): if last_living_space.expiry_ends > str(system_arrow.now()):
last_living_space.expiry_ends = str(system_arrow.shift(minutes=-10)) last_living_space.expiry_ends = str(system_arrow.shift(minutes=-10))
last_living_space.save() last_living_space.save()
user_module = Modules.filter_one(Modules.module_code == "USR-PUB") user_module = Modules.filter_one(Modules.module_code == "USR-PUB", system=True).data
ModulesBindOccupantEventMethods.modules_bind_occupant_system( ModulesBindOccupantEventMethods.modules_bind_occupant_system(
build_living_space_id=created_living_space.id, build_living_space_id=created_living_space.id,
modules_id=user_module.id, modules_id=user_module.id,
@ -189,18 +187,18 @@ class BuildingLivingSpacesPartsUpdateEventMethods(MethodToEvent):
build_id_list_query = Build.select_action( build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id employee_id=token_dict.selected_company.employee_id
) )
build_part = BuildParts.filter_active( build_part = BuildParts.filter_one(
BuildParts.uu_id == data.build_parts_uu_id, BuildParts.uu_id == data.build_parts_uu_id,
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]), BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
) BuildParts.active == True,
if not build_part.get(1): ).data
if not build_part:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id", detail=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id",
) )
build_part = build_part.get(1)
life_person = People.find_one(uu_id=data.life_person_uu_id or "") life_person = People.filter_one(People.uu_id==data.life_person_uu_id or "").data
if not life_person: if not life_person:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_418_IM_A_TEAPOT,
@ -208,15 +206,15 @@ class BuildingLivingSpacesPartsUpdateEventMethods(MethodToEvent):
f"Check build live person uu_id", f"Check build live person uu_id",
) )
living_spaces = select(BuildLivingSpace.id).order_by( living_space_id = BuildLivingSpace.select_only(
BuildLivingSpace.expiry_starts.desc() select_args=[BuildLivingSpace.id],
) order_by=BuildLivingSpace.expiry_starts.desc(),
living_space_id = BuildLivingSpace.session.execute(living_spaces).first() limit=1
).get(1)
last_living_space = BuildLivingSpace.filter_one( last_living_space = BuildLivingSpace.filter_one(
BuildLivingSpace.id == getattr(living_space_id[0], "id", None) BuildLivingSpace.id == living_space_id if living_space_id else None
if living_space_id ).data
else None
)
data_dict["expiry_starts"] = str(system_arrow.now()) data_dict["expiry_starts"] = str(system_arrow.now())
data_dict["is_tenant_live"] = bool(data.is_tenant_live) data_dict["is_tenant_live"] = bool(data.is_tenant_live)

View File

@ -18,7 +18,7 @@ from api_validations.validations_request import (
from api_events.events.abstract_class import MethodToEvent, ActionsSchema from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import AlchemyJsonResponse from api_validations.core_response import AlchemyJsonResponse
from api_library.date_time_actions.date_functions import DateTimeLocal from api_library.date_time_actions.date_functions import DateTimeLocal, system_arrow
class DecisionBookListEventMethods(MethodToEvent): class DecisionBookListEventMethods(MethodToEvent):
@ -46,15 +46,17 @@ class DecisionBookListEventMethods(MethodToEvent):
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}", detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
) )
records = BuildDecisionBook.filter_active( records = BuildDecisionBook.filter_all(
BuildDecisionBook.build_id.in_([build.id for build in build_id_list]), BuildDecisionBook.build_id.in_([build.id for build in build_id_list]),
*BuildDecisionBook.get_smart_query(list_options.query), *BuildDecisionBook.get_smart_query(list_options.query),
) BuildDecisionBook.active == True,
).data
elif isinstance(token_dict, OccupantTokenObject): elif isinstance(token_dict, OccupantTokenObject):
records = BuildDecisionBook.filter_active( records = BuildDecisionBook.filter_all(
BuildDecisionBook.build_id == token_dict.selected_occupant.build_id, BuildDecisionBook.build_id == token_dict.selected_occupant.build_id,
*BuildDecisionBook.get_smart_query(list_options.query), *BuildDecisionBook.get_smart_query(list_options.query),
) BuildDecisionBook.active == True,
).data
return AlchemyJsonResponse( return AlchemyJsonResponse(
completed=True, completed=True,
message="DecisionBook are listed successfully", message="DecisionBook are listed successfully",
@ -80,15 +82,16 @@ class DecisionBookCreateEventMethods(MethodToEvent):
Build.pre_query = Build.select_action( Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id employee_id=token_dict.selected_company.employee_id
) )
build = Build.filter_active( build = Build.filter_one(
Build.uu_id == data.build_uu_id, Build.uu_id == data.build_uu_id,
) Build.active == True,
if not build.data: ).get(1)
if not build:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Emloyee UUID {token_dict.selected_company.employee_uu_id} has no build with given UUID {data_dict.get('build_uu_id')}", detail=f"Emloyee UUID {token_dict.selected_company.employee_uu_id} has no build with given UUID {data_dict.get('build_uu_id')}",
) )
data_dict["build_id"] = build.data[0].id data_dict["build_id"] = build.id
if data.resp_company_uu_id: if data.resp_company_uu_id:
Companies.pre_query = Companies.select_action( Companies.pre_query = Companies.select_action(
duty_id_list=[ duty_id_list=[
@ -96,21 +99,22 @@ class DecisionBookCreateEventMethods(MethodToEvent):
token_dict.selected_company.bulk_duties_id, token_dict.selected_company.bulk_duties_id,
] ]
) )
company = Companies.filter_active( company = Companies.filter_one(
Companies.uu_id == data.resp_company_uu_id Companies.uu_id == data.resp_company_uu_id,
) Companies.active == True,
if not company.data: ).get(1)
if not company:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Duty UUID {token_dict.selected_company.duty_uu_id} has no company with given UUID {data_dict.get('resp_company_uu_id')}", detail=f"Duty UUID {token_dict.selected_company.duty_uu_id} has no company with given UUID {data_dict.get('resp_company_uu_id')}",
) )
data_dict["resp_company_id"] = company.data[0].id data_dict["resp_company_id"] = company.id
data_dict["resp_company_uu_id"] = str(company.data[0].uu_id) data_dict["resp_company_uu_id"] = str(company.uu_id)
build_object = build.data[0]
decision_period_date = DateTimeLocal.get(build_object.decision_period_date) decision_period_date = DateTimeLocal.get(build.decision_period_date)
data_dict["expiry_starts"] = DateTimeLocal.get( data_dict["expiry_starts"] = DateTimeLocal.get(
DateTimeLocal.now().date().year, system_arrow.now().date().year,
int(decision_period_date.date().month), int(decision_period_date.date().month),
int(decision_period_date.date().day), int(decision_period_date.date().day),
) )
@ -138,20 +142,24 @@ class DecisionBookCreateEventMethods(MethodToEvent):
detail="Only Build Manager can create decision book", detail="Only Build Manager can create decision book",
) )
occupant_build = Build.find_one(id=token_dict.selected_occupant.build_id) occupant_build = Build.filter_one(
Build.id==token_dict.selected_occupant.build_id,
Build.active == True,
).get(1)
occupant_company = Companies.find_one( occupant_company = Companies.find_one(
id=token_dict.selected_occupant.responsible_company_id Companies.id==token_dict.selected_occupant.responsible_company_id,
) Companies.active == True,
).get(1)
data_dict["build_id"] = occupant_build.id data_dict["build_id"] = occupant_build.id
data_dict["build_uu_id"] = str(occupant_build.uu_id) data_dict["build_uu_id"] = str(occupant_build.uu_id)
data_dict["resp_company_id"] = occupant_company.id data_dict["resp_company_id"] = occupant_company.id
data_dict["resp_company_uu_id"] = str(occupant_company.uu_id) data_dict["resp_company_uu_id"] = str(occupant_company.uu_id)
decision_period_date = DateTimeLocal.get( decision_period_date = system_arrow.get(
occupant_build.decision_period_date occupant_build.decision_period_date
) )
data_dict["expiry_starts"] = DateTimeLocal.get( data_dict["expiry_starts"] = DateTimeLocal.get(
DateTimeLocal.now().date().year, system_arrow.now().date().year,
int(decision_period_date.date().month), int(decision_period_date.date().month),
int(decision_period_date.date().day), int(decision_period_date.date().day),
) )

View File

@ -75,7 +75,9 @@ class DecisionBookDecisionBookItemsListEventMethods(MethodToEvent):
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"No company is match with given Employee UUID {token_dict.selected_company.employee_uu_id}", detail=f"No company is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
) )
BuildDecisionBookItems.filter_attr = BuildDecisionBookItems.FilterModel(**data.dump()) BuildDecisionBookItems.filter_attr = BuildDecisionBookItems.FilterModel(
**data.dump()
)
records = BuildDecisionBookItems.filter_active( records = BuildDecisionBookItems.filter_active(
BuildDecisionBookItems.build_decision_book_id == decision_book.id BuildDecisionBookItems.build_decision_book_id == decision_book.id
) )

View File

@ -5,7 +5,6 @@ from databases import (
BuildParts, BuildParts,
BuildDecisionBook, BuildDecisionBook,
BuildDecisionBookItems, BuildDecisionBookItems,
BuildDecisionBookPerson, BuildDecisionBookPerson,
BuildDecisionBookPayments, BuildDecisionBookPayments,
BuildDecisionBookProjects, BuildDecisionBookProjects,
@ -21,6 +20,7 @@ from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObj
from api_validations.core_response import AlchemyJsonResponse from api_validations.core_response import AlchemyJsonResponse
from api_library.date_time_actions.date_functions import system_arrow, client_arrow from api_library.date_time_actions.date_functions import system_arrow, client_arrow
class DecisionBookDecisionBookItemsDebitsListEventMethods(MethodToEvent): class DecisionBookDecisionBookItemsDebitsListEventMethods(MethodToEvent):
event_type = "SELECT" event_type = "SELECT"
@ -47,6 +47,7 @@ class DecisionBookDecisionBookItemsDebitsListEventMethods(MethodToEvent):
result=records, result=records,
) )
class DecisionBookDecisionBookItemsDebitsCreateEventMethods(MethodToEvent): class DecisionBookDecisionBookItemsDebitsCreateEventMethods(MethodToEvent):
event_type = "CREATE" event_type = "CREATE"
@ -100,4 +101,3 @@ class DecisionBookDecisionBookItemsDebitsCreateEventMethods(MethodToEvent):
message="Decision Book Items Debits are listed", message="Decision Book Items Debits are listed",
result=records, result=records,
) )

View File

@ -69,9 +69,9 @@ class DecisionBookPersonAddEventMethods(MethodToEvent):
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"No Decision Book is match with given UUID {data.build_decision_book_uu_id}", detail=f"No Decision Book is match with given UUID {data.build_decision_book_uu_id}",
) )
manager_occupant_type = OccupantTypes.find_or_abort( manager_occupant_type = OccupantTypes.filter_by_one(
occupant_code="BU-MNG", occupant_category_type="BU" occupant_code="BU-MNG", occupant_category_type="BU"
) ).get(1)
if ( if (
not manager_occupant_type.uu_id not manager_occupant_type.uu_id
== token_dict.selected_occupant.occupant_type_uu_id == token_dict.selected_occupant.occupant_type_uu_id
@ -81,42 +81,42 @@ class DecisionBookPersonAddEventMethods(MethodToEvent):
detail="Only Build Manager can update the invitation", detail="Only Build Manager can update the invitation",
) )
assign_occupant_type = OccupantTypes.find_or_abort( assign_occupant_type = OccupantTypes.filter_by_one(
uu_id=data.occupant_type_uu_id, uu_id=data.occupant_type_uu_id,
occupant_category_type="MT", occupant_category_type="MT",
) ).get(1)
if not assign_occupant_type: if not assign_occupant_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Occupant type must be a Meeting Type {data.occupant_type_uu_id} is not a MT type occupant", detail=f"Occupant type must be a Meeting Type {data.occupant_type_uu_id} is not a MT type occupant",
) )
manger_book_person = BuildDecisionBookPerson.find_one( manger_book_person = BuildDecisionBookPerson.filter_one(
token=data.token, BuildDecisionBookPerson.token==data.token,
build_decision_book_uu_id=data.build_decision_book_uu_id, BuildDecisionBookPerson.build_decision_book_uu_id==data.build_decision_book_uu_id,
is_confirmed=True, BuildDecisionBookPerson.is_confirmed==True,
active=True, BuildDecisionBookPerson.active==True,
) ).get(1)
if not manger_book_person: if not manger_book_person:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail="Manager person not found. Please check token", detail="Manager person not found. Please check token",
) )
book_invite = BuildDecisionBookInvitations.find_one( book_invite = BuildDecisionBookInvitations.filter_one(
id=manger_book_person.invite_id, BuildDecisionBookInvitations.id==manger_book_person.invite_id,
build_id=token_dict.selected_occupant.build_id, BuildDecisionBookInvitations.build_id==token_dict.selected_occupant.build_id,
) ).get(1)
if not book_invite: if not book_invite:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail="Invitation not found. Please check token", detail="Invitation not found. Please check token",
) )
selected_book_person = BuildDecisionBookPerson.find_one( selected_book_person = BuildDecisionBookPerson.filter_one(
invite_id=book_invite.id, BuildDecisionBookPerson.invite_id==book_invite.id,
person_uu_id=data.person_uu_id, BuildDecisionBookPerson.person_uu_id==data.person_uu_id,
is_confirmed=True, BuildDecisionBookPerson.is_confirmed==True,
active=True, BuildDecisionBookPerson.active==True,
) ).get(1)
if not selected_book_person: if not selected_book_person:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -171,10 +171,12 @@ class DecisionBookPersonAttendEventMethods(MethodToEvent):
detail="Employee cannot create decision book invitations", detail="Employee cannot create decision book invitations",
) )
token_user = Users.find_one(id=token_dict.user_id) token_user = Users.filter_one(Users.id==token_dict.user_id).get(1)
invitation_person = BuildDecisionBookPerson.find_one( invitation_person = BuildDecisionBookPerson.filter_one(
token=data.token, active=True, is_confirmed=True BuildDecisionBookPerson.token==data.token,
) BuildDecisionBookPerson.active==True,
BuildDecisionBookPerson.is_confirmed==True
).get(1)
if not invitation_person: if not invitation_person:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -189,10 +191,11 @@ class DecisionBookPersonAttendEventMethods(MethodToEvent):
# detail=f"Invitation for the user {token_user.email} is not valid. Please check token", # detail=f"Invitation for the user {token_user.email} is not valid. Please check token",
# ) # )
# todo check if vicarious person is valid # todo check if vicarious person is valid
invitation = BuildDecisionBookInvitations.find_one( invitation = BuildDecisionBookInvitations.filter_one(
id=invitation_person.invite_id, BuildDecisionBookInvitations.id==invitation_person.invite_id,
build_id=token_dict.selected_occupant.build_id, BuildDecisionBookInvitations.build_id==token_dict.selected_occupant.build_id,
) BuildDecisionBookInvitations.active==True,
).get(1)
if not invitation: if not invitation:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -236,66 +239,60 @@ class DecisionBookPersonAssignOccupantEventMethods(MethodToEvent):
detail="Employee cannot create decision book invitations", detail="Employee cannot create decision book invitations",
) )
book_person_manager = BuildDecisionBookPerson.find_one( book_person_manager = BuildDecisionBookPerson.filter_one(
token=data.token, BuildDecisionBookPerson.token==data.token,
build_living_space_id=token_dict.selected_occupant.living_space_id, BuildDecisionBookPerson.build_living_space_id==token_dict.selected_occupant.living_space_id,
active=True, BuildDecisionBookPerson.active==True,
is_confirmed=True, BuildDecisionBookPerson.is_confirmed==True,
) ).get(1)
manager_occupant_type = OccupantTypes.find_or_abort( manager_occupant_type = OccupantTypes.filter_by_one(
occupant_code="BU-MNG", occupant_category_type="BU" occupant_code="BU-MNG", occupant_category_type="BU"
) ).get(1)
book_person_manager.check_occupant_type(manager_occupant_type) book_person_manager.check_occupant_type(manager_occupant_type)
# supervisor_occupant_type = OccupantTypes.find_or_abort(occupant_code="BU-SPV", occupant_category_type="BU") # supervisor_occupant_type = OccupantTypes.find_or_abort(occupant_code="BU-SPV", occupant_category_type="BU")
# book_person_supervisor.check_occupant_type(supervisor_occupant_type) # book_person_supervisor.check_occupant_type(supervisor_occupant_type)
invitation = BuildDecisionBookInvitations.find_one( invitation = BuildDecisionBookInvitations.filter_one(
id=book_person_manager.invite_id, BuildDecisionBookInvitations.id==book_person_manager.invite_id,
build_id=token_dict.selected_occupant.build_id, BuildDecisionBookInvitations.build_id==token_dict.selected_occupant.build_id,
active=True, BuildDecisionBookInvitations.active==True,
is_confirmed=True, ).get(1)
)
if not invitation: if not invitation:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation not found. Please check token", detail=f"Invitation not found. Please check token",
) )
assign_occupant_type = OccupantTypes.find_or_abort( assign_occupant_type = OccupantTypes.filter_by_one(
uu_id=data.occupant_type_uu_id, is_confirmed=True, active=True uu_id=data.occupant_type_uu_id, active=True
) ).get(1)
if not assign_occupant_type: if not assign_occupant_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Occupant type must be a Meeting Type {data.occupant_type_uu_id} is not a MT type occupant", detail=f"Occupant type must be a Meeting Type {data.occupant_type_uu_id} is not a MT type occupant",
) )
build_parts_of_token = BuildParts.filter_active( build_parts_of_token = BuildParts.filter_all(
BuildParts.build_id == token_dict.selected_occupant.build_id, BuildParts.build_id == token_dict.selected_occupant.build_id,
) ).data
selected_living_space = BuildLivingSpace.filter_active( selected_living_space = BuildLivingSpace.filter_one(
BuildLivingSpace.uu_id == data.build_living_space_uu_id, BuildLivingSpace.uu_id == data.build_living_space_uu_id,
BuildLivingSpace.build_parts_id.in_( BuildLivingSpace.build_parts_id.in_(
[build.id for build in build_parts_of_token.data] [build.id for build in build_parts_of_token]
), ),
) ).get(1)
if not selected_living_space:
if not selected_living_space.data:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Person not found. Please check person uuid", detail=f"Person not found. Please check person uuid",
) )
selected_living_space = selected_living_space.get(1) book_person_to_assign: BuildDecisionBookPerson = BuildDecisionBookPerson.filter_one(
book_person_to_assign: BuildDecisionBookPerson = ( BuildDecisionBookPerson.build_living_space_id==selected_living_space.id,
BuildDecisionBookPerson.find_one( BuildDecisionBookPerson.invite_id==invitation.id,
build_living_space_id=selected_living_space.id, BuildDecisionBookPerson.active==True
invite_id=invitation.id, ).get(1)
active=True,
is_confirmed=True,
)
)
if not book_person_to_assign: if not book_person_to_assign:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -309,16 +306,16 @@ class DecisionBookPersonAssignOccupantEventMethods(MethodToEvent):
) )
if assign_occupant_type.occupant_code in ("MT-PRS", "MT-WRT"): if assign_occupant_type.occupant_code in ("MT-PRS", "MT-WRT"):
occupant_type_unique = OccupantTypes.find_or_abort( occupant_type_unique = OccupantTypes.filter_by_one(
occupant_code=assign_occupant_type.occupant_code, occupant_code=assign_occupant_type.occupant_code,
occupant_category_type="MT", occupant_category_type="MT",
) ).get(1)
if assigned_book_person_occupant := BuildDecisionBookPersonOccupants.find_one( if assigned_book_person_occupant := BuildDecisionBookPersonOccupants.filter_one(
invite_id=invitation.id, BuildDecisionBookPersonOccupants.invite_id==invitation.id,
occupant_type_id=occupant_type_unique.id, BuildDecisionBookPersonOccupants.occupant_type_id==occupant_type_unique.id,
active=True, BuildDecisionBookPersonOccupants.active==True,
is_confirmed=True, BuildDecisionBookPersonOccupants.is_confirmed==True,
): ).get(1):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Only one person can be assigned to {assign_occupant_type.occupant_code} type" detail=f"Only one person can be assigned to {assign_occupant_type.occupant_code} type"
@ -326,13 +323,13 @@ class DecisionBookPersonAssignOccupantEventMethods(MethodToEvent):
) )
if assign_occupant_type.occupant_code == "BU-MNG": if assign_occupant_type.occupant_code == "BU-MNG":
person_occupant_manager = BuildDecisionBookPersonOccupants.find_one( person_occupant_manager = BuildDecisionBookPersonOccupants.filter_one(
invite_id=invitation.id, BuildDecisionBookPersonOccupants.invite_id==invitation.id,
occupant_type_id=manager_occupant_type.id, BuildDecisionBookPersonOccupants.occupant_type_id==manager_occupant_type.id,
active=True, BuildDecisionBookPersonOccupants.active==True,
is_confirmed=True, BuildDecisionBookPersonOccupants.is_confirmed==True,
) )
person_occupant_manager.delete(destroy=True) person_occupant_manager.query.delete()
book_person_to_assign.add_occupant_type( book_person_to_assign.add_occupant_type(
occupant_type=assign_occupant_type, occupant_type=assign_occupant_type,

View File

@ -62,9 +62,9 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
detail="Employee cannot create decision book invitations", detail="Employee cannot create decision book invitations",
) )
# Check token posses the occupant type of Build Manager # Check token posses the occupant type of Build Manager
occupant_manager = OccupantTypes.find_one( occupant_manager = OccupantTypes.filter_by_one(
occupant_category_type="BU", occupant_code="BU-MNG" occupant_category_type="BU", occupant_code="BU-MNG"
) ).get(1)
if not token_dict.selected_occupant.occupant_type_id == occupant_manager.id: if not token_dict.selected_occupant.occupant_type_id == occupant_manager.id:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
@ -72,21 +72,24 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
) )
# Check decision book is valid for this token and building # Check decision book is valid for this token and building
decision_book = BuildDecisionBook.find_one( decision_book = BuildDecisionBook.filter_one(
uu_id=data.build_decision_book_uu_id, BuildDecisionBook.uu_id==data.build_decision_book_uu_id,
build_id=token_dict.selected_occupant.build_id, BuildDecisionBook.build_id==token_dict.selected_occupant.build_id,
) BuildDecisionBook.active==True,
).get(1)
if not decision_book: if not decision_book:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail="Decision book not found. Please create decision book first", detail="Decision book not found. Please create decision book first",
) )
occupant_building = Build.find_one(id=token_dict.selected_occupant.build_id) occupant_building = Build.filter_one(
Build.id==token_dict.selected_occupant.build_id
).get(1)
# Check meeting type is valid # Check meeting type is valid
meeting_type = ApiEnumDropdown.find_one( meeting_type = ApiEnumDropdown.filter_by_one(
enum_class="MeetingTypes", enum_class="MeetingTypes",
) ).get(1)
if not meeting_type: if not meeting_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
@ -104,6 +107,9 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
) )
# Create an invitation for specific invitation type to start invite sending process # Create an invitation for specific invitation type to start invite sending process
planned_date_expires = str(
system_arrow.get(data.planned_date).shift(days=15).date()
),
book_invitation = BuildDecisionBookInvitations.find_or_create( book_invitation = BuildDecisionBookInvitations.find_or_create(
build_id=token_dict.selected_occupant.build_id, build_id=token_dict.selected_occupant.build_id,
build_uu_id=token_dict.selected_occupant.build_uuid, build_uu_id=token_dict.selected_occupant.build_uuid,
@ -114,9 +120,7 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
living_part_percentage=0.51, living_part_percentage=0.51,
message=data.message, message=data.message,
planned_date=data.planned_date, planned_date=data.planned_date,
planned_date_expires=str( planned_date_expires=planned_date_expires,
system_arrow.get(data.planned_date).shift(days=15).date()
),
expiry_ends=str(system_arrow.get(data.planned_date).shift(days=15).date()), expiry_ends=str(system_arrow.get(data.planned_date).shift(days=15).date()),
is_confirmed=True, is_confirmed=True,
) )
@ -131,25 +135,22 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
) )
# Get all the parts of the building that is occupant in token # Get all the parts of the building that is occupant in token
build_parts = BuildParts.filter_active( build_parts = BuildParts.filter_all(
BuildParts.build_id == occupant_building.id BuildParts.build_id == occupant_building.id,
) BuildParts.active == True
).data
# Get all build living spaces that is found in building with distinct person id # Get all build living spaces that is found in building with distinct person id
occupants = OccupantTypes.filter_all() occupants = OccupantTypes.filter_all(system=True)
build_living_spaces_people = ( BuildLivingSpace.filter_attr = None
BuildLivingSpace.filter_active( build_living_spaces_people = BuildLivingSpace.filter_all(
BuildLivingSpace.build_parts_id.in_( BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_parts.data] [build_part.id for build_part in build_parts.data]
), ),
BuildLivingSpace.occupant_type.in_( BuildLivingSpace.occupant_type.in_(
[occupant.id for occupant in occupants.data] [occupant.id for occupant in occupants.data]
), ),
filter_records=False, ).query.distinct(BuildLivingSpace.person_id).all()
)
.query.distinct(BuildLivingSpace.person_id)
.all()
)
if not build_living_spaces_people: if not build_living_spaces_people:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
@ -199,21 +200,22 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
invitations_person.add_occupant_type(occupant_type=attendance_occupant_type) invitations_person.add_occupant_type(occupant_type=attendance_occupant_type)
if invitations_person and not invitations_person.is_found: if invitations_person and not invitations_person.is_found:
print(f'"{invitations_person.token}",') print(f'"{invitations_person.token}",')
spaces_user = Users.find_one( spaces_user = Users.filter_one(
active=True, Users.active==True,
is_confirmed=True, Users.is_confirmed==True,
person_id=build_living_spaces_user.person_id, Users.person_id==build_living_spaces_user.person_id,
) ).data
# print( # print(
# f"Invitation is send : {spaces_user.email} " # f"Invitation is send : {spaces_user.email} "
# f"Token : {invitations_person.token} " # f"Token : {invitations_person.token} "
# f"Send Date : {str(invitations_person.send_date.date())}" # f"Send Date : {str(invitations_person.send_date.date())}"
# ) # )
manager_living_spaces = BuildLivingSpace.filter_active( manager_living_spaces = BuildLivingSpace.filter_all(
BuildLivingSpace.person_id == token_dict.person_id, BuildLivingSpace.person_id == token_dict.person_id,
) BuildLivingSpace.active == True,
manager_people = BuildDecisionBookPerson.filter_active( ).data
manager_people = BuildDecisionBookPerson.filter_all(
BuildDecisionBookPerson.invite_id == book_invitation.id, BuildDecisionBookPerson.invite_id == book_invitation.id,
BuildDecisionBookPerson.build_living_space_id.in_( BuildDecisionBookPerson.build_living_space_id.in_(
[ [
@ -221,16 +223,15 @@ class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
for manager_living_space in manager_living_spaces.data for manager_living_space in manager_living_spaces.data
] ]
), ),
BuildLivingSpace.active == True,
) )
manager_people_occupants = BuildDecisionBookPersonOccupants.filter_active( manager_people_occupants = BuildDecisionBookPersonOccupants.filter_all(
BuildDecisionBookPersonOccupants.build_decision_book_person_id BuildDecisionBookPersonOccupants.build_decision_book_person_id
== manager_people.get(1).id == manager_people.get(1).id,
BuildDecisionBookPersonOccupants.active == True,
) )
dlt = [ manager_people_occupants.query.delete()
occupants.delete(destroy=True) manager_people.query.delete()
for occupants in manager_people_occupants.data
]
dlt = [occupants.delete(destroy=True) for occupants in manager_people.data]
if book_person_manager := BuildDecisionBookPerson.find_or_create( if book_person_manager := BuildDecisionBookPerson.find_or_create(
**build_decision_book_person_dict, **build_decision_book_person_dict,

View File

@ -12,15 +12,16 @@ class AlchemyJsonResponse:
completed: bool completed: bool
filter_attributes: Any = None filter_attributes: Any = None
response_model: Any = None response_model: Any = None
def __new__( def __new__(
cls, cls,
message: str, message: str,
status_code: str = 'HTTP_200_OK', status_code: str = "HTTP_200_OK",
result: Union[Any, list] = None, result: Union[Any, list] = None,
completed: bool = True, completed: bool = True,
response_model: Any = None response_model: Any = None,
): ):
cls.status_code = getattr(status, status_code, 'HTTP_200_OK') cls.status_code = getattr(status, status_code, "HTTP_200_OK")
cls.message = message cls.message = message
cls.result = result cls.result = result
cls.completed = completed cls.completed = completed
@ -76,13 +77,17 @@ class AlchemyJsonResponse:
"order_type": filter_model.order_type, "order_type": filter_model.order_type,
} }
include_joins = dict( include_joins = dict(
include_joins=filter_model.include_joins if filter_model.include_joins else [] include_joins=(
filter_model.include_joins if filter_model.include_joins else []
)
) )
data = [] data = []
for data_object in cls.result.data: for data_object in cls.result.data:
data_dict = data_object.get_dict(include_joins=include_joins) data_dict = data_object.get_dict(include_joins=include_joins)
if cls.response_model: if cls.response_model:
data_dict = cls.response_model(**data_object.get_dict(include_joins=include_joins)).dump() data_dict = cls.response_model(
**data_object.get_dict(include_joins=include_joins)
).dump()
data.append(data_dict) data.append(data_dict)
return JSONResponse( return JSONResponse(
status_code=cls.status_code, status_code=cls.status_code,

View File

@ -46,50 +46,42 @@ class AuthModule(PasswordModule):
@classmethod @classmethod
def check_user_exits(cls, access_key, domain): def check_user_exits(cls, access_key, domain):
found_user: Users = cls.filter_one(
found_user: Users = cls.filter_active(
or_( or_(
cls.email == str(access_key).lower(), cls.email == str(access_key).lower(),
cls.phone_number == str(access_key).replace(" ", ""), cls.phone_number == str(access_key).replace(" ", ""),
), ),
filter_records=False, ).data
) if not found_user:
if not found_user.data:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
detail="Given access key or domain is not matching with the any user record.", detail="Given access key or domain is not matching with the any user record.",
) )
found_user = found_user.data[0]
other_domains_list = found_user.get_main_domain_and_other_domains( other_domains_list = found_user.get_main_domain_and_other_domains(
get_main_domain=False get_main_domain=False
) )
if domain not in other_domains_list: if domain not in other_domains_list:
raise HTTPException( raise HTTPException(
status_code=401, status_code=401,
detail=dict(message="Unauthorized User attempts to connect api"), detail=dict(message="Unauthorized User attempts to connect api"),
) )
if not found_user:
raise HTTPException(
status_code=401,
detail="Given access key or domain is not matching with the any user record.",
)
return found_user return found_user
def generate_access_token(self): def generate_access_token(self):
return self.generate_token(Auth.ACCESS_TOKEN_LENGTH) return self.generate_token(Auth.ACCESS_TOKEN_LENGTH)
def remove_refresher_token(self, domain, disconnect: bool = False): def remove_refresher_token(self, domain, disconnect: bool = False):
registered_tokens = ([], 0)
if disconnect: if disconnect:
registered_tokens = UsersTokens.filter_by(user_id=self.id) registered_tokens = UsersTokens.filter_all(
UsersTokens.user_id==self.id, system=True
)
else: else:
registered_tokens = UsersTokens.filter_by(domain=domain, user_id=self.id) registered_tokens = UsersTokens.filter_all(
for token in registered_tokens[0]: UsersTokens.domain==domain, UsersTokens.user_id==self.id, system=True
token.session.delete(token) )
token.session.commit() registered_tokens.query.delete()
token.session.flush() UsersTokens.save()
def check_password(self, password): def check_password(self, password):
main_domain = self.get_main_domain_and_other_domains(get_main_domain=True) main_domain = self.get_main_domain_and_other_domains(get_main_domain=True)
@ -182,6 +174,7 @@ class AuthModule(PasswordModule):
token=refresh_token, token=refresh_token,
domain=domain, domain=domain,
) )
UsersTokens.save()
return refresh_token return refresh_token
return None return None

View File

@ -10,7 +10,6 @@ from sqlalchemy import (
Boolean, Boolean,
TIMESTAMP, TIMESTAMP,
Numeric, Numeric,
Identity,
UUID, UUID,
) )
@ -23,9 +22,7 @@ class AccountBooks(CrudCollection):
country: Mapped[str] = mapped_column(String, nullable=False) country: Mapped[str] = mapped_column(String, nullable=False)
branch_type: Mapped[str] = mapped_column(SmallInteger, server_default="0") branch_type: Mapped[str] = mapped_column(SmallInteger, server_default="0")
company_id: Mapped[int] = mapped_column( company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"), nullable=False)
ForeignKey("companies.id"), nullable=False
)
company_uu_id: Mapped[UUID] = mapped_column(String, nullable=False) company_uu_id: Mapped[UUID] = mapped_column(String, nullable=False)
branch_id: Mapped[int] = mapped_column(ForeignKey("companies.id")) branch_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
branch_uu_id: Mapped[UUID] = mapped_column(String, comment="Branch UU ID") branch_uu_id: Mapped[UUID] = mapped_column(String, comment="Branch UU ID")
@ -466,9 +463,7 @@ class AccountRecords(CrudCollection):
send_person_uu_id = mapped_column( send_person_uu_id = mapped_column(
String, nullable=True, comment="Send Person UU ID" String, nullable=True, comment="Send Person UU ID"
) )
approving_accounting_person: Mapped[int] = mapped_column( approving_accounting_person: Mapped[int] = mapped_column(ForeignKey("people.id"))
ForeignKey("people.id")
)
approving_accounting_person_uu_id = mapped_column( approving_accounting_person_uu_id = mapped_column(
String, nullable=True, comment="Approving Accounting Person UU ID" String, nullable=True, comment="Approving Accounting Person UU ID"
) )

View File

@ -16,7 +16,6 @@ from sqlalchemy import (
TIMESTAMP, TIMESTAMP,
Text, Text,
Numeric, Numeric,
Identity,
) )
from databases.sql_models.core_mixin import CrudCollection from databases.sql_models.core_mixin import CrudCollection
@ -331,25 +330,27 @@ class Build(CrudCollection, SelectActionWithEmployee):
data_dict["build_types_id"] = build_type.id data_dict["build_types_id"] = build_type.id
del data_dict["build_types_uu_id"] del data_dict["build_types_uu_id"]
build_created = cls.find_or_create(**data_dict) build_created = cls.find_or_create(**data_dict)
if not build_created.is_found: cls.__many__table__.find_or_create(
cls.__many__table__.find_or_create( company_id=token.selected_company.company_id,
company_id=token.selected_company.company_id, employee_id=token.selected_company.employee_id,
employee_id=token.selected_company.employee_id, member_id=build_created.id,
member_id=build_created.id, is_confirmed=True,
is_confirmed=True, )
)
return build_created return build_created
@classmethod @classmethod
def update_action(cls, data: UpdateBuild, build_uu_id: str, token): def update_action(cls, data: UpdateBuild, build_uu_id: str, token):
from databases import Addresses from databases import Addresses
data_dict = data.excluded_dump() data_dict = data.excluded_dump()
if data.official_address_uu_id: if data.official_address_uu_id:
official_address = Addresses.find_one(uu_id=data.address_uu_id) official_address = Addresses.filter_one(
data_dict["address_id"] = official_address.id Addresses.uu_id==data.address_uu_id
).data
data_dict["address_id"] = official_address.id if official_address else None
del data_dict["address_uu_id"] del data_dict["address_uu_id"]
if build_to_update := cls.find_one(uu_id=build_uu_id, person_id=token.id): if build_to_update := cls.filter_one(
cls.uu_id==build_uu_id, cls.person_id==token.id
).data:
return build_to_update.update(**data_dict) return build_to_update.update(**data_dict)
@property @property
@ -489,7 +490,9 @@ class BuildParts(CrudCollection):
"Check with your supervisor.", "Check with your supervisor.",
) )
if build_types := BuildTypes.find_one(uu_id=data.build_part_type_uu_id): if build_types := BuildTypes.filter_one(
BuildTypes.uu_id==data.build_part_type_uu_id
).data:
part_direction = ApiEnumDropdown.get_by_uuid( part_direction = ApiEnumDropdown.get_by_uuid(
uuid=str(data.part_direction_uu_id) uuid=str(data.part_direction_uu_id)
) )
@ -516,13 +519,13 @@ class BuildParts(CrudCollection):
if not data_dict["part_gross_size"]: if not data_dict["part_gross_size"]:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="Part Gross Size can not be empty.", detail="Part Gross Size can not be empty.",
) )
if not data_dict["part_net_size"]: if not data_dict["part_net_size"]:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT, status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="Part Net Size can not be empty.", detail="Part Net Size can not be empty.",
) )
pt = int(data_dict["part_net_size"]) pt = int(data_dict["part_net_size"])

View File

@ -26,7 +26,6 @@ from sqlalchemy import (
Text, Text,
Numeric, Numeric,
Integer, Integer,
Identity,
) )
from sqlalchemy.orm import mapped_column, Mapped, relationship from sqlalchemy.orm import mapped_column, Mapped, relationship
@ -406,15 +405,17 @@ class BuildDecisionBookPerson(CrudCollection):
if person_occupants := BuildDecisionBookPersonOccupants.find_or_create( if person_occupants := BuildDecisionBookPersonOccupants.find_or_create(
**book_dict **book_dict
): ):
decision_book = BuildDecisionBook.find_one( decision_book = BuildDecisionBook.filter_one(
id=self.build_decision_book_id, active=True, is_confirmed=True BuildDecisionBook.id==self.build_decision_book_id,
) BuildDecisionBook.active==True,
BuildDecisionBook.is_confirmed==True
).data
person_occupants.update( person_occupants.update(
expiry_starts=decision_book.expiry_starts, expiry_starts=decision_book.expiry_starts,
expiry_ends=decision_book.expiry_ends, expiry_ends=decision_book.expiry_ends,
) )
if not person_occupants.is_found and build_living_space_id: if build_living_space_id:
related_service = Services.find_one( related_service = Services.filter_by_one(
related_responsibility=str(occupant_type.occupant_code), related_responsibility=str(occupant_type.occupant_code),
active=True, active=True,
is_confirmed=True, is_confirmed=True,
@ -425,9 +426,11 @@ class BuildDecisionBookPerson(CrudCollection):
detail=f"Service is not found for {occupant_type.occupant_code}", detail=f"Service is not found for {occupant_type.occupant_code}",
) )
decision_build = Build.find_one( decision_build = Build.filter_one(
id=decision_book.build_id, active=True, is_confirmed=True Build.id==decision_book.build_id,
) Build.active==True,
Build.is_confirmed==True
).data
management_room = decision_build.management_room management_room = decision_build.management_room
if not management_room: if not management_room:
raise HTTPException( raise HTTPException(
@ -435,8 +438,16 @@ class BuildDecisionBookPerson(CrudCollection):
detail=f"Management Room is not found in {decision_build.build_name}", detail=f"Management Room is not found in {decision_build.build_name}",
) )
living_space = BuildLivingSpace.find_one( living_space = BuildLivingSpace.filter_one(
id=build_living_space_id, active=True, is_confirmed=True BuildLivingSpace.id==build_living_space_id,
BuildLivingSpace.active==True,
BuildLivingSpace.is_confirmed==True
).data
expiry_ends = str(
system_arrow.get(decision_book.meeting_date).shift(hours=23)
)
expiry_starts = str(
system_arrow.get(decision_book.meeting_date)
) )
related_living_space = BuildLivingSpace.find_or_create( related_living_space = BuildLivingSpace.find_or_create(
build_parts_id=management_room.id, build_parts_id=management_room.id,
@ -445,40 +456,36 @@ class BuildDecisionBookPerson(CrudCollection):
occupant_type_uu_id=str(occupant_type.uu_id), occupant_type_uu_id=str(occupant_type.uu_id),
person_id=living_space.person_id, person_id=living_space.person_id,
person_uu_id=str(living_space.person_uu_id), person_uu_id=str(living_space.person_uu_id),
expiry_starts=system_arrow.get( expiry_starts=expiry_starts,
decision_book.meeting_date expiry_ends=expiry_ends,
).__str__(),
expiry_ends=system_arrow.get(decision_book.meeting_date)
.shift(hours=23)
.__str__(),
is_confirmed=True, is_confirmed=True,
active=True, active=True,
) )
expires_at = str(
system_arrow.get(decision_book.meeting_date).shift(days=15)
)
ServiceBindOccupantEventMethods.bind_services_occupant_system( ServiceBindOccupantEventMethods.bind_services_occupant_system(
build_living_space_id=related_living_space.id, build_living_space_id=related_living_space.id,
service_id=related_service.id, service_id=related_service.id,
expires_at=str( expires_at=expires_at,
system_arrow.get(decision_book.meeting_date).shift(days=15)
),
) )
return person_occupants return person_occupants
return return
def get_occupant_types(self): def get_occupant_types(self):
if occupants := BuildDecisionBookPersonOccupants.filter_active( if occupants := BuildDecisionBookPersonOccupants.filter_all(
BuildDecisionBookPersonOccupants.build_decision_book_person_id == self.id, BuildDecisionBookPersonOccupants.build_decision_book_person_id == self.id,
filter_records=False,
): ):
return occupants.data return occupants.data
return return
def check_occupant_type(self, occupant_type): def check_occupant_type(self, occupant_type):
book_person_occupant_type = BuildDecisionBookPersonOccupants.find_one( book_person_occupant_type = BuildDecisionBookPersonOccupants.filter_one(
build_decision_book_person_id=self.id, BuildDecisionBookPersonOccupants.build_decision_book_person_id==self.id,
occupant_type_id=occupant_type.id, BuildDecisionBookPersonOccupants.occupant_type_id==occupant_type.id,
active=True, BuildDecisionBookPersonOccupants.active==True,
is_confirmed=True, BuildDecisionBookPersonOccupants.is_confirmed==True,
) ).data
if not book_person_occupant_type: if not book_person_occupant_type:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -839,9 +846,7 @@ class BuildDecisionBookPayments(CrudCollection):
String, nullable=True, comment="Build Part UUID" String, nullable=True, comment="Build Part UUID"
) )
budget_records_id: Mapped[int] = mapped_column( budget_records_id: Mapped[int] = mapped_column(ForeignKey("account_records.id"))
ForeignKey("account_records.id")
)
budget_records_uu_id: Mapped[str] = mapped_column( budget_records_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Budget UUID" String, nullable=True, comment="Budget UUID"
) )
@ -936,9 +941,7 @@ class BuildDecisionBookLegal(CrudCollection):
ForeignKey("people.id"), nullable=False ForeignKey("people.id"), nullable=False
) )
resp_attorney_uu_id = mapped_column(String, nullable=True, comment="Attorney UUID") resp_attorney_uu_id = mapped_column(String, nullable=True, comment="Attorney UUID")
resp_attorney_company_id: Mapped[int] = mapped_column( resp_attorney_company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
ForeignKey("companies.id")
)
resp_attorney_company_uu_id = mapped_column( resp_attorney_company_uu_id = mapped_column(
String, nullable=True, comment="Company UUID" String, nullable=True, comment="Company UUID"
) )

View File

@ -18,9 +18,7 @@ class Departments(CrudCollection):
) )
department_description: Mapped[str] = mapped_column(String, server_default="") department_description: Mapped[str] = mapped_column(String, server_default="")
company_id: Mapped[int] = mapped_column( company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"), nullable=False)
ForeignKey("companies.id"), nullable=False
)
company_uu_id: Mapped[str] = mapped_column( company_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Company UUID" String, nullable=False, comment="Company UUID"
) )

View File

@ -3,7 +3,6 @@ from sqlalchemy import (
ForeignKey, ForeignKey,
Index, Index,
Numeric, Numeric,
Identity,
) )
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import mapped_column, Mapped
from databases.sql_models.core_mixin import CrudCollection from databases.sql_models.core_mixin import CrudCollection

View File

@ -1,15 +1,17 @@
import datetime
from decimal import Decimal
from sqlalchemy import ( from sqlalchemy import (
TIMESTAMP, TIMESTAMP,
NUMERIC, NUMERIC,
func, func,
Identity, text,
UUID, UUID,
String, String,
Integer, Integer,
Boolean, Boolean,
SmallInteger, SmallInteger,
) )
from sqlalchemy.orm import ( from sqlalchemy.orm import (
Mapped, Mapped,
mapped_column, mapped_column,
@ -63,6 +65,18 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
"updated_by_id", "updated_by_id",
"replication_id", "replication_id",
) )
__system_default_model__ = [
"cryp_uu_id",
"is_confirmed",
"deleted",
"is_notification_send",
"replication_id",
"is_email_send",
"confirmed_by_id",
"confirmed_by",
"updated_by_id",
"created_by_id",
]
creds: Credentials = None # The credentials to use in the model. creds: Credentials = None # The credentials to use in the model.
client_arrow: DateTimeLocal = None # The arrow to use in the model. client_arrow: DateTimeLocal = None # The arrow to use in the model.
@ -74,6 +88,17 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
TIMESTAMP, default="2099-12-31", server_default="2099-12-31" TIMESTAMP, default="2099-12-31", server_default="2099-12-31"
) )
@classmethod
def remove_non_related_inputs(cls, kwargs):
"""
Removes the non-related inputs from the given attributes.
"""
return {
key: value
for key, value in kwargs.items()
if key in cls.columns + cls.hybrid_properties + cls.settable_relations
}
@classmethod @classmethod
def extract_system_fields(cls, filter_kwargs: dict, create: bool = True): def extract_system_fields(cls, filter_kwargs: dict, create: bool = True):
""" """
@ -87,6 +112,47 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
system_fields.pop(field, None) system_fields.pop(field, None)
return system_fields return system_fields
@classmethod
def iterate_over_variables(cls, val, key):
key_ = cls.__annotations__.get(key, None)
is_primary, value_type = key in cls.primary_keys, type(val)
row_attr = bool(getattr(getattr(cls, key), "foreign_keys", None))
if is_primary or row_attr and key_ == Mapped[int]:
return None
if key_:
if key_ == Mapped[int]:
return int(val) if val else None
elif key_ == Mapped[bool]:
return bool(val) if val else None
elif key_ == Mapped[float] or key_ == Mapped[NUMERIC]:
return round(float(val), 3) if val else None
elif key_ == Mapped[int]:
return int(val) if val else None
elif key_ == Mapped[TIMESTAMP]:
formatted_date = client_arrow.get(str(val)).format(
"DD-MM-YYYY HH:mm:ss"
)
return str(formatted_date) if val else None
else:
if isinstance(val, datetime.datetime):
formatted_date = client_arrow.get(str(val)).format(
"DD-MM-YYYY HH:mm:ss"
)
print(key, "isinstance(value_type, datetime) | ", formatted_date)
return str(formatted_date) if val else None
elif isinstance(value_type, bool):
return bool(val) if val else None
elif isinstance(value_type, float) or isinstance(value_type, Decimal):
return round(float(val), 3) if val else None
elif isinstance(value_type, int):
return int(val) if val else None
elif isinstance(value_type, str):
return str(val) if val else None
elif isinstance(value_type, type(None)):
return None
return str(val) if val else None
@classmethod @classmethod
def find_or_create(cls, **kwargs): def find_or_create(cls, **kwargs):
from api_library.date_time_actions.date_functions import system_arrow from api_library.date_time_actions.date_functions import system_arrow
@ -97,19 +163,18 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
is_found can be used to check if the record was found or created. is_found can be used to check if the record was found or created.
""" """
check_kwargs = cls.extract_system_fields(kwargs) check_kwargs = cls.extract_system_fields(kwargs)
cls.pre_query = cls.query.filter( cls.pre_query = cls.query.filter(cls.expiry_ends < system_arrow.now().date())
system_arrow.get(cls.expiry_ends).date() < system_arrow.now().date() already_record = cls.filter_by_one(**check_kwargs, system=True)
) cls.pre_query = None
already_record = cls.filter_by_one(**check_kwargs)
if already_record := already_record.data: if already_record := already_record.data:
if already_record.is_deleted: if already_record.deleted:
cls.raise_http_exception( cls.raise_http_exception(
status_code="HTTP_406_NOT_ACCEPTABLE", status_code="HTTP_406_NOT_ACCEPTABLE",
error_case="DeletedRecord", error_case="DeletedRecord",
data=check_kwargs, data=check_kwargs,
message="Record exits but is deleted. Contact with authorized user", message="Record exits but is deleted. Contact with authorized user",
) )
elif already_record.is_confirmed: elif not already_record.is_confirmed:
cls.raise_http_exception( cls.raise_http_exception(
status_code="HTTP_406_NOT_ACCEPTABLE", status_code="HTTP_406_NOT_ACCEPTABLE",
error_case="IsNotConfirmed", error_case="IsNotConfirmed",
@ -122,6 +187,7 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
data=check_kwargs, data=check_kwargs,
message="Record already exits. Refresh data and try again", message="Record already exits. Refresh data and try again",
) )
check_kwargs = cls.remove_non_related_inputs(check_kwargs)
created_record = cls() created_record = cls()
for key, value in check_kwargs.items(): for key, value in check_kwargs.items():
setattr(created_record, key, value) setattr(created_record, key, value)
@ -130,28 +196,8 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
cls.created_by = cls.creds.person_name cls.created_by = cls.creds.person_name
return created_record return created_record
@classmethod
def iterate_over_variables(cls, val, key):
key_ = cls.__annotations__.get(key, None)
is_primary, is_foreign_key = key in cls.primary_keys and bool(getattr(cls, key).foreign_keys)
if is_primary or is_foreign_key and key_ == Mapped[int]:
return None
elif key_ == Mapped[UUID]:
return str(val) if val else None
elif key_ == Mapped[int]:
return int(val) if val else None
elif key_ == Mapped[bool]:
return bool(val) if val else None
elif key_ == Mapped[float] or key_ == Mapped[NUMERIC]:
return float(val) if val else None
elif key_ == Mapped[int]:
return int(val) if val else None
elif key_ == Mapped[TIMESTAMP]:
return str(client_arrow.get(val).format("DD-MM-YYYY HH:mm:ss")) if val else None
return str(val) if val else None
def update(self, **kwargs): def update(self, **kwargs):
check_kwargs = self.remove_non_related_inputs(kwargs)
"""Updates the record with the given attributes.""" """Updates the record with the given attributes."""
is_confirmed_argument = kwargs.get("is_confirmed", None) is_confirmed_argument = kwargs.get("is_confirmed", None)
if is_confirmed_argument and not len(kwargs) == 1: if is_confirmed_argument and not len(kwargs) == 1:
@ -161,7 +207,7 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
data=kwargs, data=kwargs,
message="Confirm field can not be updated with other fields", message="Confirm field can not be updated with other fields",
) )
check_kwargs = self.extract_system_fields(kwargs, create=False) check_kwargs = self.extract_system_fields(check_kwargs, create=False)
for key, value in check_kwargs.items(): for key, value in check_kwargs.items():
setattr(self, key, value) setattr(self, key, value)
@ -178,24 +224,48 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
self, exclude: list = None, include: list = None, include_joins: list = None self, exclude: list = None, include: list = None, include_joins: list = None
): ):
return_dict = {} return_dict = {}
if exclude:
exclude.extend(list(set(self.__exclude__fields__).difference(exclude)))
else:
exclude = self.__exclude__fields__
include = include or []
if include: if include:
include.extend(["uu_id", "active"]) exclude_list = [
include = list(set(include).difference(self.__exclude__fields__)) element
for key, val in self.to_dict().items(): for element in self.__system_default_model__
if key in include: if str(element)[-2:] == "id"
if value_of_database := self.iterate_over_variables(val, key): ]
return_dict[key] = value_of_database columns_include_list = list(set(include).difference(set(exclude_list)))
columns_include_list.extend(["uu_id", "active"])
for key in list(columns_include_list):
val = getattr(self, key)
value_of_database = self.iterate_over_variables(val, key)
if value_of_database is not None:
return_dict[key] = value_of_database
elif exclude:
exclude.extend(
list(set(self.__exclude__fields__ or []).difference(exclude))
)
for i in self.__system_default_model__:
print("i", str(i)[-2:])
exclude.extend(
[
element
for element in self.__system_default_model__
if str(element)[-2:] == "id"
]
)
columns_excluded_list = set(self.columns).difference(set(exclude))
for key in list(columns_excluded_list):
val = getattr(self, key)
value_of_database = self.iterate_over_variables(val, key)
if value_of_database is not None:
return_dict[key] = value_of_database
else: else:
exclude.extend(["is_confirmed", "deleted", "cryp_uu_id"]) exclude_list = (
for key, val in self.to_dict().items(): self.__exclude__fields__ or [] + self.__system_default_model__
if key not in exclude: )
if value_of_database := self.iterate_over_variables(val, key): columns_list = list(set(self.columns).difference(set(exclude_list)))
return_dict[key] = value_of_database for key in list(columns_list):
val = getattr(self, key)
value_of_database = self.iterate_over_variables(val, key)
if value_of_database is not None:
return_dict[key] = value_of_database
all_arguments = [ all_arguments = [
record record
@ -218,15 +288,15 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
return_dict[all_argument] = ( return_dict[all_argument] = (
populate_arg.get_dict() if populate_arg else [] populate_arg.get_dict() if populate_arg else []
) )
return return_dict return dict(sorted(return_dict.items(), reverse=False))
class BaseMixin(CrudMixin, ReprMixin, SerializeMixin): class BaseMixin(CrudMixin, ReprMixin, SerializeMixin, FilterAttributes):
__abstract__ = True __abstract__ = True
class BaseCollection(CrudMixin, BaseMixin): class BaseCollection(BaseMixin):
__abstract__ = True __abstract__ = True
__repr__ = ReprMixin.__repr__ __repr__ = ReprMixin.__repr__
@ -234,14 +304,14 @@ class BaseCollection(CrudMixin, BaseMixin):
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
class CrudCollection(CrudMixin, BaseMixin, SmartQueryMixin): class CrudCollection(BaseMixin, SmartQueryMixin):
__abstract__ = True __abstract__ = True
__repr__ = ReprMixin.__repr__ __repr__ = ReprMixin.__repr__
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
uu_id: Mapped[UUID] = mapped_column( uu_id: Mapped[UUID] = mapped_column(
UUID, server_default=func.text("gen_random_uuid()"), index=True, unique=True UUID, server_default=text("gen_random_uuid()"), index=True, unique=True
) )
ref_id: Mapped[UUID] = mapped_column(String(100), nullable=True, index=True) ref_id: Mapped[UUID] = mapped_column(String(100), nullable=True, index=True)

View File

@ -8,7 +8,6 @@ from sqlalchemy import (
Boolean, Boolean,
Integer, Integer,
Index, Index,
Identity,
) )
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import mapped_column, Mapped
@ -92,9 +91,7 @@ class Services(CrudCollection):
__tablename__ = "services" __tablename__ = "services"
__exclude__fields__ = [] __exclude__fields__ = []
module_id: Mapped[int] = mapped_column( module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
ForeignKey("modules.id"), nullable=False
)
module_uu_id: Mapped[str] = mapped_column( module_uu_id: Mapped[str] = mapped_column(
String, nullable=False, comment="Module UUID" String, nullable=False, comment="Module UUID"
) )
@ -118,9 +115,7 @@ class Service2Events(CrudCollection):
__tablename__ = "services2events" __tablename__ = "services2events"
__exclude__fields__ = [] __exclude__fields__ = []
service_id: Mapped[int] = mapped_column( service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
ForeignKey("services.id"), nullable=False
)
service_uu_id = mapped_column(String, nullable=False, comment="Service UUID") service_uu_id = mapped_column(String, nullable=False, comment="Service UUID")
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False) event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
event_uu_id = mapped_column(String, nullable=False, comment="Event UUID") event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")
@ -148,9 +143,9 @@ class Event2Employee(CrudCollection):
@classmethod @classmethod
def get_event_id_by_employee_id(cls, employee_id) -> (list, list): def get_event_id_by_employee_id(cls, employee_id) -> (list, list):
active_events = cls.filter_active(cls.employee_id == employee_id) active_events = cls.filter_all(cls.employee_id == employee_id)
active_events_id = [event.event_id for event in active_events.data] active_events_id = [event.event_id for event in active_events.data]
active_events = Events.filter_active(Events.id.in_(active_events_id)) active_events = Events.filter_all(Events.id.in_(active_events_id))
active_events_uu_id = [str(event.uu_id) for event in active_events.data] active_events_uu_id = [str(event.uu_id) for event in active_events.data]
return active_events_id, active_events_uu_id return active_events_id, active_events_uu_id
@ -205,13 +200,9 @@ class ModulePrice(CrudCollection):
__exclude__fields__ = [] __exclude__fields__ = []
campaign_code = mapped_column(String, nullable=False, comment="Campaign Code") campaign_code = mapped_column(String, nullable=False, comment="Campaign Code")
module_id: Mapped[int] = mapped_column( module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
ForeignKey("modules.id"), nullable=False
)
module_uu_id = mapped_column(String, nullable=False, comment="Module UUID") module_uu_id = mapped_column(String, nullable=False, comment="Module UUID")
service_id: Mapped[int] = mapped_column( service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
ForeignKey("services.id"), nullable=False
)
service_uu_id = mapped_column(String, nullable=False, comment="Service UUID") service_uu_id = mapped_column(String, nullable=False, comment="Service UUID")
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False) event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
event_uu_id = mapped_column(String, nullable=False, comment="Event UUID") event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")

View File

@ -20,7 +20,6 @@ from sqlalchemy import (
Integer, Integer,
Text, Text,
or_, or_,
Identity,
) )
from sqlalchemy.orm import mapped_column, relationship, Mapped from sqlalchemy.orm import mapped_column, relationship, Mapped
@ -425,9 +424,7 @@ class RelationshipEmployee2PostCode(CrudCollection):
company_id: Mapped[int] = mapped_column( company_id: Mapped[int] = mapped_column(
ForeignKey("companies.id"), nullable=True ForeignKey("companies.id"), nullable=True
) # 1, 2, 3 ) # 1, 2, 3
employee_id: Mapped[int] = mapped_column( employee_id: Mapped[int] = mapped_column(ForeignKey("employees.id"), nullable=False)
ForeignKey("employees.id"), nullable=False
)
member_id: Mapped[int] = mapped_column( member_id: Mapped[int] = mapped_column(
ForeignKey("address_postcode.id"), nullable=False ForeignKey("address_postcode.id"), nullable=False
) )
@ -465,13 +462,25 @@ class Addresses(CrudCollection):
__tablename__ = "addresses" __tablename__ = "addresses"
__exclude__fields__ = [] __exclude__fields__ = []
build_number: Mapped[str] = mapped_column(String(24), nullable=False, comment="Build Number") build_number: Mapped[str] = mapped_column(
door_number: Mapped[str] = mapped_column(String(24), nullable=True, comment="Door Number") String(24), nullable=False, comment="Build Number"
floor_number: Mapped[str] = mapped_column(String(24), nullable=True, comment="Floor Number") )
door_number: Mapped[str] = mapped_column(
String(24), nullable=True, comment="Door Number"
)
floor_number: Mapped[str] = mapped_column(
String(24), nullable=True, comment="Floor Number"
)
comment_address: Mapped[str] = mapped_column(String, nullable=False, comment="Address") comment_address: Mapped[str] = mapped_column(
letter_address: Mapped[str] = mapped_column(String, nullable=False, comment="Address") String, nullable=False, comment="Address"
short_letter_address: Mapped[str] = mapped_column(String, nullable=False, comment="Address") )
letter_address: Mapped[str] = mapped_column(
String, nullable=False, comment="Address"
)
short_letter_address: Mapped[str] = mapped_column(
String, nullable=False, comment="Address"
)
latitude: Mapped[float] = mapped_column(Numeric(20, 12), server_default="0") latitude: Mapped[float] = mapped_column(Numeric(20, 12), server_default="0")
longitude: Mapped[float] = mapped_column(Numeric(20, 12), server_default="0") longitude: Mapped[float] = mapped_column(Numeric(20, 12), server_default="0")
@ -483,9 +492,10 @@ class Addresses(CrudCollection):
@classmethod @classmethod
def list_via_employee(cls, token_dict, filter_expr): def list_via_employee(cls, token_dict, filter_expr):
post_code_list = RelationshipEmployee2PostCode.filter_active( post_code_list = RelationshipEmployee2PostCode.filter_all(
RelationshipEmployee2PostCode.employee_id RelationshipEmployee2PostCode.employee_id
== token_dict.selected_company.employee_id, == token_dict.selected_company.employee_id,
RelationshipEmployee2PostCode.active==True,
).data ).data
post_code_id_list = [post_code.member_id for post_code in post_code_list] post_code_id_list = [post_code.member_id for post_code in post_code_list]
if not post_code_id_list: if not post_code_id_list:
@ -493,10 +503,10 @@ class Addresses(CrudCollection):
status_code=404, status_code=404,
detail="User has no post code registered. User can not list addresses.", detail="User has no post code registered. User can not list addresses.",
) )
cls.pre_query = Addresses.filter_active( cls.pre_query = cls.filter_active(cls.post_code_id.in_(post_code_id_list)).query
cls.post_code_id.in_(post_code_id_list) filter_cls = cls.filter_all(*filter_expr)
).query cls.pre_query = None
return cls.filter_active(*filter_expr) return filter_cls
# buildings: Mapped["Build"] = relationship( # buildings: Mapped["Build"] = relationship(
# "Build", back_populates="addresses", foreign_keys="Build.address_id" # "Build", back_populates="addresses", foreign_keys="Build.address_id"

View File

@ -4,7 +4,6 @@ from sqlalchemy import (
UUID, UUID,
String, String,
text, text,
Identity,
) )
from sqlalchemy.orm import ( from sqlalchemy.orm import (
Mapped, Mapped,
@ -40,22 +39,26 @@ class ApiEnumDropdown(BaseCollection):
if search := cls.query.filter( if search := cls.query.filter(
cls.enum_class.in_(["DebitTypes"]), cls.enum_class.in_(["DebitTypes"]),
cls.uu_id == search_uu_id, cls.uu_id == search_uu_id,
cls.active == True,
).first(): ).first():
return search return search
elif search_debit: elif search_debit:
if search := cls.query.filter( if search := cls.query.filter(
cls.enum_class.in_(["DebitTypes"]), cls.enum_class.in_(["DebitTypes"]),
cls.key == search_debit, cls.key == search_debit,
cls.active == True,
).first(): ).first():
return search return search
return cls.query.filter( return cls.query.filter(
cls.enum_class.in_(["DebitTypes"]), cls.enum_class.in_(["DebitTypes"]),
cls.active == True,
).all() ).all()
@classmethod @classmethod
def get_due_types(cls): def get_due_types(cls):
if due_list := cls.filter_active( if due_list := cls.filter_all(
cls.enum_class == "BuildDuesTypes", cls.key.in_(["BDT-A", "BDT-D"]) cls.enum_class == "BuildDuesTypes", cls.key.in_(["BDT-A", "BDT-D"]),
cls.active == True,
).data: ).data:
return [due.uu_id.__str__() for due in due_list] return [due.uu_id.__str__() for due in due_list]
raise HTTPException( raise HTTPException(
@ -69,16 +72,19 @@ class ApiEnumDropdown(BaseCollection):
if search := cls.query.filter( if search := cls.query.filter(
cls.enum_class.in_(["BuildDuesTypes"]), cls.enum_class.in_(["BuildDuesTypes"]),
cls.uu_id == search_uu_id, cls.uu_id == search_uu_id,
cls.active == True,
).first(): ).first():
return search return search
elif search_management: elif search_management:
if search := cls.query.filter( if search := cls.query.filter(
cls.enum_class.in_(["BuildDuesTypes"]), cls.enum_class.in_(["BuildDuesTypes"]),
cls.key == search_management, cls.key == search_management,
cls.active == True,
).first(): ).first():
return search return search
return cls.query.filter( return cls.query.filter(
cls.enum_class.in_(["BuildDuesTypes"]), cls.enum_class.in_(["BuildDuesTypes"]),
cls.active == True,
).all() ).all()
def get_enum_dict(self): def get_enum_dict(self):
@ -92,7 +98,9 @@ class ApiEnumDropdown(BaseCollection):
@classmethod @classmethod
def uuid_of_enum(cls, enum_class: str, key: str): def uuid_of_enum(cls, enum_class: str, key: str):
return str(getattr(cls.find_one(enum_class=enum_class, key=key), "uu_id", None)) return str(getattr(cls.filter_one(
cls.enum_class==enum_class, cls.key==key
).data, "uu_id", None))
ApiEnumDropdown.set_session(ApiEnumDropdown.__session__) ApiEnumDropdown.set_session(ApiEnumDropdown.__session__)

View File

@ -1,3 +1,4 @@
from sqlalchemy import SQLColumnExpression
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from api_validations.validations_request import ListOptions from api_validations.validations_request import ListOptions
@ -90,24 +91,51 @@ class FilterAttributes:
} }
@classmethod @classmethod
def get_not_expired_query_arg(cls, *arg, expired=True): def add_new_arg_to_args(cls, args_list, argument, value):
new_arg_list = list(
args_ for args_ in list(args_list) if isinstance(args_, SQLColumnExpression)
)
if not any(True for arg in new_arg_list if arg.left.key == argument):
new_arg_list.append(value)
return tuple(new_arg_list)
@classmethod
def get_not_expired_query_arg(cls, arg):
"""Add expiry_starts and expiry_ends to the query.""" """Add expiry_starts and expiry_ends to the query."""
from api_library.date_time_actions.date_functions import system_arrow from api_library.date_time_actions.date_functions import system_arrow
if expired: arg = cls.add_new_arg_to_args(
arg_add = ( arg, "expiry_ends", cls.expiry_ends >= str(system_arrow.now())
*arg[0], )
system_arrow.get(cls.expiry_ends) >= system_arrow.now(), arg = cls.add_new_arg_to_args(
system_arrow.now() >= system_arrow.get(cls.expiry_starts), arg, "expiry_starts", cls.expiry_starts <= str(system_arrow.now())
) )
return arg_add return arg
return arg[0]
@classmethod @classmethod
def filter_by_all(cls, **kwargs): def select_only(
cls, *args, select_args: list, order_by=None, limit=None, system=False
):
if not system:
args = cls.add_new_arg_to_args(
args, "is_confirmed", cls.is_confirmed == True
)
args = cls.get_not_expired_query_arg(args)
query = cls._query().filter(*args).with_entities(*select_args)
if order_by is not None:
query = query.order_by(order_by)
if limit:
query = query.limit(limit)
return AlchemyResponse(query=query, first=False)
@classmethod
def filter_by_all(cls, system=False, **kwargs):
""" """
Filters all the records regardless of is_deleted, is_confirmed. Filters all the records regardless of is_deleted, is_confirmed.
""" """
if "is_confirmed" not in kwargs and not system:
kwargs["is_confirmed"] = True
kwargs.pop("system", None)
query = cls._query().filter_by(**kwargs) query = cls._query().filter_by(**kwargs)
if cls.filter_attr: if cls.filter_attr:
filter_list = cls.get_filter_attributes() filter_list = cls.get_filter_attributes()
@ -116,18 +144,27 @@ class FilterAttributes:
return AlchemyResponse(query=query, first=False) return AlchemyResponse(query=query, first=False)
@classmethod @classmethod
def filter_by_one(cls, **kwargs): def filter_by_one(cls, system=False, **kwargs):
""" """
Filters one record regardless of is_deleted, is_confirmed. Filters one record regardless of is_deleted, is_confirmed.
""" """
if "is_confirmed" not in kwargs and not system:
kwargs["is_confirmed"] = True
kwargs.pop("system", None)
query = cls._query().filter_by(**kwargs) query = cls._query().filter_by(**kwargs)
return AlchemyResponse(query=query, first=True) return AlchemyResponse(query=query, first=True)
@classmethod @classmethod
def filter_all(cls, *args, expired: bool = False): def filter_all(cls, *args, system=False):
""" """
Filters all the records regardless of is_deleted, is_confirmed. Filters all the records regardless of is_deleted, is_confirmed.
""" """
if not system:
args = cls.add_new_arg_to_args(
args, "is_confirmed", cls.is_confirmed == True
)
args = cls.get_not_expired_query_arg(args)
query = cls._query().filter(*args) query = cls._query().filter(*args)
if cls.filter_attr: if cls.filter_attr:
filter_list = cls.get_filter_attributes() filter_list = cls.get_filter_attributes()
@ -136,12 +173,16 @@ class FilterAttributes:
return AlchemyResponse(query=query, first=False) return AlchemyResponse(query=query, first=False)
@classmethod @classmethod
def filter_one(cls, *args, expired: bool = False): def filter_one(cls, *args, system=False, expired: bool = False):
""" """
Filters one record regardless of is_deleted, is_confirmed. Filters one record regardless of is_deleted, is_confirmed.
""" """
arg = cls.get_not_expired_query_arg(args, expired=expired) if not system:
query = cls._query().filter(*arg) args = cls.add_new_arg_to_args(
args, "is_confirmed", cls.is_confirmed == True
)
args = cls.get_not_expired_query_arg(args)
query = cls._query().filter(*args)
return AlchemyResponse(query=query, first=True) return AlchemyResponse(query=query, first=True)
@classmethod @classmethod

View File

@ -10,6 +10,7 @@ from handlers_exception import (
exception_handler_exception, exception_handler_exception,
) )
from prometheus_fastapi_instrumentator import Instrumentator from prometheus_fastapi_instrumentator import Instrumentator
# from prometheus_client import Counter, Histogram # from prometheus_client import Counter, Histogram
from .app_runner_init import create_endpoints_from_api_functions from .app_runner_init import create_endpoints_from_api_functions