database and services updated and tested

This commit is contained in:
2025-01-08 21:35:11 +03:00
parent 364a4df4b1
commit 08896e4c61
132 changed files with 13302 additions and 95 deletions

View File

@@ -0,0 +1,229 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
Build,
BuildDecisionBook,
Companies,
OccupantTypes,
)
from api_validations.validations_request import (
InsertDecisionBook,
ListOptions,
)
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 DecisionBookListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"5c10d6ae-2aee-4243-a7c3-94826d028d13": "building_decision_book_list",
}
__event_validation__ = {"5c10d6ae-2aee-4243-a7c3-94826d028d13": None}
@classmethod
def building_decision_book_list(
cls,
list_options: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
records = []
if isinstance(token_dict, EmployeeTokenObject):
build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
build_id_list = build_id_list_query.all()
if not build_id_list:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
)
BuildDecisionBook.filter_attr = list_options
records = BuildDecisionBook.filter_all(
BuildDecisionBook.build_id.in_([build.id for build in build_id_list]),
)
elif isinstance(token_dict, OccupantTokenObject):
BuildDecisionBook.filter_attr = list_options
records = BuildDecisionBook.filter_all(
BuildDecisionBook.build_id == token_dict.selected_occupant.build_id,
)
return AlchemyJsonResponse(
completed=True,
message="DecisionBook are listed successfully",
result=records,
)
class DecisionBookCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"0a68cb44-271a-4829-81f6-cd99a5f326b4": "building_decision_book_create",
}
__event_validation__ = {"0a68cb44-271a-4829-81f6-cd99a5f326b4": InsertDecisionBook}
@classmethod
def building_decision_book_create(
cls,
data: InsertDecisionBook,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
data_dict = data.excluded_dump()
if isinstance(token_dict, EmployeeTokenObject):
Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
build = Build.filter_one(
Build.uu_id == data.build_uu_id,
).data
if not build:
raise HTTPException(
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')}",
)
data_dict["build_id"] = build.id
if data.resp_company_uu_id:
Companies.pre_query = Companies.select_action(
duty_id_list=[
token_dict.selected_company.duty_id,
token_dict.selected_company.bulk_duties_id,
]
)
company = Companies.filter_one(
Companies.uu_id == data.resp_company_uu_id,
).data
if not company:
raise HTTPException(
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')}",
)
data_dict["resp_company_id"] = company.id
data_dict["resp_company_uu_id"] = str(company.uu_id)
decision_period_date = system_arrow.get(build.decision_period_date)
data_dict["expiry_starts"] = system_arrow.get(
system_arrow.now().date().year,
int(decision_period_date.date().month),
int(decision_period_date.date().day),
)
data_dict["expiry_ends"] = str(
data_dict["expiry_starts"].shift(years=1, days=-1)
)
data_dict["expiry_starts"] = str(data_dict["expiry_starts"])
build_decision_book = BuildDecisionBook.find_or_create(**data_dict)
build_decision_book.save_and_confirm()
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message="Decision Book has created",
completed=True,
data=build_decision_book.get_dict(),
),
)
elif isinstance(token_dict, OccupantTokenObject):
occupant_manager = OccupantTypes.filter_by_one(
occupant_category_type="BU", occupant_code="BU-MNG"
).data
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",
)
occupant_build = Build.filter_one(
Build.id == token_dict.selected_occupant.build_id,
).data
occupant_company = Companies.filter_one(
Companies.id == token_dict.selected_occupant.responsible_company_id,
).data
data_dict["build_id"] = occupant_build.id
data_dict["build_uu_id"] = str(occupant_build.uu_id)
data_dict["resp_company_id"] = occupant_company.id
data_dict["resp_company_uu_id"] = str(occupant_company.uu_id)
decision_period_date = system_arrow.get(occupant_build.decision_period_date)
data_dict["expiry_starts"] = system_arrow.get(
system_arrow.now().date().year,
int(decision_period_date.date().month),
int(decision_period_date.date().day),
)
data_dict["expiry_ends"] = str(
data_dict["expiry_starts"].shift(years=1, days=-1)
)
data_dict["expiry_starts"] = str(data_dict["expiry_starts"])
build_decision_book = BuildDecisionBook.find_or_create(**data_dict)
build_decision_book.save()
build_decision_book.update(is_confirmed=True)
build_decision_book.save()
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message="Decision Book has created",
completed=True,
data=build_decision_book.get_dict(),
),
)
class DecisionBookUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"6bc7035c-3b53-4c0a-8cc9-1ec9c6af1e29": "building_decision_book_update",
}
__event_validation__ = {"6bc7035c-3b53-4c0a-8cc9-1ec9c6af1e29": None}
@classmethod
def building_decision_book_update(cls, data: InsertDecisionBook, token_dict: dict):
return
class DecisionBookPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"7b58ed84-9a65-4588-994d-30df8366b050": "building_decision_book_patch",
}
__event_validation__ = {"7b58ed84-9a65-4588-994d-30df8366b050": None}
@classmethod
def building_decision_book_patch(cls, data: InsertDecisionBook, token_dict: dict):
return
class DecisionBookApprovalEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"fc745142-3437-4ca2-89fa-c5a3e2b5c6c2": "building_decision_book_approval",
}
__event_validation__ = {"fc745142-3437-4ca2-89fa-c5a3e2b5c6c2": None}
@classmethod
def building_decision_book_approval(cls, data, token_dict):
return
DecisionBookListEventMethod = DecisionBookListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/list")
)
DecisionBookCreateEventMethod = DecisionBookCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/create")
)
DecisionBookUpdateEventMethod = DecisionBookUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/update")
)
DecisionBookPatchEventMethod = DecisionBookPatchEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/patch")
)
DecisionBookApprovalEventMethod = DecisionBookApprovalEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/approval")
)

View File

