"""Config file for lambda function.""" from enum import Enum import os import tempfile from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from secrets_manager.lambda_ext import LambdaSecretsManager from src.utils.types import DimensionMapping APPLICATION_NAME = 'lambda-moneyhub-custom-reports' # AWS region configuration DEFAULT_AWS_REGION = 'us-east-1' AWS_REGION = os.environ.get('AWS_REGION', DEFAULT_AWS_REGION) # Environment setup DEV_ENVIRONMENT = 'dev' QA_ENVIRONMENT = 'qa' PROD_ENVIRONMENT = 'prod' TEST_ENVIRONMENT = 'test' ENVIRONMENT = os.environ.get('ENVIRONMENT', DEV_ENVIRONMENT) # Output path for files FILE_OUTPUT_PATH = os.environ.get('FILE_OUTPUT_PATH') or tempfile.gettempdir() # S3 bucket S3_BUCKET = f'{ENVIRONMENT}-moneyhub-custom-reports' # Custom report statuses CUSTOM_REPORT_STATUS_COMPLETE = 'complete' CUSTOM_REPORT_STATUS_ERROR = 'error' CUSTOM_REPORT_STATUS_IN_PROGRESS = 'in_progress' # Custom report revenue types REVENUE_TYPE_DISTRIBUTION = 'distribution' REVENUE_TYPE_NEIGHBOURING_RIGHTS = 'neighbouring_rights' # Credentials SENTRY_DSN = os.environ.get('SENTRY_DSN') or None snowflake_private_key = os.environ.get('SNOWFLAKE_PRIVATE_KEY') if ENVIRONMENT in [PROD_ENVIRONMENT, QA_ENVIRONMENT]: secrets_manager_client = LambdaSecretsManager( environment=ENVIRONMENT, service_name=APPLICATION_NAME ) passphrase = secrets_manager_client.get_cred('SNOWFLAKE_KEY_PASSPHRASE') private_key = secrets_manager_client.get_cred('SNOWFLAKE_PRIVATE_KEY') private_key_bytes = bytes(private_key, 'utf-8') else: passphrase = os.environ.get('SNOWFLAKE_KEY_PASSPHRASE') private_key_path = os.environ.get('SNOWFLAKE_PRIVATE_KEY_PATH') private_key = os.environ.get('SNOWFLAKE_PRIVATE_KEY') if private_key_path: with open(private_key_path, 'rb') as key: private_key_bytes = key.read() elif private_key: private_key_bytes = bytes(private_key, 'utf-8') elif ENVIRONMENT != TEST_ENVIRONMENT: raise ValueError('SNOWFLAKE_PRIVATE_KEY_PATH or SNOWFLAKE_PRIVATE_KEY must be set.') decrypted_key_bytes: bytes | None = None if ENVIRONMENT != TEST_ENVIRONMENT: passphrase_bytes = bytes(passphrase, 'utf-8') decrypted_key = serialization.load_pem_private_key( private_key_bytes, password=passphrase_bytes, backend=default_backend(), ) decrypted_key_bytes = decrypted_key.private_bytes( encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) # DB Connectors DB_SCHEMA = os.environ.get('SNOWFLAKE_SCHEMA') SNOWFLAKE_DB_CONFIG: dict[str, str | bytes | None] = { 'role': os.environ.get('SNOWFLAKE_ROLE'), 'warehouse': os.environ.get('SNOWFLAKE_WAREHOUSE'), 'db': os.environ.get('SNOWFLAKE_DATABASE'), 'database': os.environ.get('SNOWFLAKE_DATABASE'), 'schema': DB_SCHEMA, 'user': os.environ.get('SNOWFLAKE_USER'), 'private_key': decrypted_key_bytes, 'account': os.environ.get('SNOWFLAKE_ACCOUNT'), } # Data config app_reporting_db_royalty_accounting = ( f'ORCHARD_APP_REPORTING_V2.{DB_SCHEMA}_ROYALTY_ACCOUNTING_ROYALTY_ACCOUNTING.STATEMENT_PERIOD' # noqa: E501 ) prod_app_reporting_db_art_relations = ( 'ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.CUSTOMER_MASTER_MASTER' # noqa: E501 ) REPORT_TABLE_DISTRIBUTION = 'REVENUE_DISTRO_DBT' REPORT_TABLE_NEIGHBOURING_RIGHTS = 'REVENUE_NR_DBT' REPORT_DIMENSION_MAP_DISTRIBUTION: dict[str, DimensionMapping] = { 'product': { 'column': 'DIM_RELEASE.DISPLAY_UPC', 'header': 'UPC', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_RELEASE ON DIM_RELEASE.RELEASEID = {REPORT_TABLE_DISTRIBUTION}.UPC """, 'include_mechanicals': True, 'extra': [ {'column': 'DIM_RELEASE.RELEASENAME', 'header': 'PRODUCT NAME'}, {'column': f"""{REPORT_TABLE_DISTRIBUTION}.PRODUCT_CODE""", 'header': 'PRODUCT CODE'}, { 'column': 'PROJECT.PROJECT_CODE', 'header': 'PROJECT CODE', 'join': f""" JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.PROJECT ON PROJECT.PROJECT_ID = {REPORT_TABLE_DISTRIBUTION}.PROJECT_ID """, }, {'column': 'DIM_RELEASE.FORMAT', 'header': 'FORMAT'}, { 'column': 'DIM_ARTIST.ARTISTNAME', 'header': 'PRIMARY ARTIST', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_ARTIST ON DIM_ARTIST.ARTISTID = {REPORT_TABLE_DISTRIBUTION}.ARTIST_ID """, }, { 'column': 'SUBACCOUNT.SUBACCOUNT_NAME', 'header': 'SUBACCOUNT', 'join': f""" LEFT JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.SUBACCOUNT ON SUBACCOUNT.SUBACCOUNT_ID = {REPORT_TABLE_DISTRIBUTION}.SUBACCOUNT_ID """, }, ], }, 'product_artist': { 'column': 'DIM_ARTIST.ARTISTNAME', 'header': 'PRODUCT ARTIST', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_RELEASE ON DIM_RELEASE.RELEASEID = {REPORT_TABLE_DISTRIBUTION}.UPC JOIN FACTS.{DB_SCHEMA}.DIM_ARTIST ON DIM_ARTIST.ARTISTID = DIM_RELEASE.ARTISTID """, 'include_mechanicals': True, }, 'service': { 'column': 'CUSTOMER_MASTER_MASTER.CUSTOMER_NAME', 'header': 'STORE', 'join': f""" JOIN {prod_app_reporting_db_art_relations} ON CUSTOMER_MASTER_MASTER.CUSTOMER_MASTER_MASTER_ID = {REPORT_TABLE_DISTRIBUTION}.STORE_ID """, 'include_mechanicals': False, }, 'statement_period': { 'column': 'STATEMENT_PERIOD.STATEMENT_PERIOD_NAME', 'header': 'STATEMENT PERIOD', 'join': f""" JOIN {app_reporting_db_royalty_accounting} ON STATEMENT_PERIOD.STATEMENT_PERIOD_ID = {REPORT_TABLE_DISTRIBUTION}.STATEMENT_PERIOD_ID """, 'include_mechanicals': False, }, 'territory': { 'column': 'DIM_COUNTRY.COUNTRYNAME', 'header': 'COUNTRY', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_COUNTRY ON DIM_COUNTRY.COUNTRYID = {REPORT_TABLE_DISTRIBUTION}.COUNTRY_ID """, 'include_mechanicals': False, }, 'transaction_type': { 'column': 'DIM_TRANSACTIONTYPE.TRANSACTIONTYPEDESC', 'header': 'TRANSACTION TYPE', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_TRANSACTIONTYPE ON DIM_TRANSACTIONTYPE.TRANSACTIONTYPEABBR = {REPORT_TABLE_DISTRIBUTION}.TRANSACTION_TYPE""", # noqa: E501 'include_mechanicals': False, }, 'recording': { 'column': f'{REPORT_TABLE_DISTRIBUTION}.ISRC', 'header': 'ISRC', 'include_mechanicals': False, 'default': 'No recording detail reported', 'extra': [ { 'column': 'DIM_TRACK.TRACKNAME', 'header': 'RECORDING TITLE', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_TRACK ON DIM_TRACK.TRACK_UNIQUE_ID = {REPORT_TABLE_DISTRIBUTION}.TRACK_UNIQUE_ID """, }, {'column': 'DIM_TRACK.VERSION', 'header': 'RECORDING VERSION'}, { 'column': 'DIM_ARTIST.ARTISTNAME', 'header': 'RECORDING ARTIST', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_ARTIST ON DIM_ARTIST.ARTISTID = {REPORT_TABLE_DISTRIBUTION}.ARTIST_ID """, }, ], }, 'collection_society': { 'column': 'CUSTOMER_MASTER_MASTER.CUSTOMER_NAME', 'header': 'COLLECTION SOCIETY', 'join': f""" JOIN {prod_app_reporting_db_art_relations} ON CUSTOMER_MASTER_MASTER.CUSTOMER_MASTER_MASTER_ID = {REPORT_TABLE_DISTRIBUTION}.STORE_ID """, 'include_mechanicals': False, 'extra': [ { 'column': 'DIM_COUNTRY.COUNTRYNAME', 'header': 'COUNTRY', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_COUNTRY ON DIM_COUNTRY.COUNTRYID = {REPORT_TABLE_DISTRIBUTION}.COUNTRY_ID """, } ], }, 'track': { 'column': 'DIM_TRACK.TRACKNAME', 'header': 'Track', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_TRACK ON DIM_TRACK.UPC = {REPORT_TABLE_DISTRIBUTION}.UPC AND DIM_TRACK.ISRC = {REPORT_TABLE_DISTRIBUTION}.ISRC AND DIM_TRACK.TRACK_ID = {REPORT_TABLE_DISTRIBUTION}.TRACK_ID """, 'include_mechanicals': True, 'extra': [ {'column': 'DIM_TRACK.VERSION', 'header': 'VERSION'}, { 'column': 'DIM_ARTIST.ARTISTNAME', 'header': 'ARTIST', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_ARTIST ON DIM_ARTIST.ARTISTID = {REPORT_TABLE_DISTRIBUTION}.ARTIST_ID """, }, { 'column': 'DIM_RELEASE.RELEASENAME', 'header': 'PRODUCT', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_RELEASE ON DIM_RELEASE.RELEASEID = {REPORT_TABLE_DISTRIBUTION}.UPC """, }, { 'column': 'DIM_IMPRINT.IMPRINT', 'header': 'IMPRINT', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_IMPRINT ON DIM_RELEASE.IMPRINTID = DIM_IMPRINT.IMPRINTID """, }, { 'column': 'DIM_RELEASE.DISPLAY_UPC', 'header': 'UPC', }, { 'column': f'{REPORT_TABLE_DISTRIBUTION}.ISRC', 'header': 'ISRC', }, {'column': f"""{REPORT_TABLE_DISTRIBUTION}.PRODUCT_CODE""", 'header': 'PRODUCT CODE'}, { 'column': 'PROJECT.PROJECT_CODE', 'header': ' PROJECT CODE', 'join': f""" JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.PROJECT ON PROJECT.PROJECT_ID = {REPORT_TABLE_DISTRIBUTION}.PROJECT_ID """, }, { 'column': 'SUBACCOUNT.SUBACCOUNT_NAME', 'header': 'SUBACCOUNT', 'join': f""" LEFT JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.SUBACCOUNT ON SUBACCOUNT.SUBACCOUNT_ID = {REPORT_TABLE_DISTRIBUTION}.SUBACCOUNT_ID """, }, ], }, 'imprint': { 'column': 'DIM_IMPRINT.IMPRINT', 'header': 'Imprint', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_RELEASE ON DIM_RELEASE.RELEASEID = {REPORT_TABLE_DISTRIBUTION}.UPC JOIN FACTS.{DB_SCHEMA}.DIM_IMPRINT ON DIM_RELEASE.IMPRINTID = DIM_IMPRINT.IMPRINTID """, 'include_mechanicals': True, 'extra': [ { 'column': 'SUBACCOUNT.SUBACCOUNT_NAME', 'header': 'SUBACCOUNT', 'join': f""" LEFT JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.SUBACCOUNT ON SUBACCOUNT.SUBACCOUNT_ID = {REPORT_TABLE_DISTRIBUTION}.SUBACCOUNT_ID """, }, ], }, 'subaccount': { 'column': 'SUBACCOUNT.SUBACCOUNT_NAME', 'header': 'SUBACCOUNT', 'join': f""" JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.SUBACCOUNT ON SUBACCOUNT.SUBACCOUNT_ID = {REPORT_TABLE_DISTRIBUTION}.SUBACCOUNT_ID """, 'include_mechanicals': True, }, 'project': { 'column': 'PROJECT.PROJECT_NAME', 'header': 'PROJECT', 'join': f""" JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.PROJECT ON PROJECT.PROJECT_ID = {REPORT_TABLE_DISTRIBUTION}.PROJECT_ID """, 'include_mechanicals': True, 'extra': [ { 'column': 'PROJECT.PROJECT_CODE', 'header': 'PROJECT CODE', }, ], }, } REPORT_DIMENSION_MAP_NEIGHBOURING_RIGHTS: dict[str, DimensionMapping] = { 'statement_period': { 'column': 'STATEMENT_PERIOD.STATEMENT_PERIOD_NAME', 'header': 'STATEMENT PERIOD', 'join': f""" JOIN {app_reporting_db_royalty_accounting} ON STATEMENT_PERIOD.STATEMENT_PERIOD_ID = {REPORT_TABLE_NEIGHBOURING_RIGHTS}.STATEMENT_PERIOD_ID """, }, 'territory': { 'column': 'DIM_COUNTRY.COUNTRYNAME', 'header': 'COUNTRY', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_COUNTRY ON DIM_COUNTRY.COUNTRYID = {REPORT_TABLE_NEIGHBOURING_RIGHTS}.COUNTRY_ID """, }, 'collection_society': { 'column': 'CUSTOMER_MASTER_MASTER.CUSTOMER_NAME', 'header': 'COLLECTION SOCIETY', 'join': f""" JOIN {prod_app_reporting_db_art_relations} ON CUSTOMER_MASTER_MASTER.CUSTOMER_MASTER_MASTER_ID = {REPORT_TABLE_NEIGHBOURING_RIGHTS}.STORE_ID """, 'extra': [ { 'column': 'DIM_COUNTRY.COUNTRYNAME', 'header': 'COUNTRY', 'join': f""" JOIN FACTS.{DB_SCHEMA}.DIM_COUNTRY ON DIM_COUNTRY.COUNTRYID = {REPORT_TABLE_NEIGHBOURING_RIGHTS}.COUNTRY_ID """, } ], }, 'recording': { 'column': f'{REPORT_TABLE_NEIGHBOURING_RIGHTS}.SOUND_RECORDING_ID', 'header': 'SOUND RECORDING ID', 'default': 'No recording detail reported', 'extra': [ { 'column': f'{REPORT_TABLE_NEIGHBOURING_RIGHTS}.SOUND_RECORDING_NAME', 'header': 'RECORDING TITLE', }, { 'column': f'FACTS.{DB_SCHEMA}.PERFORMANCE_NR_SOUND_RECORDING.VERSION', 'header': 'RECORDING VERSION', 'join': f""" LEFT JOIN FACTS.{DB_SCHEMA}.PERFORMANCE_NR_SOUND_RECORDING ON PERFORMANCE_NR_SOUND_RECORDING.ID = {REPORT_TABLE_NEIGHBOURING_RIGHTS}.SOUND_RECORDING_ID """, }, { 'column': f'FACTS.{DB_SCHEMA}.PERFORMANCE_NR_SOUND_RECORDING.MAIN_ARTIST', 'header': 'RECORDING ARTIST', }, ], }, } class RevenueDisplayType(str, Enum): """Revenue display type enum.""" NET = 'net' GROSS = 'gross' class DimensionType(str, Enum): """Dimension type enum.""" RECORDING = 'recording' FINANCIAL_DETAIL = 'financial_detail' STATEMENT_PERIOD = 'statement_period' NET_REVENUE_COLUMN = 'NET_SHARE_PAYEE_CURRENCY' GROSS_REVENUE_COLUMN = 'GROSS_REVENUE_PAYEE_CURRENCY' MECHANICAL_COLUMN = 'MECHANICAL_DEDUCTION_AMOUNT_PAYEE_CURRENCY' ADMIN_FEE_COLUMN = 'PUBLISHER_ADMIN_FEE_PAYEE_CURRENCY' CURRENCY_COLUMN = 'ACCOUNT_PAYEE_CURRENCY' # OWS Profile OWS_PROFILE_TYPE = os.environ.get('OWS_PROFILE_TYPE') OWS_PROFILE_ID = os.environ.get('OWS_PROFILE_ID') OWS_PROFILE_ROLES = 'administrator' # OWS Authentication OWS_CLIENT_TOKEN = os.environ.get('OWS_CLIENT_TOKEN')