diff --git a/app/methods/account_methods.py b/app/methods/account_methods.py index 9ab1246..cb475d7 100644 --- a/app/methods/account_methods.py +++ b/app/methods/account_methods.py @@ -8,11 +8,15 @@ from app.db_sql import redis_lookup_id_random, sql_select from app.lib_general import log, logging from app.methods.account_cfg_methods import load_account_cfg_obj -# from app.methods.address_methods import load_address_obj_list -from app.methods.archive_methods import load_archive_obj_list +from app.methods.address_methods import get_address_rec_list, load_address_obj +from app.methods.archive_methods import get_archive_rec_list, load_archive_obj # from app.methods.contact_methods import load_contact_obj_list from app.methods.event_methods import load_event_obj_list +from app.methods.organization_methods import get_organization_rec_list, load_organization_obj +from app.methods.person_methods import get_person_rec_list, load_person_obj +from app.methods.product_methods import get_product_rec_list, load_product_obj from app.methods.post_methods import load_post_obj_list +from app.methods.user_methods import get_user_rec_list, load_user_obj from app.models.account_models import Account_Base from app.models.account_cfg_models import Account_Cfg_Base @@ -90,6 +94,7 @@ def load_account_obj( inc_site_list: bool = False, # Priority l3 inc_user: bool = False, inc_user_list: bool = False, # Priority l2 + inc_user_role_list: bool = False, ) -> Account_Base|dict|bool: log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) @@ -120,24 +125,68 @@ def load_account_obj( account_obj.account_cfg = account_cfg_dict else: account_obj.account_cfg = None + # if inc_address_list: + # if address_dict_list := load_address_obj_list( + # account_id = account_id, + # limit = limit, + # model_as_dict = model_as_dict, + # enabled = enabled, + # ): + # account_obj.address_list = address_dict_list + # else: account_obj.address_list = [] + + # Updated 2021-06-17 if inc_address_list: - if address_dict_list := load_address_obj_list( - account_id = account_id, - limit = limit, - model_as_dict = model_as_dict, - enabled = enabled, - ): + if address_rec_list_result := get_address_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + address_dict_list = [] + for address_rec in address_rec_list_result: + address_dict_list.append( + load_address_obj( + address_id = address_rec.get('address_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + inc_address_content_list = inc_address_content_list, + ) + ) account_obj.address_list = address_dict_list else: account_obj.address_list = [] + # if inc_archive_list: + # if archive_dict_list := load_archive_obj_list( + # account_id = account_id, + # limit = limit, + # model_as_dict = model_as_dict, + # enabled = enabled, + # inc_archive_content_list = inc_archive_content_list, + # ): + # account_obj.archive_list = archive_dict_list + # else: account_obj.archive_list = [] + + # Updated 2021-06-17 if inc_archive_list: - if archive_dict_list := load_archive_obj_list( - account_id = account_id, - limit = limit, - model_as_dict = model_as_dict, - enabled = enabled, - inc_archive_content_list = inc_archive_content_list, - ): + if archive_rec_list_result := get_archive_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + archive_dict_list = [] + for archive_rec in archive_rec_list_result: + archive_dict_list.append( + load_archive_obj( + archive_id = archive_rec.get('archive_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + inc_archive_content_list = inc_archive_content_list, + ) + ) account_obj.archive_list = archive_dict_list else: account_obj.archive_list = [] @@ -162,34 +211,100 @@ def load_account_obj( # account_obj.organization = organization_obj # else: account_obj.organization = None + + # Updated 2021-06-17 if inc_event_list: - if event_dict_list := load_event_obj_list( - account_id = account_id, - limit = limit, - model_as_dict = model_as_dict, - enabled = enabled, - # inc_location_address = inc_address, - # inc_contact_1 = inc_contact, - # inc_contact_2 = inc_contact, - # inc_contact_3 = inc_contact, - # inc_event_abstract_list = inc_event_abstract_list, - # inc_event_badge_list = inc_event_badge_list, - # inc_event_device_list = inc_event_device_list, - inc_event_exhibit_list = inc_event_exhibit_list, - inc_event_file_list = inc_event_file_list, - inc_event_location_list = inc_event_location_list, - inc_event_person_list = inc_event_person_list, - inc_event_presentation_list = inc_event_presentation_list, - inc_event_presenter_list = inc_event_presenter_list, - inc_event_registration_list = inc_event_registration_list, - inc_event_session_list = inc_event_session_list, - inc_event_track_list = inc_event_track_list, - # inc_person = inc_person, - # inc_user = inc_user, - ): + if event_rec_list_result := get_event_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + event_dict_list = [] + for event_rec in event_rec_list_result: + event_dict_list.append( + load_event_obj( + event_id = event_rec.get('event_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + # inc_location_address = inc_address, + # inc_contact_1 = inc_contact, + # inc_contact_2 = inc_contact, + # inc_contact_3 = inc_contact, + # inc_event_abstract_list = inc_event_abstract_list, + # inc_event_badge_list = inc_event_badge_list, + # inc_event_device_list = inc_event_device_list, + inc_event_exhibit_list = inc_event_exhibit_list, + inc_event_file_list = inc_event_file_list, + inc_event_location_list = inc_event_location_list, + inc_event_person_list = inc_event_person_list, + inc_event_presentation_list = inc_event_presentation_list, + inc_event_presenter_list = inc_event_presenter_list, + inc_event_registration_list = inc_event_registration_list, + inc_event_session_list = inc_event_session_list, + inc_event_track_list = inc_event_track_list, + # inc_person = inc_person, + # inc_user = inc_user, + ) + ) account_obj.event_list = event_dict_list else: account_obj.event_list = [] + # if inc_event_list: + # if event_dict_list := load_event_obj_list( + # account_id = account_id, + # limit = limit, + # model_as_dict = model_as_dict, + # enabled = enabled, + # # inc_location_address = inc_address, + # # inc_contact_1 = inc_contact, + # # inc_contact_2 = inc_contact, + # # inc_contact_3 = inc_contact, + # # inc_event_abstract_list = inc_event_abstract_list, + # # inc_event_badge_list = inc_event_badge_list, + # # inc_event_device_list = inc_event_device_list, + # inc_event_exhibit_list = inc_event_exhibit_list, + # inc_event_file_list = inc_event_file_list, + # inc_event_location_list = inc_event_location_list, + # inc_event_person_list = inc_event_person_list, + # inc_event_presentation_list = inc_event_presentation_list, + # inc_event_presenter_list = inc_event_presenter_list, + # inc_event_registration_list = inc_event_registration_list, + # inc_event_session_list = inc_event_session_list, + # inc_event_track_list = inc_event_track_list, + # # inc_person = inc_person, + # # inc_user = inc_user, + # ): + # account_obj.event_list = event_dict_list + # else: account_obj.event_list = [] + + # Updated 2021-06-17 + if inc_organization_list: + if organization_rec_list_result := get_organization_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + organization_dict_list = [] + for organization_rec in organization_rec_list_result: + organization_dict_list.append( + load_organization_obj( + organization_id = organization_rec.get('organization_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + inc_address = inc_address, + inc_contact = inc_contact, + inc_person = inc_person, + inc_user = inc_user, + ) + ) + account_obj.organization_list = organization_dict_list + else: account_obj.organization_list = [] + + if inc_post_list: if post_dict_list := load_post_obj_list( account_id = account_id, @@ -203,6 +318,83 @@ def load_account_obj( account_obj.post_list = post_dict_list else: account_obj.post_list = [] + # Updated 2021-06-17 + if inc_person_list: + if person_rec_list_result := get_person_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + person_dict_list = [] + for person_rec in person_rec_list_result: + person_dict_list.append( + load_person_obj( + person_id = person_rec.get('person_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + inc_address = inc_address, + inc_contact = inc_contact, + inc_organization = inc_organization, + inc_user = inc_user, + ) + ) + account_obj.person_list = person_dict_list + else: account_obj.person_list = [] + + # Updated 2021-06-17 + if inc_product_list: + if product_rec_list_result := get_product_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + product_dict_list = [] + for product_rec in product_rec_list_result: + product_dict_list.append( + load_product_obj( + product_id = product_rec.get('product_id', None), + model_as_dict = model_as_dict, + ) + ) + account_obj.product_list = product_dict_list + else: account_obj.product_list = [] + + # Updated 2021-06-17 + if inc_user_list: + if user_rec_list_result := get_user_rec_list( + for_obj_type = 'account', + for_obj_id = account_id, + limit = limit, + enabled = enabled, + ): + user_dict_list = [] + for user_rec in user_rec_list_result: + user_dict_list.append( + load_user_obj( + user_id = user_rec.get('user_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + inc_address = inc_address, + inc_contact = inc_contact, + inc_event_list = inc_event_list, + inc_journal_list = inc_journal_list, + inc_membership_member = inc_membership_member, + inc_order_list = inc_order_list, + inc_order_cart_list = inc_order_cart_list, + inc_organization = inc_organization, + inc_person = inc_person, + inc_post_list = inc_post_list, + inc_post_comment_list = inc_post_comment_list, + inc_user_role_list = inc_user_role_list, + ) + ) + account_obj.user_list = user_dict_list + else: account_obj.user_list = [] + if model_as_dict: return account_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member else: diff --git a/app/methods/address_methods.py b/app/methods/address_methods.py index 26dbd9e..ae109a3 100644 --- a/app/methods/address_methods.py +++ b/app/methods/address_methods.py @@ -91,3 +91,57 @@ def update_address_obj( log.debug(address_obj_up_result) return False # ### END ### API Address Methods ### update_address_obj() ### + + +# ### BEGIN ### API Address Methods ### get_address_rec_list() ### +def get_address_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'address_id', `tbl`.id_random AS 'address_id_random' + FROM `address` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if address_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + address_rec_li = address_rec_li_result + else: + address_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(address_rec_li_result) + + return address_rec_li +# ### END ### API Address Methods ### get_address_rec_list() ### diff --git a/app/methods/archive_methods.py b/app/methods/archive_methods.py index 255e3c0..50f27aa 100644 --- a/app/methods/archive_methods.py +++ b/app/methods/archive_methods.py @@ -125,3 +125,57 @@ def load_archive_obj_list( return archive_result_li # ### END ### API Archive Methods ### load_archive_obj_list() ### + + +# ### BEGIN ### API Archive Methods ### get_archive_rec_list() ### +def get_archive_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'archive_id', `tbl`.id_random AS 'archive_id_random' + FROM `archive` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if archive_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + archive_rec_li = archive_rec_li_result + else: + archive_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(archive_rec_li_result) + + return archive_rec_li +# ### END ### API Archive Methods ### get_archive_rec_list() ### diff --git a/app/methods/event_methods.py b/app/methods/event_methods.py index e68683e..325109c 100644 --- a/app/methods/event_methods.py +++ b/app/methods/event_methods.py @@ -405,3 +405,57 @@ def update_event_obj( log.debug(event_obj_up_result) return False # ### END ### API Event Methods ### update_event_obj() ### + + +# ### BEGIN ### API Event Methods ### get_event_rec_list() ### +def get_event_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'event_id', `tbl`.id_random AS 'event_id_random' + FROM `event` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if event_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + event_rec_li = event_rec_li_result + else: + event_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(event_rec_li_result) + + return event_rec_li +# ### END ### API Event Methods ### get_event_rec_list() ### diff --git a/app/methods/membership_cfg_methods.py b/app/methods/membership_cfg_methods.py index fc3c61a..47b626e 100644 --- a/app/methods/membership_cfg_methods.py +++ b/app/methods/membership_cfg_methods.py @@ -24,10 +24,11 @@ def load_membership_cfg_obj( if membership_cfg_rec := sql_select( table_name = 'v_membership_cfg', field_name = 'account_id', - field_value = account_id + field_value = account_id, ): pass else: return False log.debug(membership_cfg_rec) + try: membership_cfg_obj = Membership_Cfg_Base(**membership_cfg_rec) log.debug(membership_cfg_obj) diff --git a/app/methods/membership_member_methods.py b/app/methods/membership_member_methods.py new file mode 100644 index 0000000..72cf090 --- /dev/null +++ b/app/methods/membership_member_methods.py @@ -0,0 +1,438 @@ +from __future__ import annotations +import datetime + +from typing import Dict, List, Optional, Set, Union +from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator + +from app.lib_general import log, logging +from app.db_sql import redis_lookup_id_random, sql_insert_or_update, sql_select + +#from .address_models import Address_Base +#from .contact_models import Contact_Base +from app.models.membership_member_models import Membership_Member_Base +from app.models.membership_profile_models import Membership_Profile_Base +#from .organization_models import Organization_Base +#from .person_models import Person_Base +#from .user_models import User_Base + + +# ### BEGIN ### API Membership Member Methods ### save_membership_member_obj() ### +def save_membership_member_obj(order_obj_new:Membership_Member_Base=None): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if not order_obj_new: + return False + + log.debug(order_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True)) + + order_line_obj_li_curr = [] # Initialize to store order_line list + if order_obj_new.id_random: + log.info(f'An order.id {order_obj_new.id} or order.id_random {order_obj_new.id_random} was included. We can update an existing order.') + log.info(f'Get the current order_line list to compare with what was sent...') + data = {} + data['order_id_random'] = order_obj_new.id_random + + if order_line_rec_li_curr := sql_select(table_name='v_order_line', data=data, rm_id_random=True, as_list=True): + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(order_line_rec_li_curr) + + for order_line_rec in order_line_rec_li_curr: + try: + order_line_obj = Order_Line_Base(**order_line_rec) + log.debug(order_line_obj) + except ValidationError as e: + log.error(e.json()) + order_line_obj_li_curr.append(order_line_obj) + else: + log.info(f'No order_line records were found') + + + elif order_obj_new.account_id_random and (order_obj_new.person_id_random or order_obj_new.user_id_random): + log.info(f'An account.id_random {order_obj_new.account_id_random} was passed. And either a person.id_random {order_obj_new.person_id_random} or user.id_random {order_obj_new.user_id_random} was passed. We can create a new order.') + # Because there was not an order ID, assume there are no order lines yet. So no look up. + else: + log.info('Either an order ID is required to update an order or an account ID along with a person ID or user ID is required to create an order.') + return False + + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(order_line_obj_li_curr) + + if repl_order_line_list: # This will remove any order line list items not sent with the new order information. + log.info('Removing any order line list items not sent with the new order information...') + for index, order_line_obj_curr in enumerate(order_line_obj_li_curr): + log.info(f'Current: order line ID={order_line_obj_curr.id_random} and product ID= {order_line_obj_curr.product_id_random}') + matched_product_id = False + for order_line_obj_new in order_obj_new.order_line_list: + log.debug(f'Checking new: product ID={order_line_obj_new.product_id_random}') + + if order_line_obj_curr.product_id_random == order_line_obj_new.product_id_random: + matched_product_id = True + log.debug(f'Matched: product ID={order_line_obj_new.product_id_random}') + break + else: + log.debug(f'No match: product ID={order_line_obj_new.product_id_random}') + if not matched_product_id: # Was not found in the new order line list sent + log.info(f'Current order line product ID did not match any of the new list. DELETE order line ID {order_line_obj_curr.id_random} with product ID {order_line_obj_curr.product_id_random}') + + if order_line_del_result := sql_delete(table_name='order_line', record_id_random=order_line_obj_curr.id_random): + log.info(f'Deleted record and now pop the current list item {index}...') + order_line_obj_li_curr.pop(index) + else: + log.info(f'Current order line product ID matched. Keeping order line ID {order_line_obj_curr.id_random} with product ID {order_line_obj_curr.product_id_random}') + # NOTE: That this current order line item will be updated below. + log.debug(order_line_obj_li_curr) + + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + + log.info('Loop through the line list that was sent and compare with what was pulled from the DB') + # Loop through the new line list that was sent and compare with the current line list that was pulled from the DB + # Only insert if a product ID does not match + # Only update if a product ID does match + for order_line_obj_new in order_obj_new.order_line_list: + log.info(f'New: order line ID={order_line_obj_new.id_random} and product ID= {order_line_obj_new.product_id_random}') + matched_product_id = False + for index, order_line_obj_curr in enumerate(order_line_obj_li_curr): + log.debug(f'Checking current: product ID={order_line_obj_curr.product_id_random}') + + if order_line_obj_new.product_id_random == order_line_obj_curr.product_id_random: + matched_product_id = True + log.debug(f'Matched: product ID={order_line_obj_curr.product_id_random}') + log.info(f'Updating the current line item with the new line item.') + order_line_obj_new.id_random = order_line_obj_curr.id_random + order_line_obj_new.id = order_line_obj_curr.id + order_line_obj_li_curr[index] = order_line_obj_new + break + else: + log.debug(f'No match: product ID={order_line_obj_curr.product_id_random}') + + if not matched_product_id: # Was not found in the current order line list that was pulled from the DB + log.info(f'New order line product ID did not match any of the current list. Append order line ID {order_line_obj_new.id_random} with product ID {order_line_obj_new.product_id_random}') + log.info('Append to current list...') + order_line_obj_li_curr.append(order_line_obj_new) # These will be inserted/updated below + + # Save merged current and new list to the new order object + order_obj_new.order_line_list = order_line_obj_li_curr + log.debug(order_obj_new) + + # Final loop through to get the new order totals + # Calculate totals + order_total_amount:int = 0 + order_total_quantity:int = 0 + for order_line_obj_new in order_obj_new.order_line_list: + order_total_amount += order_line_obj_new.quantity * order_line_obj_new.amount + order_total_quantity += order_line_obj_new.quantity + + order_obj_new.total_bill = order_total_amount # "amount" is used by order_cart and Stripe + order_obj_new.total_quantity = order_total_quantity + order_obj_new.balance = order_total_amount - order_obj_new.total_paid + + log.debug(order_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'order_line_list', 'cfg', 'created_on', 'updated_on'})) + order_obj_data = order_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'order_line_list', 'cfg', 'created_on', 'updated_on'}) + + # SQL INSERT or UPDATE the order record + log.info('SQL INSERT or UPDATE the order record') + if order_obj_resp := sql_insert_or_update(data=order_obj_data, table_name='order', rm_id_random=True, id_random_length=8): pass + else: return False + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(order_obj_resp) + + if isinstance(order_obj_resp, bool) and order_obj_resp: + if order_id := order_obj_new.id: pass + elif order_id := order_obj_new.id_random: pass + elif isinstance(order_obj_resp, int): + order_id = order_obj_resp + else: + return False + log.debug(f'Order ID={order_id}') + + # Loop through the order_line list to SQL INSERT or UPDATE the records + log.info('Loop through the order_line list to SQL INSERT or UPDATE the records') + for order_line_obj_new in order_obj_new.order_line_list: + log.info(f"New order_line: order_line_id_random={order_line_obj_new.id_random}; product_id_random={order_line_obj_new.product_id_random}") + log.debug(order_line_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=False, exclude={'order_line_id_random', 'product_type_id', 'product_type', 'created_on', 'updated_on'})) + + order_line_obj_data = order_line_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'order_line_id_random', 'product_type_id', 'product_type', 'created_on', 'updated_on'}) + + order_line_obj_data['order_id'] = order_id + + if order_line_obj_resp := sql_insert_or_update(sql=None, data=order_line_obj_data, table_name='order_line', rm_id_random=True, id_random_length=8): pass + else: return False + log.debug(order_line_obj_resp) + return order_id +# ### END ### API Membership Member Methods ### save_membership_member_obj() ### + + +# ### BEGIN ### API Membership Member Methods ### load_membership_member_obj() ### +def load_membership_member_obj( + membership_member_id:int|str, + limit: int = 1000, + model_as_dict: bool = False, + enabled: str = 'enabled', # enabled, disabled, all + inc_address: bool = False, + inc_contact: bool = False, + inc_membership_cfg: bool = False, + inc_membership_group_list: bool = False, + inc_membership_profile: bool = False, + # inc_membership_profile_cust: bool = False, + inc_organization: bool = False, + inc_person: bool = False, + inc_user: bool = False, + ) -> Membership_Member_Base: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if membership_member_id := redis_lookup_id_random(record_id_random=membership_member_id, table_name='membership_member'): pass + else: return False + + if membership_member_rec := sql_select(table_name='v_membership_member', record_id=membership_member_id): pass + else: return False + + try: + membership_member_obj = Membership_Member_Base(**membership_member_rec) + log.debug(membership_member_obj) + except ValidationError as e: + log.error(e.json()) + + if inc_membership_profile: + membership_profile_id = membership_member_rec.get('membership_profile_id', None) + log.debug(membership_profile_id) + if membership_profile_dict := load_membership_profile_obj( + membership_profile_id = membership_profile_id, + model_as_dict = model_as_dict, + inc_address = inc_address, + inc_contact = inc_contact, + # inc_membership = inc_membership, + # inc_organization = inc_organization, + ): + membership_member_obj.membership_profile = membership_profile_dict + else: membership_member_obj.membership_profile = None + log.debug(membership_profile_dict) + + if inc_person: + person_id = membership_member_rec.get('person_id', None) + log.debug(person_id) + if person_dict := load_person_obj( + person_id = person_id, + model_as_dict = model_as_dict, + inc_address = inc_address, + inc_contact = inc_contact, + # inc_organization = inc_organization, + # inc_user = inc_user, + ): + membership_member_obj.person = person_dict + else: membership_member_obj.person = None + log.debug(person_dict) + + if inc_user: + user_id = membership_member_rec.get('user_id', None) + if user_dict := load_user_obj( + user_id = user_id, + model_as_dict = model_as_dict, + inc_address = inc_address, + inc_contact = inc_contact, + # inc_organization = inc_organization, + # inc_person = inc_person, + ): + membership_member_obj.user = user_dict + else: membership_member_obj.user = None + log.debug(user_dict) + + if membership_member_rec := sql_select(table_name='v_membership', record_id=membership_member_id): + #log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_rec) + + if inc_membership_member_profile: + if membership_member_profile_rec := sql_select(table_name='v_membership_member_profile', field_name='membership_member_id', field_value=membership_member_id): + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_profile_rec) + + membership_member_rec['profile'] = membership_member_profile_rec + + if inc_membership_member_cfg: + if membership_member_cfg_rec := sql_select(table_name='v_membership_member_cfg', field_name='account_id', field_value=membership_member_rec.get('account_id', None)): + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_cfg_rec) + + membership_member_rec['cfg'] = membership_member_cfg_rec + + if inc_extended_profile: + account_code = membership_member_rec.get('account_code', None) + table_name = f'c_{account_code}_membership_member_profile' + if extended_profile_rec := sql_select(table_name=table_name, field_name='membership_member_id', field_value=membership_member_id): + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(extended_profile_rec) + + membership_member_rec['extended_profile'] = extended_profile_rec + + if inc_person: + if person_rec := sql_select(table_name='v_person', record_id=membership_member_rec.get('person_id')): + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(person_rec) + + membership_member_rec['person'] = person_rec + + if inc_user: + if user_rec := sql_select(table_name='v_user', record_id=membership_member_rec.get('user_id')): + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(user_rec) + + membership_member_rec['user'] = user_rec + + #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_rec) + else: + return False + + if model_as_dict: + return membership_member_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member + else: + return membership_member_obj +# ### END ### API Membership Member Methods ### load_membership_member_obj() ### + + + +# ### BEGIN ### API Membership Member Methods ### load_membership_member_obj_list() ### +def load_membership_member_obj_list( + account_id: int|str|None = None, + membership_id: int|str|None = None, + limit: int = 1000, + model_as_dict: bool = False, + enabled: str = 'enabled', # enabled, disabled, all + inc_address: bool = False, + inc_contact: bool = False, + inc_membership_cfg: bool = False, + inc_membership_group_list: bool = False, + inc_membership_profile: bool = False, + # inc_membership_profile_cust: bool = False, + inc_organization: bool = False, + inc_person: bool = False, + inc_user: bool = False + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + data = {} + if account_id: + if account_id := redis_lookup_id_random(record_id_random=account_id, table_name='account'): pass + else: return False + data['account_id'] = account_id + sql_obj_type_id = f'`tbl`.account_id = :account_id' + elif membership_id: + if membership_id := redis_lookup_id_random(record_id_random=membership_id, table_name='membership'): pass + else: return False + data['membership_id'] = membership_id + sql_obj_type_id = f'`tbl`.membership_id = :membership_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + # else: tbl_obj['account'] = None + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'membership_member_id', `tbl`.id_random AS 'membership_member_id_random' + FROM `membership_member` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if membership_member_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_rec_li_result) + membership_member_result_li = [] + for membership_member_rec in membership_member_rec_li_result: + membership_member_id = membership_member_rec.get('membership_member_id', None) + if membership_member_result := load_membership_member_obj( + membership_member_id = membership_member_id, + model_as_dict = model_as_dict, + enabled = enabled, + # inc_membership = inc_membership, + inc_membership_group_list = inc_membership_group_list, + inc_membership_profile = inc_membership_profile, + inc_organization = inc_organization, + inc_person = inc_person, + # inc_product = inc_product, + inc_user = inc_user, + ): + log.debug(membership_member_result) + membership_member_result_li.append(membership_member_result) + else: + log.debug(membership_member_result) + membership_member_result_li.append(None) + log.debug(membership_member_result_li) + else: + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_rec_li_result) + membership_member_result_li = [] + + return membership_member_result_li +# ### END ### API Membership Member Methods ### load_membership_member_obj_list() ### + + +# ### BEGIN ### API Membership Member Methods ### get_membership_member_rec_list() ### +def get_membership_member_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'membership_member_id', `tbl`.id_random AS 'membership_member_id_random' + FROM `membership_member` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if membership_member_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + membership_member_rec_li = membership_member_rec_li_result + else: + membership_member_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(membership_member_rec_li_result) + + return membership_member_rec_li +# ### END ### API Membership Member Methods ### get_membership_member_rec_list() ### diff --git a/app/methods/membership_methods.py b/app/methods/membership_methods.py index d1a2a0a..b27507e 100644 --- a/app/methods/membership_methods.py +++ b/app/methods/membership_methods.py @@ -4,217 +4,53 @@ import datetime from typing import Dict, List, Optional, Set, Union from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator -from app.lib_general import * +from app.lib_general import log, logging from app.db_sql import redis_lookup_id_random, sql_select -#from .address_models import Address_Base -#from .contact_models import Contact_Base +from app.methods.membership_cfg_methods import load_membership_cfg_obj +from app.methods.membership_member_methods import get_membership_member_rec_list, load_membership_member_obj +from app.methods.product_methods import get_product_rec_list, load_product_obj + from app.models.membership_models import Membership_Base -#from .organization_models import Organization_Base -#from .person_models import Person_Base -#from .user_models import User_Base # ### BEGIN ### API Membership Methods ### save_membership_obj() ### -def save_membership_obj(order_obj_new:Membership_Base=None): +def save_membership_obj(membership_obj_new:Membership_Base): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - if not order_obj_new: - return False - - log.debug(order_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True)) - - order_line_obj_li_curr = [] # Initialize to store order_line list - if order_obj_new.id_random: - log.info(f'An order.id {order_obj_new.id} or order.id_random {order_obj_new.id_random} was included. We can update an existing order.') - log.info(f'Get the current order_line list to compare with what was sent...') - data = {} - data['order_id_random'] = order_obj_new.id_random - - if order_line_rec_li_curr := sql_select(table_name='v_order_line', data=data, rm_id_random=True, as_list=True): - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(order_line_rec_li_curr) - - for order_line_rec in order_line_rec_li_curr: - try: - order_line_obj = Order_Line_Base(**order_line_rec) - log.debug(order_line_obj) - except ValidationError as e: - log.error(e.json()) - order_line_obj_li_curr.append(order_line_obj) - else: - log.info(f'No order_line records were found') - - - elif order_obj_new.account_id_random and (order_obj_new.person_id_random or order_obj_new.user_id_random): - log.info(f'An account.id_random {order_obj_new.account_id_random} was passed. And either a person.id_random {order_obj_new.person_id_random} or user.id_random {order_obj_new.user_id_random} was passed. We can create a new order.') - # Because there was not an order ID, assume there are no order lines yet. So no look up. - else: - log.info('Either an order ID is required to update an order or an account ID along with a person ID or user ID is required to create an order.') - return False - - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(order_line_obj_li_curr) - - if repl_order_line_list: # This will remove any order line list items not sent with the new order information. - log.info('Removing any order line list items not sent with the new order information...') - for index, order_line_obj_curr in enumerate(order_line_obj_li_curr): - log.info(f'Current: order line ID={order_line_obj_curr.id_random} and product ID= {order_line_obj_curr.product_id_random}') - matched_product_id = False - for order_line_obj_new in order_obj_new.order_line_list: - log.debug(f'Checking new: product ID={order_line_obj_new.product_id_random}') - - if order_line_obj_curr.product_id_random == order_line_obj_new.product_id_random: - matched_product_id = True - log.debug(f'Matched: product ID={order_line_obj_new.product_id_random}') - break - else: - log.debug(f'No match: product ID={order_line_obj_new.product_id_random}') - if not matched_product_id: # Was not found in the new order line list sent - log.info(f'Current order line product ID did not match any of the new list. DELETE order line ID {order_line_obj_curr.id_random} with product ID {order_line_obj_curr.product_id_random}') - - if order_line_del_result := sql_delete(table_name='order_line', record_id_random=order_line_obj_curr.id_random): - log.info(f'Deleted record and now pop the current list item {index}...') - order_line_obj_li_curr.pop(index) - else: - log.info(f'Current order line product ID matched. Keeping order line ID {order_line_obj_curr.id_random} with product ID {order_line_obj_curr.product_id_random}') - # NOTE: That this current order line item will be updated below. - log.debug(order_line_obj_li_curr) - - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - - log.info('Loop through the line list that was sent and compare with what was pulled from the DB') - # Loop through the new line list that was sent and compare with the current line list that was pulled from the DB - # Only insert if a product ID does not match - # Only update if a product ID does match - for order_line_obj_new in order_obj_new.order_line_list: - log.info(f'New: order line ID={order_line_obj_new.id_random} and product ID= {order_line_obj_new.product_id_random}') - matched_product_id = False - for index, order_line_obj_curr in enumerate(order_line_obj_li_curr): - log.debug(f'Checking current: product ID={order_line_obj_curr.product_id_random}') - - if order_line_obj_new.product_id_random == order_line_obj_curr.product_id_random: - matched_product_id = True - log.debug(f'Matched: product ID={order_line_obj_curr.product_id_random}') - log.info(f'Updating the current line item with the new line item.') - order_line_obj_new.id_random = order_line_obj_curr.id_random - order_line_obj_new.id = order_line_obj_curr.id - order_line_obj_li_curr[index] = order_line_obj_new - break - else: - log.debug(f'No match: product ID={order_line_obj_curr.product_id_random}') - - if not matched_product_id: # Was not found in the current order line list that was pulled from the DB - log.info(f'New order line product ID did not match any of the current list. Append order line ID {order_line_obj_new.id_random} with product ID {order_line_obj_new.product_id_random}') - log.info('Append to current list...') - order_line_obj_li_curr.append(order_line_obj_new) # These will be inserted/updated below - - # Save merged current and new list to the new order object - order_obj_new.order_line_list = order_line_obj_li_curr - log.debug(order_obj_new) - - # Final loop through to get the new order totals - # Calculate totals - order_total_amount:int = 0 - order_total_quantity:int = 0 - for order_line_obj_new in order_obj_new.order_line_list: - order_total_amount += order_line_obj_new.quantity * order_line_obj_new.amount - order_total_quantity += order_line_obj_new.quantity - - order_obj_new.total_bill = order_total_amount # "amount" is used by order_cart and Stripe - order_obj_new.total_quantity = order_total_quantity - order_obj_new.balance = order_total_amount - order_obj_new.total_paid - - log.debug(order_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'order_line_list', 'cfg', 'created_on', 'updated_on'})) - order_obj_data = order_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'order_line_list', 'cfg', 'created_on', 'updated_on'}) - - # SQL INSERT or UPDATE the order record - log.info('SQL INSERT or UPDATE the order record') - if order_obj_resp := sql_insert_or_update(data=order_obj_data, table_name='order', rm_id_random=True, id_random_length=8): pass - else: return False - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(order_obj_resp) - - if isinstance(order_obj_resp, bool) and order_obj_resp: - if order_id := order_obj_new.id: pass - elif order_id := order_obj_new.id_random: pass - elif isinstance(order_obj_resp, int): - order_id = order_obj_resp - else: - return False - log.debug(f'Order ID={order_id}') - - # Loop through the order_line list to SQL INSERT or UPDATE the records - log.info('Loop through the order_line list to SQL INSERT or UPDATE the records') - for order_line_obj_new in order_obj_new.order_line_list: - log.info(f"New order_line: order_line_id_random={order_line_obj_new.id_random}; product_id_random={order_line_obj_new.product_id_random}") - log.debug(order_line_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=False, exclude={'order_line_id_random', 'product_type_id', 'product_type', 'created_on', 'updated_on'})) - - order_line_obj_data = order_line_obj_new.dict(by_alias=False, exclude_defaults=False, exclude_unset=True, exclude={'order_line_id_random', 'product_type_id', 'product_type', 'created_on', 'updated_on'}) - - order_line_obj_data['order_id'] = order_id - - if order_line_obj_resp := sql_insert_or_update(sql=None, data=order_line_obj_data, table_name='order_line', rm_id_random=True, id_random_length=8): pass - else: return False - log.debug(order_line_obj_resp) - return order_id + return membership_id # ### END ### API Membership Methods ### save_membership_obj() ### # ### BEGIN ### API Membership Methods ### load_membership_obj() ### -def load_membership_obj(membership_id:int|str, inc_membership_profile:bool=False, inc_membership_cfg:bool=False, inc_extended_profile:bool=False, inc_person:bool=False, inc_user:bool=False) -> Membership_Base: +def load_membership_obj( + membership_id:int|str, + limit: int = 1000, + model_as_dict: bool = False, + enabled: str = 'enabled', # enabled, disabled, all + inc_address: bool = False, + inc_contact: bool = False, + inc_membership_cfg: bool = False, + inc_membership_group_list: bool = False, + inc_membership_member_list: bool = False, + inc_membership_profile: bool = False, + inc_organization: bool = False, + inc_person: bool = False, + inc_product: bool = False, + inc_product_list: bool = False, + inc_user: bool = False, + ) -> Membership_Base: log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if membership_id := redis_lookup_id_random(record_id_random=membership_id, table_name='membership'): pass else: return False - if membership_rec := sql_select(table_name='v_membership', record_id=membership_id): - #log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(membership_rec) + if membership_rec := sql_select(table_name='v_membership', record_id=membership_id): pass + else: return False - if inc_membership_profile: - if membership_profile_rec := sql_select(table_name='v_membership_profile', field_name='membership_id', field_value=membership_id): - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(membership_profile_rec) - - membership_rec['profile'] = membership_profile_rec - - if inc_membership_cfg: - if membership_cfg_rec := sql_select(table_name='v_membership_cfg', field_name='account_id', field_value=membership_rec.get('account_id', None)): - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(membership_cfg_rec) - - membership_rec['cfg'] = membership_cfg_rec - - if inc_extended_profile: - account_code = membership_rec.get('account_code', None) - table_name = f'c_{account_code}_membership_profile' - if extended_profile_rec := sql_select(table_name=table_name, field_name='membership_id', field_value=membership_id): - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(extended_profile_rec) - - membership_rec['extended_profile'] = extended_profile_rec - - if inc_person: - if person_rec := sql_select(table_name='v_person', record_id=membership_rec.get('person_id')): - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(person_rec) - - membership_rec['person'] = person_rec - - if inc_user: - if user_rec := sql_select(table_name='v_user', record_id=membership_rec.get('user_id')): - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(user_rec) - - membership_rec['user'] = user_rec - - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(membership_rec) - else: - return False + log.debug(membership_rec) try: membership_obj = Membership_Base(**membership_rec) @@ -222,5 +58,59 @@ def load_membership_obj(membership_id:int|str, inc_membership_profile:bool=False except ValidationError as e: log.error(e.json()) - return membership_obj + if inc_membership_cfg: + if membership_cfg_rec := sql_select(table_name='v_membership_cfg', field_name='account_id', field_value=membership_rec.get('account_id', None)): + log.debug(membership_cfg_rec) + + membership_rec['cfg'] = membership_cfg_rec + + if inc_membership_member_list: + if membership_member_rec_list_result := get_membership_member_rec_list( + for_obj_type = 'membership', + for_obj_id = membership_id, + limit = limit, + enabled = enabled, + ): + membership_member_dict_list = [] + for membership_member_rec in membership_member_rec_list_result: + membership_member_dict_list.append( + load_membership_member_obj( + membership_member_id = membership_member_rec.get('membership_member_id', None), + limit = limit, + model_as_dict = model_as_dict, + enabled = enabled, + # inc_membership = inc_membership, + inc_membership_group_list = inc_membership_group_list, + inc_membership_profile = inc_membership_profile, + inc_organization = inc_organization, + inc_person = inc_person, + inc_product = inc_product, + inc_user = inc_user, + ) + ) + membership_obj.membership_member_list = membership_member_dict_list + else: membership_obj.membership_member_list = [] + + if inc_product_list: + if product_rec_list_result := get_product_rec_list( + for_obj_type = 'membership', + for_obj_id = membership_id, + limit = limit, + enabled = enabled, + ): + product_dict_list = [] + for product_rec in product_rec_list_result: + product_dict_list.append( + load_product_obj( + product_id = product_rec.get('product_id', None), + model_as_dict = model_as_dict, + ) + ) + membership_obj.product_list = product_dict_list + else: membership_obj.product_list = [] + + if model_as_dict: + return membership_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member + else: + return membership_obj # ### END ### API Membership Methods ### load_membership_obj() ### diff --git a/app/methods/organization_methods.py b/app/methods/organization_methods.py index d89dceb..da75bb8 100644 --- a/app/methods/organization_methods.py +++ b/app/methods/organization_methods.py @@ -106,4 +106,58 @@ def update_organization_obj( else: log.debug(organization_obj_up_result) return False -# ### END ### API Organization Methods ### update_organization_obj() ### \ No newline at end of file +# ### END ### API Organization Methods ### update_organization_obj() ### + + +# ### BEGIN ### API Organization Methods ### get_organization_rec_list() ### +def get_organization_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'organization_id', `tbl`.id_random AS 'organization_id_random' + FROM `organization` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if organization_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + organization_rec_li = organization_rec_li_result + else: + organization_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(organization_rec_li_result) + + return organization_rec_li +# ### END ### API Organization Methods ### get_organization_rec_list() ### diff --git a/app/methods/person_methods.py b/app/methods/person_methods.py index bc5a0c5..67e378f 100644 --- a/app/methods/person_methods.py +++ b/app/methods/person_methods.py @@ -240,3 +240,57 @@ def update_person_obj( log.debug(person_obj_up_result) return False # ### END ### API Person Methods ### update_person_obj() ### + + +# ### BEGIN ### API Person Methods ### get_person_rec_list() ### +def get_person_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'person_id', `tbl`.id_random AS 'person_id_random' + FROM `person` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if person_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + person_rec_li = person_rec_li_result + else: + person_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(person_rec_li_result) + + return person_rec_li +# ### END ### API Person Methods ### get_person_rec_list() ### diff --git a/app/methods/product_methods.py b/app/methods/product_methods.py new file mode 100644 index 0000000..17f9894 --- /dev/null +++ b/app/methods/product_methods.py @@ -0,0 +1,92 @@ +from __future__ import annotations +import datetime + +from typing import Dict, List, Optional, Set, Union +from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator + +from app.lib_general import log, logging +from app.db_sql import redis_lookup_id_random, sql_insert_or_update, sql_select + +from app.models.product_models import Product_Base + + +# ### BEGIN ### API Product Methods ### load_product_obj() ### +def load_product_obj( + product_id: int|str, + limit: int = 1000, + model_as_dict: bool = False, + ) -> Product_Base: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if product_id := redis_lookup_id_random(record_id_random=product_id, table_name='product'): pass + else: return False + + if product_rec := sql_select(table_name='v_product', record_id=product_id): pass + else: return False + + try: + product_obj = Product_Base(**product_rec) + log.debug(product_obj) + except ValidationError as e: + log.error(e.json()) + + if model_as_dict: + return product_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member + else: + return product_obj +# ### END ### API Product Methods ### load_product_obj() ### + + +# ### BEGIN ### API Product Methods ### get_product_rec_list() ### +def get_product_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'product_id', `tbl`.id_random AS 'product_id_random' + FROM `product` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if product_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + product_rec_li = product_rec_li_result + else: + product_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(product_rec_li_result) + + return product_rec_li +# ### END ### API Product Methods ### get_product_rec_list() ### diff --git a/app/methods/user_methods.py b/app/methods/user_methods.py index b0fb8ef..e51bde8 100644 --- a/app/methods/user_methods.py +++ b/app/methods/user_methods.py @@ -180,18 +180,18 @@ def load_user_obj( # NOTE: Including user roles should probably be reviewed if inc_user_role_list: if role_rec_li := sql_select(table_name='v_user_role_detail', field_name='user_id', field_value=user_id, as_list=True): - user_rec['role_list'] = role_rec_li - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(role_rec_li) + # user_rec['role_list'] = role_rec_li user_obj.role_list = role_rec_li else: - user_rec['role_list'] = None + # user_rec['role_list'] = None user_obj.role_list = None + log.debug(user_rec) + log.debug(user_obj) - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(user_rec) - - return user_obj + if model_as_dict: + return user_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member + else: + return user_obj # ### END ### API User Methods ### load_user_obj() ### @@ -299,3 +299,57 @@ def update_user_obj( log.debug(user_obj_up_result) return False # ### END ### API User Methods ### update_user_obj() ### + + +# ### BEGIN ### API User Methods ### get_user_rec_list() ### +def get_user_rec_list( + for_obj_type: str, + for_obj_id: str, + limit: int = 1000, + enabled: str = 'enabled', # enabled, disabled, all + ) -> list|bool: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if for_obj_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name='for_obj_type'): pass + else: return False + data = {} + data[f'{for_obj_type}_id'] = for_obj_id + # data['for_obj_type'] = for_obj_type + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' + + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'user_id', `tbl`.id_random AS 'user_id_random' + FROM `user` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + + if user_rec_li_result := sql_select(data=data, sql=sql, as_list=True): + user_rec_li = user_rec_li_result + else: + user_rec_li = [] + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(user_rec_li_result) + + return user_rec_li +# ### END ### API User Methods ### get_user_rec_list() ### diff --git a/app/models/common_field_schema.py b/app/models/common_field_schema.py index 3272315..517e2b4 100644 --- a/app/models/common_field_schema.py +++ b/app/models/common_field_schema.py @@ -49,6 +49,9 @@ base_fields['hosted_file_id_random'] = xxx_id_random_field_schema base_fields['journal_id_random'] = xxx_id_random_field_schema base_fields['journal_entry_id_random'] = xxx_id_random_field_schema base_fields['membership_id_random'] = xxx_id_random_field_schema +base_fields['membership_cfg_id_random'] = xxx_id_random_field_schema +base_fields['membership_group_id_random'] = xxx_id_random_field_schema +base_fields['membership_member_id_random'] = xxx_id_random_field_schema base_fields['membership_profile_id_random'] = xxx_id_random_field_schema base_fields['order_cart_id_random'] = xxx_id_random_field_schema base_fields['order_cart_line_id_random'] = xxx_id_random_field_schema diff --git a/app/models/membership_cfg_models.py b/app/models/membership_cfg_models.py index 89f13d4..a5b31b3 100644 --- a/app/models/membership_cfg_models.py +++ b/app/models/membership_cfg_models.py @@ -7,7 +7,7 @@ from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationEr from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging -from .common_field_schema import base_fields, default_num_bytes +from app.models.common_field_schema import base_fields, default_num_bytes class Membership_Cfg_Base(BaseModel): diff --git a/app/models/membership_group_models.py b/app/models/membership_group_models.py new file mode 100644 index 0000000..d62c538 --- /dev/null +++ b/app/models/membership_group_models.py @@ -0,0 +1,86 @@ +from __future__ import annotations +import datetime, hashlib, logging, os, pytz, redis, secrets + +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.membership_models import Membership_Base + + +class Membership_Group_Base(BaseModel): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + id_random: Optional[str] = Field( + **base_fields['membership_group_id_random'], + alias='membership_group_id_random', + default_factory=lambda:secrets.token_urlsafe(default_num_bytes), + ) + id: Optional[int] = Field( + #alias='membership_group_id' + ) + membership_id_random: Optional[str] + membership_id: Optional[int] + parent_membership_group_id_random: Optional[str] + parent_membership_group_id: Optional[int] + + name: Optional[str] + overview: Optional[str] + description: Optional[str] + + notes: Optional[str] + created_on: Optional[datetime.datetime] = None + updated_on: Optional[datetime.datetime] = None + + # Including other related objects + membership: Optional[Membership_Base] # The membership option they currently have + parent_membership_group: Optional[Membership_Group_Base] + + _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + + #@validator('membership_group_id_random', always=True) + def membership_group_id_random_copy(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['id_random']: + return values['id_random'] + return None + + @validator('id', always=True) + def membership_group_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['id_random']: + log.debug(values['id_random']) + return redis_lookup_id_random(record_id_random=values['id_random'], table_name='membership_group') + return None + + @validator('membership_id', always=True) + def membership_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['membership_id_random']: + return redis_lookup_id_random(record_id_random=values['membership_id_random'], table_name='membership') + return None + + @validator('parent_membership_group_id', always=True) + def parent_membership_group_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['parent_membership_group_id_random']: + return redis_lookup_id_random(record_id_random=values['parent_membership_group_id_random'], table_name='membership_group') + return None + + class Config: + underscore_attrs_are_private = True + fields = base_fields + +# Membership_Group_Base.update_forward_refs() diff --git a/app/models/membership_member_models.py b/app/models/membership_member_models.py new file mode 100644 index 0000000..3365bc5 --- /dev/null +++ b/app/models/membership_member_models.py @@ -0,0 +1,145 @@ +from __future__ import annotations +import datetime, hashlib, logging, os, pytz, redis, secrets + +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.membership_models import Membership_Base +from app.models.membership_cfg_models import Membership_Cfg_Base +from app.models.membership_profile_models import Membership_Profile_Base +from app.models.person_models import Person_Base +from app.models.user_models import User_Base + + +class Membership_Member_Base(BaseModel): + log.setLevel(logging.WARNING) + log.debug(locals()) + + id_random: Optional[str] = Field( + **base_fields['membership_member_id_random'], + alias='membership_member_id_random', + default_factory=lambda:secrets.token_urlsafe(default_num_bytes), + ) + id: Optional[int] = Field( + #alias='membership_member_id' + ) + + account_id_random: Optional[str] + account_id: Optional[int] + membership_id_random: Optional[str] + membership_id: Optional[int] # NOTE: This is not optional + person_id_random: Optional[str] + person_id: Optional[int] + product_id_random: Optional[str] + product_id: Optional[int] # The product they purchased to get this membership + user_id_random: Optional[str] + user_id: Optional[int] + + level_number: Optional[int] = Field(0, ge=0, lt=150) + level_name: Optional[str] + + # type_id: Optional[int] + # type_name: Optional[str] + # status_id: Optional[int] + # status_name: Optional[str] + + application_start_on: Optional[datetime.datetime] = None + approved_on: Optional[datetime.datetime] = None + first_start_on: Optional[datetime.datetime] = None + start_buffer_on: Optional[datetime.datetime] = None + start_on: Optional[datetime.datetime] = None + end_on: Optional[datetime.datetime] = None + end_buffer_on: Optional[datetime.datetime] = None + + flag: Optional[bool] + flag_message: Optional[str] + + notes: Optional[str] + + created_on: Optional[datetime.datetime] = None + updated_on: Optional[datetime.datetime] = None + + # Including other related objects + membership: Optional[Membership_Base] # The membership option they currently have + membership_cfg: Optional[Membership_Cfg_Base] + membership_group_list: Optional[list] # Membership_Group_Base() The membership groups they are a part of + membership_profile: Optional[Membership_Profile_Base] + person: Optional[Person_Base] + user: Optional[User_Base] + + extended_member_profile: Optional[dict] = {} + + _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + + #@validator('membership_member_id_random', always=True) + def membership_member_id_random_copy(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['id_random']: + return values['id_random'] + return None + + @validator('id', always=True) + def membership_member_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['id_random']: + return redis_lookup_id_random(record_id_random=values['id_random'], table_name='membership_member') + return None + + @validator('account_id', always=True) + def account_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['account_id_random']: + return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account') + return None + + @validator('membership_id', always=True) + def membership_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['membership_id_random']: + return redis_lookup_id_random(record_id_random=values['membership_id_random'], table_name='membership') + return None + + @validator('person_id', always=True) + def person_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['person_id_random']: + return redis_lookup_id_random(record_id_random=values['person_id_random'], table_name='person') + return None + + @validator('product_id', always=True) + def product_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['product_id_random']: + return redis_lookup_id_random(record_id_random=values['product_id_random'], table_name='product') + return None + + @validator('user_id', always=True) + def user_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['user_id_random']: + return redis_lookup_id_random(record_id_random=values['user_id_random'], table_name='user') + return None + + class Config: + underscore_attrs_are_private = True + fields = base_fields + +# Membership_Base.update_forward_refs() diff --git a/app/models/membership_models.py b/app/models/membership_models.py index 16b214d..091d023 100644 --- a/app/models/membership_models.py +++ b/app/models/membership_models.py @@ -7,135 +7,14 @@ from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationEr from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging -from .common_field_schema import base_fields, default_num_bytes -from .address_models import Address_Base -from .contact_models import Contact_Base -from .membership_cfg_models import Membership_Cfg_Base -from .organization_models import Organization_Base -from .person_models import Person_Base -from .user_models import User_Base - - -class Membership_Profile_Base(BaseModel): - log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.debug(locals()) - - # if TYPE_CHECKING: - # from .supporting_core_models import Address_Base, Contact_Base, Organization_Base, User_Base - # from .person_models import Person_Base - - # from .address_models import Address_Base - # from .contact_models import Contact_Base - # from .organization_models import Organization_Base - # from .person_models import Person_Base - # from .user_models import User_Base - - id_random: Optional[str] = Field( - **base_fields['membership_profile_id_random'], - alias='membership_profile_id_random', - default_factory=lambda:secrets.token_urlsafe(default_num_bytes), - ) - id: Optional[int] = Field( - #alias='membership_profile_id' - ) - membership_id_random: Optional[str] - membership_id: Optional[int] - person_id_random: Optional[str] - person_id: Optional[int] - user_id_random: Optional[str] - user_id: Optional[int] - organization_id_random: Optional[str] - organization_id: Optional[int] - contact_id_random: Optional[str] - contact_id: Optional[int] - address_id_random: Optional[str] - address_id: Optional[int] - - display_name: Optional[str] - email: Optional[str] - - email_allowed: Optional[bool] - email_newsletter: Optional[bool] - mail_newsletter: Optional[bool] - show_online: Optional[bool] - show_printed: Optional[bool] - - biography: Optional[str] - - notes: Optional[str] - created_on: Optional[datetime.datetime] = None - updated_on: Optional[datetime.datetime] = None - - address: 'Optional[Address_Base]' = Address_Base() - contact: 'Optional[Contact_Base]' = Contact_Base() - organization: 'Optional[Organization_Base]' = Organization_Base() - person: 'Optional[Person_Base]' = Person_Base() - user: 'Optional[User_Base]' = User_Base() - - _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - - #@validator('membership_profile_id_random', always=True) - def membership_profile_id_random_copy(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['id_random']: - return values['id_random'] - return None - - @validator('id', always=True) - def membership_profile_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['id_random']: - log.debug(values['id_random']) - return redis_lookup_id_random(record_id_random=values['id_random'], table_name='membership_profile') - return None - - @validator('membership_id', always=True) - def membership_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['membership_id_random']: - return redis_lookup_id_random(record_id_random=values['membership_id_random'], table_name='membership') - return None - - @validator('person_id', always=True) - def person_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['person_id_random']: - return redis_lookup_id_random(record_id_random=values['person_id_random'], table_name='person') - return None - - @validator('user_id', always=True) - def user_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['user_id_random']: - return redis_lookup_id_random(record_id_random=values['user_id_random'], table_name='user') - return None - - class Config: - underscore_attrs_are_private = True - fields = base_fields - -Membership_Profile_Base.update_forward_refs() +from app.models.common_field_schema import base_fields, default_num_bytes +from app.models.membership_cfg_models import Membership_Cfg_Base class Membership_Base(BaseModel): log.setLevel(logging.WARNING) log.debug(locals()) - #from .supporting_core_models import User_Base - # from .account_models import Account_Base - # from .person_models import Person_Base - # from .user_models import User_Base - id_random: Optional[str] = Field( **base_fields['membership_id_random'], alias='membership_id_random', @@ -146,51 +25,57 @@ class Membership_Base(BaseModel): ) account_id_random: Optional[str] - account_id: Optional[int] # NOTE: This is not really optional - person_id_random: Optional[str] - person_id: Optional[int] - user_id_random: Optional[str] - user_id: Optional[int] - level_number: Optional[int] = Field(0, ge=0, lt=150) - level_name: Optional[str] - product_id: Optional[int] - type_id: Optional[int] - type_name: Optional[str] - category_id: Optional[int] - category_name: Optional[str] - division_id: Optional[int] - division_name: Optional[str] - status_id: Optional[int] - status_name: Optional[str] + account_id: Optional[int] - application_start_on: Optional[datetime.datetime] = None - approved_on: Optional[datetime.datetime] = None - first_start_on: Optional[datetime.datetime] = None - start_buffer_on: Optional[datetime.datetime] = None - start_on: Optional[datetime.datetime] = None - end_on: Optional[datetime.datetime] = None - end_buffer_on: Optional[datetime.datetime] = None + name: Optional[str] + description: Optional[str] - flag: Optional[bool] - flag_message: Optional[str] + cycle_type: Optional[str] # Override membership_cfg + membership_length: Optional[int] = Field(0, ge=0, lt=150) # Override membership_cfg + prorate: Optional[bool] = False # Override membership_cfg + calendar_year_start_buffer_days: Optional[int] = Field(0, ge=0, lt=150) # Override membership_cfg + calendar_year_start_buffer_on: Optional[datetime.datetime] # Override membership_cfg + calendar_year_start_on: Optional[datetime.datetime] # Override membership_cfg + calendar_year_end_on: Optional[datetime.datetime] # Override membership_cfg + calendar_year_end_buffer_days: Optional[int] = Field(0, ge=0, lt=150) # Override membership_cfg + calendar_year_end_buffer_on: Optional[datetime.datetime] # Override membership_cfg + enable_privacy_view: Optional[bool] # Override membership_cfg + + renew_warning_hours: Optional[int] # Override membership_cfg + + accept_message: Optional[str] # Override membership_cfg + reject_message: Optional[str] # Override membership_cfg + renew_message: Optional[str] # Override membership_cfg + + default_no_reply_email: Optional[str] # Override membership_cfg + default_no_reply_name: Optional[str] # Override membership_cfg + confirm_email: Optional[str] # Override membership_cfg + confirm_name: Optional[str] # Override membership_cfg + + enable: Optional[bool] + enable_from: Optional[datetime.datetime] = None + enable_to: Optional[datetime.datetime] = None + + priority: Optional[bool] + sort: Optional[int] = Field(0, ge=0, lt=100) # Essentially the membership level. Should there be a range limit? + group: Optional[str] notes: Optional[str] created_on: Optional[datetime.datetime] = None updated_on: Optional[datetime.datetime] = None - #account: Optional[Account_Base] = Account_Base() - profile: 'Optional[Membership_Profile_Base]' = Membership_Profile_Base() - person: 'Optional[Person_Base]' = Person_Base() - user: 'Optional[User_Base]' = User_Base() - cfg: 'Optional[Membership_Cfg_Base]' = Membership_Cfg_Base() + # Including JSON data + # additional_terms_conditions: Optional[dict] = {} # Is this useful? - extended_profile: Optional[dict] = {} + # Including other related objects + product: Optional[list] # Product_Base() List of products (for_type and for_id) that get this membership option + cfg: Optional[Membership_Cfg_Base] = Membership_Cfg_Base() _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - #@validator('order_id_random', always=True) - def order_id_random_copy(cls, v, values, **kwargs): + #@validator('membership_id_random', always=True) + def membership_id_random_copy(cls, v, values, **kwargs): log.setLevel(logging.WARNING) log.debug(locals()) @@ -207,35 +92,13 @@ class Membership_Base(BaseModel): return redis_lookup_id_random(record_id_random=values['id_random'], table_name='membership') return None - @validator('account_id', always=True) - def account_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) + # @validator('account_id', always=True) + # def account_id_lookup(cls, v, values, **kwargs): + # log.setLevel(logging.WARNING) + # log.debug(locals()) - if values['account_id_random']: - return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account') - return None - - @validator('person_id', always=True) - def person_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['person_id_random']: - return redis_lookup_id_random(record_id_random=values['person_id_random'], table_name='person') - return None - - @validator('user_id', always=True) - def user_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['user_id_random']: - return redis_lookup_id_random(record_id_random=values['user_id_random'], table_name='user') - return None - - class Config: - underscore_attrs_are_private = True - fields = base_fields + # if values['account_id_random']: + # return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account') + # return None # Membership_Base.update_forward_refs() diff --git a/app/models/membership_profile_models.py b/app/models/membership_profile_models.py new file mode 100644 index 0000000..8045e31 --- /dev/null +++ b/app/models/membership_profile_models.py @@ -0,0 +1,104 @@ +from __future__ import annotations +import datetime, hashlib, logging, os, pytz, redis, secrets + +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.contact_models import Contact_Base +from app.models.membership_models import Membership_Base +from app.models.organization_models import Organization_Base + + +class Membership_Profile_Base(BaseModel): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + id_random: Optional[str] = Field( + **base_fields['membership_profile_id_random'], + alias='membership_profile_id_random', + default_factory=lambda:secrets.token_urlsafe(default_num_bytes), + ) + id: Optional[int] = Field( + #alias='membership_profile_id' + ) + contact_id_random: Optional[str] + contact_id: Optional[int] + membership_id_random: Optional[str] + membership_id: Optional[int] + organization_id_random: Optional[str] + organization_id: Optional[int] + + display_name: Optional[str] + email: Optional[str] + + email_allowed: Optional[bool] + email_newsletter: Optional[bool] + mail_newsletter: Optional[bool] + show_online: Optional[bool] + show_printed: Optional[bool] + + biography: Optional[str] + + notes: Optional[str] + created_on: Optional[datetime.datetime] = None + updated_on: Optional[datetime.datetime] = None + + # Including other related objects + contact: Optional[Contact_Base] + organization: Optional[Organization_Base] = Organization_Base() + + _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + + #@validator('membership_profile_id_random', always=True) + def membership_profile_id_random_copy(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['id_random']: + return values['id_random'] + return None + + @validator('id', always=True) + def membership_profile_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['id_random']: + log.debug(values['id_random']) + return redis_lookup_id_random(record_id_random=values['id_random'], table_name='membership_profile') + return None + + @validator('membership_id', always=True) + def membership_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['membership_id_random']: + return redis_lookup_id_random(record_id_random=values['membership_id_random'], table_name='membership') + return None + + @validator('contact_id', always=True) + def contact_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['contact_id_random']: + return redis_lookup_id_random(record_id_random=values['contact_id_random'], table_name='contact') + return None + + @validator('organization_id', always=True) + def organization_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['organization_id_random']: + return redis_lookup_id_random(record_id_random=values['organization_id_random'], table_name='organization') + return None + + class Config: + underscore_attrs_are_private = True + fields = base_fields diff --git a/app/routers/event.py b/app/routers/event.py index 4cca8a2..4f7cf3c 100644 --- a/app/routers/event.py +++ b/app/routers/event.py @@ -290,31 +290,31 @@ async def get_event_obj( return mk_resp(data=None, status_code=404) if event_obj := load_event_obj( - event_id=event_id, - enabled=enabled, - limit=limit, - inc_contact_1=inc_contact_1, - inc_contact_2=inc_contact_2, - inc_contact_3=inc_contact_3, - inc_event_abstract_list=inc_event_abstract_list, - inc_event_badge_list=inc_event_badge_list, - inc_event_device_list=inc_event_device_list, - inc_event_exhibit_list=inc_event_exhibit_list, - inc_event_file_list=inc_event_file_list, - inc_event_location=inc_event_location, - inc_event_location_list=inc_event_location_list, - inc_event_person_list=inc_event_person_list, - inc_event_presentation_list=inc_event_presentation_list, - inc_event_presenter_cat=inc_event_presenter_cat, - inc_event_presenter_list=inc_event_presenter_list, - inc_event_registration_list=inc_event_registration_list, - inc_event_session_list=inc_event_session_list, - inc_event_track=inc_event_track, - inc_event_track_list=inc_event_track_list, - inc_event_cfg=inc_event_cfg, - inc_event_registration_cfg=inc_event_registration_cfg, - inc_location_address=inc_location_address, - inc_poc_event_person=inc_poc_event_person, + event_id = event_id, + enabled = enabled, + limit = limit, + inc_contact_1 = inc_contact_1, + inc_contact_2 = inc_contact_2, + inc_contact_3 = inc_contact_3, + inc_event_abstract_list = inc_event_abstract_list, + inc_event_badge_list = inc_event_badge_list, + inc_event_device_list = inc_event_device_list, + inc_event_exhibit_list = inc_event_exhibit_list, + inc_event_file_list = inc_event_file_list, + inc_event_location = inc_event_location, + inc_event_location_list = inc_event_location_list, + inc_event_person_list = inc_event_person_list, + inc_event_presentation_list = inc_event_presentation_list, + inc_event_presenter_cat = inc_event_presenter_cat, + inc_event_presenter_list = inc_event_presenter_list, + inc_event_registration_list = inc_event_registration_list, + inc_event_session_list = inc_event_session_list, + inc_event_track = inc_event_track, + inc_event_track_list = inc_event_track_list, + inc_event_cfg = inc_event_cfg, + inc_event_registration_cfg = inc_event_registration_cfg, + inc_location_address = inc_location_address, + inc_poc_event_person = inc_poc_event_person, ): # event_dict = event_obj.dict(by_alias=by_alias, exclude_unset=exclude_unset) pass diff --git a/app/routers/event_session.py b/app/routers/event_session.py index 5151bb6..a881d8b 100644 --- a/app/routers/event_session.py +++ b/app/routers/event_session.py @@ -289,26 +289,26 @@ async def get_event_session_obj( return mk_resp(data=None, status_code=404) if event_session_obj := load_event_session_obj( - event_session_id=event_session_id, - enabled=enabled, - limit=limit, - inc_address=inc_address, - inc_contact=inc_contact, - inc_event_abstract_list=inc_event_abstract_list, - inc_event_badge_list=inc_event_badge_list, - inc_event_device_list=inc_event_device_list, - inc_event_file_list=inc_event_file_list, - inc_event_location=inc_event_location, - inc_event_person=inc_event_person, - inc_event_person_list=inc_event_person_list, - inc_event_presentation_list=inc_event_presentation_list, - inc_event_presenter_cat=inc_event_presenter_cat, - inc_event_presenter_list=inc_event_presenter_list, - inc_event_registration_list=inc_event_registration_list, - inc_event_track=inc_event_track, - inc_poc_event_person=inc_poc_event_person, - inc_person=inc_person, - inc_user=inc_user, + event_session_id = event_session_id, + enabled = enabled, + limit = limit, + inc_address = inc_address, + inc_contact = inc_contact, + inc_event_abstract_list = inc_event_abstract_list, + inc_event_badge_list = inc_event_badge_list, + inc_event_device_list = inc_event_device_list, + inc_event_file_list = inc_event_file_list, + inc_event_location = inc_event_location, + inc_event_person = inc_event_person, + inc_event_person_list = inc_event_person_list, + inc_event_presentation_list = inc_event_presentation_list, + inc_event_presenter_cat = inc_event_presenter_cat, + inc_event_presenter_list = inc_event_presenter_list, + inc_event_registration_list = inc_event_registration_list, + inc_event_track = inc_event_track, + inc_poc_event_person = inc_poc_event_person, + inc_person = inc_person, + inc_user = inc_user, ): event_session_dict = event_session_obj.dict(by_alias=by_alias, exclude_unset=exclude_unset) pass diff --git a/app/routers/membership.py b/app/routers/membership.py index f34e49e..89f6263 100644 --- a/app/routers/membership.py +++ b/app/routers/membership.py @@ -1,19 +1,18 @@ import datetime -#from datetime import datetime, time, timedelta from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, status from pydantic import BaseModel, EmailStr, Field from typing import Dict, List, Optional, Set, Union -from app.lib_general import * -from ..log import * +from app.lib_general import log, logging from app.config import settings -from app.db_sql import * +from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random -from .api_crud import delete_obj_template, get_obj_template, get_obj_li_template, patch_obj_template, post_obj_template +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.membership_methods import load_membership_obj from app.models.membership_models import Membership_Base -from app.methods.membership_methods import load_membership_obj -from app.models.response_models import * +from app.models.response_models import Resp_Body_Base, mk_resp router = APIRouter() @@ -179,8 +178,64 @@ async def lookup_membership_obj( return mk_resp(data=data) -@router.get('/{obj_id}', response_model=Resp_Body_Base) + +# ### BEGIN ### API Membership ### get_membership_obj() ### +# Working well as of 2021-06-04. Using as a template for other routes. +@router.get('/{membership_id}', response_model=Resp_Body_Base) async def get_membership_obj( + membership_id: str = Query(..., min_length=1, max_length=22), + enabled: str = 'enabled', # For now this covers any included objects or object lists + limit: int = 500, # For now this covers any included objects or object lists + inc_address: bool = False, # Per member + inc_contact: bool = False, # Per member + inc_membership_cfg: bool = False, + inc_membership_group_list: bool = False, # Per member + inc_membership_member_list: bool = False, + inc_membership_profile: bool = False, # Per member + inc_organization: bool = False, # Per member + inc_person: bool = False, # Per member + inc_product: bool = False, # Per member + inc_product_list: bool = False, + inc_user: bool = False, # Per member + x_account_id: str = Header(...), + by_alias: Optional[bool] = True, + exclude_unset: Optional[bool] = True, + ): + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + if membership_id := redis_lookup_id_random(record_id_random=membership_id, table_name='membership'): pass + else: + return mk_resp(data=None, status_code=404) + + if membership_obj := load_membership_obj( + membership_id = membership_id, + enabled = enabled, + # model_as_dict = model_as_dict, + limit = limit, + inc_address = inc_address, + inc_contact = inc_contact, + inc_membership_cfg = inc_membership_cfg, + inc_membership_group_list = inc_membership_group_list, + inc_membership_member_list = inc_membership_member_list, + inc_membership_profile = inc_membership_profile, + inc_organization = inc_organization, + inc_person = inc_person, + inc_product = inc_product, + inc_product_list = inc_product_list, + inc_user = inc_user, + ): + # membership_dict = membership_obj.dict(by_alias=by_alias, exclude_unset=exclude_unset) + pass + else: + return mk_resp(data=False, status_code=400) # Bad Request + + return mk_resp(data=membership_obj) +# ### END ### API Membership ### get_membership_obj() ### + + +@router.get('/{obj_id}', response_model=Resp_Body_Base) +async def get_membership_obj_old( obj_id: str = Query(..., min_length=1, max_length=22), x_account_id: str = Header(...), by_alias: Optional[bool] = True,