@@ -0,0 +1,570 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from api_events.events.events.events_bind_services import (
ServiceBindOccupantEventMethods,
)
from databases import (
Build,
BuildParts,
BuildDecisionBook,
BuildDecisionBookItems,
BuildDecisionBookPerson,
BuildDecisionBookPayments,
BuildDecisionBookProjects,
BuildDecisionBookProjectPerson,
ApiEnumDropdown,
OccupantTypes,
Companies,
BuildLivingSpace,
)
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, client_arrow
from api_validations.validations_request import (
InsertBuildDecisionBookItems,
ListOptions,
ListDecisionBook,
)
from databases.sql_models.event.event import Services
class DecisionBookDecisionBookItemsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"eb36de59-8268-4d96-80b6-5d01c12bf0b1": "building_decision_book_items_list",
}
__event_validation__ = {"eb36de59-8268-4d96-80b6-5d01c12bf0b1": None}
@classmethod
def building_decision_book_items_list(
cls,
data: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
decision_book = BuildDecisionBook.filter_one(
BuildDecisionBook.uu_id == data.build_decision_book_uu_id,
).data
if not decision_book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No Decision Book is match with given UUID {data.build_decision_book_uu_id}",
)
if isinstance(token_dict, EmployeeTokenObject):
Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id,
filter_expr=[
Build.uu_id == str(decision_book.uu_id),
],
)
reachable_building = Build.filter_all()
if not reachable_building.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
)
Companies.pre_query = Companies.select_action(
duty_id_list=[
token_dict.selected_company.duty_id,
token_dict.selected_company.bulk_duties_id,
],
filter_expr=[Companies.id == decision_book.resp_company_id],
)
reachable_companies = Companies.filter_all()
if not reachable_companies.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No company is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
)
BuildDecisionBookItems.filter_attr = BuildDecisionBookItems.FilterModel(
**data.dump()
)
records = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.build_decision_book_id == decision_book.id
)
return AlchemyJsonResponse(
completed=True,
message="DecisionBook are listed successfully",
result=records,
)
# return JSONResponse(
# status_code=status.HTTP_200_OK,
# content=dict(
# total_count=records.count,
# count=len(records.data),
# message=f"Decision Book Items has found from given Decision Book UUID {data.build_decision_book_uu_id}",
# completed=True,
# data=[record.get_dict() for record in records.data],
# ),
# )
else:
# BuildDecisionBookItems.pre_query = BuildDecisionBookItems.select_action(
# occupant_id=token_dict.occupant_list["occupant_id"]
# )
# BuildDecisionBookItems.filter_attr = list_options
# records = BuildDecisionBookItems.filter_all(
# )
# return return_json_response_from_alchemy(response=records, pagination=list_options)
return
class DecisionBookDecisionBookItemsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"dce10509-0da5-46fb-af3c-a81d54d5481c": "building_decision_book_items_create",
}
__event_validation__ = {
"dce10509-0da5-46fb-af3c-a81d54d5481c": InsertBuildDecisionBookItems
}
@classmethod
def iterate_over_build_parts(
cls,
build_parts_list,
payment_types,
local_date,
end_date,
unit_price,
unit_type,
book_payment_dict,
unit_price_is_fixed,
):
start_date, payment_return_dict = local_date, {}
for build_part_single in build_parts_list:
local_date = start_date
while local_date.is_between(start_date, end_date, "[]"):
local_date = system_arrow.find_last_day_of_month(local_date)
payment_amount = unit_price
if not unit_price_is_fixed:
unit_amount = int(build_part_single.part_net_size)
payment_amount = abs(unit_price * float(unit_amount)) * -1
payment_amount = -1 * (
abs(payment_amount) + (50 - float(abs(payment_amount)) % 50)
)
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_types.id,
payment_types_uu_id=str(payment_types.uu_id),
process_date=str(local_date),
process_date_m=int(local_date.month),
process_date_y=int(local_date.year),
period_time=f"{local_date.year}-{str(local_date.month).zfill(2)}",
**book_payment_dict,
)
created_book_payment.save_and_confirm()
local_date = local_date.shift(days=2)
part_key = str(build_part_single.due_part_key).upper()
if part_key not in payment_return_dict:
payment_return_dict[part_key] = payment_amount
return payment_return_dict
@classmethod
def create_payment_records_for_each_build_part(
cls,
data_info_type,
build_id,
unit_price,
unit_type,
decision_book,
decision_book_item,
unit_price_is_fixed,
currency,
debit_start_date: str = None,
debit_end_date: str = None,
):
build_parts_list = BuildParts.filter_all(
BuildParts.human_livable == True,
BuildParts.build_id == build_id,
)
print("data_info_type.key", data_info_type.key)
book_payment_dict = dict(
payment_plan_time_periods=str(data_info_type.key),
build_decision_book_item_id=decision_book_item.id,
build_decision_book_item_uu_id=str(decision_book_item.uu_id),
currency=currency,
)
payment_types = ApiEnumDropdown.get_debit_search(search_debit="DT-D")
if data_info_type.key == "BDT-D":
local_date = system_arrow.get(
system_arrow.get(decision_book.expiry_starts).date()
)
end_date = system_arrow.get(
system_arrow.get(decision_book.expiry_ends).date()
)
payment_return_dict = cls.iterate_over_build_parts(
build_parts_list=build_parts_list.data,
payment_types=payment_types,
local_date=local_date,
end_date=end_date,
unit_price=unit_price,
unit_type=unit_type,
unit_price_is_fixed=unit_price_is_fixed,
book_payment_dict=book_payment_dict,
)
return payment_return_dict
elif data_info_type.key == "BDT-A":
local_date = system_arrow.get(system_arrow.get(debit_start_date).date())
end_date = system_arrow.get(system_arrow.get(debit_end_date).date())
payment_return_dict = cls.iterate_over_build_parts(
build_parts_list=build_parts_list.data,
payment_types=payment_types,
local_date=local_date,
end_date=end_date,
unit_price=unit_price,
unit_type=unit_type,
unit_price_is_fixed=unit_price_is_fixed,
book_payment_dict=book_payment_dict,
)
return payment_return_dict
elif data_info_type.key == "BDT-R" or data_info_type.key == "BDT-L":
local_date = system_arrow.get(system_arrow.get(debit_start_date).date())
end_date = system_arrow.get(system_arrow.get(debit_end_date).date())
decision_date = system_arrow.get(decision_book.expiry_starts).date()
meeting_date = system_arrow.get(decision_book.meeting_date).date()
already_book_projects = BuildDecisionBookProjects.filter_all(
BuildDecisionBookProjects.build_decision_book_id == decision_book.id,
BuildDecisionBookProjects.project_type
== f"{decision_book.decision_type}_{data_info_type.key}",
system=True,
)
management_room = BuildParts.filter_one(
BuildParts.build_id == build_id, BuildParts.part_no == 0, system=True
).data
occupant_man = OccupantTypes.filter_by_one(
system=True, occupant_code="MT-VPR", occupant_category_type="MT"
).data
manager_living_space = BuildLivingSpace.filter_one(
BuildLivingSpace.build_parts_id == management_room.id,
BuildLivingSpace.occupant_type == occupant_man.id,
).data
if not manager_living_space:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"{occupant_man.occupant_description} Living Space is not found. Check manager living space and try again",
)
already_book_project_count = already_book_projects.count + 1
book_project_dict = dict(
project_no=f"{data_info_type.key}_{decision_date.year}_{already_book_project_count}",
project_name=f"{str(meeting_date)}_{decision_book.decision_type} Project {already_book_projects.count + 1}",
project_start_date=str(local_date),
project_stop_date=str(end_date),
project_type=f"{decision_book.decision_type}_{data_info_type.key}",
project_note=str(decision_book_item.item_comment),
build_decision_book_id=decision_book.id,
build_decision_book_uu_id=str(decision_book.uu_id),
build_decision_book_item_id=decision_book_item.id,
build_decision_book_item_uu_id=str(decision_book_item.uu_id),
project_response_living_space_id=manager_living_space.id,
project_response_living_space_uu_id=str(manager_living_space.uu_id),
)
book_project_created = BuildDecisionBookProjects.find_or_create(
**book_project_dict
)
book_project_created.save_and_confirm()
print("book_project_created", book_project_created)
item_comment_at_database = decision_book_item.item_comment
decision_book_item.update(
item_comment=f"{book_project_created.project_no}_{book_project_created.project_name} "
f"is assigned to {occupant_man.occupant_description} | {item_comment_at_database}"
)
decision_book_item.save_and_confirm()
project_lead = OccupantTypes.filter_by_one(
system=True, occupant_code="PRJ-LDR", occupant_category_type="PRJ"
).data
build_new_president = OccupantTypes.filter_by_one(
system=True, occupant_code="MT-VPR", occupant_category_type="MT"
).data
new_president = BuildLivingSpace.filter_one(
BuildLivingSpace.occupant_type == build_new_president.id,
BuildLivingSpace.build_parts_id == management_room.id,
).data
project_leader = BuildLivingSpace.filter_one(
BuildLivingSpace.occupant_type == project_lead.id,
BuildLivingSpace.build_parts_id == management_room.id,
BuildLivingSpace.person_id == new_president.person_id,
).data
if not project_leader:
project_leader = BuildLivingSpace.find_or_create(
person_id=new_president.person_id,
person_uu_id=str(new_president.person_uu_id),
build_parts_id=management_room.id,
build_parts_uu_id=str(management_room.uu_id),
occupant_type=project_lead.id,
occupant_type_uu_id=str(project_lead.uu_id),
)
project_leader.save_and_confirm()
related_service = Services.filter_by_one(
system=True,
related_responsibility=project_lead.occupant_code,
).data
ServiceBindOccupantEventMethods.bind_services_occupant_system(
service_id=related_service.id,
build_living_space_id=project_leader.id,
)
project_person = BuildDecisionBookProjectPerson.find_or_create(
build_decision_book_project_id=book_project_created.id,
build_decision_book_project_uu_id=str(book_project_created.uu_id),
living_space_id=project_leader.id,
living_space_uu_id=str(project_leader.uu_id),
)
project_person.save_and_confirm()
book_project_created.update(
project_response_living_space_id=project_leader.id,
project_response_living_space_uu_id=str(project_leader.uu_id),
)
book_project_created.save()
return book_project_created
elif data_info_type.key == "BDT-S":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="BDT-S is not implemented yet. Check info type and try again",
)
elif data_info_type.key == "BDT-I":
return
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Payment Info Type is not valid. Check payment type and try again",
)
@classmethod
def building_decision_book_items_create(
cls,
data: InsertBuildDecisionBookItems,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="No employee can reach this event. An notification is send to admin about event registration",
)
elif isinstance(token_dict, OccupantTokenObject):
data_dict = data.dump()
occupant_wrt = OccupantTypes.filter_by_one(
system=True, occupant_code="MT-WRT", occupant_category_type="MT"
).data
if token_dict.selected_occupant.occupant_type_id != occupant_wrt.id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only WRITER can create decision book item. Check your occupant type and try again",
)
decision_book_person = BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.token == data.token,
).data
decision_book = BuildDecisionBook.filter_one(
BuildDecisionBook.id == decision_book_person.build_decision_book_id,
).data
book_items = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.build_decision_book_id == decision_book.id,
system=True,
)
if int(book_items.count) < 3:
BuildDecisionBookItems.check_meeting_is_valid_to_start_add_attendance(
decision_book=decision_book,
token_dict=token_dict,
)
book_items = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.build_decision_book_id == decision_book.id,
system=True,
)
data_dict["item_order"] = int(book_items.count) + 1
data_dict["build_decision_book_id"] = decision_book.id
data_dict["build_decision_book_uu_id"] = str(decision_book.uu_id)
data_info_type = ApiEnumDropdown.filter_by_one(
system=True,
enum_class="BuildDuesTypes",
key="BDT-I",
).data
data_info_types = ApiEnumDropdown.due_type_search()
for info_type in data_info_types:
if str(info_type.uu_id) == data_dict["info_type_uu_id"]:
data_info_type = info_type
break
row_is_debit = str(data_info_type.key).upper() in ["BDT-A", "BDT-D"]
row_is_project = str(data_info_type.key).upper() in [
"BDT-R",
"BDT-L",
"BDT-S",
]
debit_dates_required = (
not data_dict["debit_start_date"] or not data_dict["debit_end_date"]
)
if row_is_project and debit_dates_required:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Debit Start Date and Debit End Date is required for this payment type. "
"Check debit start date and debit end date and try again",
)
data_dict["info_type_id"] = data_info_type.id
data_dict["info_type_uu_id"] = str(data_info_type.uu_id)
unit_price, unit_type = float(data_dict["unit_price"]), str(
data_dict["unit_type"]
)
debit_start_date, debit_end_date = (
data_dict["debit_start_date"],
data_dict["debit_end_date"],
)
currency = data_dict["currency"]
del (
data_dict["token"],
data_dict["unit_price"],
data_dict["unit_type"],
data_dict["unit_price_is_fixed"],
data_dict["debit_start_date"],
data_dict["debit_end_date"],
data_dict["currency"],
)
new_decision_book_item = BuildDecisionBookItems.find_or_create(**data_dict)
new_decision_book_item.save_and_confirm()
print("new_decision_book_item", new_decision_book_item)
if created_payment_records_dict := cls.create_payment_records_for_each_build_part(
data_info_type=data_info_type,
build_id=decision_book.build_id,
unit_price=unit_price,
unit_type=unit_type.upper(),
decision_book=decision_book,
decision_book_item=new_decision_book_item,
unit_price_is_fixed=data.unit_price_is_fixed,
debit_start_date=debit_start_date,
debit_end_date=debit_end_date,
currency=currency,
):
if row_is_debit:
if data_info_type.key == "BDT-D":
item_comment = "Regular Payment Plan : "
else:
item_comment = "Additional Payment Plan : "
for key, value in dict(
sorted(
created_payment_records_dict.items(),
key=lambda x: x[1],
reverse=True,
)
).items():
item_comment += f" {key} | {abs(float(value))} {currency}, "
item_comment = item_comment[:-2]
new_decision_book_item.update(item_comment=item_comment)
new_decision_book_item.update(is_payment_created=True)
elif row_is_project:
project_no = str(created_payment_records_dict.project_no)
item_comment = (
f"{data.item_comment} | @ Project is created no : {project_no}."
)
new_decision_book_item.update(item_comment=item_comment)
new_decision_book_item.update(is_payment_created=True)
new_decision_book_item.save_and_confirm()
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message=f"Decision Book Item has created for given Decision Book UUID {decision_book.uu_id}",
completed=True,
data=new_decision_book_item.get_dict(),
),
)
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail="Decision Book Item is not created. Check info type and info no and try again. Unique constraint index is implemented for info type and info no",
# )
class DecisionBookDecisionBookItemsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"f0fdfe1b-806b-4175-ad50-a1a165c0dfb7": "building_decision_book_items_update",
}
__event_validation__ = {"f0fdfe1b-806b-4175-ad50-a1a165c0dfb7": None}
@classmethod
def building_decision_book_items_update(
cls,
data: InsertBuildDecisionBookItems,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
class DecisionBookDecisionBookItemsPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"42328809-b516-477b-82cc-2d6fadf28843": "building_decision_book_items_patch",
}
__event_validation__ = {"42328809-b516-477b-82cc-2d6fadf28843": None}
@classmethod
def building_decision_book_items_patch(
cls,
data: InsertBuildDecisionBookItems,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
DecisionBookDecisionBookItemsListEventMethod = (
DecisionBookDecisionBookItemsListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/list")
)
)
DecisionBookDecisionBookItemsCreateEventMethod = (
DecisionBookDecisionBookItemsCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/create")
)
)
DecisionBookDecisionBookItemsUpdateEventMethod = (
DecisionBookDecisionBookItemsUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/update")
)
)
DecisionBookDecisionBookItemsPatchEventMethod = (
DecisionBookDecisionBookItemsPatchEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/patch")
)
)
# if data.info_no is None:
# data_dict["info_no"] = data_dict["item_order"]
# elif data.occupant_types_uu_id:
# data_dict["info_type"] = None
# if occupant_type := OccupantTypes.find_one(
# uu_id=data.occupant_types_uu_id
# ):
# if (
# str(data.occupant_types_uu_id)
# in OccupantTypes.get_manager_occupant_type()
# ):
# if BuildDecisionBookItems.find_one(
# build_decision_book_id=decision_book.id,
# occupant_type=occupant_type.id,
# ):
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail="This Occupant Type is already exist for given Decision Book UUID. Check occupant type and try again",
# )
# data_dict["occupant_type"] = occupant_type.id
# data_dict["occupant_type_uu_id"] = str(occupant_type.uu_id)

