diff --git a/epictrack-api/migrations/versions/08209ce361c2_add_eac_signed_and_expires_fields_to_.py b/epictrack-api/migrations/versions/08209ce361c2_add_eac_signed_and_expires_fields_to_.py new file mode 100644 index 000000000..5d6398a02 --- /dev/null +++ b/epictrack-api/migrations/versions/08209ce361c2_add_eac_signed_and_expires_fields_to_.py @@ -0,0 +1,40 @@ +"""add eac signed and expires fields to project + +Revision ID: 08209ce361c2 +Revises: 19227722dffc +Create Date: 2024-08-29 08:45:46.100404 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '08209ce361c2' +down_revision = '19227722dffc' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('projects', schema=None) as batch_op: + batch_op.add_column(sa.Column('eac_signed', sa.Date(), nullable=True)) + batch_op.add_column(sa.Column('eac_expires', sa.Date(), nullable=True)) + + with op.batch_alter_table('projects_history', schema=None) as batch_op: + batch_op.add_column(sa.Column('eac_signed', sa.Date(), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column('eac_expires', sa.Date(), autoincrement=False, nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('projects_history', schema=None) as batch_op: + batch_op.drop_column('eac_expires') + batch_op.drop_column('eac_signed') + + with op.batch_alter_table('projects', schema=None) as batch_op: + batch_op.drop_column('eac_expires') + batch_op.drop_column('eac_signed') + # ### end Alembic commands ### diff --git a/epictrack-api/src/api/models/project.py b/epictrack-api/src/api/models/project.py index 0ba06e1e8..aa4026d30 100644 --- a/epictrack-api/src/api/models/project.py +++ b/epictrack-api/src/api/models/project.py @@ -14,7 +14,7 @@ """Model to manage Project.""" import enum -from sqlalchemy import Boolean, Column, Enum, Float, ForeignKey, Integer, String, Text, func +from sqlalchemy import Boolean, Column, Date, Enum, Float, ForeignKey, Integer, String, Text, func from sqlalchemy.orm import relationship from .base_model import BaseModelVersioned @@ -64,6 +64,8 @@ class Project(BaseModelVersioned): region_id_env = Column(ForeignKey("regions.id"), nullable=True) region_id_flnro = Column(ForeignKey("regions.id"), nullable=True) abbreviation = Column(String(10), nullable=True, unique=True) + eac_signed = Column(Date(), nullable=True) + eac_expires = Column(Date(), nullable=True) sub_type = relationship("SubType", foreign_keys=[sub_type_id], lazy="select") type = relationship("Type", foreign_keys=[type_id], lazy="select") proponent = relationship("Proponent", foreign_keys=[proponent_id], lazy="select") diff --git a/epictrack-api/src/api/schemas/request/project_request.py b/epictrack-api/src/api/schemas/request/project_request.py index e0c70a248..bbd6962b1 100644 --- a/epictrack-api/src/api/schemas/request/project_request.py +++ b/epictrack-api/src/api/schemas/request/project_request.py @@ -118,6 +118,18 @@ class ProjectBodyParameterSchema(RequestBodyParameterSchema): load_default=None ) + eac_signed = fields.Date( + metadata={"description": "Date the EAC was signed on"}, + allow_none=True, + load_default=None + ) + + eac_expires = fields.Date( + metadata={"description": "Date the EAC expires on"}, + allow_none=True, + load_default=None + ) + is_active = fields.Bool(metadata={"description": "Active state of the project"}) is_project_closed = fields.Bool(metadata={"description": "Closed state of the project"}, default=False) diff --git a/epictrack-web/src/components/project/Dialog/index.tsx b/epictrack-web/src/components/project/Dialog/index.tsx index c1b872cc4..15ded778d 100644 --- a/epictrack-web/src/components/project/Dialog/index.tsx +++ b/epictrack-web/src/components/project/Dialog/index.tsx @@ -67,6 +67,12 @@ export const ProjectDialog = ({ }; const saveProject = async (data: any) => { + if (data.eac_signed) { + data.eac_signed = new Date(data.eac_signed).toISOString().split("T")[0]; + } + if (data.eac_expires) { + data.eac_expires = new Date(data.eac_expires).toISOString().split("T")[0]; + } if (projectId) { await editProject(data); } else { diff --git a/epictrack-web/src/components/project/ProjectForm/index.tsx b/epictrack-web/src/components/project/ProjectForm/index.tsx index 986f4ed5e..a06211a4f 100644 --- a/epictrack-web/src/components/project/ProjectForm/index.tsx +++ b/epictrack-web/src/components/project/ProjectForm/index.tsx @@ -26,6 +26,7 @@ import typeService from "services/typeService"; import proponentService from "services/proponentService/proponentService"; import { useAppSelector } from "hooks"; import { sort } from "utils"; +import ControlledDatePicker from "components/shared/controlledInputComponents/ControlledDatePicker"; const schema = yup.object().shape({ name: yup @@ -449,6 +450,20 @@ export default function ProjectForm({ /> + + EAC Signed + + + + EAC Expires + +