297 lines
12 KiB
Python
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")
|
|
)
|
|
)
|