diff --git a/app/db_sql.py b/app/db_sql.py index 771603a..a700a60 100644 --- a/app/db_sql.py +++ b/app/db_sql.py @@ -285,8 +285,8 @@ def sql_update( else: log.debug(result_update) log.debug(f'rowcount = {result_update.rowcount}; lastrowid = {result_update.lastrowid}') - if result_update.rowcount == 1 and result_update.lastrowid == 0: # update with no change - log.info('Update record (with no change???)') # With SQL UPDATE this record may have actually changed + if result_update.rowcount >= 1 and result_update.lastrowid == 0: # update with no change + log.info(f'Updated {result_update.rowcount} records (with no changes?)') # With SQL UPDATE this record may have actually changed return True elif result_update.rowcount == 2 and result_update.lastrowid > 0: # update with change log.warning('Should we be here???') @@ -625,11 +625,10 @@ def sql_select( return False # Not successful else: - log.info('Successfully executed the SQL on the first try.') + log.debug('Successfully executed the SQL on the first try.') pass - #log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL - log.info(f'Row count: {result.rowcount}') + log.debug(f'Row count: {result.rowcount}') #log.debug(vars(result)) #log.debug(dir(result)) if result.rowcount == 1: diff --git a/app/main.py b/app/main.py index d801f89..67c0153 100644 --- a/app/main.py +++ b/app/main.py @@ -18,7 +18,7 @@ from . import config from app.log import log, logging # Import the routers here first: -from app.routers import api_crud, api, importing, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, event, event_badge, event_badge_template, event_exhibit, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, site, site_domain, user, websockets, e_cvent#, e_impexium +from app.routers import api_crud, api, importing, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, event, event_badge, event_badge_template, event_exhibit, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, site, site_domain, user, websockets, e_cvent, c_idaa #, e_impexium from app.db_sql import db @@ -327,6 +327,12 @@ app.include_router( # tags=['External Service: Impexium'], # ) +app.include_router( + c_idaa.router, + prefix='/c/idaa', + tags=['Client: IDAA'], +) + # BEGIN: CORS origins = [ diff --git a/app/methods/e_cvent_methods.py b/app/methods/e_cvent_methods.py index cbfce63..3c1181c 100644 --- a/app/methods/e_cvent_methods.py +++ b/app/methods/e_cvent_methods.py @@ -1,12 +1,12 @@ from __future__ import annotations -import datetime, pprint, pytz, random, requests +import datetime, pprint, pytz, random, requests, time from requests.auth import HTTPBasicAuth from typing import Dict, List, Optional, Set, Union from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator from app.db_sql import redis_lookup_id_random, sql_insert, sql_select, sql_update -from app.lib_general import log, logging +from app.lib_general import log, logging, logger_reset from app.methods.person_methods import get_person_rec_w_external_id, load_person_obj, update_person_kiss @@ -20,9 +20,10 @@ api['base_url'] = 'https://api-platform.cvent.com/ea' # Including /ea as the Cve api['headers'] = {} # { 'Content-Type': content_type, 'Authorization': 'Basic '+str(cvent_authorization_base64) } -# def get_access_token(api, app): +# Updated 2022-02-01 +@logger_reset def get_access_token(): - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) log.debug(f'API data:\n{api}') @@ -85,6 +86,8 @@ def get_access_token(): return api +# Updated 2022-01-31 +@logger_reset def get_contact_custom_field_list(api): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) @@ -110,7 +113,9 @@ def get_contact_custom_field_list(api): return response_data -def get_contact_list(api, external_id=False): +# Updated 2022-01-31 +@logger_reset +def get_contact_list(api, external_id: str=False): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) @@ -140,8 +145,9 @@ def get_contact_list(api, external_id=False): return response_data -# def get_contact_id(api, contact_id): -def get_contact_id(contact_id): +# Updated 2022-02-01 +@logger_reset +def get_contact_id(contact_id: str): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) @@ -149,6 +155,9 @@ def get_contact_id(contact_id): # else: get_access_token() get_access_token() + log.warning('Sleeping for 1 second to avoid Cvent rate limit...') + time.sleep(1) + endpoint = f'/contacts/{contact_id}' uri = api['base_url']+endpoint @@ -167,3 +176,43 @@ def get_contact_id(contact_id): # f.write(pprint.pformat(response_data, indent=2, width=160)) return response_data + + +# Updated 2022-02-01 +@logger_reset +def modify_contact_id(contact_id: str, field_list: list=[], custom_field_id: str=None, custom_field_value: str=None): + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + get_access_token() + + if custom_field_id: + endpoint = f'/contacts/{contact_id}/custom-fields/{custom_field_id}/answers' + elif field_list: + endpoint = f'/contacts/{contact_id}' + else: + log.error('Missing required parameters') + return False + uri = api['base_url']+endpoint + + params = {} + + data = {} + if custom_field_id: + data['id'] = custom_field_id + data['value'] = custom_field_value + else: + data = field_list + data['id'] = contact_id + + if custom_field_id: + resp = requests.put(url=uri, headers=api['headers'], params=params, json=data) + else: + resp = requests.patch(url=uri, headers=api['headers'], params=params, json=data) + + response_data = resp.json() + log.debug(response_data) + + if 'message' in response_data and response_data['message'] == 'Too Many Requests': return False + + return response_data diff --git a/app/methods/membership_person_methods.py b/app/methods/membership_person_methods.py index 22750c2..ec16139 100644 --- a/app/methods/membership_person_methods.py +++ b/app/methods/membership_person_methods.py @@ -4,7 +4,7 @@ import datetime, json 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.lib_general import log, logging, logger_reset from app.db_sql import redis_lookup_id_random, sql_insert, sql_insert_or_update, sql_select, sql_update from app.methods.membership_cfg_methods import load_membership_cfg_obj @@ -22,6 +22,7 @@ from app.models.membership_person_models import Membership_Person_Base # ### BEGIN ### API Membership Person Methods ### load_membership_person_obj() ### # Updated 2022-01-11 +@logger_reset def load_membership_person_obj( membership_person_id: int|str, limit: int = 100, @@ -50,7 +51,7 @@ def load_membership_person_obj( inc_product_list: bool = False, # The list of products that give access to a member_type or member_group # inc_user: bool = False, ) -> Membership_Person_Base: - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if membership_person_id := redis_lookup_id_random(record_id_random=membership_person_id, table_name='membership_person'): pass diff --git a/app/methods/membership_person_type_methods.py b/app/methods/membership_person_type_methods.py index 96b2c0d..c7db28f 100644 --- a/app/methods/membership_person_type_methods.py +++ b/app/methods/membership_person_type_methods.py @@ -5,7 +5,7 @@ from typing import Dict, List, Optional, Set, Union from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator from app.db_sql import redis_lookup_id_random, sql_insert, sql_select, sql_update -from app.lib_general import log, logging +from app.lib_general import log, logging, logger_reset # from app.methods.membership_person_methods import get_membership_person_rec_list, load_membership_person_obj from app.methods.membership_cfg_methods import load_membership_cfg_obj from app.methods.product_methods import get_product_rec_list, load_product_obj @@ -16,6 +16,7 @@ from app.models.membership_person_type_models import Membership_Person_Type_Base # ### BEGIN ### API Membership Type Person Methods ### load_membership_person_type_obj() ### # Updated 2021-07-09 +@logger_reset def load_membership_person_type_obj( membership_person_type_id: int|str, limit: int = 1000, @@ -36,7 +37,7 @@ def load_membership_person_type_obj( inc_product_list: bool = False, inc_person: bool = False, ) -> Membership_Person_Type_Base|bool: - # log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if membership_person_type_id := redis_lookup_id_random(record_id_random=membership_person_type_id, table_name='membership_person_type'): pass diff --git a/app/methods/person_methods.py b/app/methods/person_methods.py index 0d4af5f..6c5ed58 100644 --- a/app/methods/person_methods.py +++ b/app/methods/person_methods.py @@ -624,7 +624,7 @@ def get_person_rec_list( limit: int = 1000, offset: int = 0, ) -> list|bool: - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # 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 diff --git a/app/routers/c_idaa.py b/app/routers/c_idaa.py new file mode 100644 index 0000000..bcd5915 --- /dev/null +++ b/app/routers/c_idaa.py @@ -0,0 +1,129 @@ +import datetime, json, pytz, random, secrets, string, time +from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, Response, status +from pydantic import BaseModel, EmailStr, Field +from typing import Dict, List, Optional, Set, Union + +from app.lib_general import log, logging, secure_hash_string, verify_secure_hash_string, common_route_params, Common_Route_Params +from app.config import settings +from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, 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.models.response_models import Resp_Body_Base, mk_resp + + +router = APIRouter() + + +# ### BEGIN ### API Client: IDAA ### refresh_membership_status() ### +# Updated 2022-02-01 +@router.get('/refresh_membership_status', response_model=Resp_Body_Base) +async def refresh_membership_status( + commons: Common_Route_Params = Depends(common_route_params), + ): + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + sql = f""" + UPDATE user + INNER JOIN person ON user.id = person.user_id + INNER JOIN membership_person ON person.id = membership_person.person_id + SET user.email_verified = 1, user.enable = 1, user.enable_from = membership_person.start_on, user.enable_to = membership_person.end_on, user.verified = 1, user.group = 'current_member' + WHERE user.account_id = 13 AND membership_person.end_on >= NOW(); + """ + if user_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(user_update_result) + else: + log.warning(f'The SQL UPDATE of user table records failed for current members') + + sql = f""" + UPDATE user + INNER JOIN person ON user.id = person.user_id + INNER JOIN membership_person ON person.id = membership_person.person_id + SET user.group = 'inactive_member' + WHERE user.account_id = 13 AND membership_person.end_on < NOW() AND membership_person.end_on >= DATE(NOW() - INTERVAL 4 WEEK); + """ + if user_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(user_update_result) + else: + log.warning(f'The SQL UPDATE of user table records failed for inactive members') + + sql = f""" + UPDATE user + INNER JOIN person ON user.id = person.user_id + INNER JOIN membership_person ON person.id = membership_person.person_id + SET user.group = 'suspended_member' + WHERE user.account_id = 13 AND membership_person.end_on < DATE(NOW() - INTERVAL 4 WEEK); + """ + if user_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(user_update_result) + else: + log.warning(f'The SQL UPDATE of user table records failed for suspended members') + + sql = f""" + UPDATE user + INNER JOIN person ON user.id = person.user_id + LEFT JOIN membership_person ON person.id = membership_person.person_id + SET user.group = 'not_member' + WHERE user.account_id = 13 AND membership_person.id IS NULL; + """ + if user_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(user_update_result) + else: + log.warning(f'The SQL UPDATE of user table records failed for not members') + + + sql = f""" + UPDATE person + INNER JOIN membership_person ON person.id = membership_person.person_id + SET person.enable = 1, person.group = 'current_member' + WHERE person.account_id = 13 AND membership_person.end_on >= NOW(); + """ + if person_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(person_update_result) + else: + log.warning(f'The SQL UPDATE of person table records failed for current members') + + sql = f""" + UPDATE person + INNER JOIN membership_person ON person.id = membership_person.person_id + SET person.group = 'inactive_member' + WHERE person.account_id = 13 AND membership_person.end_on < NOW() AND membership_person.end_on >= DATE(NOW() - INTERVAL 4 WEEK); + """ + if person_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(person_update_result) + else: + log.warning(f'The SQL UPDATE of person table records failed for inactive members') + + sql = f""" + UPDATE person + INNER JOIN membership_person ON person.id = membership_person.person_id + SET person.group = 'suspended_member' + WHERE person.account_id = 13 AND membership_person.end_on < DATE(NOW() - INTERVAL 4 WEEK); + """ + if person_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(person_update_result) + else: + log.warning(f'The SQL UPDATE of person table records failed for suspended members') + + sql = f""" + UPDATE person + LEFT JOIN membership_person ON person.id = membership_person.person_id + SET person.group = 'not_member' + WHERE person.account_id = 13 AND membership_person.id IS NULL; + """ + if person_update_result := sql_update(sql=sql): + # Pull out IDs of existing person record + log.debug(person_update_result) + else: + log.warning(f'The SQL UPDATE of person table records failed for not members') + + return mk_resp(data=True, status_message='Updated person and user records with current membership status', response=commons.response) +# ### END ### API Client: IDAA ### refresh_membership_status() ### \ No newline at end of file diff --git a/app/routers/e_cvent.py b/app/routers/e_cvent.py index 04933d6..6ece381 100644 --- a/app/routers/e_cvent.py +++ b/app/routers/e_cvent.py @@ -9,7 +9,7 @@ from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, 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.e_cvent_methods import get_access_token, get_contact_custom_field_list, get_contact_list, get_contact_id +from app.methods.e_cvent_methods import get_access_token, get_contact_custom_field_list, get_contact_list, get_contact_id, modify_contact_id from app.methods.person_methods import create_person_kiss, get_person_rec_list, get_person_rec_w_external_id, load_person_obj, update_person_kiss from app.methods.membership_person_methods import create_membership_person_obj, update_membership_person_obj @@ -21,7 +21,7 @@ router = APIRouter() # ### BEGIN ### API Cvent ### get_person() ### -# Updated 2022-01-28 +# Updated 2022-02-01 @router.get('/person/{e_person_id}', response_model=Resp_Body_Base) async def get_person( e_person_id: str = Query(..., min_length=36, max_length=36), # UUID v4; actually the Cvent Contact UUID for a person @@ -29,7 +29,7 @@ async def get_person( commons: Common_Route_Params = Depends(common_route_params), ): - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) # current_datetime = datetime.datetime.now() @@ -51,13 +51,17 @@ async def get_person( else: return mk_resp(data=None, status_code=404, response=commons.response) # ### SECTION ### Get the Cvent Contact with the Cvent UUID. - # if cvent_contact_obj_result := get_contact_id(contact_id=e_person_id): - # cvent_contact_obj = cvent_contact_obj_result - # else: - # log.info(f'Cvent contact not found with ID: {e_person_id}') - # return mk_resp(data=None, status_code=404, response=commons.response) # Not Found + if cvent_contact_obj_result := get_contact_id(contact_id=e_person_id): + cvent_contact_obj = cvent_contact_obj_result + else: + log.info(f'Cvent contact not found with ID: {e_person_id}') + return mk_resp(data=None, status_code=404, response=commons.response) # Not Found - cvent_contact_obj = {'id': 'E1DB2588-8CFA-439B-82E7-63F65BA9CE90', 'firstName': 'Edward', 'lastName': 'Breslow', 'email': 'ed.breslow@yahoo.com', 'homePhone': '4344268975', 'homeAddress': {'address1': '10566 Ratcliffe Trail', 'city': 'Manassas', 'region': 'Virginia', 'regionCode': 'VA', 'postalCode': '20110', 'country': 'USA', 'countryCode': 'US'}, 'sourceId': '00010745', 'deleted': False, 'type': {'id': 'A01900AB-496A-48A1-9B04-C2874651227E', 'name': 'Member'}, 'created': '2022-01-24T16:43:38.307Z', 'lastModified': '2022-02-01T15:06:55.540Z', 'createdBy': 'ed.breslow@yahoo.com', 'lastModifiedBy': 'ed.breslow@yahoo.com', 'optOut': {'optedOut': False, 'by': 'Cvent Support'}, 'membership': {'joined': '2022-01-24', 'expiration': '2023-01-24'}, 'customFields': [{'id': 'e46d8043-705b-4315-9611-6fba9211b2e2', 'name': 'Non-Binary Gender', 'value': ['Male'], 'type': 'SingleSelect', 'order': 2}, {'id': '656b419b-d974-49a7-85df-cda564a7a06e', 'name': 'Qualifying Degree', 'value': ['R.Ph.'], 'type': 'SingleSelect', 'order': 3}, {'id': 'd6c6eb81-b08f-4970-9853-2fbb799d9bd1', 'name': 'Professional Designations', 'value': ['Rph'], 'type': 'FreeText', 'order': 4}, {'id': '1ef02428-59a1-493a-8535-407ed5d65f6f', 'name': 'Practice Status', 'value': ['Active'], 'type': 'SingleSelect', 'order': 5}, {'id': 'c33feaa8-a135-48b3-96c5-d6b46f894a06', 'name': 'Practice Specialty', 'value': ['Pharmacology, Doctorate'], 'type': 'SingleSelect', 'order': 6}, {'id': 'c1b47d46-d219-4f1a-a8f9-8030c7f55f31', 'name': 'Recovery Programs', 'value': ['AA', 'NA'], 'type': 'MultiSelect', 'order': 7}, {'id': '90ec10c2-59c9-47bd-8c2f-fc253da4975c', 'name': 'Emergency Contact', 'value': ['Jamie Long 434-386-1144'], 'type': 'FreeText', 'order': 8}, {'id': 'd0b462b8-b9f3-420d-836c-6c0c75dcbe12', 'name': 'SO Name Prefix', 'value': ['Mrs'], 'type': 'FreeText', 'order': 9}, {'id': '59284f29-b089-4e49-b980-795861514798', 'name': 'SO First Name', 'value': ['Edward'], 'type': 'FreeText', 'order': 10}, {'id': '65235cc9-5b66-48d4-a7d5-8a8d3f22872a', 'name': 'SO Last Name', 'value': ['Breslow'], 'type': 'FreeText', 'order': 11}, {'id': '84210a3a-43c9-491d-badf-fd5bb19151b7', 'name': 'Paper Mail Opted Out', 'value': ['Yes'], 'type': 'SingleSelect', 'order': 17}, {'id': '3b91172f-3cde-4ffc-822e-6bcc80a1eda7', 'name': 'I am joining IDAA as a', 'value': ['Medical member with a qualifying degree'], 'type': 'SingleSelect', 'order': 21}, {'id': '2245946b-2634-4044-8ad5-3cd897424f32', 'name': 'Sobriety Date', 'value': ['2021-10-15T00:00'], 'type': 'Date', 'order': 22}]} + # cvent_contact_obj = {'id': '59B1642A-E193-4B47-910B-566029C44620', 'firstName': 'Nicholas', 'lastName': 'Kasnick', 'email': 'kasnick6412@gmail.com', 'homePhone': '3603494072', 'homeAddress': {'address1': '14924 89th ave', 'city': 'Yelm', 'postalCode': '98597', 'country': 'USA', 'countryCode': 'US'}, 'sourceId': '00293862', 'deleted': False, 'type': {'id': '03622AEE-F586-4AE5-A191-B8372543A8C8', 'name': 'Student Member'}, 'created': '2022-01-25T02:43:17.157Z', 'lastModified': '2022-01-26T16:07:43.505Z', 'createdBy': 'kasnick6412@gmail.com', 'lastModifiedBy': 'kasnick6412@gmail.com', 'optOut': {'optedOut': False, 'by': 'Cvent Support'}, 'membership': {'joined': '2022-01-24', 'expiration': '2023-01-24'}, 'customFields': [{'id': 'e46d8043-705b-4315-9611-6fba9211b2e2', 'name': 'Non-Binary Gender', 'value': ['Male'], 'type': 'SingleSelect', 'order': 2}, {'id': '656b419b-d974-49a7-85df-cda564a7a06e', 'name': 'Qualifying Degree', 'value': ['Student, Qualifying Healthcare Professional'], 'type': 'SingleSelect', 'order': 3}, {'id': '1ef02428-59a1-493a-8535-407ed5d65f6f', 'name': 'Practice Status', 'value': ['In Training'], 'type': 'SingleSelect', 'order': 5}, {'id': 'c1b47d46-d219-4f1a-a8f9-8030c7f55f31', 'name': 'Recovery Programs', 'value': ['AA', 'Al-Anon'], 'type': 'MultiSelect', 'order': 7}, {'id': '84210a3a-43c9-491d-badf-fd5bb19151b7', 'name': 'Paper Mail Opted Out', 'value': ['Yes'], 'type': 'SingleSelect', 'order': 17}, {'id': '3b91172f-3cde-4ffc-822e-6bcc80a1eda7', 'name': 'I am joining IDAA as a', 'value': ['Medical member with a qualifying degree'], 'type': 'SingleSelect', 'order': 21}, {'id': '2245946b-2634-4044-8ad5-3cd897424f32', 'name': 'Sobriety Date', 'value': ['2022-01-08T00:00'], 'type': 'Date', 'order': 22}]} + + # cvent_contact_obj = {'id': 'C5D6EBB7-8CDE-492E-A953-5243942CB66E', 'firstName': 'C Eve J', 'lastName': 'Kimball', 'email': 'doceve1@gmail.com', 'prefix': 'Dr.', 'homePhone': '6104638775', 'homeAddress': {'address1': '14 GAELSONG LN', 'city': 'WYOMISSING', 'region': 'Pennsylvania', 'regionCode': 'PA', 'postalCode': '19610', 'country': 'USA', 'countryCode': 'US'}, 'sourceId': '00037205', 'deleted': False, 'type': {'id': 'A01900AB-496A-48A1-9B04-C2874651227E', 'name': 'Member'}, 'created': '2022-01-29T14:00:36.103Z', 'lastModified': '2022-01-31T18:36:34.809Z', 'createdBy': 'doceve1@gmail.com', 'lastModifiedBy': 'doceve1@gmail.com', 'optOut': {'optedOut': False, 'by': 'Cvent Support'}, 'membership': {'joined': '2022-01-29', 'expiration': '2023-01-29'}, 'customFields': [{'id': 'e46d8043-705b-4315-9611-6fba9211b2e2', 'name': 'Non-Binary Gender', 'value': ['Female'], 'type': 'SingleSelect', 'order': 2}, {'id': '656b419b-d974-49a7-85df-cda564a7a06e', 'name': 'Qualifying Degree', 'value': ['M.D.'], 'type': 'SingleSelect', 'order': 3}, {'id': 'd6c6eb81-b08f-4970-9853-2fbb799d9bd1', 'name': 'Professional Designations', 'value': ['MD'], 'type': 'FreeText', 'order': 4}, {'id': '1ef02428-59a1-493a-8535-407ed5d65f6f', 'name': 'Practice Status', 'value': ['Retired'], 'type': 'SingleSelect', 'order': 5}, {'id': 'c33feaa8-a135-48b3-96c5-d6b46f894a06', 'name': 'Practice Specialty', 'value': ['Pediatrics'], 'type': 'SingleSelect', 'order': 6}, {'id': 'c1b47d46-d219-4f1a-a8f9-8030c7f55f31', 'name': 'Recovery Programs', 'value': ['AA', 'Al-Anon', 'OA'], 'type': 'MultiSelect', 'order': 7}, {'id': '90ec10c2-59c9-47bd-8c2f-fc253da4975c', 'name': 'Emergency Contact', 'value': ['Dan Kimball - 610-406-7753'], 'type': 'FreeText', 'order': 8}, {'id': 'd0b462b8-b9f3-420d-836c-6c0c75dcbe12', 'name': 'SO Name Prefix', 'value': ['Dr.'], 'type': 'FreeText', 'order': 9}, {'id': '59284f29-b089-4e49-b980-795861514798', 'name': 'SO First Name', 'value': ['Daniel B'], 'type': 'FreeText', 'order': 10}, {'id': '65235cc9-5b66-48d4-a7d5-8a8d3f22872a', 'name': 'SO Last Name', 'value': ['Kimball, Jr.'], 'type': 'FreeText', 'order': 11}, {'id': '50d5efaa-d629-4eeb-8d6e-f51b95eb2eb9', 'name': 'SO Professional Designation', 'value': ['MD'], 'type': 'FreeText', 'order': 12}, {'id': '84210a3a-43c9-491d-badf-fd5bb19151b7', 'name': 'Paper Mail Opted Out', 'value': ['Yes'], 'type': 'SingleSelect', 'order': 17}, {'id': '3b91172f-3cde-4ffc-822e-6bcc80a1eda7', 'name': 'I am joining IDAA as a', 'value': ['Medical member with a qualifying degree'], 'type': 'SingleSelect', 'order': 21}, {'id': '2245946b-2634-4044-8ad5-3cd897424f32', 'name': 'Sobriety Date', 'value': ['1979-03-31T00:00'], 'type': 'Date', 'order': 22}]} + + # cvent_contact_obj = {'id': 'E1DB2588-8CFA-439B-82E7-63F65BA9CE90', 'firstName': 'Edward', 'lastName': 'Breslow', 'email': 'ed.breslow@yahoo.com', 'homePhone': '4344268975', 'homeAddress': {'address1': '10566 Ratcliffe Trail', 'city': 'Manassas', 'region': 'Virginia', 'regionCode': 'VA', 'postalCode': '20110', 'country': 'USA', 'countryCode': 'US'}, 'sourceId': '00010745', 'deleted': False, 'type': {'id': 'A01900AB-496A-48A1-9B04-C2874651227E', 'name': 'Member'}, 'created': '2022-01-24T16:43:38.307Z', 'lastModified': '2022-02-01T15:06:55.540Z', 'createdBy': 'ed.breslow@yahoo.com', 'lastModifiedBy': 'ed.breslow@yahoo.com', 'optOut': {'optedOut': False, 'by': 'Cvent Support'}, 'membership': {'joined': '2022-01-24', 'expiration': '2023-01-24'}, 'customFields': [{'id': 'e46d8043-705b-4315-9611-6fba9211b2e2', 'name': 'Non-Binary Gender', 'value': ['Male'], 'type': 'SingleSelect', 'order': 2}, {'id': '656b419b-d974-49a7-85df-cda564a7a06e', 'name': 'Qualifying Degree', 'value': ['R.Ph.'], 'type': 'SingleSelect', 'order': 3}, {'id': 'd6c6eb81-b08f-4970-9853-2fbb799d9bd1', 'name': 'Professional Designations', 'value': ['Rph'], 'type': 'FreeText', 'order': 4}, {'id': '1ef02428-59a1-493a-8535-407ed5d65f6f', 'name': 'Practice Status', 'value': ['Active'], 'type': 'SingleSelect', 'order': 5}, {'id': 'c33feaa8-a135-48b3-96c5-d6b46f894a06', 'name': 'Practice Specialty', 'value': ['Pharmacology, Doctorate'], 'type': 'SingleSelect', 'order': 6}, {'id': 'c1b47d46-d219-4f1a-a8f9-8030c7f55f31', 'name': 'Recovery Programs', 'value': ['AA', 'NA'], 'type': 'MultiSelect', 'order': 7}, {'id': '90ec10c2-59c9-47bd-8c2f-fc253da4975c', 'name': 'Emergency Contact', 'value': ['Jamie Long 434-386-1144'], 'type': 'FreeText', 'order': 8}, {'id': 'd0b462b8-b9f3-420d-836c-6c0c75dcbe12', 'name': 'SO Name Prefix', 'value': ['Mrs'], 'type': 'FreeText', 'order': 9}, {'id': '59284f29-b089-4e49-b980-795861514798', 'name': 'SO First Name', 'value': ['Edward'], 'type': 'FreeText', 'order': 10}, {'id': '65235cc9-5b66-48d4-a7d5-8a8d3f22872a', 'name': 'SO Last Name', 'value': ['Breslow'], 'type': 'FreeText', 'order': 11}, {'id': '84210a3a-43c9-491d-badf-fd5bb19151b7', 'name': 'Paper Mail Opted Out', 'value': ['Yes'], 'type': 'SingleSelect', 'order': 17}, {'id': '3b91172f-3cde-4ffc-822e-6bcc80a1eda7', 'name': 'I am joining IDAA as a', 'value': ['Medical member with a qualifying degree'], 'type': 'SingleSelect', 'order': 21}, {'id': '2245946b-2634-4044-8ad5-3cd897424f32', 'name': 'Sobriety Date', 'value': ['2021-10-15T00:00'], 'type': 'Date', 'order': 22}]} # log.debug(json.dumps(cvent_contact_obj, indent=2, default=str)) @@ -116,18 +120,20 @@ async def get_person( log.debug(contact_data) address_data = {} - address_data['line_1'] = cvent_contact_obj.get('homeAddress').get('address1') - address_data['line_2'] = cvent_contact_obj.get('homeAddress').get('address2') - address_data['line_3'] = cvent_contact_obj.get('homeAddress').get('address3') - address_data['city'] = cvent_contact_obj.get('homeAddress').get('city') - address_data['state_province'] = cvent_contact_obj.get('homeAddress').get('region') - country_subdivision_code = cvent_contact_obj.get('homeAddress').get('countryCode') +'-'+cvent_contact_obj.get('homeAddress').get('regionCode') - address_data['country_subdivision_code'] = country_subdivision_code - address_data['postal_code'] = cvent_contact_obj.get('homeAddress').get('postalCode') - address_data['country_alpha_2_code'] = cvent_contact_obj.get('homeAddress').get('countryCode') - address_data['country'] = cvent_contact_obj.get('homeAddress').get('country') - address_data['country_alpha_2_code'] = cvent_contact_obj.get('homeAddress').get('countryCode') - log.debug(address_data) + if cvent_contact_obj.get('homeAddress'): + address_data['line_1'] = cvent_contact_obj.get('homeAddress').get('address1') + address_data['line_2'] = cvent_contact_obj.get('homeAddress').get('address2') + address_data['line_3'] = cvent_contact_obj.get('homeAddress').get('address3') + address_data['city'] = cvent_contact_obj.get('homeAddress').get('city') + address_data['state_province'] = cvent_contact_obj.get('homeAddress').get('region') + if cvent_contact_obj.get('homeAddress').get('countryCode') and cvent_contact_obj.get('homeAddress').get('regionCode'): + country_subdivision_code = cvent_contact_obj.get('homeAddress').get('countryCode') +'-'+ cvent_contact_obj.get('homeAddress').get('regionCode') + address_data['country_subdivision_code'] = country_subdivision_code + address_data['postal_code'] = cvent_contact_obj.get('homeAddress').get('postalCode') + address_data['country_alpha_2_code'] = cvent_contact_obj.get('homeAddress').get('countryCode') + address_data['country'] = cvent_contact_obj.get('homeAddress').get('country') + address_data['country_alpha_2_code'] = cvent_contact_obj.get('homeAddress').get('countryCode') + log.debug(address_data) contact_data['address'] = address_data person_data['contact'] = contact_data @@ -281,7 +287,20 @@ async def get_person( person_external_id = f'{random_string}~{email}' log.info(f'Created new Person External ID: {person_external_id}') person_data['external_id'] = person_external_id - # NOTE: Need to update Cvent record!!! + + # NOTE: Update Cvent Contact + custom_field_id = '609ab766-7d79-4a9d-a72c-f126412659ee' # IDAA Cvent External ID UUID + custom_field_value = [person_external_id] + + log.warning('Sleeping for 1 second to avoid Cvent rate limit...') + time.sleep(1) + + contact_mod_result = modify_contact_id( + contact_id = e_person_id, # This is the Cvent Contact UUID for a person + # field_list = field_list, + custom_field_id = custom_field_id, + custom_field_value = custom_field_value, + ) if person_id: # ### SECTION ### Load person object to populate the person_data and membership_person_data dicts. @@ -297,8 +316,8 @@ async def get_person( if person_obj.membership_person: membership_person_id = person_obj.membership_person.id - if person_obj.membership_person.membership_person_type: - membership_person_type_id = person_obj.membership_person.membership_person_type.id + if person_obj.membership_person.membership_person_type: + membership_person_type_id = person_obj.membership_person.membership_person_type.id if not person_obj.external_id: person_data['external_id'] = person_external_id @@ -361,3 +380,4 @@ async def get_person( return mk_resp(data=person_obj, status_message='Created/Updated and loaded person based on Cvent contact information', response=commons.response) # return mk_resp(data=person_data, status_message='Got Cvent contact information', response=commons.response) +# ### END ### API Cvent ### get_person() ###