wag-managment-api-service-v.../api_events/events/decision_book/decision_book_invitations.py

297 lines
12 KiB
Python

import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
Build,
BuildLivingSpace,
BuildParts,
BuildDecisionBookInvitations,
BuildDecisionBookPerson,
BuildDecisionBook,
BuildDecisionBookPersonOccupants,
OccupantTypes,
Users,
ApiEnumDropdown,
)
from api_validations.validations_request import (
DecisionBookDecisionBookInvitationsUpdate,
DecisionBookDecisionBookInvitations,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import AlchemyJsonResponse
from api_library.date_time_actions.date_functions import system_arrow
class BuildDecisionBookInvitationsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"e2277528-8c9c-4c0c-ae64-3ce80cae664b": "decision_book_invitations_list",
}
@classmethod
def decision_book_invitations_list(
cls,
data,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"d0bfa20c-841d-421c-98e6-d308f938d16a": "decision_book_invitations_create",
}
@classmethod
def decision_book_invitations_create(
cls,
data: DecisionBookDecisionBookInvitations,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee cannot create decision book invitations",
)
# Check token posses the occupant type of Build Manager
occupant_manager = OccupantTypes.filter_by_one(
occupant_category_type="BU", occupant_code="BU-MNG"
).get(1)
if not token_dict.selected_occupant.occupant_type_id == occupant_manager.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Only Build Manager can create decision book",
)
# Check decision book is valid for this token and building
decision_book = BuildDecisionBook.filter_one(
BuildDecisionBook.uu_id == data.build_decision_book_uu_id,
BuildDecisionBook.build_id == token_dict.selected_occupant.build_id,
BuildDecisionBook.active == True,
).get(1)
if not decision_book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Decision book not found. Please create decision book first",
)
occupant_building = Build.filter_one(
Build.id == token_dict.selected_occupant.build_id
).get(1)
# Check meeting type is valid
meeting_type = ApiEnumDropdown.filter_by_one(
enum_class="MeetingTypes",
).get(1)
if not meeting_type:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Meeting type not found",
)
# Check planned decision book date is valid
if (
not system_arrow.get(data.planned_date).date()
>= system_arrow.shift(days=1).date()
):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Planned date must be greater than today",
)
# 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(
build_id=token_dict.selected_occupant.build_id,
build_uu_id=token_dict.selected_occupant.build_uuid,
decision_book_id=decision_book.id,
decision_book_uu_id=str(decision_book.uu_id),
invitation_type=meeting_type.key,
living_part_count=occupant_building.livable_part_count,
living_part_percentage=0.51,
message=data.message,
planned_date=data.planned_date,
planned_date_expires=planned_date_expires,
expiry_ends=str(system_arrow.get(data.planned_date).shift(days=15).date()),
is_confirmed=True,
)
if book_invitation.is_found:
detail_message = (
f"Invitation with: {str(book_invitation.planned_date)} already exists"
f" for {book_invitation.invitation_type}"
)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=detail_message,
)
# Get all the parts of the building that is occupant in token
build_parts = BuildParts.filter_all(
BuildParts.build_id == occupant_building.id,
*BuildParts.valid_record_args(BuildParts),
)
# Get all build living spaces that is found in building with distinct person id
occupants = OccupantTypes.filter_all(system=True)
BuildLivingSpace.filter_attr = None
build_living_spaces_people = (
BuildLivingSpace.filter_all(
BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_parts.data]
),
BuildLivingSpace.occupant_type.in_(
[occupant.id for occupant in occupants.data]
),
)
.query.distinct(BuildLivingSpace.person_id)
.all()
)
if not build_living_spaces_people:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="No living spaces found for the building",
)
print(
f"Tnvite UUID : {book_invitation.uu_id} Message : {data.message} Planned date : {data.planned_date}"
)
# Send invitation to all the users as attend and update the manager as build manager
attendance_occupant_type = OccupantTypes.find_or_abort(
occupant_code="MT-ATT", occupant_category_type="MT"
)
manager_occupant_type = OccupantTypes.find_or_abort(
occupant_code="BU-MNG", occupant_category_type="BU"
)
build_decision_book_person_dict = dict(
build_decision_book_id=decision_book.id,
build_decision_book_uu_id=str(decision_book.uu_id),
invite_id=book_invitation.id,
invite_uu_id=str(book_invitation.uu_id),
send_date=str(system_arrow.now().date()),
expiry_starts=decision_book.expiry_starts,
expiry_ends=decision_book.expiry_ends,
is_confirmed=True,
)
# Check if the invitation is already created at database
for build_living_spaces_user in build_living_spaces_people:
if invite := BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.invite_id == book_invitation.id,
BuildDecisionBookPerson.build_living_space_id
== build_living_spaces_user.id,
*BuildDecisionBookPerson.valid_record_args(BuildDecisionBookPerson),
).data:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invitation already send to {build_living_spaces_user.email} "
f"for invite {invite.uu_id} date : {str(book_invitation.planned_date)}",
)
invitations_person = BuildDecisionBookPerson.find_or_create(
**build_decision_book_person_dict,
build_living_space_id=build_living_spaces_user.id,
build_living_space_uu_id=str(build_living_spaces_user.uu_id),
person_id=build_living_spaces_user.person_id,
token=Users.generate_token(40),
)
invitations_person.add_occupant_type(occupant_type=attendance_occupant_type)
if invitations_person and not invitations_person.is_found:
print(f'"{invitations_person.token}",')
spaces_user = Users.filter_one(
Users.active == True,
Users.is_confirmed == True,
Users.person_id == build_living_spaces_user.person_id,
).data
# print(
# f"Invitation is send : {spaces_user.email} "
# f"Token : {invitations_person.token} "
# f"Send Date : {str(invitations_person.send_date.date())}"
# )
manager_living_spaces = BuildLivingSpace.filter_all(
BuildLivingSpace.person_id == token_dict.person_id,
*BuildLivingSpace.valid_record_args(BuildLivingSpace),
)
manager_people = BuildDecisionBookPerson.filter_all(
BuildDecisionBookPerson.invite_id == book_invitation.id,
BuildDecisionBookPerson.build_living_space_id.in_(
[
manager_living_space.id
for manager_living_space in manager_living_spaces.data
]
),
*BuildLivingSpace.valid_record_args(BuildLivingSpace),
)
manager_people_occupants = BuildDecisionBookPersonOccupants.filter_all(
BuildDecisionBookPersonOccupants.build_decision_book_person_id
== manager_people.get(1).id,
*BuildDecisionBookPersonOccupants.valid_record_args(
BuildDecisionBookPersonOccupants
),
)
manager_people_occupants.query.delete()
manager_people.query.delete()
if book_person_manager := BuildDecisionBookPerson.find_or_create(
**build_decision_book_person_dict,
build_living_space_id=token_dict.selected_occupant.living_space_id,
build_living_space_uu_id=str(
token_dict.selected_occupant.living_space_uu_id
),
person_id=token_dict.person_id,
token=Users.generate_token(40),
):
book_person_manager.add_occupant_type(occupant_type=manager_occupant_type)
print(f"Manager Token : {book_person_manager.token}")
BuildDecisionBookPerson.save()
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Invitation are send to people related with building",
"data": book_invitation.get_dict(),
},
)
class BuildDecisionBookInvitationsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"92413636-53a8-4a05-842c-1485a64e00d1": "decision_book_invitations_attend",
}
@classmethod
def decision_book_invitations_attend(
cls,
data: DecisionBookDecisionBookInvitationsUpdate,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
BuildDecisionBookInvitationsListEventMethod = (
BuildDecisionBookInvitationsListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invite/list")
)
)
BuildDecisionBookInvitationsCreateEventMethod = (
BuildDecisionBookInvitationsCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invite/create")
)
)
BuildDecisionBookInvitationsUpdateEventMethod = (
BuildDecisionBookInvitationsUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invite/update")
)
)