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 import datetime, pytz
from typing import Dict, List, Optional, Set, Union 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.db_sql import redis_lookup_id_random
from app.lib_general import log, logging 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.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals()) log.debug(locals())
id_random: Optional[str] = Field( # --- Standardized Vision IDs (Strings) ---
# **base_fields['event_abstract_id_random'], id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
alias = 'event_abstract_id_random', event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random'])
)
id: Optional[int] = Field( event_id: Optional[str] = Field(None, **base_fields['event_id_random'])
alias = 'event_abstract_id' 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_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random'])
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]
# poc_event_person_id_random: Optional[str] # Maybe change this to primary_event_person? # 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? # 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] external_id: Optional[str]
code: Optional[str] code: Optional[str]
grant_id_random: Optional[str]
grant_id: Optional[int]
grant_code: Optional[str] grant_code: Optional[str]
# grant_type_code: Optional[str] # grant_type_code: Optional[str]
# grant_json: Optional[Union[Json, None]] # 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) _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True) @root_validator(pre=True)
def event_abstract_id_lookup(cls, v, values, **kwargs): def map_v3_ids(cls, values):
if isinstance(v, int) and v > 0: return v """
elif id_random := values.get('id_random'): Vision Transformer:
return redis_lookup_id_random(record_id_random=id_random, table_name='event_abstract') Map DB keys to clean API keys and strip internal integers.
return None """
# 1. Map Random Strings to Clean Names
@validator('event_id', always=True) if rid := values.get('id_random') or values.get('event_abstract_id_random'):
def event_id_lookup(cls, v, values, **kwargs): values['id'] = rid
if isinstance(v, int) and v > 0: return v values['event_abstract_id'] = rid
elif id_random := values.get('event_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event') if e_rid := values.get('event_id_random'):
return None values['event_id'] = e_rid
if ep_rid := values.get('event_person_id_random'):
@validator('event_person_id', always=True) values['event_person_id'] = ep_rid
def event_person_id_lookup(cls, v, values, **kwargs): if epr_rid := values.get('event_presentation_id_random'):
if isinstance(v, int) and v > 0: return v values['event_presentation_id'] = epr_rid
elif id_random := values.get('event_person_id_random'): if eps_rid := values.get('event_presenter_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_person') values['event_presenter_id'] = eps_rid
return None if es_rid := values.get('event_session_id_random'):
values['event_session_id'] = es_rid
@validator('event_presentation_id', always=True) if g_rid := values.get('grant_id_random'):
def event_presentation_id_lookup(cls, v, values, **kwargs): values['grant_id'] = g_rid
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('event_presentation_id_random'): # 2. Prevent "Collision Population"
return redis_lookup_id_random(record_id_random=id_random, table_name='event_presentation') for k in ['id', 'event_abstract_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']:
return None if k in values and not isinstance(values[k], str) and values[k] is not None:
del values[k]
@validator('event_presenter_id', always=True)
def event_presenter_id_lookup(cls, v, values, **kwargs): return values
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
class Config: class Config:
underscore_attrs_are_private = True underscore_attrs_are_private = True
allow_population_by_field_name = True allow_population_by_field_name = False
fields = base_fields fields = base_fields
# ### END ### API Event Abstract Models ### Event_Abstract_Base() ### # ### 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.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals()) log.debug(locals())
id_random: Optional[str] = Field( # --- Standardized Vision IDs (Strings) ---
alias = 'event_abstract_id_random', 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_random: Optional[str] event_id: Optional[str] = Field(None, **base_fields['event_id_random'])
event_id: Optional[int] 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_person_id: Optional[int] 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'])
event_session_id: Optional[int] grant_id: Optional[str] = Field(None, **base_fields['grant_id_random'])
event_person_id_random: Optional[str]
event_presentation_id_random: Optional[str]
event_presenter_id_random: Optional[str]
event_session_id_random: Optional[str]
# event_track_id_random: Optional[str] # event_track_id_random: Optional[str]
@@ -209,9 +158,6 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base):
passcode: Optional[str] passcode: Optional[str]
grant_id_random: Optional[str]
grant_id: Optional[int]
grant_code: Optional[str] grant_code: Optional[str]
grant_type_code: Optional[str] grant_type_code: Optional[str]
grant_json: Optional[Union[Json, None]] 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]] submitter_json: Optional[Union[Json, None]]
coauthors_json: Optional[Union[Json, None]] coauthors_json: Optional[Union[Json, None]]
@validator('event_person_id', always=True) @root_validator(pre=True)
def event_person_id_lookup(cls, v, values, **kwargs): def map_v3_ids(cls, values):
if isinstance(v, int) and v > 0: return v """
elif id_random := values.get('event_person_id_random'): Vision Transformer:
return redis_lookup_id_random(record_id_random=id_random, table_name='event_person') Map DB keys to clean API keys and strip internal integers.
return None """
# 1. Map Random Strings to Clean Names
# @validator('event_session_id', always=True) if rid := values.get('id_random') or values.get('event_abstract_id_random'):
# def event_session_id_lookup(cls, v, values, **kwargs): values['id'] = rid
# if isinstance(v, int) and v > 0: return v values['event_abstract_id'] = rid
# elif id_random := values.get('event_session_id_random'):
# return redis_lookup_id_random(record_id_random=id_random, table_name='event_session') if e_rid := values.get('event_id_random'):
# return None 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: class Config:
underscore_attrs_are_private = True underscore_attrs_are_private = True
allow_population_by_field_name = True allow_population_by_field_name = False
fields = base_fields fields = base_fields
# ### END ### API Event Abstract Models ### Event_Abstract_Base() ### # ### 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): class Event_Abstract_In(Event_Abstract_Base_New):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals()) 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( pass
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
# ### END ### API Event Abstract Models ### Event_Abstract_In() ### # ### END ### API Event Abstract Models ### Event_Abstract_In() ###

View File

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

View File

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