from typing import Union from api_library.date_time_actions.date_functions import system_arrow, client_arrow from databases import ( BuildDecisionBookProjects, BuildDecisionBookProjectPerson, BuildDecisionBookPayments, OccupantTypes, ) from api_events.events.abstract_class import MethodToEvent, ActionsSchema from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject from api_validations.validations_request import ( InsertBuildDecisionBookProjects, UpdateBuildDecisionBookProjects, ApprovalsBuildDecisionBookProjects, ListOptions, ) from api_validations.core_response import AlchemyJsonResponse from databases import Build, BuildLivingSpace, BuildParts, ApiEnumDropdown from databases.sql_models.building.decision_book import ( BuildDecisionBookProjectItems, BuildDecisionBookItems, BuildDecisionBook, ) class ProjectDecisionBookListEventMethods(MethodToEvent): event_type = "LIST" __event_keys__ = { "96459b36-37f2-4d5b-8370-c459058d5bce": "project_decision_book_list", } __event_validation__ = {"96459b36-37f2-4d5b-8370-c459058d5bce": None} @classmethod def project_decision_book_list( cls, list_options: ListOptions, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): if isinstance(token_dict, EmployeeTokenObject): raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_403_FORBIDDEN", error_case="NOT_ALLOWED", message="Employee cannot create project project decision book", data={}, ) elif isinstance(token_dict, OccupantTokenObject): build_decision_book = BuildDecisionBook.filter_one( BuildDecisionBook.build_id == token_dict.selected_occupant.build_id, ).data if not build_decision_book: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message="Build decision book not found", data={}, ) BuildDecisionBookProjects.filter_attr = list_options decision_book_projects = BuildDecisionBookProjects.filter_all( BuildDecisionBookProjects.build_decision_book_id == build_decision_book.id, ) return AlchemyJsonResponse( status_code="HTTP_200_OK", message="Project decision book created successfully", result=decision_book_projects, ) class ProjectDecisionBookCreateEventMethods(MethodToEvent): event_type = "CREATE" __event_keys__ = { "b8e44bb2-f157-4dd5-8a24-0e02db4877c9": "project_decision_book_create", } __event_validation__ = { "b8e44bb2-f157-4dd5-8a24-0e02db4877c9": InsertBuildDecisionBookProjects } @classmethod def project_decision_book_create( cls, data: InsertBuildDecisionBookProjects, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): if isinstance(token_dict, EmployeeTokenObject): raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_403_FORBIDDEN", error_case="NOT_ALLOWED", message="Employee cannot create project project decision book", data={}, ) elif isinstance(token_dict, OccupantTokenObject): living_space = BuildLivingSpace.filter_one( BuildLivingSpace.id == token_dict.selected_occupant.living_space_id, ).data if not living_space: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message="Living space not found", data={}, ) occupant_type = OccupantTypes.filter_by_one( occupant_category_type="PRJ", occupant_code="PRJ-LDR", id=living_space.occupant_type, ).data if not occupant_type: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message=f"{token_dict.selected_occupant.occupant_type_uu_id} occupant type is not allowed, only PRJ-LDR occupant type is allowed", data={}, ) decision_book_project_person = BuildDecisionBookProjectPerson.filter_one( BuildDecisionBookProjectPerson.living_space_id == token_dict.selected_occupant.living_space_id, ) return AlchemyJsonResponse( status_code="HTTP_200_OK", message="Project decision book created successfully", result=decision_book_project_person, ) class ProjectDecisionBookUpdateEventMethods(MethodToEvent): event_type = "UPDATE" __event_keys__ = { "bfe3ef13-030f-495f-b692-94bcb746d700": "project_decision_book_update", } __event_validation__ = { "bfe3ef13-030f-495f-b692-94bcb746d700": UpdateBuildDecisionBookProjects } @classmethod def project_decision_book_update( cls, data: UpdateBuildDecisionBookProjects, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): if isinstance(token_dict, EmployeeTokenObject): raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_403_FORBIDDEN", error_case="NOT_ALLOWED", message="Employee cannot create project project decision book", data={}, ) elif isinstance(token_dict, OccupantTokenObject): living_space = BuildLivingSpace.filter_one( BuildLivingSpace.id == token_dict.selected_occupant.living_space_id, ).data if not living_space: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message="Living space not found", data={}, ) occupant_type = OccupantTypes.filter_by_one( occupant_category_type="PRJ", occupant_code="PRJ-LDR", id=living_space.occupant_type, ).data if not occupant_type: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message=f"{token_dict.selected_occupant.occupant_type_uu_id} occupant type is not allowed, only PRJ-LDR occupant type is allowed", data={}, ) decision_book_project_person = BuildDecisionBookProjectPerson.filter_one( BuildDecisionBookProjectPerson.build_decision_book_project_uu_id == data.build_decision_book_project_uu_id, BuildDecisionBookProjectPerson.living_space_id == token_dict.selected_occupant.living_space_id, ).data if not decision_book_project_person: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message="This project is not allowed for this occupant", data={}, ) decision_book_project = BuildDecisionBookProjects.filter_one( BuildDecisionBookProjects.id == decision_book_project_person.build_decision_book_project_id, ) if decision_book_project.is_completed: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_403_FORBIDDEN", error_case="NOT_ALLOWED", message="Project decision book is closed. No modification is allowed", data={}, ) data_dict = data.excluded_dump() decision_book_project.update(**data_dict) return AlchemyJsonResponse( status_code="HTTP_200_OK", message="Project decision book created successfully", result=decision_book_project_person, ) class ProjectDecisionBookApprovalEventMethods(MethodToEvent): event_type = "UPDATE" __event_keys__ = { "a83a83fe-8446-4c60-9ae5-d1c06adbf626": "project_decision_book_approval", } __event_validation__ = { "a83a83fe-8446-4c60-9ae5-d1c06adbf626": ApprovalsBuildDecisionBookProjects } @classmethod def project_decision_book_approval( cls, data: ApprovalsBuildDecisionBookProjects, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): BuildDecisionBookPayments.client_arrow = client_arrow BuildDecisionBookPayments.client_arrow.timezone = token_dict.timezone or "GMT+3" if isinstance(token_dict, EmployeeTokenObject): raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_403_FORBIDDEN", error_case="NOT_ALLOWED", message="Employee cannot create project project decision book", data={}, ) elif isinstance(token_dict, OccupantTokenObject): living_space = BuildLivingSpace.filter_one( BuildLivingSpace.id == token_dict.selected_occupant.living_space_id, ).data if not living_space: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message="Living space not found", data={}, ) occupant_type = OccupantTypes.filter_by_one( system=True, occupant_category_type="PRJ", occupant_code="PRJ-LDR", id=living_space.occupant_type, ).data if not occupant_type: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message=f"{token_dict.selected_occupant.occupant_type_uu_id} occupant type is not allowed, only PRJ-LDR occupant type is allowed", data={}, ) decision_book_project_person = BuildDecisionBookProjectPerson.filter_one( BuildDecisionBookProjectPerson.build_decision_book_project_uu_id == data.build_decision_book_project_uu_id, BuildDecisionBookProjectPerson.living_space_id == token_dict.selected_occupant.living_space_id, ).data if not decision_book_project_person: raise BuildDecisionBookProjectPerson.raise_http_exception( status_code="HTTP_404_NOT_FOUND", error_case="NOT_FOUND", message="This project is not allowed for this occupant", data={}, ) decision_book_project = BuildDecisionBookProjects.filter_one( BuildDecisionBookProjects.id == decision_book_project_person.build_decision_book_project_id, ).data if decision_book_project.is_completed: raise BuildDecisionBookProjects.raise_http_exception( status_code="HTTP_403_FORBIDDEN", error_case="NOT_ALLOWED", message="Project decision book is closed. No modification is allowed", data={}, ) data_dict = data.excluded_dump() data_dict["is_completed"] = True build_parts_list = BuildParts.filter_all( BuildParts.human_livable == True, BuildParts.build_id == token_dict.selected_occupant.build_id, ).data decision_book_project_item = BuildDecisionBookItems.filter_one( BuildDecisionBookItems.id == decision_book_project.build_decision_book_item_id ).data book_payment_dict = dict( build_decision_book_item_id=decision_book_project_item.id, build_decision_book_item_uu_id=str(decision_book_project_item.uu_id), currency=decision_book_project.currency, ) payment_type = ApiEnumDropdown.get_debit_search(search_debit="DT-D") for final_price in data.final_price_list or []: for build_part_single in build_parts_list: local_date = BuildDecisionBookPayments.client_arrow.get( str(final_price["date"]) ) local_date = system_arrow.get(local_date) payment_amount = abs(float(final_price["price"])) * -1 created_book_payment = BuildDecisionBookPayments.find_or_create( build_parts_id=build_part_single.id, build_parts_uu_id=str(build_part_single.uu_id), payment_amount=payment_amount, payment_types_id=payment_type.id, payment_types_uu_id=str(payment_type.uu_id), process_date=str(local_date), process_date_m=int(local_date.month), process_date_y=int(local_date.year), payment_plan_time_periods=str( decision_book_project.project_type ), period_time=f"{local_date.year}-{str(local_date.month).zfill(2)}", decision_book_project_id=decision_book_project.id, decision_book_project_uu_id=str(decision_book_project.uu_id), **book_payment_dict, ) created_book_payment.save_and_confirm() updated_decision_book_project = decision_book_project.update(**data_dict) updated_decision_book_project.save_and_confirm() return AlchemyJsonResponse( status_code="HTTP_200_OK", message="Project decision book created successfully", result=updated_decision_book_project, ) class ProjectDecisionBookPatchEventMethods(MethodToEvent): event_type = "PATCH" __event_keys__ = { "444d67a0-b3a8-4ca2-9d8d-f1acc75011e0": "project_decision_book_patch", } __event_validation__ = {"444d67a0-b3a8-4ca2-9d8d-f1acc75011e0": None} @classmethod def project_decision_book_patch( cls, data, token_dict: Union[EmployeeTokenObject, OccupantTokenObject], ): return ProjectDecisionBookListEventMethod = ProjectDecisionBookListEventMethods( action=ActionsSchema(endpoint="/build/decision_book/project/list") ) ProjectDecisionBookCreateEventMethod = ProjectDecisionBookCreateEventMethods( action=ActionsSchema(endpoint="/build/decision_book/project/create") ) ProjectDecisionBookUpdateEventMethod = ProjectDecisionBookUpdateEventMethods( action=ActionsSchema(endpoint="/build/decision_book/project/update") ) ProjectDecisionBookApprovalEventMethod = ProjectDecisionBookApprovalEventMethods( action=ActionsSchema(endpoint="/build/decision_book/project/approval") ) ProjectDecisionBookPatchEventMethod = ProjectDecisionBookPatchEventMethods( action=ActionsSchema(endpoint="/build/decision_book/project/patch") )