From 78ca44c3f3f6892ff783330b88b737ec32590b66 Mon Sep 17 00:00:00 2001 From: shivamg9 Date: Sat, 18 May 2024 03:19:51 +0530 Subject: [PATCH] Implemented dynamic field mapping for updating partner info based on program registrant info --- src/openg2p_portal_api/context.py | 6 ++++- .../models/orm/partner_orm.py | 26 +++++++++---------- .../services/form_service.py | 26 ++++++++++++++++--- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/openg2p_portal_api/context.py b/src/openg2p_portal_api/context.py index 2e3c43d..12908b0 100644 --- a/src/openg2p_portal_api/context.py +++ b/src/openg2p_portal_api/context.py @@ -1,6 +1,10 @@ from contextvars import ContextVar -from typing import Any, Dict +from typing import Any, Dict, List auth_id_type_config_cache: ContextVar[Dict[str, Any]] = ContextVar( "auth_id_type_config_cache", default={} ) + +partner_fields_cache: ContextVar[List[str]] = ContextVar( + "partner_fields_cache", default=[] +) diff --git a/src/openg2p_portal_api/models/orm/partner_orm.py b/src/openg2p_portal_api/models/orm/partner_orm.py index 05a10f0..5d0c2e7 100644 --- a/src/openg2p_portal_api/models/orm/partner_orm.py +++ b/src/openg2p_portal_api/models/orm/partner_orm.py @@ -5,12 +5,12 @@ from openg2p_fastapi_common.models import BaseORMModel, BaseORMModelWithId from sqlalchemy import ( Boolean, - CheckConstraint, Date, DateTime, ForeignKey, String, select, + text, ) from sqlalchemy.ext.asyncio import async_sessionmaker from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -32,19 +32,7 @@ class PartnerORM(BaseORMModelWithId): birth_place: Mapped[str] = mapped_column() phone: Mapped[str] = mapped_column() company_id: Mapped[Optional[int]] = mapped_column() - income: Mapped[Optional[int]] = mapped_column() - display_name: Mapped[str] = mapped_column() - area_id: Mapped[Optional[int]] = mapped_column() - civil_status: Mapped[str] = mapped_column() - occupation: Mapped[str] = mapped_column() - district: Mapped[str] = mapped_column() - birthdate_not_exact: Mapped[bool] = mapped_column(Boolean(), default=False) registration_date: Mapped[date] = mapped_column(Date()) - notification_preference: Mapped[str] = mapped_column( - String, - CheckConstraint("notification_preference IN ('none', 'email', 'sms', 'both')"), - default="none", - ) reg_ids: Mapped[Optional[List[RegIDORM]]] = relationship(back_populates="partner") create_date: Mapped[datetime] = mapped_column(DateTime(), default=datetime.utcnow) @@ -62,6 +50,18 @@ async def get_partner_data(cls, id: int): result = await session.execute(stmt) return result.scalar() + @classmethod + async def get_partner_fields(cls): + async_session_maker = async_sessionmaker(dbengine.get()) + async with async_session_maker() as session: + result = await session.execute( + text( + "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = :tbl_name" + ), + params={"tbl_name": cls.__tablename__}, + ) + return result.scalars().all() + class PartnerBankORM(BaseORMModelWithId): __tablename__ = "res_partner_bank" diff --git a/src/openg2p_portal_api/services/form_service.py b/src/openg2p_portal_api/services/form_service.py index ca0927d..5492e2a 100644 --- a/src/openg2p_portal_api/services/form_service.py +++ b/src/openg2p_portal_api/services/form_service.py @@ -3,9 +3,11 @@ from openg2p_fastapi_common.context import dbengine from openg2p_fastapi_common.service import BaseService +from sqlalchemy import text from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import async_sessionmaker +from ..context import partner_fields_cache from ..models.form import ProgramForm from ..models.orm.partner_orm import PartnerORM from ..models.orm.program_orm import ProgramORM @@ -152,12 +154,20 @@ def _compute_application_id(self): async def update_partner_info(self, session, partner_info, program_registrant_info): # Update partner_info with fields from program_registrant_info updated_fields = {} + partner_fields = await self.get_partner_fields() for key, value in program_registrant_info.items(): - if hasattr(partner_info, key) and getattr(partner_info, key) != value: - setattr(partner_info, key, value) + # if hasattr(partner_info, key) and getattr(partner_info, key) != value: + if key in partner_fields: updated_fields[key] = value - session.add(partner_info) - await session.commit() + if updated_fields: + set_clause = ", ".join( + [f"{key} = '{value}'" for key, value in updated_fields.items()] + ) + await session.execute( + text( + f"UPDATE {PartnerORM.__tablename__} SET {set_clause} WHERE id='{partner_info.id}'" + ) + ) return updated_fields def clean_program_registrant_info(self, program_registrant_info, updated_fields): @@ -168,3 +178,11 @@ def clean_program_registrant_info(self, program_registrant_info, updated_fields) if key not in updated_fields } return cleaned_info + + async def get_partner_fields(self): + partner_field = partner_fields_cache.get() + if partner_field: + return partner_field + partner_field = await PartnerORM.get_partner_fields() + partner_fields_cache.set(partner_field) + return partner_field