Saving changes now that most things have been migrated to CRUD V3 and appear to be working. This still needs testing though.
This commit is contained in:
@@ -723,7 +723,7 @@ def sql_select(
|
|||||||
sql_search_qry = ''
|
sql_search_qry = ''
|
||||||
if search_query:
|
if search_query:
|
||||||
log.info('Creating partial SQL string for complex SearchQuery.')
|
log.info('Creating partial SQL string for complex SearchQuery.')
|
||||||
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields)
|
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields, table_name=table_name)
|
||||||
data = {**data, **data_search}
|
data = {**data, **data_search}
|
||||||
|
|
||||||
sql = text(
|
sql = text(
|
||||||
@@ -830,7 +830,7 @@ def sql_select(
|
|||||||
sql_search_qry = ''
|
sql_search_qry = ''
|
||||||
if search_query:
|
if search_query:
|
||||||
log.info('Creating partial SQL string for complex SearchQuery.')
|
log.info('Creating partial SQL string for complex SearchQuery.')
|
||||||
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields)
|
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields, table_name=table_name)
|
||||||
data = {**data, **data_search}
|
data = {**data, **data_search}
|
||||||
|
|
||||||
# # NOTE: Version 3 of the fulltext search
|
# # NOTE: Version 3 of the fulltext search
|
||||||
@@ -2052,7 +2052,7 @@ def sql_enable_part(table_name: str, enabled: str) -> bool|dict:
|
|||||||
sql = f'AND `{table_name}`.enable = false'
|
sql = f'AND `{table_name}`.enable = false'
|
||||||
enable = False
|
enable = False
|
||||||
elif enabled == 'all':
|
elif enabled == 'all':
|
||||||
sql = f'AND (`{table_name}`.enable = true OR `{table_name}`.enable = false OR `{table_name}`.enable IS NULL)'
|
sql = ''
|
||||||
enable = None
|
enable = None
|
||||||
log.debug(sql)
|
log.debug(sql)
|
||||||
|
|
||||||
@@ -2080,7 +2080,7 @@ def sql_hidden_part(table_name: str, hidden: str) -> bool|dict:
|
|||||||
sql = f'AND (`{table_name}`.hide = false OR `{table_name}`.hide IS NULL)'
|
sql = f'AND (`{table_name}`.hide = false OR `{table_name}`.hide IS NULL)'
|
||||||
hide = False
|
hide = False
|
||||||
elif hidden == 'all':
|
elif hidden == 'all':
|
||||||
sql = f'AND (`{table_name}`.hide = true OR `{table_name}`.hide = false OR `{table_name}`.hide IS NULL)'
|
sql = ''
|
||||||
hide = None
|
hide = None
|
||||||
log.debug(sql)
|
log.debug(sql)
|
||||||
|
|
||||||
@@ -2109,11 +2109,13 @@ def sql_limit_offset_part(limit: int, offset: int = 0) -> bool|str:
|
|||||||
# ### BEGIN ### API DB SQL Methods ### sql_search_qry_part() ###
|
# ### BEGIN ### API DB SQL Methods ### sql_search_qry_part() ###
|
||||||
# NEW 2026-01-02
|
# NEW 2026-01-02
|
||||||
# Updated to support complex POST-based searches with recursive logical grouping.
|
# Updated to support complex POST-based searches with recursive logical grouping.
|
||||||
|
# Updated 2026-01-06 to handle missing default_qry_str column gracefully.
|
||||||
@logger_reset
|
@logger_reset
|
||||||
def sql_search_qry_part(
|
def sql_search_qry_part(
|
||||||
search_query: Any, # SearchQuery model instance
|
search_query: Any, # SearchQuery model instance
|
||||||
searchable_fields: List[str]|None = None, # List of allowed fields
|
searchable_fields: List[str]|None = None, # List of allowed fields
|
||||||
max_depth: int = 5, # Maximum recursion depth
|
max_depth: int = 5, # Maximum recursion depth
|
||||||
|
table_name: str|None = None, # Target table for schema validation
|
||||||
) -> tuple[str, dict]:
|
) -> tuple[str, dict]:
|
||||||
"""
|
"""
|
||||||
Recursively builds a SQL WHERE clause from a SearchQuery model.
|
Recursively builds a SQL WHERE clause from a SearchQuery model.
|
||||||
@@ -2157,9 +2159,35 @@ def sql_search_qry_part(
|
|||||||
|
|
||||||
# Process 'query_string' (Standardized Full-Text Search)
|
# Process 'query_string' (Standardized Full-Text Search)
|
||||||
if hasattr(query_node, 'query_string') and query_node.query_string:
|
if hasattr(query_node, 'query_string') and query_node.query_string:
|
||||||
p_name = get_param_name()
|
if query_node.query_string == '%':
|
||||||
clauses.append(f"MATCH( default_qry_str ) AGAINST( :{p_name} IN BOOLEAN MODE )")
|
# Wildcard: Skip filtering for this part
|
||||||
data[p_name] = query_node.query_string
|
pass
|
||||||
|
else:
|
||||||
|
# Check if default_qry_str exists in this table/view
|
||||||
|
use_match = True
|
||||||
|
if table_name:
|
||||||
|
try:
|
||||||
|
db.execute(text(f"SELECT default_qry_str FROM `{table_name}` LIMIT 0"))
|
||||||
|
except:
|
||||||
|
use_match = False
|
||||||
|
else:
|
||||||
|
use_match = False # Safe default if no table_name
|
||||||
|
|
||||||
|
if use_match:
|
||||||
|
p_name = get_param_name()
|
||||||
|
clauses.append(f"MATCH( default_qry_str ) AGAINST( :{p_name} IN BOOLEAN MODE )")
|
||||||
|
data[p_name] = query_node.query_string
|
||||||
|
elif searchable_fields:
|
||||||
|
# Fallback: OR LIKE across all searchable fields
|
||||||
|
like_clauses = []
|
||||||
|
for field in searchable_fields:
|
||||||
|
# Skip internal/numeric fields for full-text-like search
|
||||||
|
if not any(x in field for x in ['_id', 'enable', 'hide', 'priority', 'sort', 'group', 'created_on', 'updated_on']):
|
||||||
|
f_p_name = get_param_name()
|
||||||
|
like_clauses.append(f"`{field}` LIKE :{f_p_name}")
|
||||||
|
data[f_p_name] = f"%{query_node.query_string}%"
|
||||||
|
if like_clauses:
|
||||||
|
clauses.append(f"({' OR '.join(like_clauses)})")
|
||||||
|
|
||||||
# Process 'and' filters
|
# Process 'and' filters
|
||||||
if hasattr(query_node, 'and_filters') and query_node.and_filters:
|
if hasattr(query_node, 'and_filters') and query_node.and_filters:
|
||||||
|
|||||||
@@ -95,4 +95,5 @@ class Account_Base(BaseModel):
|
|||||||
class Config:
|
class Config:
|
||||||
underscore_attrs_are_private = True
|
underscore_attrs_are_private = True
|
||||||
fields = base_fields
|
fields = base_fields
|
||||||
|
allow_population_by_field_name = True
|
||||||
# ### END ### API Account Models ### Account_Base() ###
|
# ### END ### API Account Models ### Account_Base() ###
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from app.models.event_models import *
|
from app.models.event_models import *
|
||||||
from app.models.event_file_models import *
|
from app.models.event_file_models import *
|
||||||
from app.models.event_device_models import *
|
from app.models.event_device_models import *
|
||||||
|
from app.models.event_cfg_models import *
|
||||||
|
|
||||||
events_general_obj_li = {
|
events_general_obj_li = {
|
||||||
'event': {
|
'event': {
|
||||||
@@ -91,4 +92,22 @@ events_general_obj_li = {
|
|||||||
'enable', 'hide', 'priority', 'group', 'notes', 'created_on', 'updated_on'
|
'enable', 'hide', 'priority', 'group', 'notes', 'created_on', 'updated_on'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
'event_cfg': {
|
||||||
|
'tbl': 'event_cfg',
|
||||||
|
'tbl_default': 'event_cfg',
|
||||||
|
'tbl_update': 'event_cfg',
|
||||||
|
'mdl': Event_Cfg_Base,
|
||||||
|
'mdl_default': Event_Cfg_Base,
|
||||||
|
'mdl_in': Event_Cfg_Base,
|
||||||
|
'mdl_out': Event_Cfg_Base,
|
||||||
|
# Legacy V2 keys:
|
||||||
|
'table_name': 'event_cfg',
|
||||||
|
'tbl_name_update': 'event_cfg',
|
||||||
|
'base_name': Event_Cfg_Base,
|
||||||
|
# V3 Search Security:
|
||||||
|
'searchable_fields': [
|
||||||
|
'event_cfg_id_random', 'event_id_random', 'enable', 'conference',
|
||||||
|
'status', 'hide', 'priority', 'group', 'notes'
|
||||||
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from app.models.event_badge_template_models import *
|
|||||||
from app.models.event_person_models import *
|
from app.models.event_person_models import *
|
||||||
from app.models.event_person_tracking_models import *
|
from app.models.event_person_tracking_models import *
|
||||||
from app.models.event_registration_models import *
|
from app.models.event_registration_models import *
|
||||||
|
from app.models.event_person_profile_models import *
|
||||||
|
|
||||||
events_registration_obj_li = {
|
events_registration_obj_li = {
|
||||||
'event_badge': {
|
'event_badge': {
|
||||||
@@ -66,6 +67,28 @@ events_registration_obj_li = {
|
|||||||
'notes', 'created_on', 'updated_on'
|
'notes', 'created_on', 'updated_on'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
'event_person_profile': {
|
||||||
|
'tbl': 'event_person_profile',
|
||||||
|
'tbl_default': 'v_event_person_profile',
|
||||||
|
'tbl_update': 'event_person_profile',
|
||||||
|
'mdl': Event_Person_Profile_Base,
|
||||||
|
'mdl_default': Event_Person_Profile_Base,
|
||||||
|
'mdl_in': Event_Person_Profile_Base,
|
||||||
|
'mdl_out': Event_Person_Profile_Base,
|
||||||
|
# Legacy V2 keys:
|
||||||
|
'table_name': 'v_event_person_profile',
|
||||||
|
'tbl_name_update': 'event_person_profile',
|
||||||
|
'base_name': Event_Person_Profile_Base,
|
||||||
|
# V3 Search Security:
|
||||||
|
'searchable_fields': [
|
||||||
|
'event_person_profile_id_random', 'account_id_random',
|
||||||
|
'contact_id_random', 'event_id_random', 'event_person_id_random',
|
||||||
|
'organization_id_random', 'pronouns', 'informal_name', 'given_name',
|
||||||
|
'family_name', 'professional_title', 'full_name', 'affiliations',
|
||||||
|
'email', 'enable', 'priority', 'group', 'notes', 'created_on',
|
||||||
|
'updated_on'
|
||||||
|
],
|
||||||
|
},
|
||||||
'event_person_tracking': {
|
'event_person_tracking': {
|
||||||
'tbl': 'event_person_tracking',
|
'tbl': 'event_person_tracking',
|
||||||
'tbl_default': 'v_event_person_tracking',
|
'tbl_default': 'v_event_person_tracking',
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from app.models.order_models import *
|
from app.models.order_models import *
|
||||||
from app.models.order_cart_models import *
|
from app.models.order_cart_models import *
|
||||||
|
from app.models.product_models import *
|
||||||
|
from app.models.order_cfg_models import *
|
||||||
|
|
||||||
order_obj_li = {
|
order_obj_li = {
|
||||||
'order': {
|
'order': {
|
||||||
@@ -73,4 +75,42 @@ order_obj_li = {
|
|||||||
'enable', 'hide', 'priority', 'group', 'created_on', 'updated_on'
|
'enable', 'hide', 'priority', 'group', 'created_on', 'updated_on'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
'product': {
|
||||||
|
'tbl': 'product',
|
||||||
|
'tbl_default': 'v_product',
|
||||||
|
'tbl_update': 'product',
|
||||||
|
'mdl': Product_Base,
|
||||||
|
'mdl_default': Product_Base,
|
||||||
|
'mdl_in': Product_Base,
|
||||||
|
'mdl_out': Product_Base,
|
||||||
|
# Legacy V2 keys:
|
||||||
|
'table_name': 'v_product',
|
||||||
|
'tbl_name_update': 'product',
|
||||||
|
'base_name': Product_Base,
|
||||||
|
# V3 Search Security:
|
||||||
|
'searchable_fields': [
|
||||||
|
'product_id_random', 'account_id_random', 'for_type', 'for_id_random',
|
||||||
|
'type_code', 'type_name', 'name', 'description', 'unit_price',
|
||||||
|
'tax_rate', 'vat_rate', 'max_quantity', 'recurring', 'enable',
|
||||||
|
'hide', 'priority', 'group', 'created_on', 'updated_on'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'order_cfg': {
|
||||||
|
'tbl': 'order_cfg',
|
||||||
|
'tbl_default': 'order_cfg',
|
||||||
|
'tbl_update': 'order_cfg',
|
||||||
|
'mdl': Order_Cfg_Base,
|
||||||
|
'mdl_default': Order_Cfg_Base,
|
||||||
|
'mdl_in': Order_Cfg_Base,
|
||||||
|
'mdl_out': Order_Cfg_Base,
|
||||||
|
# Legacy V2 keys:
|
||||||
|
'table_name': 'order_cfg',
|
||||||
|
'tbl_name_update': 'order_cfg',
|
||||||
|
'base_name': Order_Cfg_Base,
|
||||||
|
# V3 Search Security:
|
||||||
|
'searchable_fields': [
|
||||||
|
'account_id_random', 'account_name', 'default_no_reply_email',
|
||||||
|
'confirm_email'
|
||||||
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user