View File

@@ -0,0 +1,105 @@
import typing
from databases import (
Build,
BuildParts,
BuildDecisionBook,
BuildDecisionBookItems,
BuildDecisionBookPerson,
BuildDecisionBookPayments,
BuildDecisionBookProjects,
BuildDecisionBookProjectPerson,
ApiEnumDropdown,
OccupantTypes,
Companies,
BuildLivingSpace,
)
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, client_arrow
class DecisionBookDecisionBookItemsDebitsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"a1d2b1f6-9b8d-4f6b-8f4d-6b1f6a9d8b1a": "decision_book_decision_book_items_debits_list",
}
__event_validation__ = {"a1d2b1f6-9b8d-4f6b-8f4d-6b1f6a9d8b1a": None}
@classmethod
def decision_book_decision_book_items_debits_list(
cls,
decision_book_id: str,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
BuildDecisionBookItems.pre_query = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.decision_book_id == decision_book_id,
).query
BuildDecisionBookItems.filter_attr = None
records = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.decision_book_id == decision_book_id,
)
return AlchemyJsonResponse(
completed=True,
message="Decision Book Items Debits are listed",
result=records,
)
class DecisionBookDecisionBookItemsDebitsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"a1d2b1f6-9b8d-4f6b-8f4d-6b1f6a9d8b1a": "decision_book_decision_book_items_debits_create",
}
__event_validation__ = {"a1d2b1f6-9b8d-4f6b-8f4d-6b1f6a9d8b1a": None}
@classmethod
def decision_book_decision_book_items_debits_create(
cls,
decision_book_id: str,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
decision_book_items_debits: dict,
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="No employee can reach this event. An notification is send to admin about event registration",
)
decision_book_items_debits["decision_book_id"] = decision_book_id
decision_book_items_debits["created_at"] = system_arrow().datetime
decision_book_items_debits["created_by"] = token_dict.employee_id
decision_book_items_debits["updated_at"] = system_arrow().datetime
decision_book_items_debits["updated_by"] = token_dict.employee_id
decision_book_items_debits["is_active"] = True
decision_book_items_debits["is_confirmed"] = False
decision_book_items_debits["is_deleted"] = False
decision_book_items_debits["confirmed_at"] = None
decision_book_items_debits["confirmed_by"] = None
decision_book_items_debits["deleted_at"] = None
decision_book_items_debits["deleted_by"] = None
decision_book_items_debits["confirmed_at"] = None
decision_book_items_debits["confirmed_by"] = None
decision_book_items_debits["deleted_at"] = None
decision_book_items_debits["deleted_by"] = None
decision_book_items_debits["confirmed_at"] = None
decision_book_items_debits["confirmed_by"] = None
decision_book_items_debits["deleted_at"] = None
decision_book_items_debits["deleted_by"] = None
BuildDecisionBookItems.pre_query = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.decision_book_id == decision_book_id,
).query
BuildDecisionBookItems.filter_attr = None
records = BuildDecisionBookItems.filter_all(
BuildDecisionBookItems.decision_book_id == decision_book_id,
)
return AlchemyJsonResponse(
completed=True,
message="Decision Book Items Debits are listed",
result=records,
)

