project items added

This commit is contained in:
berkay 2024-11-18 20:21:38 +03:00
parent 7bc16e02d1
commit 1e8f5023e8
9 changed files with 534 additions and 44 deletions

View File

@ -1,6 +1,65 @@
from typing import Union
from api_library.date_time_actions.date_functions import system_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
class ProjectDecisionBookPersonListEvents(MethodToEvent):
event_type = "LIST"
__event_keys__ = {
"96459b36-37f2-4d5b-8370-c459058d5bce": "project_decision_book_person_list",
}
@classmethod
def project_decision_book_person_list(
cls,
data: 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 book created successfully",
result=decision_book_projects,
)
class ProjectDecisionBookCreateEvents(MethodToEvent):
@ -12,8 +71,51 @@ class ProjectDecisionBookCreateEvents(MethodToEvent):
}
@classmethod
def project_decision_book_create(cls, request, *args, **kwargs):
pass
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.living_space_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.get("build_decision_book_uu_id"),
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 ProjectDecisionBookUpdateEvents(MethodToEvent):
@ -25,8 +127,187 @@ class ProjectDecisionBookUpdateEvents(MethodToEvent):
}
@classmethod
def project_decision_book_update(cls, request, *args, **kwargs):
pass
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.living_space_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(
BuildDecisionBookProjects.build_decision_book_project_uu_id == data.get("build_decision_book_project_uu_id"),
BuildDecisionBookProjects.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 ProjectDecisionBookApprovalEvents(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"a83a83fe-8446-4c60-9ae5-d1c06adbf626": "project_decision_book_approval",
}
@classmethod
def project_decision_book_approval(
cls,
data: ApprovalsBuildDecisionBookProjects,
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.living_space_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(
BuildDecisionBookProjects.build_decision_book_project_uu_id == data.get(
"build_decision_book_project_uu_id"),
BuildDecisionBookProjects.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,
).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
data_dict["status_id"] = 1 # is completed status
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(
payment_plan_time_periods=str(),
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:
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),
period_time=f"{local_date.year}-{str(local_date.month).zfill(2)}",
**book_payment_dict,
)
created_book_payment.save_and_confirm()
return
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 ProjectDecisionBookPatchEvents(MethodToEvent):
@ -38,5 +319,9 @@ class ProjectDecisionBookPatchEvents(MethodToEvent):
}
@classmethod
def project_decision_book_patch(cls, request, *args, **kwargs):
pass
def project_decision_book_patch(
cls,
data,
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
):
return

View File

@ -0,0 +1,19 @@
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

View File

@ -1,8 +1,57 @@
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 ProjectDecisionBookPersonListEvents(MethodToEvent):
event_type = "LIST"
__event_keys__ = {
"7101b5ca-8bef-40f9-8b4d-646d9994e18f": "project_decision_book_person_list",
}
@classmethod
def project_decision_book_person_list(
cls,
data: 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 book created successfully",
result=decision_book_projects,
)
class ProjectDecisionBookPersonCreateEvents(MethodToEvent):
event_type = "CREATE"
@ -12,8 +61,28 @@ class ProjectDecisionBookPersonCreateEvents(MethodToEvent):
}
@classmethod
def project_decision_book_create(cls, request, *args, **kwargs):
return
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 ProjectDecisionBookPersonUpdateEvents(MethodToEvent):
@ -25,8 +94,29 @@ class ProjectDecisionBookPersonUpdateEvents(MethodToEvent):
}
@classmethod
def project_decision_book_update(cls, request, *args, **kwargs):
return
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 ProjectDecisionBookPersonPatchEvents(MethodToEvent):
@ -38,5 +128,26 @@ class ProjectDecisionBookPersonPatchEvents(MethodToEvent):
}
@classmethod
def project_decision_book_patch(cls, request, *args, **kwargs):
return
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,
)

View File

@ -7,7 +7,12 @@ class ProjectLeader(AddEventFunctionality):
related_code = "PRJ-LDR"
events = [
{"function_code": ""},
{"function_code": "b8e44bb2-f157-4dd5-8a24-0e02db4877c9"},
{"function_code": "bfe3ef13-030f-495f-b692-94bcb746d700"},
{"function_code": "444d67a0-b3a8-4ca2-9d8d-f1acc75011e0"},
{"function_code": "9c88e314-84e8-435e-8c1e-6a5aae80b2e6"},
{"function_code": "7fbd18a0-c099-4494-ada1-bb23e39bb141"},
{"function_code": "a122e84a-5556-4bf7-b680-1f47c438d4f7"},
]
def __new__(cls, *args, **kwargs):

