260 lines
8.5 KiB
Python
Executable file
260 lines
8.5 KiB
Python
Executable file
#!/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()
|