View File

@@ -0,0 +1,456 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
BuildDecisionBook,
BuildDecisionBookPerson,
BuildDecisionBookInvitations,
Users,
BuildLivingSpace,
BuildParts,
BuildDecisionBookPersonOccupants,
People,
OccupantTypes,
)
from api_validations.validations_request import (
ListOptions,
RemoveDecisionBookPerson,
DecisionBookDecisionBookInvitationsAttend,
DecisionBookDecisionBookInvitationsUpdate,
DecisionBookDecisionBookInvitationsAssign,
)
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
class DecisionBookPersonListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"ea324dc0-3b08-4896-9040-7fa0401a176f": "building_decision_book_person_list",
}
__event_validation__ = {"ea324dc0-3b08-4896-9040-7fa0401a176f": None}
@classmethod
def building_decision_book_person_list(
cls,
data: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
class DecisionBookPersonAddEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"e346f720-880b-4b07-93d6-9ac76fbbaa33": "building_decision_book_person_add",
}
__event_validation__ = {
"e346f720-880b-4b07-93d6-9ac76fbbaa33": DecisionBookDecisionBookInvitationsUpdate
}
@classmethod
def building_decision_book_person_add(
cls,
data: DecisionBookDecisionBookInvitationsUpdate,
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",
)
elif isinstance(token_dict, OccupantTokenObject):
decision_book = BuildDecisionBook.filter_one(
BuildDecisionBook.uu_id == data.build_decision_book_uu_id,
).data
if not decision_book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No Decision Book is match with given UUID {data.build_decision_book_uu_id}",
)
manager_occupant_type = OccupantTypes.filter_by_one(
system=True, occupant_code="BU-MNG", occupant_category_type="BU"
).data
if (
not manager_occupant_type.uu_id
== token_dict.selected_occupant.occupant_type_uu_id
):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Only Build Manager can update the invitation",
)
assign_occupant_type = OccupantTypes.filter_by_one(
system=True,
uu_id=data.occupant_type_uu_id,
occupant_category_type="MT",
).data
if not assign_occupant_type:
raise HTTPException(
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",
)
manger_book_person = BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.token == data.token,
BuildDecisionBookPerson.build_decision_book_uu_id
== data.build_decision_book_uu_id,
).data
if not manger_book_person:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Manager person not found. Please check token",
)
book_invite = BuildDecisionBookInvitations.filter_one(
BuildDecisionBookInvitations.id == manger_book_person.invite_id,
BuildDecisionBookInvitations.build_id
== token_dict.selected_occupant.build_id,
).data
if not book_invite:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invitation not found. Please check token",
)
selected_book_person = BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.invite_id == book_invite.id,
BuildDecisionBookPerson.person_uu_id == data.person_uu_id,
).data
if not selected_book_person:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Selected person is not in the invitation list. Please check {data.person_uu_id}",
)
selected_book_person.update(
occupant_type=assign_occupant_type.id,
occupant_type_uu_id=str(assign_occupant_type.uu_id),
)
BuildDecisionBookPerson.save()
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Invitation is updated",
"data": selected_book_person.get_dict(),
},
)
class DecisionBookPersonRemoveEventMethods(MethodToEvent):
event_type = "DELETE"
__event_keys__ = {
"30588869-04cd-48ea-ad00-0e4f8dd7f735": "building_decision_book_people_remove",
}
__event_validation__ = {
"30588869-04cd-48ea-ad00-0e4f8dd7f735": RemoveDecisionBookPerson
}
@classmethod
def building_decision_book_people_remove(
cls, data: RemoveDecisionBookPerson, token_dict: EmployeeTokenObject
):
return
class DecisionBookPersonAttendEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"bdcba521-0116-441c-ace1-84c5b68c86c7": "decision_book_invitations_attend",
}
__event_validation__ = {
"bdcba521-0116-441c-ace1-84c5b68c86c7": DecisionBookDecisionBookInvitationsAttend
}
@classmethod
def decision_book_invitations_attend(
cls,
data: DecisionBookDecisionBookInvitationsAttend,
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",
)
token_user = Users.filter_one(Users.id == token_dict.user_id).data
invitation_person = BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.token == data.token,
).data
if not invitation_person:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation for the this specific user is not found. Please check token",
)
# is_token_valid = token_dict.person_id == invitation_person.person_id
# if not invitation_person.vicarious_person_id:
# if not invitation_person or not is_token_valid:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"Invitation for the user {token_user.email} is not valid. Please check token",
# )
# todo check if vicarious person is valid
invitation = BuildDecisionBookInvitations.filter_one(
BuildDecisionBookInvitations.id == invitation_person.invite_id,
BuildDecisionBookInvitations.build_id
== token_dict.selected_occupant.build_id,
).data
if not invitation:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation not found. Please check invitation uuid : {invitation.uu_id}",
)
invitation_person.update(
is_attending=bool(data.is_attend), vicarious_person_id=None
)
BuildDecisionBookInvitations.save()
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Attendance is updated. Thank you for your response",
"data": {
"is_attending": bool(data.is_attend),
"user_uuid": str(token_user.uu_id),
"invitation_uuid": str(invitation.uu_id),
},
},
)
class DecisionBookPersonAssignOccupantEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"c0b65098-9c79-4212-b1d0-c7e7836cf141": "decision_book_invitations_assign_occupant",
}
__event_validation__ = {
"c0b65098-9c79-4212-b1d0-c7e7836cf141": DecisionBookDecisionBookInvitationsAssign
}
@classmethod
def decision_book_invitations_assign_occupant(
cls,
data: DecisionBookDecisionBookInvitationsAssign,
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",
)
book_person_manager = BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.token == data.token,
BuildDecisionBookPerson.build_living_space_id
== token_dict.selected_occupant.living_space_id,
).data
manager_occupant_type = OccupantTypes.filter_by_one(
system=True, occupant_code="BU-MNG", occupant_category_type="BU"
).data
book_person_manager.check_occupant_type(manager_occupant_type)
# supervisor_occupant_type = OccupantTypes.find_or_abort(occupant_code="BU-SPV", occupant_category_type="BU")
# book_person_supervisor.check_occupant_type(supervisor_occupant_type)
invitation = BuildDecisionBookInvitations.filter_one(
BuildDecisionBookInvitations.id == book_person_manager.invite_id,
BuildDecisionBookInvitations.build_id
== token_dict.selected_occupant.build_id,
).data
if not invitation:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation not found. Please check token",
)
assign_occupant_type = OccupantTypes.filter_by_one(
system=True,
uu_id=data.occupant_type_uu_id,
).data
if not assign_occupant_type:
raise HTTPException(
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",
)
build_parts_of_token = BuildParts.filter_all(
BuildParts.build_id == token_dict.selected_occupant.build_id,
).data
selected_living_space = BuildLivingSpace.filter_one(
BuildLivingSpace.uu_id == data.build_living_space_uu_id,
BuildLivingSpace.build_parts_id.in_(
[build.id for build in build_parts_of_token]
),
).data
if not selected_living_space:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Person not found. Please check person uuid",
)
book_person_to_assign: BuildDecisionBookPerson = (
BuildDecisionBookPerson.filter_one(
BuildDecisionBookPerson.build_living_space_id
== selected_living_space.id,
BuildDecisionBookPerson.invite_id == invitation.id,
).data
)
if not book_person_to_assign:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Person not found in the invitation list. Please check person uuid: {data.build_living_space_uu_id}",
)
if not book_person_to_assign.is_attending:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Person is declined the invitation. This person is not attending the meeting. "
f"Please check person uuid: {data.build_living_space_uu_id}. Invite UUID: {invitation.uu_id}",
)
if assign_occupant_type.occupant_code in ("MT-PRS", "MT-WRT"):
occupant_type_unique = OccupantTypes.filter_by_one(
system=True,
occupant_code=assign_occupant_type.occupant_code,
occupant_category_type="MT",
).data
if assigned_book_person_occupant := BuildDecisionBookPersonOccupants.filter_one(
BuildDecisionBookPersonOccupants.invite_id == invitation.id,
BuildDecisionBookPersonOccupants.occupant_type_id
== occupant_type_unique.id,
).data:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Only one person can be assigned to {assign_occupant_type.occupant_code} type"
f" {assigned_book_person_occupant.uu_id} is already assigned",
)
if assign_occupant_type.occupant_code == "BU-MNG":
person_occupant_manager = BuildDecisionBookPersonOccupants.filter_one(
BuildDecisionBookPersonOccupants.invite_id == invitation.id,
BuildDecisionBookPersonOccupants.occupant_type_id
== manager_occupant_type.id,
)
person_occupant_manager.query.delete()
book_person_to_assign.add_occupant_type(
occupant_type=assign_occupant_type,
build_living_space_id=selected_living_space.id,
)
BuildDecisionBookPersonOccupants.save()
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Invitation is updated",
"data": book_person_to_assign.get_dict(),
},
)
DecisionBookPersonListEventMethod = DecisionBookPersonListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/people/list")
)
DecisionBookPersonAddEventMethod = DecisionBookPersonAddEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/people/add")
)
DecisionBookPersonRemoveEventMethod = DecisionBookPersonRemoveEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/people/remove")
)
DecisionBookPersonAttendEventMethod = DecisionBookPersonAttendEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invitations/attend")
)
DecisionBookPersonAssignOccupantEventMethod = (
DecisionBookPersonAssignOccupantEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invitations/assign")
)
)
# Build.pre_query = Build.select_action(
# employee_id=token_dict.selected_company.employee_id,
# filter_expr=[
# Build.id == decision_book.build_id,
# ],
# )
# reachable_building = Build.filter_all()
# if not reachable_building.data:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
# )
#
# Companies.pre_query = Companies.select_action(
# duty_id_list=[
# token_dict.selected_company.duty_id,
# token_dict.selected_company.bulk_duties_id,
# ],
# filter_expr=[Companies.id == decision_book.resp_company_id],
# )
# reachable_companies = Companies.filter_all()
# if not reachable_companies.data:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No company is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
# )
# person_to_add = People.find_one(uu_id=data.person_uu_id)
# if not person_to_add:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No person is match with given UUID {data.person_uu_id}",
# )
# management_typecode = ApiEnumDropdown.filter_all(
# ApiEnumDropdown.uu_id == data.management_typecode_uu_id,
# ApiEnumDropdown.enum_class.in_("BuildManagementType", "BuildDuesTypes"),
# )
# if not management_typecode.data:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No management type is match with given UUID {data.management_typecode_uu_id}",
# )
# condition_to_met = (
# data.management_typecode_uu_id
# in ApiEnumDropdown.get_management_type_codes_list()
# )
# any_type_already = BuildDecisionBookPerson.find_one(
# build_decision_book_id=decision_book.id,
# management_typecode=data.management_typecode_uu_id,
# )
# if condition_to_met and any_type_already:
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail=f"Management type is already exist in given Decision Book UUID {data.build_decision_book_uu_id}.",
# )
#
# data_dict.pop("build_decision_book_uu_id", None)
# data_dict.pop("person_uu_id", None)
# data_dict["management_typecode"] = data_dict.pop(
# "management_typecode_uu_id", None
# )
# data_dict["build_decision_book_id"] = decision_book.id
# data_dict["person_id"] = person_to_add.id
#
# created = BuildDecisionBookPerson.find_or_create(**data_dict)
# if created.is_found:
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail=f"Decision Book Person is already exist in given Decision Book UUID {data.build_decision_book_uu_id}.",
# )
# return JSONResponse(
# status_code=status.HTTP_200_OK,
# content=dict(
# message=f"Decision Book Person has added for given Decision Book UUID {data.build_decision_book_uu_id}",
# completed=True,
# data=created.get_dict(),
# ),
# )

