"""GraphQL logic.""" from connectors.logging import logger as log from connectors.graphql import GraphQLBackoffConnector from constants import graphql_queries from constants.graphql_headers import GRASS_ACCOUNT_TYPE from utils.graphql_utils import ( format_product_participations ) from config import ( GRAPHQL_GATEWAY_URL, APPLICATION_NAME, OA_USER, ORCH_HEADER_IDENTITY_ID, ORCH_HEADER_PROFILE_ID, ORCH_HEADER_PROFILE_TYPE, ORCH_HEADER_ROLE, PRINT_STACK_TRACES ) if PRINT_STACK_TRACES: from traceback_with_variables import activate_by_import # noqa # create GraphQL connector graphql_conn = GraphQLBackoffConnector(GRAPHQL_GATEWAY_URL, APPLICATION_NAME) graphql_conn.set_headers({ 'Orchard-Profile-Type': ORCH_HEADER_PROFILE_TYPE, 'Orchard-Profile-Id': ORCH_HEADER_PROFILE_ID, 'Orchard-Identity-Id': ORCH_HEADER_IDENTITY_ID, 'Orchard-Roles': ORCH_HEADER_ROLE, 'Orchard-User-Id': OA_USER, 'GRASS-ACCOUNT-TYPE': GRASS_ACCOUNT_TYPE, }) def fix_product_participants( participant_report, product_participants, upcs_and_product_ids ): """Fix SME product participants. Args: participant_report: (dict) The participant report. Format: "responses": [ { "request": { "data": { "name": "ISON", "spotifyId": "7zJdWmVoGsqxaEl09XOvM5", "appleMusicId": "258614476" }, "vendorId": 34584, "subaccountId": 59868 }, "response": { "data": { "createLabelParticipant": { "uuid": "8e9e8149-e88b-4d82-90f8-6d79b5c87399", "name": "ISON" } } } }, ] product_participants: (dict) product participants to fix. Format: [ { "digital_upc": "886447814703", "orchlabelid": 34584, "subaccount_id": 59868, "participant_name": "ISON" }, { "digital_upc": "886447814703", "orchlabelid": 34584, "subaccount_id": 59868, "participant_name": "Ison & Fille" }, ] upcs_and_product_ids: list of tuples (upc: int, release_id: int) """ if 'errors' in participant_report: log.warning( f'participant_report has ' f'{len(participant_report["errors"])} errors. ' f'It might affect the results.') # remap participant_report by vendor_id + name participant_report_map = {} for entry in participant_report['responses']: participant_name_request = entry["request"]["data"]["name"] participant_name_response = ( entry)["response"]["data"]["createLabelParticipant"]["name"] vendor_id = entry["request"]["vendorId"] if participant_name_request != participant_name_response: log.warning( f'Name mismatch in participant_report entry: ' f'{participant_name_request} != {participant_name_response}') log.warning(entry) key = (vendor_id, participant_name_request) participant_report_map[key] = ( entry)['response']['data']['createLabelParticipant']['uuid'] log.info(f'There are {len(participant_report_map)} label participants.') # build map upc -> release_id upc_to_release_id = { upc: release_id for upc, release_id in upcs_and_product_ids } # build a list of unique UPCs unique_upcs = { p['digital_upc'] for p in product_participants } log.info(f'There are {len(unique_upcs)} UPCs to fix participants.') graphql_conn = GraphQLBackoffConnector( GRAPHQL_GATEWAY_URL, APPLICATION_NAME) graphql_conn.set_headers({'Orchard-User-Id': OA_USER}) results = { 'responses': [], 'errors': [], } for upc in unique_upcs: log.info(f'Fixing participants for UPC {upc}') # filter participants by upc participants = [ p for p in product_participants if p['digital_upc'] == upc ] n_participants = len(participants) log.info(f'There are {n_participants} participants' f' to fix for UPC {upc}') assert participants if n_participants < 3: log.warning(f'UPC {upc} has less than 3 participants. Hmmmm...') log.warning(participants) # additional validation vendor_ids = {p['orchlabelid'] for p in participants} assert len(vendor_ids) == 1, f'Expected 1 vendor_id, got {vendor_ids}' vendor_id = vendor_ids.pop() if not vendor_id: log.error(f'vendor_id is empty for UPC {upc}. Skipping') continue # AR release_id release_id = upc_to_release_id.get(int(upc)) if not release_id: log.error(f'release_id not found for UPC {upc}. Skipping') continue graphql_participations = [] for participant in participants: participant_name = participant['participant_name'] key = (vendor_id, participant_name) if key not in participant_report_map: log.error( f'Participant "{participant_name}" not found in' f' participant_report for vendor_id {vendor_id}') continue label_participant_uuid = participant_report_map[key] log.info(f'Participant "{participant_name}" ' f'for vendor {vendor_id} found in ' f'participant_report with ' f'uuid {label_participant_uuid}') product_participation_input = { 'labelParticipantUuid': label_participant_uuid, 'role': 'PRIMARY_ARTIST' } graphql_participations.append(product_participation_input) if not graphql_participations: log.error(f'No participants found for UPC {upc} ' f'and vendor_id {vendor_id}. Skipping') continue graphql_query_data = format_product_participations( product_id=release_id, participations=graphql_participations) try: # Fire single GraphQL call response = graphql_conn.execute( graphql_queries.update_product_participations, {"data": graphql_query_data} ) msg = 'GraphQL Call Completed - Project {}' \ .format(release_id) log.info(msg) # Push success metadata to method result object results['responses'].append(response) except Exception as ge: # Push error metadata to method result object results['errors'].append({ 'vendor_id': vendor_id, 'status': 'graphql_error', 'error_code': None, 'status_text': 'GraphQL Error', 'message': str(ge) }) log.exception('failure in fix_product_participants')