From 824bdd29a293ad67b2a5692cc5dbfa53d7f0819c Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Sat, 21 Aug 2021 16:04:17 -0400 Subject: [PATCH] Work on event, event_session, event_presentation, event_presenter, user, and person routes, methods, and models --- app/methods/event_person_methods.py | 117 ++++++++++++++++ app/methods/event_presentation_methods.py | 67 +++++++++- app/methods/event_presenter_methods.py | 65 +++++++++ app/methods/event_session_methods.py | 156 +++++++++++++++++++++- app/methods/person_methods.py | 70 +++++++--- app/methods/user_methods.py | 62 ++++++--- app/models/event_abstract_models.py | 3 +- app/models/event_badge_models.py | 1 + app/models/event_exhibit_models.py | 4 +- app/models/event_file_models.py | 3 +- app/models/event_location_models.py | 4 +- app/models/event_presentation_models.py | 3 +- app/models/event_presenter_models.py | 3 +- app/models/event_registration_models.py | 1 + app/models/event_session_models.py | 3 +- app/models/event_track_models.py | 3 +- app/models/user_models.py | 11 +- app/routers/event_session.py | 87 +++++++++++- app/routers/user.py | 48 +++---- 19 files changed, 631 insertions(+), 80 deletions(-) diff --git a/app/methods/event_person_methods.py b/app/methods/event_person_methods.py index 75973c9..776ce41 100644 --- a/app/methods/event_person_methods.py +++ b/app/methods/event_person_methods.py @@ -207,6 +207,19 @@ def create_event_person_obj(event_person_obj_new:Event_Person_Base) -> int|bool: event_person_id = event_person_obj_in_result + # Linked to (from event_person) + if event_person_obj_new.event_badge and event_person_obj_new.event_badge_id: pass + if event_person_obj_new.event_badge_vendor and event_person_obj_new.event_badge_vendor_id: pass + if event_person_obj_new.event_badge_vip and event_person_obj_new.event_badge_vip_id: pass + if event_person_obj_new.event_registration and event_person_obj_new.event_registration_id: pass + + # Linked from + if event_person_obj_new.event and event_person_obj_new.poc_event_id: pass # POC for event; only one + if event_person_obj_new.event_presenter and event_person_obj_new.event_presenter_id: pass # actual presenter; could be more than one + if event_person_obj_new.event_session and event_person_obj_new.poc_event_session_id: pass # POC for event session; could be more than one + if event_person_obj_new.event_registration and event_person_obj_new.poc_event_registration_id: pass # Primary registrant for registration; only one + + log.debug(f'Returning the new event_person_id: {event_person_id}') return event_person_id # ### END ### API Event Person Methods ### create_event_person_obj() ### @@ -299,3 +312,107 @@ def update_event_person_obj( log.debug(event_person_obj_up_result) return False # ### END ### API Event Person Methods ### update_event_person_obj() ### + + + + + + + +# ### BEGIN ### API Event Person Methods ### create_event_person_obj() ### +# NOTE: This will create an event_person. This event_person should include at least a person_id. +# NOTE: Is it a good idea to create and or update a person and or user here??? The create_event_person_obj() below does do that. +# Reviewed and updated 2021-08-10 +def smart_event_person_obj(event_person_obj_new:Event_Person_Base) -> int|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_person_id := event_person_obj_new.event_person_id: pass + + if event_id := event_person_obj_new.event_id: pass + if event_presentation_id := event_person_obj_new.event_presentation_id: pass + if event_session_id := event_person_obj_new.event_session_id: pass + + # 1: Pull out the event_person data and possible sub object data + # event_person + # if not event_person_id: create_event_person + # if event_person_id: update_event_person + # + # event + # event_badge + # event_presenter # could be more than one + # event_registration # POC/primary or secondary + # event_session # could be more than one + + + # def create_event_person(): + # 1: Pull out the event_person data and possible sub object data + # event + # ignore for now + + # event_badge + # ignore for now + + # event_presenter # could be more than one + # if event_id and event_session_id and event_presentation_id and not event_presenter_id: create_event_presenter + # if event_presenter_id: update_event_presenter + + # event_registration # POC/primary or secondary + # ignore for now + + # event_session # could be more than one + # if event_id and not event_session_id: create_event_session + # if event_session_id: update_event_session + + + + # def update_event_person(): + # 1: Pull out the event_person data and possible sub object data + # event + # ignore for now + + # event_badge + # ignore for now + + # event_presenter # could be more than one + # if event_id and event_session_id and event_presentation_id and not event_presenter_id: create_event_presenter + # if event_presenter_id: update_event_presenter + + # event_registration # POC/primary or secondary + # ignore for now + + # event_session # could be more than one + # if event_id and not event_session_id: create_event_session + # if event_session_id: update_event_session + + + + + event_person_obj_data = event_person_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'created_on', 'updated_on'}) + log.debug(event_person_obj_data) + + if event_person_obj_in_result := sql_insert(data=event_person_obj_data, table_name='event_person', rm_id_random=True, id_random_length=8): pass + else: + return False + + #log.setLevel(logging.DEBUG) + log.debug(event_person_obj_in_result) + + event_person_id = event_person_obj_in_result + + # Linked to (from event_person) + if event_person_obj_new.event_badge and event_person_obj_new.event_badge_id: pass + if event_person_obj_new.event_badge_vendor and event_person_obj_new.event_badge_vendor_id: pass + if event_person_obj_new.event_badge_vip and event_person_obj_new.event_badge_vip_id: pass + if event_person_obj_new.event_registration and event_person_obj_new.event_registration_id: pass + + # Linked from + if event_person_obj_new.event and event_person_obj_new.poc_event_id: pass # POC for event; only one + if event_person_obj_new.event_presenter and event_person_obj_new.event_presenter_id: pass # actual presenter; could be more than one + if event_person_obj_new.event_session and event_person_obj_new.poc_event_session_id: pass # POC for event session; could be more than one + if event_person_obj_new.event_registration and event_person_obj_new.poc_event_registration_id: pass # Primary registrant for registration; only one + + + log.debug(f'Returning the new event_person_id: {event_person_id}') + return event_person_id +# ### END ### API Event Person Methods ### create_event_person_obj() ### \ No newline at end of file diff --git a/app/methods/event_presentation_methods.py b/app/methods/event_presentation_methods.py index 94a4bc4..5e6d9f9 100644 --- a/app/methods/event_presentation_methods.py +++ b/app/methods/event_presentation_methods.py @@ -11,7 +11,7 @@ from app.lib_general import log, logging # from app.methods.event_file_methods import load_event_file_obj # from app.methods.event_location_methods import load_event_location_obj # from app.methods.event_presentation_methods import load_event_presentation_obj -from app.methods.event_presenter_methods import load_event_presenter_obj +from app.methods.event_presenter_methods import create_event_presenter_obj, load_event_presenter_obj, update_event_presenter_obj_exist # from app.methods.event_session_methods import create_event_session_obj, load_event_session_obj, update_event_session_obj # from app.methods.person_methods import load_person_obj # from app.methods.user_methods import load_user_obj @@ -141,7 +141,72 @@ def load_event_presentation_obj( return event_presentation_obj + + +# ### BEGIN ### API Event Presentation Methods ### create_event_presentation_obj() ### +# Updated 2021-08-21 +def create_event_presentation_obj( + event_presentation_obj_new: Event_Presentation_Base, + create_sub_obj: bool = False, + fail_any: bool = False, # Fail if any thing goes wrong for sub objects + ) -> bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_id := event_presentation_obj_new.event_id: pass + else: + log.error('Event ID is required') + return False + + if event_session_id := event_presentation_obj_new.event_session_id: pass + else: + log.error('Event Session ID is required') + return False +# ### END ### API Event Presentation Methods ### create_event_presentation_obj() ### + + +# ### BEGIN ### API Event Presentation Methods ### update_event_presentation_obj_exist() ### +# Updated 2021-08-21 +def update_event_presentation_obj_exist( + event_presentation_id: int|str, + event_presentation_obj_exist: Event_Presentation_Base, + create_sub_obj: bool = False, + fail_any: bool = False, # Fail if any thing goes wrong for sub objects + ) -> bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_presentation_id := redis_lookup_id_random(record_id_random=event_presentation_id, table_name='event_presentation'): pass + else: return False + + # Can't update the event_presentation_id alias if the .id was never set. + # event_presentation_obj_exist.event_presentation_id = event_presentation_id + if not event_presentation_obj_exist.id: + event_presentation_obj_exist.id = event_presentation_id + + event_presentation_obj_data = event_presentation_obj_exist.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'event_presenter', 'event_presenter_list', 'created_on', 'updated_on'}) + log.debug(event_presentation_obj_data) + + if event_presentation_obj_up_result := sql_update(data=event_presentation_obj_data, table_name='event_presentation', rm_id_random=True): pass + else: + log.warning(f'Event Presentation not updated.') + log.debug(event_presentation_obj_up_result) + return False + + return_dict = {} + return_dict['event_presentation_id'] = event_presentation_id + return_dict['event_presenter_list'] = [] + + + + + return False + + + + # ### BEGIN ### API Event Presentation Methods ### update_event_presentation_obj() ### +# This will be taken over by _exist version def update_event_presentation_obj( event_presentation_id: int|str, # Ideally the int ID should be passed. This allows for updating of the id_random value. event_presentation_obj_up: Event_Presentation_Base, diff --git a/app/methods/event_presenter_methods.py b/app/methods/event_presenter_methods.py index 15d662f..4c223b6 100644 --- a/app/methods/event_presenter_methods.py +++ b/app/methods/event_presenter_methods.py @@ -111,7 +111,72 @@ def load_event_presenter_obj( # ### END ### API Event Presenter Methods ### load_event_presenter_obj() ### + + +# ### BEGIN ### API Event Presenter Methods ### create_event_presenter_obj() ### +# Updated 2021-08-21 +def create_event_presenter_obj( + event_presenter_obj_new: Event_Presenter_Base, + create_sub_obj: bool = False, + fail_any: bool = False, # Fail if any thing goes wrong for sub objects + ) -> bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_id := event_presenter_obj_new.event_id: pass + else: + log.error('Event ID is required') + return False + + if event_session_id := event_presenter_obj_new.event_session_id: pass + else: + log.error('Event Session ID is required') + return False +# ### END ### API Event Presenter Methods ### create_event_presenter_obj() ### + + +# ### BEGIN ### API Event Presenter Methods ### update_event_presenter_obj_exist() ### +# Updated 2021-08-21 +def update_event_presenter_obj_exist( + event_presenter_id: int|str, + event_presenter_obj_exist: Event_Presenter_Base, + create_sub_obj: bool = False, + fail_any: bool = False, # Fail if any thing goes wrong for sub objects + ) -> bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_presenter_id := redis_lookup_id_random(record_id_random=event_presenter_id, table_name='event_presenter'): pass + else: return False + + # Can't update the event_presenter_id alias if the .id was never set. + # event_presenter_obj_exist.event_presenter_id = event_presenter_id + if not event_presenter_obj_exist.id: + event_presenter_obj_exist.id = event_presenter_id + + event_presenter_obj_data = event_presenter_obj_exist.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'event_presenter', 'event_presenter_list', 'created_on', 'updated_on'}) + log.debug(event_presenter_obj_data) + + if event_presenter_obj_up_result := sql_update(data=event_presenter_obj_data, table_name='event_presenter', rm_id_random=True): pass + else: + log.warning(f'Event Presenter not updated.') + log.debug(event_presenter_obj_up_result) + return False + + return_dict = {} + return_dict['event_presenter_id'] = event_presenter_id + # return_dict['something_list'] = [] + + + + + return False + + + + # ### BEGIN ### API Event Presenter Methods ### update_event_presenter_obj() ### +# This will be taken over by _exist version def update_event_presenter_obj( event_presenter_id: int|str, # Ideally the int ID should be passed. This allows for updating of the id_random value. event_presenter_obj_up: Event_Presenter_Base, diff --git a/app/methods/event_session_methods.py b/app/methods/event_session_methods.py index 37a88a9..1f1370c 100644 --- a/app/methods/event_session_methods.py +++ b/app/methods/event_session_methods.py @@ -11,7 +11,7 @@ from app.lib_general import log, logging from app.methods.event_file_methods import load_event_file_obj_list from app.methods.event_location_methods import load_event_location_obj from app.methods.event_person_methods import load_event_person_obj, update_event_person_obj -from app.methods.event_presentation_methods import load_event_presentation_obj +from app.methods.event_presentation_methods import create_event_presentation_obj, load_event_presentation_obj, update_event_presentation_obj_exist # from app.methods.event_presenter_methods import load_event_presenter_obj from app.methods.person_methods import load_person_obj # from app.methods.user_methods import load_user_obj @@ -200,7 +200,161 @@ def load_event_session_obj( return event_session_obj + + +# ### BEGIN ### API Event Session Methods ### create_event_session_obj() ### +# Updated 2021-08-21 +def create_event_session_obj( + event_session_obj_new: Event_Session_Base, + create_sub_obj: bool = False, + fail_any: bool = False, # Fail if any thing goes wrong for sub objects + ) -> bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_id := event_session_obj_new.event_id: pass + else: + log.error('Event ID is required') + return False + + event_session_obj_data = event_session_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'event_presentation', 'event_presentation_list', 'event_presenter', 'event_presenter_list', 'created_on', 'updated_on'}) + log.debug(event_session_obj_data) + + if event_session_obj_in_result := sql_insert(data=event_session_obj_data, table_name='event_session', rm_id_random=True, id_random_length=8): pass + else: + log.warning(f'Event Session not created.') + log.debug(event_session_obj_in_result) + return False + + event_session_id = event_session_obj_in_result + + return_dict = {} + return_dict['event_session_id'] = None + return_dict['event_presentation_list'] = [] + + # event_presentation_id = event_session_obj_new.event_presentation_id + if event_session_obj_new.event_presentation_list and isinstance(event_session_obj_new.event_presentation_list, list): + for event_presentation_obj_new in event_session_obj_new.event_presentation_list: + if create_event_presentation_obj_result := create_event_presentation_obj( + event_presentation_obj_new = event_presentation_obj_new, + create_sub_obj = create_sub_obj, + fail_any = fail_any, + ): + if isinstance(create_event_presentation_obj_result, int): + event_presentation_id = create_event_presentation_obj_result + log.info(f'Event Presentation created. Event Presentation ID: {event_presentation_id}') + else: + log.warning(f'Event Presentation not created. Event Session ID: {event_session_id}') + log.debug(create_event_presentation_obj_result) + event_presentation_id = None + if fail_any: return False + else: + log.warning(f'Event Presentation not created. Event Session ID: {event_session_id}') + log.debug(create_event_presentation_obj_result) + event_presentation_id = None + if fail_any: return False + return_dict['event_presentation_list'].append(event_presentation_id) + else: + log.info('Event presentation list not found') + pass + + log.debug(f'Returning the new event_session_id: {event_session_id}') + return event_session_id +# ### END ### API Event Session Methods ### create_event_session_obj() ### + + +# ### BEGIN ### API Event Session Methods ### update_event_session_obj_exist() ### +# Updated 2021-08-21 +def update_event_session_obj_exist( + event_session_id: int|str, + event_session_obj_exist: Event_Session_Base, + create_sub_obj: bool = False, + fail_any: bool = False, # Fail if any thing goes wrong for sub objects + ) -> bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_session_id := redis_lookup_id_random(record_id_random=event_session_id, table_name='event_session'): pass + else: return False + + # Can't update the event_session_id alias if the .id was never set. + # event_session_obj_exist.event_session_id = event_session_id + if not event_session_obj_exist.id: + event_session_obj_exist.id = event_session_id + + event_session_obj_data = event_session_obj_exist.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'event_presentation', 'event_presentation_list', 'event_presenter', 'event_presenter_list', 'created_on', 'updated_on'}) + log.debug(event_session_obj_data) + + if event_session_obj_up_result := sql_update(data=event_session_obj_data, table_name='event_session', rm_id_random=True): pass + else: + log.warning(f'Event Session not updated.') + log.debug(event_session_obj_up_result) + return False + + return_dict = {} + return_dict['event_session_id'] = event_session_id + return_dict['event_presentation_list'] = [] + + # event_presentation_id = event_session_obj_exist.event_presentation_id + if event_session_obj_exist.event_presentation_list and isinstance(event_session_obj_exist.event_presentation_list, list): + for event_presentation_obj_unknown in event_session_obj_exist.event_presentation_list: + if event_presentation_id := event_presentation_obj_unknown.event_presentation_id: + if update_event_presentation_obj_result := update_event_presentation_obj_exist( + event_presentation_id = event_presentation_id, + event_presentation_obj_exist = event_presentation_obj_unknown, + create_sub_obj = create_sub_obj, + fail_any = fail_any, + ): + event_presentation_id = update_event_presentation_obj_result + log.info(f'Event Presentation updated. Event Presentation ID: {event_presentation_id}') + else: + log.warning(f'Event Presentation not updated. Event Session ID: {event_session_id}') + log.debug(update_event_presentation_obj_result) + event_presentation_id = None + if fail_any: return False + + if isinstance(update_event_presentation_obj_result, int): + event_presentation_id = update_event_presentation_obj_result + log.info(f'Event Presentation updated. Event Presentation ID: {event_presentation_id}') + else: + log.warning(f'Event Presentation not updated. Event Session ID: {event_session_id}') + log.debug(update_event_presentation_obj_result) + event_presentation_id = None + if fail_any: return False + else: + log.info(f'No Event Presentation ID found.') + if create_event_presentation_obj_result := create_event_presentation_obj( + event_presentation_obj_new = event_presentation_obj_unknown, + create_sub_obj = create_sub_obj, + fail_any = fail_any, + ): + if isinstance(create_event_presentation_obj_result, int): + event_presentation_id = create_event_presentation_obj_result + log.info(f'Event Presentation created. Event Presentation ID: {event_presentation_id}') + else: + log.warning(f'Event Presentation not created. Event Session ID: {event_session_id}') + log.debug(create_event_presentation_obj_result) + event_presentation_id = None + if fail_any: return False + else: + log.warning(f'Event Presentation not created. Event Session ID: {event_session_id}') + log.debug(create_event_presentation_obj_result) + event_presentation_id = None + if fail_any: return False + return_dict['event_presentation_list'].append(event_presentation_id) + else: + log.info('Event presentation list not found') + pass + + log.debug(f'Returning the new event_session_id: {event_session_id}') + return event_session_id +# ### END ### API Event Session Methods ### update_event_session_obj_exist() ### + + + + # ### BEGIN ### API Event Session Methods ### update_event_session_obj() ### +# This will be taken over by _exist version def update_event_session_obj( event_session_id: int|str, # Ideally the int ID should be passed. This allows for updating of the id_random value. event_session_obj_up: Event_Session_Base, diff --git a/app/methods/person_methods.py b/app/methods/person_methods.py index 4c41fd4..9101c7b 100644 --- a/app/methods/person_methods.py +++ b/app/methods/person_methods.py @@ -11,7 +11,7 @@ from app.lib_general import log, logging from app.methods.contact_methods import create_contact_obj, create_update_contact_obj, load_contact_obj, update_contact_obj from app.methods.order_methods import load_order_obj, get_order_rec_list from app.methods.organization_methods import create_update_organization_obj, load_organization_obj, update_organization_obj -# from app.methods.user_methods import create_user_obj, load_user_obj, update_user_obj +# from app.methods.user_methods import create_user_obj # , load_user_obj, update_user_obj from app.models.common_field_schema import default_num_bytes from app.models.person_models import Person_Base @@ -341,45 +341,74 @@ def get_person_rec_w_external_id( # ### BEGIN ### API Person Methods ### create_person_obj() ### # NOTE: This will create a person and then also create a linked contact if person_obj.contact data is passed. The create_contact_obj will create a contact and then also create a linked address if person_obj.contact.address data is passed. +# Reviewed and updated 2021-08-21 # Reviewed and updated 2021-08-10 -def create_person_obj(person_obj_new:Person_Base): +def create_person_obj( + person_obj_new: Person_Base, + create_sub_obj: bool = False, + fail_any: bool = True, # Fail if any thing goes wrong for sub objects + return_dict: bool = False, + ) -> bool|dict|int: log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - if not person_obj_new: - return False - - person_obj_data = person_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'contact', 'organization', 'created_on', 'updated_on'}) + person_obj_data = person_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'contact', 'organization', 'user', 'created_on', 'updated_on'}) + log.debug(person_obj_data) if person_obj_in_result := sql_insert(data=person_obj_data, table_name='person', rm_id_random=True, id_random_length=8): pass else: + log.warning(f'Person not created.') + log.debug(person_obj_in_result) return False - #log.setLevel(logging.DEBUG) - log.debug(person_obj_in_result) - person_id = person_obj_in_result + return_dict = {} + return_dict['person_id'] = None + return_dict['contact_id'] = None + return_dict['contact'] = {} + return_dict['contact']['address_id'] = None + return_dict['user_id'] = None + if person_obj_new.contact: + log.info(f'Contact data was found. Create a new contact and link it to the new person. Person ID: {person_id}') contact_obj_new = person_obj_new.contact contact_obj_new.for_type = 'person' contact_obj_new.for_id = person_id create_contact_obj_result = create_contact_obj(contact_obj_new=contact_obj_new) if isinstance(create_contact_obj_result, int): contact_id = create_contact_obj_result - log.debug(f'Update person with new contact_id: {contact_id}') - # NOTE: This last update should no longer be needed now that the person.contact_id is not supposed to be used. - # Need to update the person with the new contact_id - person_obj_up = {} # REMOVE - person_obj_up['id'] = person_id # REMOVE - person_obj_up['contact_id_old'] = contact_id # REMOVE - if person_obj_up_result := sql_update(data=person_obj_up, table_name='person'): pass # REMOVE - else: # REMOVE - return False # REMOVE - log.debug(person_obj_up_result) # REMOVE + log.info(f'Contact created. Contact ID: {contact_id}') else: - log.debug(f'No contact_id was returned when tyring to create_contact_obj(): {create_contact_obj_result}') + log.warning(f'Contact not created. Person ID: {person_id}') + log.debug(create_contact_obj_result) contact_id = None + if fail_any: return False + + if person_obj_new.user: + log.info(f'User data was found. Create a new user and link it to the new person. Person ID: {person_id}') + from app.methods.user_methods import create_user_obj + user_obj_new = person_obj_new.user + user_obj_new.person_id = person_id + create_user_obj_result = create_user_obj(user_obj_new=user_obj_new) + if isinstance(create_user_obj_result, int): + log.info(f'User created. User ID: {user_id} Update person {person_id} with new user ID.') + user_id = create_user_obj_result + # Need to update the person with the new user_id + person_obj_up = {} + person_obj_up['id'] = person_id + person_obj_up['user_id'] = user_id + if person_obj_up_result := sql_update(data=person_obj_up, table_name='person'): + log.info(f'Person updated with user ID. Person ID: {person_id} User ID: {user_id}') + else: + log.warning(f'Person not updated with user ID. Person ID: {person_id} User ID: {user_id}') + if fail_any: return False + log.debug(person_obj_up_result) + else: + log.warning(f'User not created. Person ID: {person_id}') + log.debug(create_user_obj_result) + user_id = None + if fail_any: return False log.debug(f'Returning the new person_id: {person_id}') return person_id @@ -393,6 +422,7 @@ def update_person_obj( person_id: int|str, # Ideally the int ID should be passed. This allows for updating of the id_random value. person_obj_up: Person_Base, create_missing_obj: bool = False, + fail_any: bool = True, # Fail if any thing goes wrong for sub objects ) -> bool: log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) diff --git a/app/methods/user_methods.py b/app/methods/user_methods.py index 13225e0..4b7dba6 100644 --- a/app/methods/user_methods.py +++ b/app/methods/user_methods.py @@ -1,5 +1,5 @@ from __future__ import annotations -import datetime +import datetime, random from typing import Dict, List, Optional, Set, Union from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator @@ -21,22 +21,27 @@ from app.models.user_models import User_Base, User_New_Base, User_Out_Base # ### BEGIN ### API User Methods ### create_user_obj() ### # NOTE: This will create a new user and also hash a new password string if given. # NOTE: This uses the User_New_Base model, not User_Base or User_Out_Base +# Reviewed and updated 2021-08-21 # Reviewed and updated 2021-08-10 -def create_user_obj(user_obj_new:User_New_Base) -> int|bool: +def create_user_obj( + user_obj_new: User_New_Base, + allow_update: bool = False, # Allow updating the user account if one is found + avoid_dup_username: bool = False, # Avoid creating a duplicate by modifying the supplied username + return_dict: bool = False, + ) -> bool|dict|int: log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - if not user_obj_new: - return False - - # user_obj_data = user_obj_new.dict(by_alias=False, exclude_defaults=False, include={'password'}, exclude={'new_password'}) - user_obj_data = user_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'new_password'}) + user_obj_data = user_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'contact', 'new_password', 'organization', 'person', 'created_on', 'updated_on'}) log.debug(user_obj_data) user_obj_data['password'] = user_obj_new.password # There has to be a better way to do this??? It thinks "password" is unset and so is excluded? log.debug(user_obj_data) - log.info('Checking if the username is already in use for the account...') + account_id = user_obj_data.get('account_id', None) + username = user_obj_data.get('username', None) + + log.info(f'Checking if the username is already in use for the account... Account: {account_id} Username: {username}') sql_select_user = f""" SELECT user.id, user.id_random, user.name, user.email FROM `user` AS user @@ -45,30 +50,47 @@ def create_user_obj(user_obj_new:User_New_Base) -> int|bool: if sql_select_result := sql_select(sql=sql_select_user, data=user_obj_data, rm_id_random=True): if isinstance(sql_select_result, list): - log.exception(f"Multiple user accounts already exists with this username ({user_obj_data['username']}). The database needs to be checked.") + log.exception(f'Multiple user accounts already exists with this username. The database needs to be checked. Account ID: {account_id} Username: {username}') return False - log.info('A user account already exists with this username. Updating instead of inserting.') user_id = sql_select_result.get('id', None) - user_obj_data['id'] = user_id - if user_obj_up_result := sql_update(data=user_obj_data, table_name='user', rm_id_random=True): pass + log.info('A user account already exists with this username. Current User ID: {user_id} Username: {username}') + if allow_update: + log.info('Updating instead of inserting. Current User ID: {user_id} Username: {username}') + user_obj_data['id'] = user_id + if user_obj_up_result := sql_update(data=user_obj_data, table_name='user', rm_id_random=True): + log.info(f'User updated with new user data. User ID: {user_id}') + else: + log.warning(f'User not updated with new user data. User ID: {user_id}') + log.debug(user_obj_up_result) + return False else: - return False - + log.info('Updating is now allowed. Current User ID: {user_id} Username: {username}') + if avoid_dup_username: + log.info('Avoiding duplicate username is now allowed. Suggested Username: {username}') + new_username = username+'-'+str(random.randint(10, 99)) + user_obj_data['username'] = new_username + if user_obj_in_result := sql_insert(data=user_obj_data, table_name='user', rm_id_random=True, id_random_length=8): pass + else: + log.warning(f'User not created.') + log.debug(user_obj_in_result) + return False + user_id = user_obj_in_result + else: + log.warning(f'Updating is not allowed and avoid duplicate username is not allowed. Username: {username}') + return False #log.setLevel(logging.DEBUG) - log.debug(user_obj_up_result) + # log.debug(user_obj_up_result) log.debug(f'Returning the existing user_id: {user_id}') else: if user_obj_in_result := sql_insert(data=user_obj_data, table_name='user', rm_id_random=True, id_random_length=8): pass else: + log.warning(f'User not created.') + log.debug(user_obj_in_result) return False - - log.setLevel(logging.DEBUG) - log.debug(user_obj_in_result) - user_id = user_obj_in_result - log.debug(f'Returning the new user_id: {user_id}') + log.debug(f'Returning the new user_id: {user_id}') return user_id # ### END ### API User Methods ### create_user_obj() ### diff --git a/app/models/event_abstract_models.py b/app/models/event_abstract_models.py index 7051be5..41d55cd 100644 --- a/app/models/event_abstract_models.py +++ b/app/models/event_abstract_models.py @@ -28,7 +28,7 @@ class Event_Abstract_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_abstract_id' + alias = 'event_abstract_id' ) event_id_random: Optional[str] event_id: Optional[int] @@ -172,6 +172,7 @@ class Event_Abstract_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields #Event_Abstract_Base.update_forward_refs() diff --git a/app/models/event_badge_models.py b/app/models/event_badge_models.py index 451210c..ea54c5f 100644 --- a/app/models/event_badge_models.py +++ b/app/models/event_badge_models.py @@ -22,6 +22,7 @@ class Event_Badge_Base(BaseModel): id: Optional[int] = Field( alias = 'event_badge_id' ) + # account_id_random: Optional[str] # account_id: Optional[int] event_id_random: Optional[str] diff --git a/app/models/event_exhibit_models.py b/app/models/event_exhibit_models.py index f37df21..81cea38 100644 --- a/app/models/event_exhibit_models.py +++ b/app/models/event_exhibit_models.py @@ -20,8 +20,9 @@ class Event_Exhibit_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_exhibit_id' + alias = 'event_exhibit_id' ) + account_id_random: Optional[str] account_id: Optional[int] event_id_random: Optional[str] @@ -139,6 +140,7 @@ class Event_Exhibit_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields Event_Exhibit_Base.update_forward_refs() diff --git a/app/models/event_file_models.py b/app/models/event_file_models.py index d936a0c..2c120d8 100644 --- a/app/models/event_file_models.py +++ b/app/models/event_file_models.py @@ -21,7 +21,7 @@ class Event_File_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_file_id' + alias = 'event_file_id' ) hosted_file_id_random: Optional[str] @@ -130,6 +130,7 @@ class Event_File_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields @validator('for_id_random', always=True) diff --git a/app/models/event_location_models.py b/app/models/event_location_models.py index 9733994..c1cb5ac 100644 --- a/app/models/event_location_models.py +++ b/app/models/event_location_models.py @@ -22,8 +22,9 @@ class Event_Location_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_location_id' + alias = 'event_location_id' ) + event_id_random: Optional[str] event_id: Optional[int] event_track_id_random: Optional[str] # Can a track be assigned to one location? @@ -104,6 +105,7 @@ class Event_Location_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields #Event_Location_Base.update_forward_refs() diff --git a/app/models/event_presentation_models.py b/app/models/event_presentation_models.py index 8cf68bb..3d376d8 100644 --- a/app/models/event_presentation_models.py +++ b/app/models/event_presentation_models.py @@ -25,7 +25,7 @@ class Event_Presentation_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_presentation_id' + alias = 'event_presentation_id' ) event_id_random: Optional[str] event_id: Optional[int] @@ -129,6 +129,7 @@ class Event_Presentation_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields #Event_Presentation_Base.update_forward_refs() diff --git a/app/models/event_presenter_models.py b/app/models/event_presenter_models.py index 20bd43b..e70aabf 100644 --- a/app/models/event_presenter_models.py +++ b/app/models/event_presenter_models.py @@ -27,7 +27,7 @@ class Event_Presenter_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_presenter_id' + alias = 'event_presenter_id' ) event_id_random: Optional[str] event_id: Optional[int] @@ -157,6 +157,7 @@ class Event_Presenter_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields #Event_Presenter_Base.update_forward_refs() diff --git a/app/models/event_registration_models.py b/app/models/event_registration_models.py index 2c608dc..c354f97 100644 --- a/app/models/event_registration_models.py +++ b/app/models/event_registration_models.py @@ -23,6 +23,7 @@ class Event_Registration_Base(BaseModel): id: Optional[int] = Field( alias = 'event_registration_id' ) + account_id_random: Optional[str] account_id: Optional[int] event_id_random: Optional[str] diff --git a/app/models/event_session_models.py b/app/models/event_session_models.py index 07960f5..20a994d 100644 --- a/app/models/event_session_models.py +++ b/app/models/event_session_models.py @@ -25,7 +25,7 @@ class Event_Session_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_session_id' + alias = 'event_session_id' ) event_id_random: Optional[str] event_id: Optional[int] @@ -151,6 +151,7 @@ class Event_Session_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields #Event_Session_Base.update_forward_refs() diff --git a/app/models/event_track_models.py b/app/models/event_track_models.py index 0625a66..cebc05b 100644 --- a/app/models/event_track_models.py +++ b/app/models/event_track_models.py @@ -21,7 +21,7 @@ class Event_Track_Base(BaseModel): default_factory = lambda:secrets.token_urlsafe(default_num_bytes), ) id: Optional[int] = Field( - #alias = 'event_track_id' + alias = 'event_track_id' ) event_id_random: Optional[str] event_id: Optional[int] @@ -106,6 +106,7 @@ class Event_Track_Base(BaseModel): class Config: underscore_attrs_are_private = True + allow_population_by_field_name = True fields = base_fields #Event_Track_Base.update_forward_refs() diff --git a/app/models/user_models.py b/app/models/user_models.py index a9d170c..f803fff 100644 --- a/app/models/user_models.py +++ b/app/models/user_models.py @@ -44,12 +44,13 @@ class User_New_Base(BaseModel): username: str name: str email: str + email_verified: bool = False new_password: str = Field(default_factory = lambda:secrets.token_urlsafe(default_num_bytes)) password: Optional[str] # If new_password is found then the validator below will create secure_hash_string() from the new password string. - allow_auth_key: Optional[int] + allow_auth_key: bool = False - enable: Optional[bool] = False + enable: bool = False enable_from: Optional[datetime.datetime] = datetime.datetime.now(datetime.timezone.utc) #enable_from: Optional[datetime.datetime] = datetime.datetime.now() enable_to: Optional[datetime.datetime] = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365) @@ -57,9 +58,9 @@ class User_New_Base(BaseModel): #super: Optional[bool] = False #manager: Optional[bool] = False - administrator: Optional[bool] = False - public: Optional[bool] = False - verified: Optional[bool] = False + administrator: bool = False + public: bool = False + verified: bool = False notes: Optional[str] diff --git a/app/routers/event_session.py b/app/routers/event_session.py index f979c87..d79dc51 100644 --- a/app/routers/event_session.py +++ b/app/routers/event_session.py @@ -5,11 +5,11 @@ from typing import Dict, List, Optional, Set, Union from app.lib_general import log, logging from app.config import settings -from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random +from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, lookup_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.event_session_methods import load_event_session_obj +from app.methods.event_session_methods import create_event_session_obj, load_event_session_obj, update_event_session_obj_exist from app.models.event_session_models import Event_Session_Base from app.models.response_models import * @@ -42,6 +42,89 @@ async def post_event_session_obj( return result +# ### BEGIN ### API Event Session ### post_event_session_obj_new() ### +# Updated 2021-08-21 (all new) +@router.post('/new', response_model=Resp_Body_Base) +async def post_event_session_obj_new( + event_session_obj: Event_Session_Base, + create_sub_obj: bool = False, + fail_any: bool = True, # Fail if any thing goes wrong for sub objects + x_account_id: str = Header(...), + return_obj: bool = True, + by_alias: bool = True, + exclude_unset: bool = True, + response: Response = Response, + ): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if create_event_session_obj_result := create_event_session_obj(event_session_obj_new=event_session_obj, create_sub_obj=create_sub_obj, fail_any=fail_any): pass + else: return mk_resp(data=False, status_code=400, response=response, status_message='The event session was not created. Check the field names and data types.') + + if isinstance(create_event_session_obj_result, int): + event_session_id = create_event_session_obj_result + if return_obj: + if load_event_session_obj_result := load_event_session_obj(event_session_id=event_session_id): + data = load_event_session_obj_result + else: + data = False + else: + event_session_id = create_event_session_obj_result + event_session_id_random = lookup_id_random(record_id=event_session_id, table_name='event_session') + data = {} + data['event_session_id'] = event_session_id + data['event_session_id_random'] = event_session_id_random + return mk_resp(data=data, response=response, status_message='The event session was created.') + else: + return mk_resp(data=False, status_code=400, response=response, status_message='The result from trying to create an event session was unexpected.') +# ### BEGIN ### API Event Session ### post_event_session_obj_new() ### + + +# ### BEGIN ### API Event Session ### patch_event_session_obj_exist() ### +@router.patch('/{event_session_id}/exist', response_model=Resp_Body_Base) +async def patch_event_session_obj_exist( + event_session_obj: Event_Session_Base, + event_session_id: str = Query(..., min_length=11, max_length=22), + create_sub_obj: bool = False, + fail_any: bool = True, # Fail if any thing goes wrong for sub objects + x_account_id: Optional[str] = Header(..., ), + return_obj: Optional[bool] = True, + by_alias: Optional[bool] = True, + exclude_unset: Optional[bool] = True, + exclude_none: Optional[bool] = True, + response: Response = Response, + ): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if event_session_id := redis_lookup_id_random(record_id_random=event_session_id, table_name='event_session'): pass + else: return mk_resp(data=None, status_code=404) + + if update_event_session_obj_result := update_event_session_obj_exist( + event_session_id = event_session_id, + event_session_obj_exist = event_session_obj, + create_sub_obj = create_sub_obj, + fail_any = fail_any, + ): pass + else: return mk_resp(data=False, status_code=400, response=response, status_message='The event session was not created. Check the field names and data types.') + + if update_event_session_obj_result: + if return_obj: + if load_event_session_obj_result := load_event_session_obj(event_session_id=event_session_id): + data = load_event_session_obj_result + else: + data = False + else: + event_session_id_random = lookup_id_random(record_id=event_session_id, table_name='event_session') + data = {} + data['event_session_id'] = event_session_id + data['event_session_id_random'] = event_session_id_random + return mk_resp(data=data, response=response, status_message='The event session was created.') + else: + return mk_resp(data=False, status_code=400, response=response, status_message='The result from trying to create an event session was unexpected.') +# ### END ### API Event Session ### patch_event_session_obj_exist() ### + + @router.patch('/{obj_id}', response_model=Resp_Body_Base) async def patch_event_session_obj( obj: Event_Session_Base, diff --git a/app/routers/user.py b/app/routers/user.py index 0ba6b9d..76e12ee 100644 --- a/app/routers/user.py +++ b/app/routers/user.py @@ -5,12 +5,12 @@ from typing import Dict, List, Optional, Set, Union from app.lib_general import log, logging, secure_hash_string, verify_secure_hash_string from app.config import settings -from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random +from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, lookup_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.order_methods import get_order_rec_list, load_order_obj -from app.methods.user_methods import load_user_obj +from app.methods.user_methods import create_user_obj, load_user_obj from app.models.common_field_schema import default_num_bytes from app.models.response_models import Resp_Body_Base, mk_resp @@ -44,9 +44,13 @@ async def post_user_obj( return result +# ### BEGIN ### API User ### post_user_obj_new() ### +# Updated 2021-08-21 (complete re-write) @router.post('/new', response_model=Resp_Body_Base) -async def post_user_new_obj( +async def post_user_obj_new( user_obj: User_New_Base, + allow_update: bool = False, + avoid_dup_username: bool = False, x_account_id: str = Header(...), return_obj: bool = True, by_alias: bool = True, @@ -56,28 +60,26 @@ async def post_user_new_obj( log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - user_data = user_obj.dict(by_alias=False, exclude_unset=False, exclude={'new_password', 'account_id_random'}) + if create_user_obj_result := create_user_obj(user_obj_new=user_obj, allow_update=allow_update, avoid_dup_username=avoid_dup_username): pass + else: return mk_resp(data=False, status_code=400, response=response, status_message='The user account was not created. This is likely because that username already exists for this account.') - log.info('Checking if the username is already in use for the account...') - sql_select_user = f""" - SELECT * - FROM `user` AS user - WHERE user.account_id = :account_id and user.username = :username - """ - - if sql_select_result := sql_select(sql=sql_select_user, data=user_data): - return mk_resp(data=False, status_message='The user account was not created. This is likely because of a duplicate username.') - - log.info('Adding new user account...') - if sql_insert_result := sql_insert(table_name='user', data=user_data): - log.info('Selecting new user account to return as an object...') - sql_select_user_result = sql_select(table_name='v_user', record_id=sql_insert_result) - - user_obj_new = User_Out_Base(**sql_select_user_result) - - return mk_resp(data=user_obj_new.dict(by_alias=True, exclude_unset=True)) + if isinstance(create_user_obj_result, int): + user_id = create_user_obj_result + if return_obj: + if load_user_obj_result := load_user_obj(user_id=user_id): + data = load_user_obj_result + else: + data = False + else: + user_id = create_user_obj_result + user_id_random = lookup_id_random(record_id=user_id, table_name='user') + data = {} + data['user_id'] = user_id + data['user_id_random'] = user_id_random + return mk_resp(data=data, response=response, status_message='The user account was created.') else: - return mk_resp(data=False, status_message='The user account was not created. Something seems to have gone wrong on insert.') + return mk_resp(data=False, status_code=400, response=response, status_message='The result from trying to create a user account was unexpected.') +# ### END ### API User ### post_user_obj_new() ### @router.patch('/change_password/{user_id}', response_model=Resp_Body_Base)