View File

@@ -0,0 +1,282 @@
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",
}
__event_validation__ = {"e2277528-8c9c-4c0c-ae64-3ce80cae664b": None}
@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",
}
__event_validation__ = {
"d0bfa20c-841d-421c-98e6-d308f938d16a": DecisionBookDecisionBookInvitations
}
@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(
system=True, occupant_category_type="BU", occupant_code="BU-MNG"
).data
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,
).data
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
).data
# Check planned decision book date is valid
if (
not system_arrow.get(data.planned_date).date()
>= system_arrow.now().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=str(decision_book.decision_type),
living_part_count=occupant_building.livable_part_count,
living_part_percentage=0.51,
message=data.message,
planned_date=str(system_arrow.get(data.planned_date)),
planned_date_expires=planned_date_expires,
expiry_ends=str(system_arrow.get(data.planned_date).shift(days=15).date()),
)
book_invitation.save_and_confirm()
# Get all the parts of the building that is occupant in token
build_parts = BuildParts.filter_all(
BuildParts.build_id == occupant_building.id,
)
# 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.filter_by_one(
system=True, occupant_code="MT-ATT", occupant_category_type="MT"
).data
manager_occupant_type = OccupantTypes.filter_by_one(
system=True, occupant_code="BU-MNG", occupant_category_type="BU"
).data
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,
)
# 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,
).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.save_and_confirm()
invitations_person.add_occupant_type(occupant_type=attendance_occupant_type)
if invitations_person:
print(f'"{invitations_person.token}",')
spaces_user = Users.filter_one(
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,
)
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
]
),
system=True,
)
manager_people_occupants = BuildDecisionBookPersonOccupants.filter_all(
BuildDecisionBookPersonOccupants.build_decision_book_person_id
== manager_people.get(1).id,
system=True,
)
if manager_people_occupants.count:
manager_people_occupants.query.delete()
BuildDecisionBookPersonOccupants.save()
if manager_people.count:
manager_people.query.delete()
BuildDecisionBookPerson.save()
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.save_and_confirm()
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",
}
__event_validation__ = {
"92413636-53a8-4a05-842c-1485a64e00d1": DecisionBookDecisionBookInvitationsUpdate
}
@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")
)
)

