"""Project utils.""" from typing import Dict from bulk_metadata_ingester_common.models.bulk_release import BulkRelease from bulk_metadata_ingester_common.utils.catalog_ingestion import \ save_catalog_ingestion_action from bulk_metadata_ingester_common.utils.error import graphql_execute from config import graphql_gateway from constants import queries from ddex_ingester_common.constants.catalog_ingestion import ( INSERT_ACTION, UPDATE_ACTION ) from exceptions import ( DuplicateProjectCodeException, ProjectCodeMismatchException) from graphql import GraphQLError def check_for_project(model: BulkRelease, logger: object) -> Dict: """Check for existence of a project.""" vendor_id = model.vendor_id project_code = model.project_code subaccount_id = model.subaccount_id or 0 payload = { 'projectCode': str(project_code), 'accountId': vendor_id, 'subaccountId': subaccount_id or 0 } result = graphql_execute( graphql_gateway, queries.GET_PROJECT_BY_PROJECT_CODE, payload, logger )['data']['projectByProjectCode'] return result def check_project_code_mismatch(model: BulkRelease, logger: object): """Check if the UPC has a different project associated to it. Raises: ProjectCodeMismatchException: If the project code does not match """ # Get UPC and Project Code from CSV csv_project_code = model.project_code upc = model.upc # Query for Product by UPC graphql_result = graphql_execute( graphql_gateway, queries.GET_PRODUCT_BY_UPC, {'upc': str(upc)}, logger )['data']['productByUpc'] if not graphql_result: return # Query for existing Project Code graphql_project_code = graphql_result['project']['projectCode'] logger.info( f'Received the Project Code {graphql_project_code} for UPC {upc}') # Check for mismatch if graphql_project_code and graphql_project_code != str(csv_project_code): csv_vendor = model.vendor_id graphql_vendor = graphql_result['vendorId'] or None message = (f'GraphQL project code "{graphql_project_code}" does ' f'not match CSV project code "{csv_project_code}" ' f'CSV Vendor ID: {csv_vendor} - GraphQL ' f'Vendor ID: {graphql_vendor}') logger.error(message) raise ProjectCodeMismatchException(message) def create_project(event: Dict, model: BulkRelease, logger: object) -> Dict: """Create a project from given params.""" # Project GraphQL queries need a null subaccount id to be 0 vendor_id = model.vendor_id project_code = model.project_code subaccount_id = model.subaccount_id or 0 project_name = project_code = model.project_code description = '' payload = { 'data': { 'projectCode': str(project_code), 'name': str(project_name), 'artistId': int(model.project_artist_id), 'description': str(description), 'accountId': int(vendor_id), 'subaccountId': int(subaccount_id) } } try: result = graphql_execute( graphql_gateway, queries.CREATE_PROJECT, payload, logger )['data']['createProject'] except GraphQLError as err: # We need to check for this error because it means the project was # created by another execution after we checked if it existed. # This means if we run the lambda again, we will see the project exists # and the execution can continue without issue. # We raise this exception instead of the GraphQLError as Terraform # catches this particular exception and runs the lambda again. if f"Project code '{project_code}' already exists" in str(err): raise DuplicateProjectCodeException(err) raise err if result: save_catalog_ingestion_action( event, model, {}, INSERT_ACTION ) return result def update_project(event: Dict, model: BulkRelease, logger: object) -> Dict: """Update existing project.""" # Project GraphQL queries need a null subaccount id to be 0 # subaccount_id = model.subaccount_id or 0 # vendor_id = model.vendor_id project_id = model.project_id # project_code = model.project_code project_name = model.release_name """ This check is in place temporarily while extended metadata is not mandatory. When we are starting to see this included with all DDEX product then we will no longer need to fake the data. """ payload = { 'data': { 'name': str(project_name), 'artistId': int(model.project_artist_id), 'projectId': int(project_id) } } result = graphql_execute( graphql_gateway, queries.UPDATE_PROJECT, payload, logger )['data']['updateProject'] if result: save_catalog_ingestion_action( event, model, {}, UPDATE_ACTION ) return result