feat(data_store): implement V3 cascading lookup and ID Vision standardization

- Added GET /v3/data_store/code/{code} with hierarchical context-aware fallback.
- Implemented ID Vision standard in Data_Store_Base (string IDs, internal int exclusion).
- Enhanced Data_Store_Base robustness to handle stringified 'NULL' values from the database.
- Fixed legacy router bugs by removing undefined parameters (inc_event_cfg, inc_event_location).
- Corrected type hints and resolved UnboundLocalError in data_store methods.
- Updated Frontend Integration Guide with Section 8: Data Store V3.
- Added unified E2E test script: tests/e2e/test_e2e_v3_data_store_lookup.py.
This commit is contained in:
Scott Idem
2026-01-28 16:51:48 -05:00
parent 9c0aae9a6d
commit fdcc859017
5 changed files with 224 additions and 78 deletions

View File

@@ -20,7 +20,7 @@ router = APIRouter()
# ### BEGIN ### API Data Store Routers ### post_data_store_obj() ###
# Updated 2022-03-11
# Updated 2026-01-28
@router.post('/data_store', response_model=Resp_Body_Base)
async def post_data_store_obj(
data_store_obj: Data_Store_Base,
@@ -47,8 +47,6 @@ async def post_data_store_obj(
if return_obj:
data_store_obj = load_data_store_obj(
data_store_id = data_store_id,
inc_event_cfg = inc_event_cfg,
inc_event_location = inc_event_location,
)
data = data_store_obj
else:
@@ -103,7 +101,7 @@ async def patch_data_store_obj(
# ### BEGIN ### API Data Store ### get_data_store_obj() ###
# Updated 2022-03-11
# Updated 2026-01-28
@router.get('/data_store/{data_store_id}', response_model=Resp_Body_Base)
async def get_data_store_obj(
data_store_id: str = Path(min_length=11, max_length=22),
@@ -121,8 +119,6 @@ async def get_data_store_obj(
data_store_id = data_store_id,
limit = commons.limit,
enabled = commons.enabled,
inc_event_cfg = inc_event_cfg,
inc_event_location = inc_event_location,
):
log.info('Loading successful. Returning result')
return mk_resp(data=data_store_rec_result, response=commons.response)
@@ -135,6 +131,46 @@ async def get_data_store_obj(
# ### END ### API Data Store ### get_data_store_obj() ###
# ### BEGIN ### API Data Store ### get_v3_data_store_obj_w_code() ###
# NEW V3 Endpoint for Code Lookup
# Updated 2026-01-28
from app.lib_general_v3 import AccountContext, get_account_context, SerializationParams, StatusFilterParams
@router.get('/v3/data_store/code/{data_store_code}', response_model=Resp_Body_Base, tags=['Data Store V3'])
async def get_v3_data_store_obj_w_code(
data_store_code: str = Path(min_length=3, max_length=50),
for_type: Optional[str] = Query(None, min_length=1, max_length=25),
for_id: Optional[str] = Query(None, min_length=11, max_length=22),
account: AccountContext = Depends(get_account_context),
serialization: SerializationParams = Depends(),
status_filter: StatusFilterParams = Depends(),
):
"""
V3 Standardized Data Store Lookup.
Uses JWT-based AccountContext and supports cascading fallback logic (Object > Account > Global).
"""
log.setLevel(logging.INFO)
# Map V3 params to the shared handler
# We create a dummy Common_Route_Params object to satisfy the handler's interface
# while using the more secure V3 dependencies.
v3_commons = Common_Route_Params(
x_account_id=account.account_id,
x_account_id_random=account.account_id_random,
enabled=status_filter.enabled,
response=Response()
)
return handle_get_data_store_obj_w_code(
data_store_code = data_store_code,
for_type = for_type,
for_id = for_id,
commons = v3_commons,
)
# ### END ### API Data Store ### get_v3_data_store_obj_w_code() ###
# ### BEGIN ### API Data Store ### get_data_store_obj_w_code() ###
# NOTE: Adding some explanation because this is not quickly obvious how it fully works.
# The look up order starts with a required data_store_code. Then the first result that matches the most specific method. The for_type and for_id fields are not required. I think it makes the most sense to be a part of the URL path, not the GET params. Either should work with no problem though.