View File

@@ -0,0 +1,169 @@
from typing import Union
from fastapi.responses import JSONResponse
from fastapi import status
from api_validations.validations_response.parts import BuildPartsListResponse
from databases import (
Build,
BuildParts,
)
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_validations.validations_request import (
InsertBuildParts,
UpdateBuildParts,
ListOptions,
)
from databases.sql_models.building.decision_book import BuildDecisionBookPayments
class DecisionBookPaymentListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"49bb8ab8-520d-4676-a159-aaf84f37f372": "decision_book_payment_list"
}
__event_validation__ = {"49bb8ab8-520d-4676-a159-aaf84f37f372": None}
@classmethod
def decision_book_payment_list(
cls,
list_options: ListOptions,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
"""
SELECT payment_plan_time_periods, process_date, payment_amount, currency, payment_types_id,
payment_types_uu_id, period_time, process_date_y, process_date_m, build_decision_book_item_id,
build_decision_book_item_uu_id, decision_book_project_id, decision_book_project_uu_id, build_parts_id,
build_parts_uu_id, id, uu_id, ref_id, created_at, updated_at, cryp_uu_id, created_by, created_by_id,
updated_by, updated_by_id, confirmed_by, confirmed_by_id, is_confirmed, replication_id, deleted,
active, is_notification_send, is_email_send, expiry_starts, expiry_ends, account_records_id,
account_records_uu_id FROM public.build_decision_book_payments;
"""
from sqlalchemy import func, select, union_all, extract, Integer
build_parts_id, build_decision_book_id = 7, ""
payment_types_id_recv, payment_types_id_deb = 46, 45
BuildDecisionBookPayments.filter_attr = list_options
# Define the subqueries
debit_subquery = (
select(
BuildDecisionBookPayments.payment_plan_time_periods,
func.sum(BuildDecisionBookPayments.payment_amount).label("debit"),
func.cast(0, Integer).label("recv"),
func.max(BuildDecisionBookPayments.process_date).label("ls"),
)
.where(
BuildDecisionBookPayments.build_parts_id == build_parts_id,
BuildDecisionBookPayments.payment_types_id == payment_types_id_deb,
BuildDecisionBookPayments.build_decision_book_id
== build_decision_book_id,
extract("year", func.current_date())
== extract("year", BuildDecisionBookPayments.process_date),
extract("month", func.current_date())
== extract("month", BuildDecisionBookPayments.process_date),
)
.group_by(BuildDecisionBookPayments.payment_plan_time_periods)
)
recv_subquery = (
select(
BuildDecisionBookPayments.payment_plan_time_periods,
func.cast(0, Integer).label("debit"),
func.sum(BuildDecisionBookPayments.payment_amount).label("recv"),
func.max(BuildDecisionBookPayments.process_date).label("ls"),
)
.where(
BuildDecisionBookPayments.build_parts_id == build_parts_id,
BuildDecisionBookPayments.payment_types_id == payment_types_id_recv,
BuildDecisionBookPayments.build_decision_book_id
== build_decision_book_id,
extract("year", func.current_date())
== extract("year", BuildDecisionBookPayments.process_date),
extract("month", func.current_date())
== extract("month", BuildDecisionBookPayments.process_date),
)
.group_by(BuildDecisionBookPayments.payment_plan_time_periods)
)
# Combine the subqueries using union_all
combined_subquery = union_all(debit_subquery, recv_subquery).alias("AA")
# Final query
final_query = select(
combined_subquery.c.payment_plan_time_periods,
func.sum(combined_subquery.c.debit).label("debit"),
func.sum(combined_subquery.c.recv).label("recv"),
combined_subquery.c.ls.label("Last Seen"),
).group_by(
combined_subquery.c.payment_plan_time_periods, combined_subquery.c.ls
)
# Execute the query
book_payments_month = BuildDecisionBookPayments.session.execute(
final_query
).fetchall()
print("book_payments_month", book_payments_month)
debit_subquery = (
select(
BuildDecisionBookPayments.payment_plan_time_periods,
func.sum(BuildDecisionBookPayments.payment_amount).label("debit"),
func.cast(0, Integer).label("recv"),
func.max(BuildDecisionBookPayments.process_date).label("ls"),
)
.where(
BuildDecisionBookPayments.build_parts_id == build_parts_id,
BuildDecisionBookPayments.payment_types_id == payment_types_id_deb,
BuildDecisionBookPayments.build_decision_book_id
== build_decision_book_id,
)
.group_by(BuildDecisionBookPayments.payment_plan_time_periods)
)
recv_subquery = (
select(
BuildDecisionBookPayments.payment_plan_time_periods,
func.cast(0, Integer).label("debit"),
func.sum(BuildDecisionBookPayments.payment_amount).label("recv"),
func.max(BuildDecisionBookPayments.process_date).label("ls"),
)
.where(
BuildDecisionBookPayments.build_parts_id == build_parts_id,
BuildDecisionBookPayments.payment_types_id == payment_types_id_recv,
BuildDecisionBookPayments.build_decision_book_id
== build_decision_book_id,
)
.group_by(BuildDecisionBookPayments.payment_plan_time_periods)
)
# Combine the subqueries using union_all
combined_subquery = union_all(debit_subquery, recv_subquery).alias("AA")
# Final query
final_query = select(
combined_subquery.c.payment_plan_time_periods,
func.sum(combined_subquery.c.debit).label("debit"),
func.sum(combined_subquery.c.recv).label("recv"),
combined_subquery.c.ls.label("Last Seen"),
).group_by(
combined_subquery.c.payment_plan_time_periods, combined_subquery.c.ls
)
# Execute the query
book_payments = BuildDecisionBookPayments.session.execute(
final_query
).fetchall()
print("book_payments", book_payments)
return AlchemyJsonResponse(
completed=True,
message="Building Parts Records are listed",
result=[book_payments, book_payments_month],
cls_object=BuildParts,
response_model=BuildPartsListResponse,
filter_attributes=list_options,
)

View File

@@ -0,0 +1,372 @@
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")
)

