From 702357910af3518b65072702f81b444e46320397 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 23 Jun 2023 17:48:31 -0400 Subject: [PATCH] Work on abstract submissions and related grants --- app/main.py | 10 +- app/methods/grant_methods.py | 423 ++++++++++++++++++++++++++++ app/models/event_abstract_models.py | 1 + app/models/grant_models.py | 212 ++++++++++++++ app/routers/grant.py | 246 ++++++++++++++++ 5 files changed, 889 insertions(+), 3 deletions(-) create mode 100644 app/methods/grant_methods.py create mode 100644 app/models/grant_models.py create mode 100644 app/routers/grant.py diff --git a/app/main.py b/app/main.py index 1ace2cf..0352d08 100644 --- a/app/main.py +++ b/app/main.py @@ -18,14 +18,14 @@ from . import config from app.log import log, logging # Import the routers here first: -from app.routers import aether_cfg, api_crud, api, importing, sql, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, data_store, event, event_abstract, event_badge, event_badge_importing, event_badge_template, event_device, event_exhibit, event_exhibit_tracking, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, fundraising, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, qr, site, site_domain, user, websockets_redis, e_confex, e_cvent, c_idaa, e_impexium, e_stripe +from app.routers import aether_cfg, api_crud, api, importing, sql, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, data_store, event, event_abstract, event_badge, event_badge_importing, event_badge_template, event_device, event_exhibit, event_exhibit_tracking, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, fundraising, grant, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, qr, site, site_domain, user, websockets_redis, e_confex, e_cvent, c_idaa, e_impexium, e_stripe # from app.routers import aether_cfg, sql from app.db_sql import sql_select # , sql_connect -print('### **** *** ** * The Aether API v5 using FastAPI is loading... * ** *** **** ###') +print('### **** *** ** * The Aether API v4 using FastAPI is loading... * ** *** **** ###') #log = logging.getLogger('root') @@ -38,7 +38,7 @@ print('### **** *** ** * The Aether API v5 using FastAPI is loading... * ** *** app = FastAPI( # debug = True, title = 'Aether API', - description = 'One Sky IT\'s Aether API v5 using FastAPI.', + description = 'One Sky IT\'s Aether API v4 using FastAPI.', version = '4.9.0', operationsSorter = 'method', ) @@ -262,6 +262,10 @@ app.include_router( fundraising.router, tags=['Fundraising'], ) +app.include_router( + grant.router, + tags=['Grant'], +) app.include_router( hosted_file.router, prefix='/hosted_file', diff --git a/app/methods/grant_methods.py b/app/methods/grant_methods.py new file mode 100644 index 0000000..4d9a4eb --- /dev/null +++ b/app/methods/grant_methods.py @@ -0,0 +1,423 @@ +import datetime, json + +from typing import Dict, List, Optional, Set, Union +from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator + +from app.db_sql import redis_lookup_id_random, sql_delete, sql_insert, sql_select, sql_update, sql_enable_part, sql_limit_offset_part +from app.lib_general import log, logging, logger_reset + +from app.models.common_field_schema import default_num_bytes +from app.models.grant_models import Grant_Ext, Grant_In + + +# ### BEGIN ### API Grant Methods ### load_grant_obj() ### +# Updated 2023-06-23 +@logger_reset +def load_grant_obj( + grant_id: int|str, + + enabled: str = 'enabled', # enabled, disabled, all + hidden: str = 'not_hidden', # hidden, not_hidden, all + + inc_event_abstract: bool = False, + + limit: int = 1500, + offset: int = 0, + by_alias: bool = True, + exclude_unset: bool = True, + model_as_dict: bool = False, + ) -> Grant_Ext|dict|bool: + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + # if grant_id := redis_lookup_id_random(record_id_random=grant_id, table_name='grant'): pass + # else: return False + + if grant_rec := sql_select(table_name='v_grant', record_id=grant_id): pass + else: return False + + try: + grant_obj = Grant_Ext(**grant_rec) + log.debug(grant_obj) + except ValidationError as e: + log.error(e.json()) + return False + + # Updated 2023-06-23 + if inc_event_abstract: + # log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.info('Need to include event abstract...') + + if event_abstract_obj := load_event_abstract_obj( + event_abstract_id = grant_obj.event_abstract_id, + enabled = enabled, + ): + log.debug(event_abstract_obj) + grant_obj.event_abstract = event_abstract_obj + else: + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(event_abstract_obj) + grant_obj.event_abstract = None + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + + if model_as_dict: + return grant_obj.dict(by_alias=by_alias, exclude_unset=exclude_unset) # pylint: disable=no-member + else: + return grant_obj +# ### END ### API Grant Methods ### load_grant_obj() ### + + +# ### BEGIN ### API Grant Methods ### get_grant_rec_list() ### +# Updated 2023-06-23 +@logger_reset +def get_grant_rec_list( + account_id: None|str = None, + event_id: None|str = None, + + grant_type_code: str = None, # not sure yet + + hidden: str = 'all', # hidden, not_hidden, all + + enabled: str = 'enabled', # enabled, disabled, all + limit: int = 250, + offset: int = 0, + ) -> list|bool: + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if not account_id and not event_id: return False + + if account_id := redis_lookup_id_random(record_id_random=account_id, table_name='account'): pass + elif account_id is None: pass + else: return False + + if event_id := redis_lookup_id_random(record_id_random=event_id, table_name='event'): pass + elif event_id is None: pass + else: return False + + data = {} + if account_id: + data['account_id'] = account_id + sql_account_id = f'`grant`.account_id = :account_id' + else: sql_account_id = '1=1' + + if event_id: + data['event_id'] = event_id + sql_event_id = f'AND `grant`.event_id = :event_id' + else: sql_event_id = '' + + # if abstract_type_code: + # data['abstract_type_code'] = abstract_type_code + # sql_abstract_type_code = f'AND `grant`.abstract_type_code = :abstract_type_code' + # else: sql_abstract_type_code = '' + + if hidden in ['hidden', 'not_hidden', 'all']: + log.info(f'Creating partial SQL string for "hidden" check. Printed: {hidden}') + if hidden == 'not_hidden': + sql_hidden = f'AND (`grant`.hide IS NULL OR `grant`.hide = FALSE)' + elif hidden == 'hidden': + sql_hidden = f'AND `grant`.hide = TRUE' + elif hidden == 'all': + sql_hidden = f'AND (`grant`.hide IS NULL OR `grant`.hide IS NOT NULL)' + log.debug(sql_hidden) + else: sql_hidden = '' + + sql_enabled, data['enable'] = sql_enable_part(table_name='grant', enabled=enabled) # Reasonably safe return str and bool + sql_limit = sql_limit_offset_part(limit=limit, offset=offset) # Reasonably safe return str + + sql = f""" + SELECT `grant`.id AS 'grant_id', `grant`.id_random AS 'grant_id_random' + FROM `v_grant` AS `grant` + WHERE + {sql_account_id} + {sql_event_id} + {sql_hidden} + {sql_enabled} + ORDER BY grant.priority DESC, grant.sort DESC, grant.name ASC, `grant`.created_on DESC, `grant`.updated_on DESC + {sql_limit}; + """ + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(sql) + + if grant_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + grant_rec_li = grant_rec_li_result + else: # [] or False + grant_rec_li = grant_rec_li_result + + log.debug(grant_rec_li_result) + + return grant_rec_li +# ### END ### API Grant Methods ### get_grant_rec_list() ### + + +# # ### BEGIN ### API Grant Methods ### create_update_grant_obj() ### +# # Updated 2023-03-22 +# @logger_reset +# def create_update_grant_obj( +# grant_obj: Grant_In, +# grant_id: int = None, +# event_id: int = None, +# event_person_id: int = None, + +# create_sub_obj: bool = False, +# fail_any: bool = False, # Fail if any thing goes wrong for sub objects +# return_outline: bool = False, +# ) -> int|bool: +# log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# log.debug(locals()) + +# log.info('Checking requirements...') +# if grant_id: +# log.info(f'Got: grant_id={grant_id}; Update existing Grant') +# grant_obj.id = grant_id +# elif event_id and event_person_id: +# log.info(f'Got: event_id={event_id}; event_person_id={event_person_id}; Create Grant') +# grant_obj.event_id = event_id +# grant_obj.event_person_id = event_person_id +# else: +# return False + +# log.debug(type(grant_obj)) +# log.debug(grant_obj +# ) + +# grant_dict = grant_obj.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'event_file_list', 'event_person', 'event_person_list', 'event_presenter_list', 'created_on', 'updated_on'}) + +# # log.debug(type(grant_dict.get('topics_json', None))) +# # if 'topics_json' in grant_dict and (isinstance(grant_dict['topics_json'], dict) or isinstance(grant_dict['topics_json'], list)): +# # log.debug('Need to convert to JSON string') +# # grant_dict['topics_json'] = json.dumps(grant_dict['topics_json']) +# # log.debug(grant_dict) + + +# if grant_id: +# if grant_dict_up_result := sql_update(data=grant_dict, table_name='grant', rm_id_random=True): +# log.info(f'Grant updated. grant_id={grant_id}') +# pass +# else: +# log.warning(f'Grant not updated. grant_id={grant_id}') +# log.debug(grant_dict_up_result) +# return False +# log.debug(grant_dict_up_result) +# else: +# if grant_dict_in_result := sql_insert(data=grant_dict, table_name='grant', rm_id_random=True, id_random_length=None): +# log.info(f'Grant created. grant_id={grant_dict_in_result}') +# else: +# log.warning(f'Grant not created.') +# log.debug(grant_dict_in_result) +# return False +# log.debug(grant_dict_in_result) + +# grant_id = grant_dict_in_result # False, None, integer + +# grant_outline = {} +# grant_outline['event_id'] = event_id +# grant_outline['grant_id'] = grant_id +# grant_outline['event_person_id'] = event_person_id +# # grant_outline['event_file_count'] = event_file_count + +# if return_outline: +# log.debug(f'Returning the Grant Outline: {grant_outline}') +# return grant_outline +# else: +# log.debug(f'Returning the Grant ID: {grant_id}') +# return grant_id +# # ### END ### API Grant Methods ### create_update_grant_obj() ### + + + +# # ### BEGIN ### API Grant Methods ### create_update_grant_obj_old() ### +# # Updated 2023-03-20 +# @logger_reset +# def create_update_grant_obj_old( +# grant_dict_obj: Grant_In|dict, +# grant_id: int|str = None, +# event_id: int|str = None, +# event_person_id: int|str = None, +# create_sub_obj: bool = False, +# fail_any: bool = False, # Fail if any thing goes wrong for sub objects +# return_outline: bool = False, +# ) -> int|bool: +# log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# log.debug(locals()) + +# log.info('Checking requirements...') +# if grant_id: +# log.info(f'Grant ID passed. Update existing Grant. Grant ID: {grant_id}') + +# if grant_id := redis_lookup_id_random(record_id_random=grant_id, table_name='grant'): pass +# else: +# log.error('Grant ID passed but is invalid. Failed requirement.') +# return False + +# if event_id := redis_lookup_id_random(record_id_random=event_id, table_name='event'): +# log.info(f'Event ID: {event_id}') +# elif event_id is None: +# log.error('Missing Event ID. Not required. Ignoring.') +# log.info(f'Event ID: {event_id}') +# else: +# log.error('Invalid Event ID passed. Not required. But not ignoring since it is likely invalid.') +# log.info(f'Event ID: {event_id}') +# return False +# else: +# log.info('No Grant ID passed. Create new Grant. Required: Event ID') + +# if event_id := redis_lookup_id_random(record_id_random=event_id, table_name='event'): +# log.info(f'Event ID: {event_id}') +# elif event_id is None: +# log.error('Missing Event ID. Failed requirement.') +# log.info(f'Event ID: {event_id}') +# return False +# else: +# log.error('Invalid Event ID passed. Failed requirement.') +# log.info(f'Event ID: {event_id}') +# return False +# # else: +# # log.error('Missing or invalid Event ID passed. Failed requirement.') +# # log.info(f'Event ID: {event_id}') +# # return False + +# log.debug(type(grant_dict_obj)) +# if isinstance(grant_dict_obj, dict): +# grant_dict = grant_dict_obj +# if grant_id: +# grant_dict['grant_id'] = grant_id +# if event_id: +# grant_dict['event_id'] = event_id +# if event_person_id: +# grant_dict['event_person_id'] = event_person_id +# try: +# grant_obj = Grant_In(**grant_dict) +# log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# log.debug(grant_obj) +# except ValidationError as e: +# log.error(e.json()) +# return False +# else: +# grant_obj = grant_dict_obj +# if grant_id: +# # NOTE: Can't update the ID alias if it was never set. +# grant_obj.id = grant_id +# if event_id: +# grant_obj.event_id = event_id +# if event_person_id: +# grant_obj.event_person_id = event_person_id + +# grant_dict = grant_obj.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'event_person', 'event_person_list', 'created_on', 'updated_on'}) + +# if grant_id: +# if grant_dict_up_result := sql_update(data=grant_dict, table_name='grant', rm_id_random=True): pass +# else: +# log.warning(f'Grant not updated. Grant ID: {grant_id}') +# log.debug(grant_dict_up_result) +# return False +# log.debug(grant_dict_up_result) +# else: +# if grant_dict_in_result := sql_insert(data=grant_dict, table_name='grant', rm_id_random=True, id_random_length=None): pass +# else: +# log.warning(f'Grant not created.') +# log.debug(grant_dict_in_result) +# return False +# log.debug(grant_dict_in_result) + +# grant_id = grant_dict_in_result + +# grant_outline = {} +# grant_outline['event_id'] = event_id +# grant_outline['grant_id'] = grant_id +# grant_outline['event_person_id'] = event_person_id +# # grant_outline['event_presenter_list'] = [] + +# # if grant_obj.event_presenter_list and isinstance(grant_obj.event_presenter_list, list): +# # log.info(f'Event Presenter List was found. Loop through and create a new Event Presenter for each and link them to the new Grant. Grant ID: {grant_id}') +# # for event_presenter_obj in grant_obj.event_presenter_list: +# # # NOTE: Use object model version because of better type checking and validations +# # log.debug(event_presenter_obj) +# # if event_presenter_id := event_presenter_obj.id: pass +# # else: event_presenter_id = None +# # # event_presenter_obj.event_id = event_id +# # # event_presenter_obj.event_session_id = event_session_id +# # create_update_event_presenter_obj_result = create_update_event_presenter_obj_v4( +# # event_presenter_dict_obj = event_presenter_obj, +# # event_presenter_id = event_presenter_id, +# # event_id = event_id, +# # event_session_id = event_session_id, +# # grant_id = grant_id, +# # fail_any = fail_any, +# # return_outline = return_outline, +# # ) +# # if isinstance(create_update_event_presenter_obj_result, int): +# # event_presenter_id = create_update_event_presenter_obj_result +# # elif create_update_event_presenter_obj_result == True: pass +# # else: +# # log.warning(f'Create or Update failed while trying create_update_event_presenter_obj_v4(): {create_update_event_presenter_obj_result}') +# # event_presenter_id = None + +# # grant_outline['event_presenter_id'] = event_presenter_id + +# if return_outline: +# log.debug(f'Returning the Grant Outline: {grant_outline}') +# return grant_outline +# else: +# log.debug(f'Returning the Grant ID: {grant_id}') +# return grant_id +# # ### END ### API Grant Methods ### create_update_grant_obj_old() ### + + +# # ### BEGIN ### API Grant Methods ### remove_grant_obj() ### +# # Updated 2023-03-22 +# @logger_reset +# def remove_grant_obj( +# grant_id: int, + +# method: None|str = None, + +# log_lvl: int = logging.DEBUG, # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# ) -> bool|None: +# log.setLevel(log_lvl) + +# if method is None or method == 'disable': +# data = {'enable': False} + +# if grant_dict_up_result := sql_update( +# table_name = 'grant', +# record_id = grant_id, +# data = data, +# log_lvl = log_lvl, +# ): +# log.info(f'Grant was disabled.') +# return True +# else: +# log.warning(f'Grant not disabled.') +# return grant_dict_up_result # False or None +# elif method == 'delete': +# if grant_dict_del_result := sql_delete( +# table_name = 'grant', +# record_id = grant_id, +# log_lvl = log_lvl, +# ): +# log.info(f'Grant was deleted.') +# return True +# else: +# log.warning(f'Grant not deleted.') +# return grant_dict_del_result # False or None +# elif method == 'hide': +# data = {'hide': True} + +# if grant_dict_up_result := sql_update( +# table_name = 'grant', +# record_id = grant_id, +# data = data, +# log_lvl = log_lvl, +# ): +# log.info(f'Grant was hidden.') +# return True +# else: +# log.warning(f'Grant not hidden.') +# return grant_dict_up_result # False or None +# else: +# log.error('We should not be here. Something went wrong in remove_grant_obj()!') +# return False + + +# # ### END ### API Grant Methods ### remove_grant_obj() ### diff --git a/app/models/event_abstract_models.py b/app/models/event_abstract_models.py index 3f3ac8e..4f8a849 100644 --- a/app/models/event_abstract_models.py +++ b/app/models/event_abstract_models.py @@ -188,6 +188,7 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base): passcode: Optional[str] + grant_id: Optional[int] grant_code: Optional[str] grant_type_code: Optional[str] grant_json: Optional[Union[Json, None]] diff --git a/app/models/grant_models.py b/app/models/grant_models.py new file mode 100644 index 0000000..03086af --- /dev/null +++ b/app/models/grant_models.py @@ -0,0 +1,212 @@ +import datetime, pytz + +from typing import Dict, List, Optional, Set, Union +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator + +from app.db_sql import redis_lookup_id_random +from app.lib_general import log, logging + +from app.models.common_field_schema import base_fields, default_num_bytes + +from app.models.core_object_models import Core_Std_Obj_Base + + +# ### BEGIN ### API Grant Models ### Grant_Base() ### +# Update 2023-06-23 +class Grant_Base(BaseModel): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + id_random: Optional[str] = Field( + # **base_fields['grant_id_random'], + alias = 'grant_id_random', + ) + id: Optional[int] = Field( + alias = 'grant_id' + ) + + account_id_random: Optional[str] + account_id: Optional[int] + + event_id_random: Optional[str] + event_id: Optional[int] + + event_abstract_id_random: Optional[str] + event_abstract_id: Optional[int] + + # event_person_id_random: Optional[str] # This is the primary person/submitter + # event_person_id: Optional[int] + + for_type: Optional[str] + for_id: Optional[int] + + external_id: Optional[str] + code: Optional[str] + + name: Optional[str] + description: Optional[str] + + organization: Optional[str] + state_province_name: Optional[str] + + pi_given_name: Optional[str] + pi_middle_name: Optional[str] + pi_family_name: Optional[str] + pi_email: Optional[str] + pi_affiliations: Optional[str] + + # passcode: Optional[str] # = '7777777' + + # json: Optional[str] # "json" is reserved; need to change field name? json_str? + json_str: Optional[Union[Json, None]] = Field( + alias = 'json', + ) + text: Optional[str] + + enable: Optional[bool] + hide: Optional[bool] + priority: Optional[bool] + sort: Optional[int] + group: Optional[str] + + notes: Optional[str] + + created_on: Optional[datetime.datetime] = None + updated_on: Optional[datetime.datetime] = None + + # Including other related objects + # event_abstract: Optional[Event_Abstract_Base] + event_abstract: Optional[dict] + + _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + + @validator('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('id_random'): + return redis_lookup_id_random(record_id_random=id_random, table_name='grant') + return None + + @validator('account_id', always=True) + def account_id_lookup(cls, v, values, **kwargs): + if isinstance(v, int) and v > 0: return v + elif id_random := values.get('account_id_random'): + return redis_lookup_id_random(record_id_random=id_random, table_name='account') + 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_abstract_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('event_abstract_id_random'): + return redis_lookup_id_random(record_id_random=id_random, table_name='event_abstract') + return None + + class Config: + underscore_attrs_are_private = True + allow_population_by_field_name = True + fields = base_fields +# ### END ### API Grant Models ### Grant_Base() ### + + + +# ### BEGIN ### API Grant Models ### Grant_Base() ### +# Update 2023-06-23 +class Grant_Base_New(Core_Std_Obj_Base): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + id_random: Optional[str] = Field( + alias = 'grant_id_random', + ) + + account_id_random: Optional[str] + account_id: Optional[int] + + event_id_random: Optional[str] + event_id: Optional[int] + + event_abstract_id: Optional[int] + + for_type: Optional[str] + for_id: Optional[int] + + external_id: Optional[str] + code: Optional[str] + + # type_code: Optional[str] + + description: Optional[str] + text: Optional[str] # Actual grant text + + organization: Optional[str] + state_province_name: Optional[str] + + pi_given_name: Optional[str] + pi_middle_name: Optional[str] + pi_family_name: Optional[str] + pi_email: Optional[str] + pi_affiliations: Optional[str] + + # passcode: Optional[str] + + class Config: + underscore_attrs_are_private = True + allow_population_by_field_name = True + fields = base_fields +# ### END ### API Grant Models ### Grant_Base() ### + + +# ### BEGIN ### API Grant Models ### Grant_In() ### +# Update 2023-06-23 +class Grant_In(Grant_Base_New): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + id: Optional[int] = Field( + alias = 'grant_id' + ) + + account_id: Optional[int] + event_id: Optional[int] + event_abstract_id: Optional[int] + + @validator('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('id_random'): + return redis_lookup_id_random(record_id_random=id_random, table_name='grant') + 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_abstract_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('event_abstract_id_random'): + return redis_lookup_id_random(record_id_random=id_random, table_name='event_abstract') + return None +# ### END ### API Grant Models ### Grant_In() ### + + +# ### BEGIN ### API Grant Models ### Grant_Ext() ### +# Update 2023-06-23 +class Grant_Ext(Grant_Base_New): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + # Including other related objects + # event_abstract: Optional[Event_Abstract_Base] + event_abstract: Optional[dict] +# ### END ### API Grant Models ### Grant_Ext() ### diff --git a/app/routers/grant.py b/app/routers/grant.py new file mode 100644 index 0000000..89eedb1 --- /dev/null +++ b/app/routers/grant.py @@ -0,0 +1,246 @@ +import datetime, json +from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, Response, status +from pydantic import BaseModel, EmailStr, Field +from typing import Dict, List, Optional, Set, Union + +from app.lib_general import log, logging, common_route_params, Common_Route_Params +from app.config import settings +from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, get_id_random, redis_lookup_id_random + +from app.routers.api_crud import delete_obj_template, get_obj_template, get_obj_li_template, patch_obj_template, post_obj_template + +from app.methods.grant_methods import load_grant_obj, get_grant_rec_list +# from app.methods.grant_methods import create_update_grant_obj, load_grant_obj, get_grant_rec_list, remove_grant_obj + +from app.models.grant_models import Grant_In +from app.models.response_models import Resp_Body_Base, mk_resp + + +router = APIRouter() + + +# # ### BEGIN ### API Grant ### post_grant_obj() ### +# # Updated 2023-03-22 +# @router.post('/grant', response_model=Resp_Body_Base) +# async def post_grant_obj( +# grant_obj: Grant_In, +# # account_id: str = Query(..., min_length=11, max_length=22), +# event_id: str = Query(..., min_length=11, max_length=22), + +# return_obj: bool = False, +# inc_event_abstract: bool = False, + +# commons: Common_Route_Params = Depends(common_route_params), +# ): +# log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# log.debug(locals()) + +# if event_id := redis_lookup_id_random(record_id_random=event_id, table_name='event'): pass +# else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The Event ID was invalid or not found.') + +# # There should probably be a check for the event ID before calling the create function? +# if create_grant_obj_result := create_update_grant_obj( +# grant_obj = grant_obj, +# account_id = commons.account_id, +# event_id = event_id, + +# return_outline = False, +# ): pass +# else: return mk_resp(data=False, status_code=400, response=commons.response, status_message='The grant was not created. Check the field names and data types.') + +# if isinstance(create_grant_obj_result, int): +# grant_id = create_grant_obj_result +# if return_obj: +# if load_grant_obj_result := load_grant_obj( +# grant_id = grant_id, +# inc_event_file_list = inc_event_file_list, +# inc_event_person = inc_event_person, +# inc_event_presentation_list = inc_event_presentation_list, +# inc_event_presenter_list = inc_event_presenter_list, +# ): +# data = load_grant_obj_result +# else: +# data = False +# else: +# grant_id = grant_id +# grant_id_random = get_id_random(record_id=grant_id, table_name='grant') +# data = {} +# data['grant_id'] = grant_id +# data['grant_id_random'] = grant_id_random +# return mk_resp(data=data, response=commons.response, status_message='The grant was created.') +# else: +# return mk_resp(data=False, status_code=400, response=commons.response, status_message='The result from trying to create an grant was unexpected.') +# # ### END ### API Grant ### post_grant_obj() ### + + +# # ### BEGIN ### API Grant ### patch_grant_obj() ### +# # Updated 2023-03-22 +# @router.patch('/grant/{grant_id}', response_model=Resp_Body_Base) +# async def patch_grant_obj( +# grant_obj: Grant_In, +# grant_id: str = Query(..., min_length=11, max_length=22), + +# return_obj: bool = True, +# inc_event_abstract: bool = False, + +# commons: Common_Route_Params = Depends(common_route_params), +# ): +# log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# log.debug(locals()) + +# if grant_id := redis_lookup_id_random(record_id_random=grant_id, table_name='grant'): pass +# else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The Grant ID was invalid or not found.') + +# if update_grant_obj_result := create_update_grant_obj( +# grant_obj = grant_obj, +# grant_id = grant_id, +# return_outline = False, +# ): pass +# else: return mk_resp(data=False, status_code=400, response=commons.response, status_message='The grant was not created. Check the field names and data types.') + +# if update_grant_obj_result: +# if return_obj: +# if load_grant_obj_result := load_grant_obj( +# grant_id = grant_id, +# inc_event_abstract = inc_event_abstract, +# ): +# data = load_grant_obj_result +# else: +# data = False +# else: +# grant_id_random = get_id_random(record_id=grant_id, table_name='grant') +# data = {} +# data['grant_id'] = grant_id +# data['grant_id_random'] = grant_id_random +# return mk_resp(data=data, response=commons.response, status_message='The grant was created or updated.') +# else: +# return mk_resp(data=False, status_code=400, response=commons.response, status_message='The result from trying to create an grant was unexpected.') +# # ### END ### API Grant ### patch_grant_obj() ### + + +# ### BEGIN ### API Grant ### get_grant_obj() ### +# Updated 2023-03-22 +@router.get('/grant/{grant_id}', response_model=Resp_Body_Base) +async def get_grant_obj( + grant_id: str = Query(..., min_length=11, max_length=22), + + inc_event_abstract: bool = False, + + hidden: str = 'not_hidden', # hidden, not_hidden, all + + commons: Common_Route_Params = Depends(common_route_params), + ): + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + # time.sleep(.5) + + # ### SECTION ### Secondary data validation + grant_id_random = grant_id # This is used later for the response data + if grant_id := redis_lookup_id_random(record_id_random=grant_id, table_name='grant'): pass + else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The Grant ID was invalid or not found.') + + if grant_obj_result := load_grant_obj( + grant_id = grant_id, + + enabled = commons.enabled, + hidden = hidden, # hidden, not_hidden, all + + inc_event_abstract = inc_event_abstract, + ): + log.info('Loading successful. Returning result') + log.debug(grant_obj_result) + return mk_resp(data=grant_obj_result, response=commons.response) # Success + elif isinstance(grant_obj_result, list) or grant_obj_result is None: # Empty list or None + log.info('No results') + return mk_resp(data=None, status_code=404, response=commons.response) # Not Found + else: + log.warning('Likely bad request') + return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request +# ### END ### API Grant ### get_grant_obj() ### + + +# ### BEGIN ### API Grant ### get_event_id_grant_obj_li() ### +# Updated 2023-06-23 +@router.get('/event/{event_id}/grant/list', response_model=Resp_Body_Base) +async def get_event_id_grant_obj_li( + event_id: str = Query(..., min_length=11, max_length=22), + + inc_event_abstract: bool = False, + + hidden: str = 'not_hidden', # hidden, not_hidden, all + + commons: Common_Route_Params = Depends(common_route_params), + ): + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_id := redis_lookup_id_random(record_id_random=event_id, table_name='event'): pass + else: return mk_resp(data=None, status_code=404, response=commons.response) + + # Updated 2023-06-23 + if grant_rec_list_result := get_grant_rec_list( + event_id = event_id, + + hidden = hidden, # hidden, not_hidden, all + + enabled = commons.enabled, + limit = commons.limit, + offset = commons.offset, + ): + grant_result_list = [] + for grant_rec in grant_rec_list_result: + if load_grant_result := load_grant_obj( + grant_id = grant_rec.get('grant_id', None), + + hidden = hidden, + + enabled = commons.enabled, + limit = commons.limit, + inc_event_abstract = inc_event_abstract, + ): + grant_result_list.append(load_grant_result) + else: + grant_result_list.append(None) + response_data = grant_result_list + elif isinstance(grant_rec_list_result, list) or grant_rec_list_result is None: # Empty list or None + log.info('No results') + return mk_resp(data=False, status_code=404, response=commons.response) # Not Found + else: + log.warning('Likely bad request') + return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request + + return mk_resp(data=response_data, response=commons.response) +# ### END ### API Grant ### get_event_id_grant_obj_li() ### + + +# # ### BEGIN ### API Grant ### delete_grant_obj() ### +# # Updated 2023-03-22 +# @router.delete('/grant/{grant_id}', response_model=Resp_Body_Base) +# def delete_grant_obj( +# grant_id: str = Query(..., min_length=11, max_length=22), + +# method: str = None, # None, delete, disable, hide + +# commons: Common_Route_Params = Depends(common_route_params), +# ): +# log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL +# log.debug(locals()) + +# # ### SECTION ### Secondary data validation +# if grant_id := redis_lookup_id_random(record_id_random=grant_id, table_name='grant'): pass +# else: return mk_resp(data=None, status_code=404, response=response, status_message='The Grant ID was invalid or not found.') + +# if grant_obj_result := remove_grant_obj( +# grant_id = grant_id, +# method = method, +# ): +# log.info('Delete successful. Returning True') +# return mk_resp(data=True, response=response) # Success +# elif grant_obj_result is None: # None +# log.info('No results') +# return mk_resp(data=None, status_code=404, response=response) # Not Found +# else: +# log.warning('Likely bad request') +# return mk_resp(data=False, status_code=400, response=response) # Bad Request +# # ### END ### API Grant ### delete_grant_obj() ###