Skip to content

Commit

Permalink
Merge pull request #6 from mkumar-02/main
Browse files Browse the repository at this point in the history
Added Form Submission and Program Form POST and PUT request.
  • Loading branch information
shibu-narayanan authored Oct 27, 2023
2 parents 7d900d3 + eeba627 commit 95833e9
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 32 deletions.
2 changes: 0 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

# ruff: noqa: I001

from openg2p_fastapi_common.context import config_registry
from openg2p_portal_api.app import Initializer

main_init = Initializer()
print(config_registry.get())
main_init.main()
15 changes: 14 additions & 1 deletion src/openg2p_portal_api/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# ruff: noqa: E402
import asyncio

from .config import Settings

Expand All @@ -8,12 +9,24 @@

from .controllers.form_controller import FormController
from .controllers.program_controller import ProgramController
from .models.orm.program_registrant_info_orm import ProgramRegistrantInfoDraftORM
from .services.form_service import FormService
from .services.membership_service import MembershipService


class Initializer(Initializer):
def initialize(self, **kwargs):
super().initialize()
# Initialize all Services, Controllers, any utils here.

MembershipService()
FormService()
ProgramController().post_init()
FormController().post_init()

def migrate_database(self, args):
super().migrate_database(args)

async def migrate():
await ProgramRegistrantInfoDraftORM.create_migrate()

asyncio.run(migrate())
62 changes: 48 additions & 14 deletions src/openg2p_portal_api/controllers/form_controller.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from openg2p_fastapi_common.controller import BaseController

from ..config import Settings
from ..models.form import ProgramForm
from ..models.form import ProgramForm, ProgramRegistrantInfo
from ..models.orm.program_orm import ProgramORM
from ..services.form_service import FormService

_config = Settings.get_config()


class FormController(BaseController):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._form_service = FormService.get_component()

