diff --git a/alembic/versions/04fe150da553_add_request_revision.py b/alembic/versions/04fe150da553_add_request_revision.py new file mode 100644 index 00000000..2a3cb040 --- /dev/null +++ b/alembic/versions/04fe150da553_add_request_revision.py @@ -0,0 +1,78 @@ +"""add request revision + +Revision ID: 04fe150da553 +Revises: 2c2a2af465d3 +Create Date: 2018-08-30 13:28:16.928946 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '04fe150da553' +down_revision = '2c2a2af465d3' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('request_revisions', + sa.Column('time_created', sa.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('time_updated', sa.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('request_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('am_poc', sa.Boolean(), nullable=True), + sa.Column('dodid_poc', sa.String(), nullable=True), + sa.Column('email_poc', sa.String(), nullable=True), + sa.Column('fname_poc', sa.String(), nullable=True), + sa.Column('lname_poc', sa.String(), nullable=True), + sa.Column('jedi_usage', sa.String(), nullable=True), + sa.Column('start_date', sa.Date(), nullable=True), + sa.Column('cloud_native', sa.Boolean(), nullable=True), + sa.Column('dollar_value', sa.Integer(), nullable=True), + sa.Column('dod_component', sa.String(), nullable=True), + sa.Column('data_transfers', sa.String(), nullable=True), + sa.Column('expected_completion_date', sa.String(), nullable=True), + sa.Column('jedi_migration', sa.Boolean(), nullable=True), + sa.Column('num_software_systems', sa.Integer(), nullable=True), + sa.Column('number_user_sessions', sa.Integer(), nullable=True), + sa.Column('average_daily_traffic', sa.Integer(), nullable=True), + sa.Column('engineering_assessment', sa.Boolean(), nullable=True), + sa.Column('technical_support_team', sa.Boolean(), nullable=True), + sa.Column('estimated_monthly_spend', sa.Integer(), nullable=True), + sa.Column('average_daily_traffic_gb', sa.Integer(), nullable=True), + sa.Column('rationalization_software_systems', sa.Boolean(), nullable=True), + sa.Column('organization_providing_assistance', sa.String(), nullable=True), + sa.Column('citizenship', sa.String(), nullable=True), + sa.Column('designation', sa.String(), nullable=True), + sa.Column('phone_number', sa.String(), nullable=True), + sa.Column('email_request', sa.String(), nullable=True), + sa.Column('fname_request', sa.String(), nullable=True), + sa.Column('lname_request', sa.String(), nullable=True), + sa.Column('service_branch', sa.String(), nullable=True), + sa.Column('date_latest_training', sa.Date(), nullable=True), + sa.Column('pe_id', sa.String(), nullable=True), + sa.Column('task_order_number', sa.String(), nullable=True), + sa.Column('fname_co', sa.String(), nullable=True), + sa.Column('lname_co', sa.String(), nullable=True), + sa.Column('email_co', sa.String(), nullable=True), + sa.Column('office_co', sa.String(), nullable=True), + sa.Column('fname_cor', sa.String(), nullable=True), + sa.Column('lname_cor', sa.String(), nullable=True), + sa.Column('email_cor', sa.String(), nullable=True), + sa.Column('office_cor', sa.String(), nullable=True), + sa.Column('uii_ids', sa.String(), nullable=True), + sa.Column('treasury_code', sa.String(), nullable=True), + sa.Column('ba_code', sa.String(), nullable=True), + sa.ForeignKeyConstraint(['request_id'], ['requests.id'], ), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('request_revisions') + # ### end Alembic commands ### diff --git a/atst/models/__init__.py b/atst/models/__init__.py index 95da119b..4bedebfe 100644 --- a/atst/models/__init__.py +++ b/atst/models/__init__.py @@ -14,3 +14,4 @@ from .workspace import Workspace from .project import Project from .environment import Environment from .attachment import Attachment +from .request_revision import RequestRevision diff --git a/atst/models/request.py b/atst/models/request.py index 466c6d91..68875e08 100644 --- a/atst/models/request.py +++ b/atst/models/request.py @@ -28,6 +28,8 @@ class Request(Base): task_order_id = Column(ForeignKey("task_order.id")) task_order = relationship("TaskOrder") + revisions = relationship("RequestRevision", back_populates="request") + @property def status(self): return self.status_events[-1].new_status diff --git a/atst/models/request_revision.py b/atst/models/request_revision.py new file mode 100644 index 00000000..138d32fb --- /dev/null +++ b/atst/models/request_revision.py @@ -0,0 +1,78 @@ +import pendulum +from sqlalchemy import Column, func, ForeignKey, String, Boolean, Integer, Date +from sqlalchemy.types import DateTime +from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.orm import relationship + +from atst.models import Base +from atst.models.mixins import TimestampsMixin +from atst.models.types import Id + + +class RequestRevision(Base, TimestampsMixin): + __tablename__ = "request_revisions" + + id = Id() + request_id = Column(ForeignKey("requests.id"), nullable=False) + request = relationship("Request", back_populates="revisions") + + # primary_poc + am_poc = Column(Boolean, default=False) + dodid_poc = Column(String) + email_poc = Column(String) + fname_poc = Column(String) + lname_poc = Column(String) + + # details_of_use + jedi_usage = Column(String) + start_date = Column(Date()) + cloud_native = Column(Boolean) + dollar_value = Column(Integer) + dod_component = Column(String) + data_transfers = Column(String) + expected_completion_date = Column(String) + jedi_migration = Column(Boolean) + num_software_systems = Column(Integer) + number_user_sessions = Column(Integer) + average_daily_traffic = Column(Integer) + engineering_assessment = Column(Boolean) + technical_support_team = Column(Boolean) + estimated_monthly_spend = Column(Integer) + average_daily_traffic_gb = Column(Integer) + rationalization_software_systems = Column(Boolean) + organization_providing_assistance = Column(String) + + # information_about_you + citizenship = Column(String) + designation = Column(String) + phone_number = Column(String) + email_request = Column(String) + fname_request = Column(String) + lname_request = Column(String) + service_branch = Column(String) + date_latest_training = Column(Date()) + + # financial_verification + pe_id = Column(String) + task_order_number = Column(String) + fname_co = Column(String) + lname_co = Column(String) + email_co = Column(String) + office_co = Column(String) + fname_cor = Column(String) + lname_cor = Column(String) + email_cor = Column(String) + office_cor = Column(String) + uii_ids = Column(String) + treasury_code = Column(String) + ba_code = Column(String) + + _BOOLS = ["am_poc", "jedi_migration", "engineering_assessment", "technical_support_team", "rationalization_software_systems", "cloud_native"] + _TIMESTAMPS = ["start_date", "date_latest_training"] + + @classmethod + def create_from_request_body(cls, request, **body): + coerced_bools = {k: v == "yes" for k,v in body.items() if k in RequestRevision._BOOLS} + coerced_timestamps = {k: pendulum.parse(v) for k,v in body.items() if k in RequestRevision._TIMESTAMPS} + body = {**body, **coerced_bools, **coerced_timestamps} + return RequestRevision(request=request, **body)