from typing import Any from common.connectors.graphql import obo_graphql as graphql_common from common.connectors.graphql.schemas import ProductIdUpcNFDResult from common.schemas.ingestion import Product, ProductArtistRole from lambdacommon.common_config import logger from src.constants import AccountTypes from src.exceptions import CreateProductException def sanitize_special_instructions(special_instructions: str | None) -> str | None: """Sanitizes special instructions to remove problem strings.""" # This method is to avoid GenericLFI_BODY WAF rejections # See https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-baseline.html#aws-managed-rule-groups-baseline-crs # noqa # Inherited from ddex-ingester. if special_instructions and "../" in special_instructions: return special_instructions.replace("../", "").strip() return special_instructions def prepare_participants(product: Product) -> list[dict[str, Any]]: """Format artist data and map roles.""" participants: list[dict[str, Any]] = [] for artist in product.display_artists or []: artist_data = { "labelParticipantUuid": artist.label_participant_uuid, } for role in artist.roles: role_value = role.role if role_value == "FEATURED_ARTIST" and role.featured_to_primary: participants.append( { "role": "FEATURE_TO_PRIMARY", "localizations": [], **artist_data, } ) participants.append( { "role": role_value, "localizations": prepare_artist_localizations(role), **artist_data, } ) return participants def prepare_artist_localizations(artist: ProductArtistRole) -> list[dict[str, Any]]: """Format localizations data.""" return [ {"name": ln.name, "languageId": ln.language_id} for ln in artist.localized_names or [] ] def prepare_title_localizations(product: Product) -> list[dict[str, Any]] | None: """Format localizations data.""" result = [ { "productName": lt.title, "languageId": lt.language_id, **({"deliveredVersion": lt.version} if lt.version else {}), } for lt in product.localized_titles or [] ] return result or None def get_product(product: Product) -> ProductIdUpcNFDResult | None: """ Find an existing product by passed product_code and account data. Returns None if a product isn't found. Raises: CreateProductException: if the found product has mismatched upc. """ if product.subaccount_uuid: account_type = AccountTypes.SUBACCOUNT account_uuid = product.subaccount_uuid else: account_type = AccountTypes.VENDOR account_uuid = product.vendor_uuid logger.info( f"Running 'get_product_by_product_code' product_code={product.release_reference}, account_type={account_type}, " f"account_uuid={account_uuid}" ) by_product_code_result = graphql_common.get_product_by_product_code( product.release_reference, account_type, account_uuid ) logger.info(f"'get_product_by_product_code' result: {by_product_code_result}.") if by_product_code_result: if product.upc and by_product_code_result.upc != product.upc: error = ( f"UPC doesn't match. Found an existing Product " f"for the passed Product, " f"having UPC={by_product_code_result.upc} not matching with the passed data." ) logger.error(f"{error}.\n{product}") raise CreateProductException(error) logger.info( f"Product was found for " f"product_code={product.release_reference}" ) return by_product_code_result if product.upc: logger.info(f"Running get_product_by_upc with upc={product.upc}") by_upc_result = graphql_common.get_product_by_upc(product.upc) logger.info(f"'get_product_by_upc' result: {by_upc_result}") if by_upc_result: error = ( f"Product code doesn't match. Found an existing Product " f"for the passed Product, " f"having product_code={by_upc_result.product_code} not matching with the passed data." ) logger.error(f"{error}.\n{product}") raise CreateProductException(error) return None