self.router.add_api_route(
"/form/{programid}",
Expand All @@ -20,18 +22,31 @@ def __init__(self, **kwargs):

self.router.add_api_route(
"/form/{programid}",
self.update_form_data,
self.crate_new_form_draft,
responses={200: {"model": ProgramForm}},
methods=["PUT"],
methods=["POST"],
)

self.router.add_api_route(
"/form/{programid}",
self.crate_new_form_draft,
self.update_form_draft,
responses={200: {"model": ProgramForm}},
methods=["PUT"],
)

self.router.add_api_route(
"/form/{programid}/submit",
self.submit_form,
responses={200: {"model": ProgramForm}},
methods=["POST"],
)

@property
def form_service(self):
if not self._form_service:
self._form_service = FormService.get_component()
return self._form_service

async def get_program_form(self, programid: int):
response_dict = {}
res = await ProgramORM.get_program_form(programid)
Expand All @@ -40,28 +55,47 @@ async def get_program_form(self, programid: int):
if form:
response_dict = {
"id": form.id,
"schema": form.schema,
"program_id": res.id,
"schema": form.schema,
"submission_data": None,
"name": res.name,
"description": res.description,
"program_name": res.name,
"program_description": res.description,
}
else:
response_dict = {
"id": None,
"schema": None,
"program_id": res.id,
"schema": None,
"submission_data": None,
"name": res.name,
"description": res.description,
"program_name": res.name,
"program_description": res.description,
}
return ProgramForm(**response_dict)
else:
# TODO: Add error handling
pass

async def update_form_data(self, programid: int):
return "form data updated!!"
async def update_form_draft(
self, programid: int, programreginfo: ProgramRegistrantInfo
):
registrant_id = 42

return await self.form_service.crate_form_draft(
programid, programreginfo, registrant_id
)

async def crate_new_form_draft(
self, programid: int, programreginfo: ProgramRegistrantInfo
):
registrant_id = 42

return await self.form_service.crate_form_draft(
programid, programreginfo, registrant_id
)

async def crate_new_form_draft(self, programid: int):
return "Successfully submitted the draft!!"
async def submit_form(self, programid: int, programreginfo: ProgramRegistrantInfo):
registrant_id = 42

return await self.form_service.submit_application_form(
programid, programreginfo, registrant_id
)
12 changes: 9 additions & 3 deletions src/openg2p_portal_api/models/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
class ProgramForm(BaseModel):
model_config = ConfigDict(from_attributes=True)

program_id: Optional[int]
form_id: Optional[int] = Field(default=None, alias="id")
json_schema: Optional[str] = Field(default=None, alias="schema")
program_id: Optional[int] = None
submission_data: Optional[str] = None
name: Optional[str] = None
description: Optional[str] = None
program_name: Optional[str] = None
program_description: Optional[str] = None


class ProgramRegistrantInfo(BaseModel):
model_config = ConfigDict(from_attributes=True)

program_registrant_info: Optional[dict] = {}
16 changes: 15 additions & 1 deletion src/openg2p_portal_api/models/orm/program_membership_orm.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from openg2p_fastapi_common.context import dbengine
from openg2p_fastapi_common.models import BaseORMModel
from sqlalchemy import ForeignKey, Integer
from sqlalchemy import ForeignKey, Integer, String, and_, select
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy.orm import Mapped, mapped_column, relationship


Expand All @@ -9,5 +11,17 @@ class ProgramMembershipORM(BaseORMModel):
id: Mapped[int] = mapped_column(primary_key=True)
partner_id: Mapped[int] = mapped_column(Integer())
program_id: Mapped[int] = mapped_column(ForeignKey("g2p_program.id"))
state: Mapped[str] = mapped_column(String())

program = relationship("ProgramORM", back_populates="membership")

@classmethod
async def get_membership_by_id(cls, program_id: int, partner_id: int):
async_session_maker = async_sessionmaker(dbengine.get())
async with async_session_maker() as session:
stmt = select(cls).where(
and_(cls.program_id == program_id, cls.partner_id == partner_id)
)

result = await session.execute(stmt)
return result.scalar()
30 changes: 27 additions & 3 deletions src/openg2p_portal_api/models/orm/program_registrant_info_orm.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
from openg2p_fastapi_common.context import dbengine
from openg2p_fastapi_common.models import BaseORMModel
from sqlalchemy import ForeignKey, String
from sqlalchemy import JSON, ForeignKey, Integer, String, and_, select
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy.orm import Mapped, mapped_column


class FormORM(BaseORMModel):
class ProgramRegistrantInfoORM(BaseORMModel):
__tablename__ = "g2p_program_registrant_info"

id: Mapped[int] = mapped_column(primary_key=True)
program_id: Mapped[int] = mapped_column(ForeignKey("g2p_program.id"))
program_registrant_info: Mapped[str] = mapped_column(String())
program_registrant_info: Mapped[dict] = mapped_column(JSON)
state: Mapped[str] = mapped_column(String())
program_membership_id: Mapped[int] = mapped_column(Integer())
registrant_id: Mapped[int] = mapped_column(Integer())


class ProgramRegistrantInfoDraftORM(BaseORMModel):
__tablename__ = "g2p_program_registrant_info_draft"

id: Mapped[int] = mapped_column(primary_key=True)
program_id: Mapped[int] = mapped_column(ForeignKey("g2p_program.id"))
registrant_id: Mapped[int] = mapped_column(Integer())
program_registrant_info: Mapped[dict] = mapped_column(JSON)

@classmethod
async def get_draft_reg_info_by_id(cls, program_id: int, registrant_id: int):
async_session_maker = async_sessionmaker(dbengine.get())
async with async_session_maker() as session:
stmt = select(cls).where(
and_(cls.program_id == program_id, cls.registrant_id == registrant_id)
)
result = await session.execute(stmt)
return result.scalar()
10 changes: 2 additions & 8 deletions src/openg2p_portal_api/models/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ class ProgramMembership(BaseModel):

partner_id: Optional[int] = None
program_id: Optional[int] = None
state: Optional[str] = None


class ProgramBase(BaseModel):
model_config = ConfigDict(from_attributes=True)

id: Optional[int] = None
id: Optional[int]
name: Optional[str] = None
active: Optional[bool] = None
description: Optional[str] = None


Expand All @@ -36,9 +36,3 @@ def is_portal_form(cls, v, values):
def has_applied(cls, v, values):
# TODO: Iterate over program_membership_ids and check whether the user is present or not.
return False


class ProgramRegistrantInfo(BaseModel):
model_config = ConfigDict(from_attributes=True)

program_registrant_info: Optional[str] = None
84 changes: 84 additions & 0 deletions src/openg2p_portal_api/services/form_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from openg2p_fastapi_common.context import dbengine
from openg2p_fastapi_common.service import BaseService
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import async_sessionmaker

from ..models.orm.program_registrant_info_orm import (
ProgramRegistrantInfoDraftORM,
ProgramRegistrantInfoORM,
)
from .membership_service import MembershipService


class FormService(BaseService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.membership_service = MembershipService.get_component()

async def crate_form_draft(self, program_id: int, form_data, registrant_id: int):
async_session_maker = async_sessionmaker(dbengine.get())
async with async_session_maker() as session:
check_if_draft_already_present = (
await ProgramRegistrantInfoDraftORM.get_draft_reg_info_by_id(
program_id, registrant_id
)
)

if check_if_draft_already_present is None:
program_registrant_info = ProgramRegistrantInfoDraftORM(
program_id=program_id,
program_registrant_info=form_data.program_registrant_info,
registrant_id=registrant_id,
)

try:
session.add(program_registrant_info)

await session.commit()
except IntegrityError:
return "Error: In creating the draft"

else:
check_if_draft_already_present.program_registrant_info = (
form_data.program_registrant_info
)
try:
await session.commit()
except IntegrityError:
return "Error: In updating the draft."

return "Successfully submitted the draft!!"

async def submit_application_form(
self, program_id: int, form_data, registrant_id: int
):
async_session_maker = async_sessionmaker(dbengine.get())
async with async_session_maker() as session:
program_membership_id = await self.membership_service.check_and_create_mem(
program_id, registrant_id
)
get_draft_reg_info = (
await ProgramRegistrantInfoDraftORM.get_draft_reg_info_by_id(
program_id, registrant_id
)
)
program_registrant_info = ProgramRegistrantInfoORM(
program_id=program_id,
program_membership_id=program_membership_id,
program_registrant_info=form_data.program_registrant_info,
state="active",
registrant_id=registrant_id,
)

try:
if get_draft_reg_info:
session.add(program_registrant_info)
await session.delete(get_draft_reg_info)
else:
session.add(program_registrant_info)

await session.commit()
except IntegrityError:
return "Error: Duplicate entry or integrity violation"

return "Successfully applied into the program!!"
32 changes: 32 additions & 0 deletions src/openg2p_portal_api/services/membership_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from openg2p_fastapi_common.context import dbengine
from openg2p_fastapi_common.service import BaseService
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import async_sessionmaker

from ..models.orm.program_membership_orm import ProgramMembershipORM


class MembershipService(BaseService):
def __init__(self, **kwargs):
super().__init__(**kwargs)

async def check_and_create_mem(self, programid: int, partnerid: int):
async_session_maker = async_sessionmaker(dbengine.get())
async with async_session_maker() as session:
membership = await ProgramMembershipORM.get_membership_by_id(
programid, partnerid
)

if membership is None:
membership = ProgramMembershipORM(
program_id=programid, partner_id=partnerid, state="draft"
)

try:
session.add(membership)

await session.commit()
except IntegrityError:
return "Could not add to registrant to program!!"

return membership.id

0 comments on commit 95833e9

Please sign in to comment.