feat: Implement Event File Hosted Data Fix and API Guide Update

Address critical data visibility issues for Event Files and enhance frontend documentation.

This commit resolves the persistent problem where top-level hosted file convenience fields
(e.g., , , ) were
returning as  in V3 Event File API responses, even when .

Key changes include:
- Refactored  Pydantic model:
    - Removed redundant  definitions from top-level hosted file convenience fields,
      allowing direct mapping from SQL view columns.
    - Simplified  to focus solely on conditionally loading the nested
       object, as top-level fields are now populated directly by Pydantic
      from the  view.
    - Added comprehensive comments to clarify data flow, Pydantic's behavior, and the
      expected origin of these convenience fields from SQL views.
- Updated :
    - Introduced a new section detailing how to retrieve Event File data, including the
      use of  to get both top-level convenience fields and a nested
       object.
    - Clarified all ID references as random string IDs.
    - Renumbered the troubleshooting section.
- Copied updated guide to .
- Continued ID Vision compliance audit, ensuring consistent handling of random string IDs
  across various core and event models (Account, Address, Contact, DataStore, Event Badge Template).
- Consolidated ID Vision E2E tests and updated related documentation.
- Minor updates to  and
  to support Event File data retrieval with .
This commit is contained in:
Scott Idem
2026-02-19 15:22:17 -05:00
parent 577d784fb8
commit 17a627a981
17 changed files with 391 additions and 185 deletions

View File

@@ -46,6 +46,9 @@ class Event_File_Base(BaseModel):
event_session_id_random: Optional[str] = Field(None, exclude=True)
event_track_id_random: Optional[str] = Field(None, exclude=True)
# Internal flag to signal the model to load nested hosted_file
inc_hosted_file: Optional[bool] = Field(False, exclude=True)
@root_validator(pre=True)
def map_v3_ids(cls, values):
"""
@@ -102,9 +105,20 @@ class Event_File_Base(BaseModel):
val = values.get(k)
if val is not None and not isinstance(val, str):
values[k] = None
# 4. Conditionally load nested 'hosted_file' object
if values.get('inc_hosted_file') and values.get('hosted_file_id'):
from app.methods.hosted_file_methods import load_hosted_file_obj
if hosted_file_obj := load_hosted_file_obj(hosted_file_id=values['hosted_file_id']):
values['hosted_file'] = hosted_file_obj
# Clean up internal inc_hosted_file flag after processing
if 'inc_hosted_file' in values:
del values['inc_hosted_file']
return values
for_type: Optional[str]
filename: Optional[str]
@@ -114,7 +128,7 @@ class Event_File_Base(BaseModel):
title: Optional[str]
description: Optional[str]
lu_file_purpose_id: Optional[int]
lu_file_purpose_id: Optional[int] = Field(None, exclude=True)
file_purpose: Optional[str]
# New internal use fields to help with logistics and planning 2022-09-15
@@ -143,21 +157,21 @@ class Event_File_Base(BaseModel):
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
# Including convenience data
# This is only for convenience. Probably going to keep unless it causes a problem.
hosted_file_hash_sha256: Optional[str] = Field(
alias = 'hash_sha256'
)
hosted_file_subdirectory_path: Optional[str] = Field( # NOTE: This will frequently only contain numbers, but it still needs to be a string
alias = 'subdirectory_path',
exclude = True
)
hosted_file_content_type: Optional[str] = Field(
alias = 'content_type'
)
hosted_file_size: Optional[str] = Field(
alias = 'file_size'
)
# Including convenience data for Hosted Files (top-level properties)
# These fields provide direct access to frequently needed properties from the associated
# hosted file, effectively flattening some aspects of the nested 'hosted_file' object.
#
# IMPORTANT: These fields are designed to be populated directly from the SQL View
# (e.g., `v_event_file_simple`) via JOINs. They should **NOT** have Pydantic `alias`
# definitions here if the view provides them with matching names (e.g., `hosted_file_hash_sha256`).
# Pydantic's default mapping will handle them directly from the incoming data dictionary
# (the `sql_result` in `api_crud_v3.py`).
# The `root_validator` does **NOT** populate these top-level fields; its role is
# solely to conditionally load the *nested* `hosted_file` object.
hosted_file_hash_sha256: Optional[str]
hosted_file_subdirectory_path: Optional[str]
hosted_file_content_type: Optional[str]
hosted_file_size: Optional[str]
lu_event_file_purpose_name: Optional[str] = Field(
alias = 'file_purpose_name'
@@ -194,6 +208,6 @@ class Event_File_Base(BaseModel):
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 File Models ### Event_File_Base() ###