#!/usr/bin/env python3 """ Campaign Status Update - Set specific campaign to specific status Allows updating a campaign by number or name to any A# status Compatible with Python 3.6+ """ import sys import os import logging import argparse # Add shared library to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from shared.config_loader import load_config from shared.dam_client import DAMClient # Setup simple console logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger('UpdateStatus') def find_campaign_by_identifier(dam, identifier): """ Find campaign by campaign number or name Args: dam: DAMClient instance identifier: Campaign number (e.g., C000000078) or partial campaign name Returns: list: Matching campaigns """ # Search through all common statuses to find the campaign all_statuses = ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'B1', 'B2'] found_campaigns = [] logger.info("Searching for campaign: {}".format(identifier)) for status in all_statuses: campaigns = dam.search_campaigns(status=status) if campaigns: for campaign in campaigns: campaign_id_match = False campaign_name_match = False # Check campaign number (exact match) if campaign.get('campaign_id') == identifier: campaign_id_match = True # Check campaign name (partial match, case insensitive) campaign_name = campaign.get('campaign_name', '') if identifier.upper() in campaign_name.upper(): campaign_name_match = True if campaign_id_match or campaign_name_match: # Add current status to campaign info campaign['current_status'] = status found_campaigns.append(campaign) return found_campaigns def main(): """Main entry point""" # Parse command-line arguments parser = argparse.ArgumentParser( description='Update specific campaign to specific status', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: # Update campaign C000000078 to A2 (dev environment, OAuth) python scripts/update_campaign_status.py --camp C000000078 --status A2 # Update campaign by name to A4 (dev environment, mTLS V2) python scripts/update_campaign_status.py --camp "CONTENT SCALING" --status A4 --auth-pfx-v2 # Production environment with mTLS V2 python scripts/update_campaign_status.py --camp C000000078 --status A3 --auth-pfx-v2 --env prod # Production environment with legacy mTLS python scripts/update_campaign_status.py --camp C000000078 --status A3 --auth-pfx --env prod """ ) parser.add_argument('--camp', type=str, required=True, help='Campaign number (e.g., C000000078) or partial campaign name') parser.add_argument('--status', type=str, required=True, help='Target status (A1, A2, A3, A4, A5, A6, B1, B2)') parser.add_argument('--auth-pfx', action='store_true', help='Use mTLS certificate authentication (Legacy APIM)') parser.add_argument('--auth-pfx-v2', action='store_true', help='Use mTLS V2 (Hybrid) authentication') parser.add_argument('--env', type=str, choices=['dev', 'prod'], default='dev', help='Environment: dev (default) or prod') args = parser.parse_args() # Validate status valid_statuses = ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'B1', 'B2'] target_status = args.status.upper() if target_status not in valid_statuses: print("ERROR: Invalid status '{}'".format(args.status)) print("Valid statuses: {}".format(', '.join(valid_statuses))) sys.exit(1) # Determine auth mode auth_mode = 'oauth' if args.auth_pfx_v2: auth_mode = 'mtls_v2' elif args.auth_pfx: auth_mode = 'mtls' # Set environment variable for config loader os.environ['ENV'] = args.env print("") print("=" * 70) print("Ferrero Campaign Status Update") print("=" * 70) print("Campaign Identifier: {}".format(args.camp)) print("Target Status: {}".format(target_status)) print("Environment: {}".format(args.env.upper())) if auth_mode == 'mtls_v2': print("Authentication: mTLS V2 (Hybrid)") elif auth_mode == 'mtls': print("Authentication: mTLS Certificate (Legacy)") else: print("Authentication: OAuth2 (default)") print("=" * 70) print("") # Load configuration config = load_config('config/config.yaml') # Initialize DAM client dam = DAMClient(config, auth_mode=auth_mode) # Test connection logger.info("Testing DAM connection...") if not dam.test_connection(): logger.error("DAM connection failed - exiting") sys.exit(1) logger.info("DAM connection OK") print("") # Find campaign campaigns = find_campaign_by_identifier(dam, args.camp) if not campaigns: print("") print("=" * 70) print("No campaigns found matching: {}".format(args.camp)) print("=" * 70) print("") print("Searched all statuses: {}".format(', '.join(valid_statuses))) print("Try:") print(" - Exact campaign number: C000000078") print(" - Partial campaign name: CONTENT SCALING") print(" - Different search term") sys.exit(1) # Show all matching campaigns print("") print("=" * 70) print("Found {} matching campaign(s)".format(len(campaigns))) print("=" * 70) print("") # If multiple matches, let user choose if len(campaigns) > 1: print("Multiple campaigns found:") print("") for i, campaign in enumerate(campaigns, 1): print("{}. {} ({}) - Current Status: {}".format( i, campaign['campaign_name'], campaign.get('campaign_id', 'N/A'), campaign['current_status'] )) print("") while True: try: choice = input("Which campaign? (1-{}): ".format(len(campaigns))).strip() choice_num = int(choice) if 1 <= choice_num <= len(campaigns): selected_campaign = campaigns[choice_num - 1] break else: print("Please enter a number between 1 and {}".format(len(campaigns))) except ValueError: print("Please enter a valid number") else: # Only one match selected_campaign = campaigns[0] # Show selected campaign campaign_id = selected_campaign['asset_id'] campaign_name = selected_campaign['campaign_name'] campaign_number = selected_campaign.get('campaign_id', 'N/A') current_status = selected_campaign['current_status'] print("") print("=" * 70) print("Selected Campaign") print("=" * 70) print("Name: {}".format(campaign_name)) print("Number: {}".format(campaign_number)) print("Current Status: {}".format(current_status)) print("Target Status: {}".format(target_status)) print("=" * 70) print("") # Confirm update while True: response = input("Update campaign status {} → {}? (yes/no): ".format( current_status, target_status )).strip().lower() if response in ['yes', 'y']: break elif response in ['no', 'n']: print("Cancelled - no changes made") sys.exit(0) else: print("Please enter 'yes' or 'no'") # Perform update print("") print("Updating campaign status...") result = dam.update_campaign_status(campaign_id, target_status) print("") if result['success']: print("=" * 70) print("✓ SUCCESS") print("=" * 70) print("Campaign: {}".format(campaign_name)) print("Number: {}".format(campaign_number)) print("New Status: {}".format(target_status)) print("=" * 70) print("") else: print("=" * 70) print("✗ FAILED") print("=" * 70) print("Campaign: {}".format(campaign_name)) print("Error: {}".format(result.get('error', 'Unknown error'))) print("=" * 70) print("") print("Note: The campaign folder ID may be incorrect or the API endpoint may need adjustment") sys.exit(1) if __name__ == '__main__': main()