View File

@ -103,12 +103,15 @@ from .people import (
ResponsePersonSalesMange,
)
from .project_decision_book import (
InsertBuildDecisionBookProjectItems,
UpdateBuildDecisionBookProjectItems,
InsertBuildDecisionBookProjectItemDebits,
UpdateBuildDecisionBookProjectItemDebits,
InsertBuildDecisionBookProjects,
UpdateBuildDecisionBookProjects,
InsertBuildDecisionBookProjectPerson,
UpdateBuildDecisionBookProjectPerson,
InsertBuildDecisionBookProjectItems,
UpdateBuildDecisionBookProjectItems,
ApprovalsBuildDecisionBookProjects,
)
from .rules import (
UpdateEndpointAccess,
@ -213,10 +216,13 @@ __all__ = [
"ResponsePersonSalesMange",
"InsertBuildDecisionBookProjectItems",
"UpdateBuildDecisionBookProjectItems",
"ApprovalsBuildDecisionBookProjects",
"InsertBuildDecisionBookProjectItemDebits",
"UpdateBuildDecisionBookProjectItemDebits",
"InsertBuildDecisionBookProjects",
"UpdateBuildDecisionBookProjects",
"InsertBuildDecisionBookProjectPerson",
"UpdateBuildDecisionBookProjectPerson",
"UpdateEndpointAccess",
"UpdateEndpointAccessList",
"InsertEndpointAccess",

View File

@ -19,6 +19,7 @@ class PydanticBaseModel(BaseModelRegular):
deleted: Optional[bool] = None
expiry_starts: Optional[str] = None
expiry_ends: Optional[str] = None
is_confirmed: Optional[bool] = None
class EndpointPydantic(BaseModelRegular):

View File

@ -1,12 +1,48 @@
from typing import Optional
from pydantic import BaseModel
from api_validations.core_validations import BaseModelRegular
from api_validations.validations_request import (
PydanticBaseModel,
ListOptions,
)
class InsertBuildDecisionBookProjects(PydanticBaseModel):
class InsertBuildDecisionBookProjectItems(BaseModelRegular):
item_header: str
item_comment: str
build_decision_book_project_uu_id: str
attachment_pdf_path: Optional[str] = None
item_objection: Optional[str] = None
class UpdateBuildDecisionBookProjectItems(PydanticBaseModel):
item_header: Optional[str] = None
item_comment: Optional[str] = None
attachment_pdf_path: Optional[str] = None
item_estimated_cost: Optional[float] = None
build_decision_book_project_uu_id: Optional[str] = None
class InsertBuildDecisionBookProjectPerson(BaseModelRegular):
dues_percent_discount: Optional[int] = None
job_fix_wage: Optional[float] = None
bid_price: Optional[float] = None
decision_price: Optional[float] = None
build_decision_book_project_uu_id: str
living_space_uu_id: str
project_team_type_uu_id: str
class UpdateBuildDecisionBookProjectPerson(PydanticBaseModel):
dues_percent_discount: Optional[int] = None
job_fix_wage: Optional[float] = None
bid_price: Optional[float] = None
decision_price: Optional[float] = None
build_decision_book_project_uu_id: Optional[str] = None
living_space_uu_id: Optional[str] = None
project_team_type_uu_id: Optional[str] = None
class InsertBuildDecisionBookProjects(BaseModelRegular):
build_decision_book_item_uu_id: str
project_response_person_uu_id: str
project_name: str
@ -21,40 +57,29 @@ class InsertBuildDecisionBookProjects(PydanticBaseModel):
contact_agreement_path: Optional[str] = None
contact_agreement_date: Optional[str] = None
meeting_date: Optional[str] = None
currency: Optional[str] = None
bid_price: Optional[float] = None
approved_price: Optional[float] = None
final_price: Optional[float] = None
resp_company_uu_id: Optional[str] = None
class UpdateBuildDecisionBookProjects(PydanticBaseModel):
resp_company_uu_id: Optional[str] = None
project_response: Optional[str] = None
project_name: Optional[str] = None
project_type: Optional[str] = None
build_decision_book_project_uu_id: str
is_out_sourced: Optional[bool] = False
project_note: Optional[str] = None
decision_book_pdf_path: Optional[str] = None
status_id: Optional[int] = None
resp_company_fix_wage: Optional[float] = None
is_out_sourced: Optional[bool] = None
contact_agreement_path: Optional[str] = None
contact_agreement_date: Optional[str] = None
meeting_date: Optional[str] = None
bid_price: Optional[float] = None
contact_uu_id: Optional[str] = None
resp_company_uu_id: Optional[str] = None
approved_price: Optional[float] = None
final_price: Optional[float] = None
class InsertBuildDecisionBookProjectItems(PydanticBaseModel):
item_order: int
item_comment: str
class ApprovalsBuildDecisionBookProjects(PydanticBaseModel):
build_decision_book_project_uu_id: str
item_objection: Optional[str] = None
class UpdateBuildDecisionBookProjectItems(PydanticBaseModel):
item_comment: Optional[str] = None
item_objection: Optional[str] = None
final_price_list: list[dict] # {"date": "2021-01-01", "price": 1000}
project_stop_date: str
class InsertBuildDecisionBookProjectItemDebits(PydanticBaseModel):

View File

@ -34,6 +34,7 @@ from databases.sql_models.building.decision_book import (
BuildDecisionBookProjects,
BuildDecisionBookProjectPerson,
BuildDecisionBookPersonOccupants,
BuildDecisionBookProjectItems,
)
from databases.sql_models.company.company import (
Companies,
@ -120,6 +121,7 @@ __all__ = [
"BuildDecisionBookProjects",
"BuildDecisionBookProjectPerson",
"BuildDecisionBookPersonOccupants",
"BuildDecisionBookProjectItems",
"Companies",
"RelationshipDutyCompany",
"Employees",

View File

@ -1033,17 +1033,15 @@ class BuildDecisionBookProjects(CrudCollection):
decision_book_pdf_path: Mapped[str] = mapped_column(
String, server_default="", nullable=True
)
is_completed: Mapped[bool] = mapped_column(
Boolean, server_default="0", comment="Project is Completed"
)
status_id: Mapped[int] = mapped_column(SmallInteger, nullable=True)
resp_company_fix_wage: Mapped[float] = mapped_column(
Numeric(10, 2), server_default="0"
)
is_out_sourced: Mapped[bool] = mapped_column(Boolean, server_default="0")
contact_id: Mapped[int] = mapped_column(
ForeignKey("contracts.id"), nullable=True, comment="Contract id"
)
contact_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Contract UUID"
)
meeting_date: Mapped[TIMESTAMP] = mapped_column(
TIMESTAMP, server_default="1900-01-01 00:00:00", index=True
)
@ -1052,6 +1050,12 @@ class BuildDecisionBookProjects(CrudCollection):
approved_price: Mapped[float] = mapped_column(Numeric(16, 4), server_default="0")
final_price: Mapped[float] = mapped_column(Numeric(16, 4), server_default="0")
contact_id: Mapped[int] = mapped_column(
ForeignKey("contracts.id"), nullable=True, comment="Contract id"
)
contact_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Contract UUID"
)
build_decision_book_id: Mapped[int] = mapped_column(
ForeignKey("build_decision_book.id"), nullable=False
)
@ -1209,6 +1213,38 @@ class BuildDecisionBookProjectPerson(CrudCollection):
)
class BuildDecisionBookProjectItems(CrudCollection):
"""
Builds class based on declarative_base and BaseMixin via session
"""
__tablename__ = "build_decision_book_project_items"
__exclude__fields__ = []
item_header: Mapped[str] = mapped_column(
String, nullable=False, comment="Item Header"
)
item_comment: Mapped[str] = mapped_column(
Text, nullable=False, comment="Item Comment"
)
attachment_pdf_path: Mapped[str] = mapped_column(
String, server_default="", nullable=True, comment="Attachment PDF Path"
)
item_estimated_cost: Mapped[float] = mapped_column(
Numeric(16, 2), server_default="0", comment="Estimated Cost"
)
build_decision_book_project_id: Mapped[int] = mapped_column(
ForeignKey("build_decision_book_projects.id"), nullable=False
)
build_decision_book_project_uu_id: Mapped[str] = mapped_column(
String, nullable=True, comment="Decision Book Project UUID"
)
__table_args__ = (
{"comment": "Project Items related to decision taken at building meetings"},
)
#
# class BuildDecisionBookPaymentsMaster(CrudCollection):
# """