View File

@@ -0,0 +1,156 @@
from typing import Union
from databases import (
BuildDecisionBookProjectItems,
BuildDecisionBookProjectPerson,
)
from api_validations.validations_request import (
InsertBuildDecisionBookProjectItems,
UpdateBuildDecisionBookProjectItems,
ListOptions,
)
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 databases.sql_models.building.decision_book import BuildDecisionBookProjects
class BuildDecisionBookProjectItemsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"ce3630e4-2bf9-4433-bdab-1ee72117e54b": "build_decision_book_project_items_list",
}
__event_validation__ = {"ce3630e4-2bf9-4433-bdab-1ee72117e54b": None}
@staticmethod
def build_decision_book_project_items_list(
requester: Union[EmployeeTokenObject, OccupantTokenObject],
list_options: ListOptions,
):
response = BuildDecisionBookProjectItems.list_items(
requester=requester,
list_options=list_options,
)
return AlchemyJsonResponse(
message="Build Decision Book Project Items List",
result=response,
)
class BuildDecisionBookProjectItemsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"b27e4fd0-6e3e-441b-9b33-806ac7082444": "build_decision_book_project_items_create",
}
__event_validation__ = {
"b27e4fd0-6e3e-441b-9b33-806ac7082444": InsertBuildDecisionBookProjectItems,
}
@staticmethod
def build_decision_book_project_items_create(
data: InsertBuildDecisionBookProjectItems,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise BuildDecisionBookProjectItems.raise_http_exception(
status_code="HTTP_403_FORBIDDEN",
error_case="UNAUTHORIZED",
message=f"No permission to create decision book project items",
data={},
)
elif isinstance(token_dict, OccupantTokenObject):
book_project = BuildDecisionBookProjects.filter_one(
BuildDecisionBookProjects.uu_id
== data.build_decision_book_project_uu_id,
BuildDecisionBookProjects.project_response_living_space_id
== token_dict.selected_occupant.living_space_id,
).data
if not book_project:
raise BuildDecisionBookProjectItems.raise_http_exception(
status_code="HTTP_404_NOT_FOUND",
error_case="NOT_FOUND",
message=f"This user can not create project item for this project uu_id : {data.build_decision_book_project_uu_id}",
data={},
)
data_dict = data.excluded_dump()
data_dict["build_decision_book_project_id"] = book_project.id
created_project_item = BuildDecisionBookProjectItems.find_or_create(
**data_dict
)
created_project_item.save_and_confirm()
return AlchemyJsonResponse(
message="Build Decision Book Project Items Create",
result=created_project_item.get_dict(),
)
class BuildDecisionBookProjectItemsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"b2b7cdce-9a0c-4722-90ff-8bef36b4ec6b": "build_decision_book_project_items_update",
}
__event_validation__ = {
"b2b7cdce-9a0c-4722-90ff-8bef36b4ec6b": UpdateBuildDecisionBookProjectItems
}
@staticmethod
def build_decision_book_project_items_update(
requester: Union[EmployeeTokenObject, OccupantTokenObject],
decision_book_project_items: UpdateBuildDecisionBookProjectItems,
):
raise BuildDecisionBookProjectItems.raise_http_exception(
status_code="HTTP_403_FORBIDDEN",
error_case="UNAUTHORIZED",
message=f"No permission to update decision book project items",
data={},
)
class BuildDecisionBookProjectItemsPatchEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"e59d50df-dd22-4823-aeae-b9490332885c": "build_decision_book_project_items_patch",
}
__event_validation__ = {"e59d50df-dd22-4823-aeae-b9490332885c": None}
@staticmethod
def build_decision_book_project_items_patch(
requester: Union[EmployeeTokenObject, OccupantTokenObject],
decision_book_project_items: UpdateBuildDecisionBookProjectItems,
):
response = BuildDecisionBookProjectItems.delete_item(
requester=requester,
decision_book_project_items=decision_book_project_items,
)
return AlchemyJsonResponse(
message="Build Decision Book Project Items Patch",
result=response,
)
BuildDecisionBookProjectItemsListEventMethod = (
BuildDecisionBookProjectItemsListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/items/list")
)
)
BuildDecisionBookProjectItemsCreateEventMethod = (
BuildDecisionBookProjectItemsCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/items/create")
)
)
BuildDecisionBookProjectItemsUpdateEventMethod = (
BuildDecisionBookProjectItemsUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/items/update")
)
)
BuildDecisionBookProjectItemsPatchEventMethod = (
BuildDecisionBookProjectItemsPatchEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/items/patch")
)
)

