Fix(IDAA): Harden Recovery Meetings search and fix detail page crash
- Search Hardening: Implemented 'Inclusive OR' logic for physical/virtual filters and restored robust full-text search using 'default_qry_str' with wildcards. - Crash Fix: Added null checks for 'contact_li_json' in meeting detail view to prevent TypeError. - ID Stability: Enhanced 'core__idb_dexie.ts' to support 'id_random' mapping and fixed misleading save logging. - Reliability: Both V2 and V3 search paths now consistently return processed objects with standardized IDs.
This commit is contained in:
4
TODO.md
4
TODO.md
@@ -28,7 +28,9 @@ This is a list of tasks to be completed before the next event/show/conference.
|
||||
- [ ] **Payload Validation**: Create a dry-run tool to check payloads against Pydantic models.
|
||||
- [x] **Error Transparency**: Update backend to return specific SQLAlchemy/Pydantic errors in `meta.details`. (Completed 2026-01-19)
|
||||
- [ ] **Automated Source of Truth**: Generate `V3_OBJECT_MODELS.md` automatically in `agents_sync/Aether/`.
|
||||
- [ ] **V3 Search Audit**: Investigate 'Zero-Result' bug in IDAA Recovery Meetings.
|
||||
- [x] **Fix V3 Search for IDAA Recovery Meetings**
|
||||
- *Resolution:* Isolated IDAA module to a specialized legacy function `qry_ae_obj_li__event_v2` for stability.
|
||||
- *V3 General Status:* Refined general `qry_ae_obj_li__event` to use 'Body + Header' injection, resolving the 'Integer Trap' for Main module.
|
||||
- [ ] Run raw CURL trace to bypass browser CORS and see full backend traceback.
|
||||
- [ ] Perform SQL Audit on `v_event` view types (string vs integer mismatch).
|
||||
- [ ] Test reverting to `account_id` mapping vs raw `account_id_random` body injection.
|
||||
|
||||
@@ -13,11 +13,11 @@ function find_object_id(
|
||||
table_name: string,
|
||||
log_lvl: number
|
||||
): string | number | undefined {
|
||||
const potential_keys = ['id', `${table_name}_id`, `${table_name}_id_random`];
|
||||
const potential_keys = ['id', 'id_random', `${table_name}_id`, `${table_name}_id_random`];
|
||||
|
||||
for (const key of potential_keys) {
|
||||
if (obj[key]) {
|
||||
if (key !== 'id' && log_lvl > 0) {
|
||||
if (key !== 'id' && log_lvl > 1) {
|
||||
console.warn(
|
||||
`Found legacy ID key "${key}" for table "${table_name}". Consider standardizing to "id".`,
|
||||
obj
|
||||
@@ -115,7 +115,7 @@ export async function db_save_ae_obj_li__ae_obj<T extends Record<string, any>>({
|
||||
// bulkPut efficiently handles both inserts and updates.
|
||||
const keys = await db_table.bulkPut(data_to_save);
|
||||
if (log_lvl > 0) {
|
||||
console.log(`Successfully saved ${keys.length} objects to "${table_name}".`);
|
||||
console.log(`Successfully saved ${data_to_save.length} objects to "${table_name}".`);
|
||||
}
|
||||
return keys;
|
||||
} catch (error) {
|
||||
|
||||
@@ -193,11 +193,7 @@ export async function load_ae_obj_li__event({
|
||||
if (for_obj_id) {
|
||||
search_query.and.push({ field: 'account_id_random', op: 'eq', value: for_obj_id });
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
|
||||
>>>>>>> f77938c1 (Fix(Events): Isolate IDAA Search to V2 and Refine V3 Search Pattern)
|
||||
promise = api.search_ae_obj_v3({
|
||||
api_cfg,
|
||||
obj_type: 'event',
|
||||
@@ -453,40 +449,16 @@ export async function qry_ae_obj_li__event({
|
||||
search_query.q = qry_str;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> f77938c1 (Fix(Events): Isolate IDAA Search to V2 and Refine V3 Search Pattern)
|
||||
// Use raw field name to bypass backend mapping conflicts (Integer Trap)
|
||||
if (for_obj_id) {
|
||||
search_query.and.push({ field: 'account_id_random', op: 'eq', value: for_obj_id });
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
// Use raw field name to bypass backend mapping conflicts
|
||||
// if (for_obj_id) {
|
||||
// search_query.and.push({ field: 'account_id_random', op: 'eq', value: for_obj_id });
|
||||
// }
|
||||
>>>>>>> 63c633f5 (Fix(Events): Revert to URL-based account context for V3 Search)
|
||||
=======
|
||||
>>>>>>> f77938c1 (Fix(Events): Isolate IDAA Search to V2 and Refine V3 Search Pattern)
|
||||
|
||||
const result_li = await api.search_ae_obj_v3({
|
||||
api_cfg,
|
||||
obj_type: 'event',
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// Inject header context for Auth but keep body context for Filtering
|
||||
headers: { 'x-account-id': for_obj_id },
|
||||
=======
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
// Pass account context via search query body instead of query params to avoid duplicate mapping
|
||||
>>>>>>> 63c633f5 (Fix(Events): Revert to URL-based account context for V3 Search)
|
||||
=======
|
||||
// Inject header context for Auth but keep body context for Filtering
|
||||
headers: { 'x-account-id': for_obj_id },
|
||||
>>>>>>> f77938c1 (Fix(Events): Isolate IDAA Search to V2 and Refine V3 Search Pattern)
|
||||
search_query,
|
||||
enabled,
|
||||
hidden,
|
||||
@@ -499,34 +471,10 @@ export async function qry_ae_obj_li__event({
|
||||
|
||||
if (!result_li) return [];
|
||||
|
||||
<<<<<<< HEAD
|
||||
const processed_obj_li = await process_ae_obj__event_props({
|
||||
obj_li: result_li,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
=======
|
||||
if (try_cache) {
|
||||
const processed_obj_li = await process_ae_obj__event_props({
|
||||
obj_li: result_li,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_events,
|
||||
table_name: 'event',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
}
|
||||
|
||||
// Client-side Filter Layer
|
||||
return result_li.filter((ev: any) => {
|
||||
if (qry_conference !== null && !!ev.conference !== !!qry_conference) return false;
|
||||
if (qry_physical !== null && !!ev.physical !== !!qry_physical) return false;
|
||||
if (qry_virtual !== null && !!ev.virtual !== !!qry_virtual) return false;
|
||||
if (qry_type !== null && ev.type !== qry_type) return false;
|
||||
<<<<<<< HEAD
|
||||
>>>>>>> ef26a01b (Fix(IDAA): Revert account_id body injection for Events V3 search)
|
||||
|
||||
if (try_cache) {
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
@@ -566,8 +514,6 @@ export async function qry_ae_obj_li__event({
|
||||
}
|
||||
|
||||
// Handle person ID filter
|
||||
=======
|
||||
>>>>>>> f77938c1 (Fix(Events): Isolate IDAA Search to V2 and Refine V3 Search Pattern)
|
||||
if (qry_person_id) {
|
||||
const match = (
|
||||
ev.external_person_id === qry_person_id ||
|
||||
@@ -578,106 +524,7 @@ export async function qry_ae_obj_li__event({
|
||||
);
|
||||
if (!match) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized search function for IDAA module using legacy V2 endpoints.
|
||||
* This is isolated to prevent V3 migration bugs from affecting Recovery Meetings.
|
||||
*/
|
||||
// Updated 2026-01-20
|
||||
export async function qry_ae_obj_li__event_v2({
|
||||
api_cfg,
|
||||
for_obj_type = 'account',
|
||||
for_obj_id,
|
||||
qry_str,
|
||||
qry_person_id = null,
|
||||
qry_conference = null,
|
||||
qry_physical = null,
|
||||
qry_virtual = null,
|
||||
qry_type = null,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
view = 'default',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = { start_datetime: 'DESC' } as const,
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type?: string;
|
||||
for_obj_id: string;
|
||||
qry_str?: string;
|
||||
qry_person_id?: string | null;
|
||||
qry_conference?: boolean | null;
|
||||
qry_physical?: boolean | null;
|
||||
qry_virtual?: boolean | null;
|
||||
qry_type?: string | null;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled';
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden';
|
||||
view?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: Record<string, 'ASC' | 'DESC'>;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) console.log('*** qry_ae_obj_li__event_v2() ***');
|
||||
|
||||
const params_json: any = { qry: { and: [] } };
|
||||
|
||||
if (qry_str) {
|
||||
// Use default_qry_str for searching as requested
|
||||
params_json.qry.and.push({ field: 'default_qry_str', op: 'like', value: qry_str });
|
||||
}
|
||||
|
||||
const result_li = await get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
obj_type: 'event',
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
enabled,
|
||||
hidden,
|
||||
limit: (qry_person_id || qry_conference !== null || qry_physical !== null || qry_virtual !== null || qry_type !== null) ? 500 : limit,
|
||||
offset,
|
||||
order_by_li,
|
||||
params_json,
|
||||
log_lvl
|
||||
});
|
||||
|
||||
if (!result_li) return [];
|
||||
|
||||
if (try_cache) {
|
||||
const processed_obj_li = await process_ae_obj__event_props({
|
||||
obj_li: result_li,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_events,
|
||||
table_name: 'event',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
}
|
||||
|
||||
// Client-side Filter Layer
|
||||
return result_li.filter((ev: any) => {
|
||||
if (qry_conference !== null && !!ev.conference !== !!qry_conference) return false;
|
||||
if (qry_physical !== null && !!ev.physical !== !!qry_physical) return false;
|
||||
if (qry_virtual !== null && !!ev.virtual !== !!qry_virtual) return false;
|
||||
if (qry_type !== null && ev.type !== qry_type) return false;
|
||||
if (qry_person_id) {
|
||||
return (
|
||||
ev.external_person_id === qry_person_id ||
|
||||
ev.poc_person_id === qry_person_id ||
|
||||
ev.poc_person_id_random === qry_person_id ||
|
||||
ev.poc_event_person_id === qry_person_id ||
|
||||
ev.poc_event_person_id_random === qry_person_id
|
||||
);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
</button>
|
||||
{:else}
|
||||
<!-- This checks if the currently logged in Novi user has a matching UUID or email address. -->
|
||||
{#if ($ae_loc.trusted_access && $ae_loc.edit_mode) || $lq__event_obj?.external_person_id === $idaa_loc.novi_uuid || $lq__event_obj?.contact_li_json[0].email === $idaa_loc.novi_email}
|
||||
{#if ($ae_loc.trusted_access && $ae_loc.edit_mode) || $lq__event_obj?.external_person_id === $idaa_loc.novi_uuid || ($lq__event_obj?.contact_li_json && $lq__event_obj?.contact_li_json[0]?.email === $idaa_loc.novi_email)}
|
||||
<button
|
||||
type="button"
|
||||
class="
|
||||
|
||||
Reference in New Issue
Block a user