Refactor Event models to use Vision ID string pattern

Updated Event_Presentation_Base, Event_Location_Base, and Event_Abstract_Base (and Base_New/In) to use standardized string IDs mapped from random IDs via root_validator. Removed legacy integer ID fields and validators to ensure API responses comply with the V3 Vision standard.
This commit is contained in:
Scott Idem
2026-01-27 10:49:02 -05:00
parent 48e0a31cf5
commit d6134e799e
3 changed files with 157 additions and 268 deletions

View File

@@ -1,7 +1,7 @@
import datetime, pytz
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator
from app.db_sql import redis_lookup_id_random
from app.lib_general import log, logging
@@ -23,31 +23,18 @@ class Event_Abstract_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
# **base_fields['event_abstract_id_random'],
alias = 'event_abstract_id_random',
)
id: Optional[int] = Field(
alias = 'event_abstract_id'
)
# --- Standardized Vision IDs (Strings) ---
id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
event_id: Optional[str] = Field(None, **base_fields['event_id_random'])
event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random'])
event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random'])
event_presenter_id: Optional[str] = Field(None, **base_fields['event_presenter_id_random'])
event_session_id: Optional[str] = Field(None, **base_fields['event_session_id_random'])
grant_id: Optional[str] = Field(None, **base_fields['grant_id_random'])
event_id_random: Optional[str]
event_id: Optional[int]
event_person_id_random: Optional[str] # This is the primary person/submitter
event_person_id: Optional[int]
event_presentation_id_random: Optional[str]
event_presentation_id: Optional[int]
event_presenter_id_random: Optional[str]
event_presenter_id: Optional[int]
event_session_id_random: Optional[str]
event_session_id: Optional[int]
# event_track_id_random: Optional[str]
# event_track_id: Optional[int]
# event_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random'])
# poc_event_person_id_random: Optional[str] # Maybe change this to primary_event_person?
# poc_event_person_id: Optional[int] # Maybe change this to primary_event_person?
@@ -55,9 +42,6 @@ class Event_Abstract_Base(BaseModel):
external_id: Optional[str]
code: Optional[str]
grant_id_random: Optional[str]
grant_id: Optional[int]
grant_code: Optional[str]
# grant_type_code: Optional[str]
# grant_json: Optional[Union[Json, None]]
@@ -101,67 +85,40 @@ class Event_Abstract_Base(BaseModel):
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True)
def event_abstract_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_abstract')
return None
@validator('event_id', always=True)
def event_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event')
return None
@validator('event_person_id', always=True)
def event_person_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_person_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_person')
return None
@validator('event_presentation_id', always=True)
def event_presentation_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_presentation_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_presentation')
return None
@validator('event_presenter_id', always=True)
def event_presenter_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_presenter_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_presenter')
return None
@validator('event_session_id', always=True)
def event_session_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_session_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_session')
return None
@validator('grant_id', always=True)
def grant_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('grant_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='grant')
return None
# @validator('poc_event_person_id', always=True)
# def poc_event_person_id_lookup(cls, v, values, **kwargs):
# log.setLevel(logging.WARNING)
# log.debug(locals())
# if values['poc_event_person_id_random']:
# return redis_lookup_id_random(record_id_random=values['poc_event_person_id_random'], table_name='poc_event_person')
# return None
@root_validator(pre=True)
def map_v3_ids(cls, values):
"""
Vision Transformer:
Map DB keys to clean API keys and strip internal integers.
"""
# 1. Map Random Strings to Clean Names
if rid := values.get('id_random') or values.get('event_abstract_id_random'):
values['id'] = rid
values['event_abstract_id'] = rid
if e_rid := values.get('event_id_random'):
values['event_id'] = e_rid
if ep_rid := values.get('event_person_id_random'):
values['event_person_id'] = ep_rid
if epr_rid := values.get('event_presentation_id_random'):
values['event_presentation_id'] = epr_rid
if eps_rid := values.get('event_presenter_id_random'):
values['event_presenter_id'] = eps_rid
if es_rid := values.get('event_session_id_random'):
values['event_session_id'] = es_rid
if g_rid := values.get('grant_id_random'):
values['grant_id'] = g_rid
# 2. Prevent "Collision Population"
for k in ['id', 'event_abstract_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']:
if k in values and not isinstance(values[k], str) and values[k] is not None:
del values[k]
return values
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
allow_population_by_field_name = False
fields = base_fields
# ### END ### API Event Abstract Models ### Event_Abstract_Base() ###
@@ -175,24 +132,16 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
alias = 'event_abstract_id_random',
)
event_id_random: Optional[str]
event_id: Optional[int]
event_person_id: Optional[int]
event_session_id: Optional[int]
event_person_id_random: Optional[str]
event_presentation_id_random: Optional[str]
event_presenter_id_random: Optional[str]
event_session_id_random: Optional[str]
# --- Standardized Vision IDs (Strings) ---
id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
event_id: Optional[str] = Field(None, **base_fields['event_id_random'])
event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random'])
event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random'])
event_presenter_id: Optional[str] = Field(None, **base_fields['event_presenter_id_random'])
event_session_id: Optional[str] = Field(None, **base_fields['event_session_id_random'])
grant_id: Optional[str] = Field(None, **base_fields['grant_id_random'])
# event_track_id_random: Optional[str]
@@ -209,9 +158,6 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base):
passcode: Optional[str]
grant_id_random: Optional[str]
grant_id: Optional[int]
grant_code: Optional[str]
grant_type_code: Optional[str]
grant_json: Optional[Union[Json, None]]
@@ -224,23 +170,40 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base):
submitter_json: Optional[Union[Json, None]]
coauthors_json: Optional[Union[Json, None]]
@validator('event_person_id', always=True)
def event_person_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_person_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_person')
return None
# @validator('event_session_id', always=True)
# def event_session_id_lookup(cls, v, values, **kwargs):
# if isinstance(v, int) and v > 0: return v
# elif id_random := values.get('event_session_id_random'):
# return redis_lookup_id_random(record_id_random=id_random, table_name='event_session')
# return None
@root_validator(pre=True)
def map_v3_ids(cls, values):
"""
Vision Transformer:
Map DB keys to clean API keys and strip internal integers.
"""
# 1. Map Random Strings to Clean Names
if rid := values.get('id_random') or values.get('event_abstract_id_random'):
values['id'] = rid
values['event_abstract_id'] = rid
if e_rid := values.get('event_id_random'):
values['event_id'] = e_rid
if ep_rid := values.get('event_person_id_random'):
values['event_person_id'] = ep_rid
if epr_rid := values.get('event_presentation_id_random'):
values['event_presentation_id'] = epr_rid
if eps_rid := values.get('event_presenter_id_random'):
values['event_presenter_id'] = eps_rid
if es_rid := values.get('event_session_id_random'):
values['event_session_id'] = es_rid
if g_rid := values.get('grant_id_random'):
values['grant_id'] = g_rid
# 2. Prevent "Collision Population"
for k in ['id', 'event_abstract_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']:
if k in values and not isinstance(values[k], str) and values[k] is not None:
del values[k]
return values
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
allow_population_by_field_name = False
fields = base_fields
# ### END ### API Event Abstract Models ### Event_Abstract_Base() ###
@@ -250,68 +213,11 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base):
class Event_Abstract_In(Event_Abstract_Base_New):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# Inherits everything from Event_Abstract_Base_New including the Vision ID pattern.
# We do NOT redefine 'id' as int here.
id: Optional[int] = Field(
alias = 'event_abstract_id'
)
event_id: Optional[int]
event_person_id: Optional[int]
# event_session_id: Optional[int]
# grant_json: Optional[Union[str, None]]
@validator('id', always=True)
def event_abstract_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_abstract')
return None
@validator('event_id', always=True)
def event_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event')
return None
@validator('event_person_id', always=True)
def event_person_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_person_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_person')
return None
# @validator('event_presentation_id', always=True)
# def event_presentation_id_lookup(cls, v, values, **kwargs):
# if isinstance(v, int) and v > 0: return v
# elif id_random := values.get('event_presentation_id_random'):
# return redis_lookup_id_random(record_id_random=id_random, table_name='event_presentation')
# return None
# @validator('event_presenter_id', always=True)
# def event_presenter_id_lookup(cls, v, values, **kwargs):
# if isinstance(v, int) and v > 0: return v
# elif id_random := values.get('event_presenter_id_random'):
# return redis_lookup_id_random(record_id_random=id_random, table_name='event_presenter')
# return None
# @validator('event_session_id', always=True)
# def event_session_id_lookup(cls, v, values, **kwargs):
# if isinstance(v, int) and v > 0: return v
# elif id_random := values.get('event_session_id_random'):
# return redis_lookup_id_random(record_id_random=id_random, table_name='event_session')
# return None
@validator('grant_id', always=True)
def grant_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('grant_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='grant')
return None
pass
# ### END ### API Event Abstract Models ### Event_Abstract_In() ###

View File

@@ -1,7 +1,7 @@
import datetime, pytz
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator
from app.db_sql import redis_lookup_id_random
from app.lib_general import log, logging
@@ -15,13 +15,12 @@ class Event_Location_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
# **base_fields['event_location_id_random'],
alias = 'event_location_id_random',
)
id: Optional[int] = Field(
alias = 'event_location_id'
)
# --- Standardized Vision IDs (Strings) ---
id: Optional[str] = Field(None, **base_fields['event_location_id_random'])
event_location_id: Optional[str] = Field(None, **base_fields['event_location_id_random'])
event_id: Optional[str] = Field(None, **base_fields['event_id_random'])
event_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random'])
code: Optional[str] = Field(
# alias = 'event_location_code'
@@ -31,12 +30,6 @@ class Event_Location_Base(BaseModel):
# alias = 'event_location_external_id'
)
event_id_random: Optional[str]
event_id: Optional[int]
event_track_id_random: Optional[str] # Can a track be assigned to one location?
event_track_id: Optional[int] # Can a track be assigned to one location?
lu_location_type_id: Optional[int]
location_type_code: Optional[str]
location_type: Optional[str]
@@ -104,29 +97,31 @@ class Event_Location_Base(BaseModel):
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True)
def event_location_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_location')
return None
@validator('event_id', always=True)
def event_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event')
return None
@validator('event_track_id', always=True)
def event_track_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_track_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_track')
return None
@root_validator(pre=True)
def map_v3_ids(cls, values):
"""
Vision Transformer:
Map DB keys to clean API keys and strip internal integers.
"""
# 1. Map Random Strings to Clean Names
if rid := values.get('id_random') or values.get('event_location_id_random'):
values['id'] = rid
values['event_location_id'] = rid
if e_rid := values.get('event_id_random'):
values['event_id'] = e_rid
if et_rid := values.get('event_track_id_random'):
values['event_track_id'] = et_rid
# 2. Prevent "Collision Population"
for k in ['id', 'event_location_id', 'event_id', 'event_track_id']:
if k in values and not isinstance(values[k], str) and values[k] is not None:
del values[k]
return values
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
allow_population_by_field_name = False
fields = base_fields
# ### END ### API Event Location Models ### Event_Location_Base() ###