View File

@@ -0,0 +1,189 @@
from typing import Union
from databases import (
BuildDecisionBookProjects,
BuildDecisionBookProjectPerson,
)
from api_validations.validations_request import (
InsertBuildDecisionBookProjectPerson,
UpdateBuildDecisionBookProjectPerson,
ListOptions,
)
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
class ProjectDecisionBookPersonListEventMethods(MethodToEvent):
event_type = "LIST"
__event_keys__ = {
"7101b5ca-8bef-40f9-8b4d-646d9994e18f": "project_decision_book_person_list",
}
__event_validation__ = {"7101b5ca-8bef-40f9-8b4d-646d9994e18f": None}
@classmethod
def project_decision_book_person_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):
project_person = BuildDecisionBookProjectPerson.filter_all(
BuildDecisionBookProjects.living_space_id
== token_dict.selected_occupant.living_space_id,
)
decision_book_ids = [
_.build_decision_book_project_id for _ in project_person.data
]
decision_book_projects = BuildDecisionBookProjects.filter_all(
BuildDecisionBookProjects.build_decision_book_project_id.in_(
decision_book_ids
),
)
return AlchemyJsonResponse(
status_code="HTTP_200_OK",
message="Project decision person book listed successfully",
result=decision_book_projects,
)
class ProjectDecisionBookPersonCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"9c88e314-84e8-435e-8c1e-6a5aae80b2e6": "project_decision_book_person_create",
}
__event_validation__ = {
"9c88e314-84e8-435e-8c1e-6a5aae80b2e6": InsertBuildDecisionBookProjectPerson
}
@classmethod
def project_decision_book_create(
cls,
data: InsertBuildDecisionBookProjectPerson,
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):
decision_book = BuildDecisionBookProjects.filter_one(
BuildDecisionBookProjects.build_decision_book_uu_id
== data.get("build_decision_book_uu_id"),
BuildDecisionBookProjects.project_response_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,
)
class ProjectDecisionBookPersonUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"7fbd18a0-c099-4494-ada1-bb23e39bb141": "project_decision_book_update_person",
}
__event_validation__ = {
"7fbd18a0-c099-4494-ada1-bb23e39bb141": UpdateBuildDecisionBookProjectPerson
}
@classmethod
def project_decision_book_update(
cls,
data: UpdateBuildDecisionBookProjectPerson,
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):
decision_book_project_person = BuildDecisionBookProjectPerson.filter_one(
BuildDecisionBookProjects.build_decision_book_project_uu_id
== data.get("build_decision_book_uu_id"),
BuildDecisionBookProjects.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 ProjectDecisionBookPersonPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"a122e84a-5556-4bf7-b680-1f47c438d4f7": "project_decision_book_person_patch",
}
__event_validation__ = {"a122e84a-5556-4bf7-b680-1f47c438d4f7": None}
@classmethod
def project_decision_book_patch(
cls,
data,
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):
decision_book_project_person = BuildDecisionBookProjectPerson.filter_one(
BuildDecisionBookProjects.build_decision_book_project_uu_id
== data.get("build_decision_book_uu_id"),
BuildDecisionBookProjects.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,
)
ProjectDecisionBookPersonListEventMethod = ProjectDecisionBookPersonListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/people/list")
)
ProjectDecisionBookPersonCreateEventMethod = (
ProjectDecisionBookPersonCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/people/create")
)
)
ProjectDecisionBookPersonUpdateEventMethod = (
ProjectDecisionBookPersonUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/people/update")
)
)
ProjectDecisionBookPersonPatchEventMethod = ProjectDecisionBookPersonPatchEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/project/people/patch")
)