from typing import Union from fastapi.exceptions import HTTPException from fastapi.responses import JSONResponse from api_validations.validations_response.address import ( ListAddressResponse, AddressPostCodeResponse, ) from databases import ( AddressPostcode, Addresses, RelationshipEmployee2PostCode, AddressStreet, ) from api_validations.validations_request import ( ListOptions, InsertAddress, UpdateAddress, InsertPostCode, UpdatePostCode, SearchAddress, ) from api_validations.core_response import AlchemyJsonResponse from api_events.events.abstract_class import MethodToEvent, ActionsSchema from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject class AddressListEventMethods(MethodToEvent): event_type = "SELECT" event_description = "List Address records" event_category = "Address" __event_keys__ = { "9c251d7d-da70-4d63-a72c-e69c26270442": "address_list_super_user", "52afe375-dd95-4f4b-aaa2-4ec61bc6de52": "address_list_employee", } __event_validation__ = { "9c251d7d-da70-4d63-a72c-e69c26270442": ListAddressResponse, "52afe375-dd95-4f4b-aaa2-4ec61bc6de52": ListAddressResponse, } @classmethod def address_list_super_user( cls, list_options: ListOptions, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): post_code_list = RelationshipEmployee2PostCode.filter_all( RelationshipEmployee2PostCode.company_id == token_dict.selected_company.company_id, ).data post_code_id_list = [post_code.member_id for post_code in post_code_list] if not post_code_id_list: raise HTTPException( status_code=404, detail="User has no post code registered. User can not list addresses.", ) get_street_ids = [ street_id[0] for street_id in AddressPostcode.select_only( AddressPostcode.id.in_(post_code_id_list), 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.", ) Addresses.pre_query = Addresses.filter_all( Addresses.street_id.in_(get_street_ids), ).query Addresses.filter_attr = list_options records = Addresses.filter_all().data return AlchemyJsonResponse( completed=True, message="List Address records", result=records, ) @classmethod def address_list_employee( cls, list_options: ListOptions, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): Addresses.filter_attr = list_options records = Addresses.list_via_employee( token_dict=token_dict, ) return AlchemyJsonResponse( completed=True, message="List Address records", result=records, ) class AddressCreateEventMethods(MethodToEvent): event_type = "CREATE" event_description = "" event_category = "" __event_keys__ = { "ffdc445f-da10-4ce4-9531-d2bdb9a198ae": "create_address", } __event_validation__ = { "ffdc445f-da10-4ce4-9531-d2bdb9a198ae": InsertAddress, } @classmethod def create_address( cls, data: InsertAddress, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): post_code = AddressPostcode.filter_one( AddressPostcode.uu_id == data.post_code_uu_id, ).data if not post_code: raise HTTPException( status_code=404, detail="Post code not found. User can not create address without post code.", ) data_dict = data.excluded_dump() data_dict["street_id"] = post_code.street_id data_dict["street_uu_id"] = str(post_code.street_uu_id) del data_dict["post_code_uu_id"] address = Addresses.find_or_create(**data_dict) address.save() address.update(is_confirmed=True) address.save() return JSONResponse( content={ "completed": True, "message": "Create Address record", "data": address.get_dict(), }, status_code=200, ) class AddressSearchEventMethods(MethodToEvent): event_type = "SEARCH" event_description = "" event_category = "" __event_keys__ = { "e0ac1269-e9a7-4806-9962-219ac224b0d0": "search_address", } __event_validation__ = { "e0ac1269-e9a7-4806-9962-219ac224b0d0": SearchAddress, } @classmethod def search_address( cls, data: SearchAddress, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): import databases.sql_models from time import perf_counter st = perf_counter() pre_query_first = AddressStreet.search_address_text(search_text=data.search) query, schemas, new_data_list = ( pre_query_first.get("query"), pre_query_first.get("schema"), [], ) filter_list = data.list_options.dump() filter_table = AddressStreet if filter_list.get("order_field") not in schemas: filter_list["order_field"] = "uu_id" else: filter_table = getattr( databases.sql_models, str(filter_list.get("order_field")).split(".")[0] ) filter_list["order_field"] = str(filter_list.get("order_field")).split(".")[ 1 ] order = ( getattr(filter_table, filter_list.get("order_field")).desc() if str(filter_list.get("order_type"))[0] == "d" else getattr(filter_table, filter_list.get("order_field")).asc() ) query = ( query.order_by(order) .limit(int(filter_list.get("size"))) .offset(int((filter_list.get("page")) - 1) * int(filter_list.get("size"))) .populate_existing() ) records = list(query.all()) print(perf_counter() - st) for item in records: new_data_dict = {} for index, schema in enumerate(schemas): new_data_dict[schema] = str(item[index]) if "uu_id" in str(item[index]): new_data_dict[schema] = str(new_data_dict.get(schema)) new_data_list.append(new_data_dict) return JSONResponse( content={ "completed": True, "pagination": filter_list, "count": len(new_data_list), "data": new_data_list, "message": "Search Address records", }, status_code=200, ) class AddressUpdateEventMethods(MethodToEvent): event_type = "UPDATE" event_description = "" event_category = "" __event_keys__ = { "1f9c3a9c-e5bd-4dcd-9b9a-3742d7e03a27": "update_address", } __event_validation__ = { "1f9c3a9c-e5bd-4dcd-9b9a-3742d7e03a27": UpdateAddress, } @classmethod def update_address( cls, address_uu_id: str, data: UpdateAddress, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): if isinstance(token_dict, EmployeeTokenObject): address = Addresses.filter_one( Addresses.uu_id == address_uu_id, ).data if not address: raise HTTPException( status_code=404, detail=f"Address not found. User can not update with given address uuid : {address_uu_id}", ) data_dict = data.excluded_dump() updated_address = address.update(**data_dict) updated_address.save() return JSONResponse( content={ "completed": True, "message": "Update Address record", "data": updated_address.get_dict(), }, status_code=200, ) elif isinstance(token_dict, OccupantTokenObject): raise HTTPException( status_code=403, detail="Occupant can not update address.", ) class AddressPatchEventMethods(MethodToEvent): event_type = "PATCH" event_description = "" event_category = "" __event_keys__ = { "b0e55a7e-af81-468c-b46c-a6b3a6b68d5d": "patch_address", } __event_validation__ = { "b0e55a7e-af81-468c-b46c-a6b3a6b68d5d": None, } @classmethod def patch_address( cls, address_uu_id: str, data: InsertAddress, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): address = Addresses.filter_one( Addresses.uu_id == address_uu_id, ).data post_code = RelationshipEmployee2PostCode.filter_one( RelationshipEmployee2PostCode.member_id == address.post_code_id, ) if not post_code: raise HTTPException( status_code=404, detail="Post code not found. User can not patch address without post code.", ) data_dict = data.excluded_dump() data_dict["post_code_id"] = post_code.id del data_dict["post_code_uu_id"] patched_address = address.patch(**data_dict) return JSONResponse( content={ "completed": True, "message": "Patch Address record", "data": patched_address.get_dict(), }, status_code=200, ) class AddressPostCodeCreateEventMethods(MethodToEvent): event_type = "CREATE" event_description = "" event_category = "" __event_keys__ = { "6f1406ac-577d-4f2c-8077-71fff2252c5f": "create_post_code_address", } __event_validation__ = { "6f1406ac-577d-4f2c-8077-71fff2252c5f": InsertPostCode, } @classmethod def create_post_code_address( cls, data: InsertPostCode, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): data_dump = data.excluded_dump() street = AddressStreet.filter_one( AddressStreet.uu_id == data.street_uu_id, ).data if not street: raise HTTPException( status_code=404, detail="Street not found. User can not create post code without street.", ) data_dump["street_id"] = street.id data_dump["postcode"] = data.post_code del data_dump["post_code"] post_code = AddressPostcode.find_or_create(**data_dump) relation_table = AddressPostcode.__many__table__.find_or_create( member_id=post_code.id, employee_id=token_dict.selected_company.employee_id, company_id=token_dict.selected_company.company_id, ) post_code.save() post_code.update(is_confirmed=True) post_code.save() relation_table.update(is_confirmed=True) relation_table.save() return JSONResponse( content={ "completed": True, "message": "Create Post Code record", "data": post_code.get_dict(), }, status_code=200, ) class AddressPostCodeUpdateEventMethods(MethodToEvent): event_type = "UPDATE" event_description = "" event_category = "" __event_keys__ = { "df18e489-a63c-477f-984c-aa52d30640ad": "update_post_code_address", } __event_validation__ = { "df18e489-a63c-477f-984c-aa52d30640ad": UpdatePostCode, } @classmethod def update_post_code_address( cls, post_code_uu_id: str, data: UpdatePostCode, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): if isinstance(token_dict, EmployeeTokenObject): AddressPostcode.pre_query = AddressPostcode.select_action( employee_id=token_dict.selected_company.employee_id, ) post_code = AddressPostcode.filter_one( AddressPostcode.uu_id == post_code_uu_id, ).data if not post_code: raise HTTPException( status_code=404, detail="Street not found. User can not update post code without street.", ) data_dict = data.excluded_dump() updated_post_code = post_code.update(**data_dict) updated_post_code.save() return JSONResponse( content={ "completed": True, "message": "Update Post Code record", "data": updated_post_code.get_dict(), }, status_code=200, ) elif isinstance(token_dict, OccupantTokenObject): raise HTTPException( status_code=403, detail="Occupant can not update post code.", ) return JSONResponse( content={ "completed": True, "message": "Update Post Code record", "data": {}, }, status_code=404, ) class AddressPostCodeListEventMethods(MethodToEvent): event_type = "SELECT" event_description = "" event_category = "" __event_keys__ = { "88d37b78-1ac4-4513-9d25-090ac3a24f31": "list_post_code_address", } __event_validation__ = { "88d37b78-1ac4-4513-9d25-090ac3a24f31": AddressPostCodeResponse, } @classmethod def list_post_code_address( cls, list_options: ListOptions, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): post_code_list = AddressPostcode.__many__table__.filter_all( AddressPostcode.__many__table__.company_id == token_dict.selected_company.company_id, ).data if not post_code_list: raise HTTPException( status_code=404, detail="User has no post code registered or not yet any post code created.", ) AddressPostcode.pre_query = AddressPostcode.filter_all( AddressPostcode.id.in_( [post_code.member_id for post_code in post_code_list] ), ).query AddressPostcode.filter_attr = list_options records = AddressPostcode.filter_all().data return AlchemyJsonResponse( completed=True, message="List Address records", result=records, ) AddressListEventMethod = AddressListEventMethods( action=ActionsSchema(endpoint="/address/list") ) AddressCreateEventMethod = AddressCreateEventMethods( action=ActionsSchema(endpoint="/address/create") ) AddressUpdateEventMethod = AddressUpdateEventMethods( action=ActionsSchema(endpoint="/address/update") ) AddressPatchEventMethod = AddressPatchEventMethods( action=ActionsSchema(endpoint="/address/patch") ) AddressPostCodeCreateEventMethod = AddressPostCodeCreateEventMethods( action=ActionsSchema(endpoint="/postcode/create") ) AddressPostCodeUpdateEventMethod = AddressPostCodeUpdateEventMethods( action=ActionsSchema(endpoint="/postcode/update") ) AddressPostCodeListEventMethod = AddressPostCodeListEventMethods( action=ActionsSchema(endpoint="/postcode/list") ) AddressSearchEventMethod = AddressSearchEventMethods( action=ActionsSchema(endpoint="/address/search") )