View File

@@ -1,7 +1,7 @@
import datetime, pytz
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator
from app.db_sql import redis_lookup_id_random
from app.lib_general import log, logging
@@ -18,13 +18,15 @@ class Event_Presentation_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
# **base_fields['event_presentation_id_random'],
alias = 'event_presentation_id_random',
)
id: Optional[int] = Field(
alias = 'event_presentation_id'
)
# --- Standardized Vision IDs (Strings) ---
id: Optional[str] = Field(None, **base_fields['event_presentation_id_random'])
event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random'])
event_id: Optional[str] = Field(None, **base_fields['event_id_random'])
event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
event_location_id: Optional[str] = Field(None, **base_fields['event_location_id_random'])
event_session_id: Optional[str] = Field(None, **base_fields['event_session_id_random'])
event_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random'])
external_id: Optional[str] = Field(
# alias = 'event_presentation_external_id'
@@ -32,21 +34,6 @@ class Event_Presentation_Base(BaseModel):
code: Optional[str]
event_id_random: Optional[str]
event_id: Optional[int]
event_abstract_id_random: Optional[str]
event_abstract_id: Optional[int]
event_location_id_random: Optional[str]
event_location_id: Optional[int]
event_session_id_random: Optional[str]
event_session_id: Optional[int]
event_track_id_random: Optional[str]
event_track_id: Optional[int]
poc_event_person: Optional[Event_Person_Base]
poc_person: Optional[Person_Base]
@@ -111,36 +98,37 @@ class Event_Presentation_Base(BaseModel):
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True)
def event_presentation_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_presentation')
return None
@validator('event_id', always=True)
def event_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event')
return None
@validator('event_abstract_id', always=True)
def event_abstract_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_abstract_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_abstract')
return None
@validator('event_session_id', always=True)
def event_session_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_session_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_session')
return None
@root_validator(pre=True)
def map_v3_ids(cls, values):
"""
Vision Transformer:
Map DB keys to clean API keys and strip internal integers.
"""
# 1. Map Random Strings to Clean Names
if rid := values.get('id_random') or values.get('event_presentation_id_random'):
values['id'] = rid
values['event_presentation_id'] = rid
if e_rid := values.get('event_id_random'):
values['event_id'] = e_rid
if ea_rid := values.get('event_abstract_id_random'):
values['event_abstract_id'] = ea_rid
if el_rid := values.get('event_location_id_random'):
values['event_location_id'] = el_rid
if es_rid := values.get('event_session_id_random'):
values['event_session_id'] = es_rid
if et_rid := values.get('event_track_id_random'):
values['event_track_id'] = et_rid
# 2. Prevent "Collision Population"
for k in ['id', 'event_presentation_id', 'event_id', 'event_abstract_id', 'event_location_id', 'event_session_id', 'event_track_id']:
if k in values and not isinstance(values[k], str) and values[k] is not None:
del values[k]
return values
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
allow_population_by_field_name = False
fields = base_fields
# ### END ### API Event Presentation Models ### Event_Presentation_Base() ###