# A2→A3 CreativeX Integration Guide ## Overview The A2→A3 upload workflow now automatically looks up CreativeX scores from the database instead of reading from Box metadata templates. ## How It Works ### Old Method (Box Metadata Template) ❌ **Removed:** `box.get_file_metadata(file_id, template_name='Ferrero-DAM-Metadata')` - Required manual metadata entry in Box - Error-prone, easy to miss - No history tracking ### New Method (Database Lookup) ✅ **Implemented:** `db.get_creativex_score_by_filename(clean_filename)` - Automatic lookup by filename - Always gets latest `active` score - History preserved for audit - Fallback to defaults if not found ## Workflow Sequence ### Step-by-Step: 1. **Agency uploads file to Box** (folder 348526703108) - Filename: `Brand_Country_Language_123456_OMG7654321_AbCdEf.mp4` 2. **A2→A3 script polls Box folder** - Parses filename to get tracking ID: `AbCdEf` - Strips upload components to get clean filename: `Brand_Country_Language_123456.mp4` 3. **Database lookup for CreativeX score** ```python creativex_data = db.get_creativex_score_by_filename("Brand_Country_Language_123456.mp4") ``` 4. **Two scenarios:** **✅ Score Found in Database:** ```python { 'filename': 'Brand_Country_Language_123456.mp4', 'creativex_id': '6864255', 'creativex_url': 'https://app.creativex.com/audit/scorecards/32456797', 'quality_score': '85', 'box_file_id': '2043306479381', 'full_extraction_data': {...}, # Complete JSON 'extracted_at': '2025-11-11 21:29:45' } ``` - Uses score `85` and actual URL - Email shows: "✅ CreativeX Score Added: 85 (from database)" **⚠️ Score NOT Found:** ```python None # No matching filename in database ``` - Uses default score: `0` - Uses placeholder URL: `https://app.creativex.com/preflight/pretests` - Email shows orange warning box with instructions - Upload still succeeds (defaults allow it to pass) 5. **Metadata applied to DAM upload** - Field: `FERRERO.TAB.FIELD.CREATIVEX` = score value - Field: `FERRERO.FIELD.CREATIVEX LINK` = URL - Plus all other MVP fields 6. **File uploaded to DAM and deleted from Box** ## Code Changes ### A2→A3 Script Changes **File:** `scripts/a2_to_a3_upload_polling.py` **Lines 101-124:** Replaced Box metadata lookup with database lookup ```python # Old code (removed): # box_metadata = box.get_file_metadata(file_id, template_name='Ferrero-DAM-Metadata') # New code: clean_filename_for_lookup = parser.strip_upload_components(filename) creativex_data = db.get_creativex_score_by_filename(clean_filename_for_lookup) if creativex_data: box_metadata = { 'score': creativex_data['quality_score'], 'url': creativex_data['creativex_url'] } creativex_found = True else: box_metadata = { 'score': '0', 'url': 'https://app.creativex.com/preflight/pretests' } creativex_found = False ``` **Lines 193-202:** Pass CreativeX status to email ```python return { 'success': True, 'creativex_found': creativex_found, 'creativex_score': box_metadata.get('score', '0'), 'creativex_url': box_metadata.get('url', '...') } ``` ### Email Template Changes **File:** `scripts/shared/notifier.py` **Template:** `a2_to_a3_file_uploaded` **Added to checklist:** ```html {% if creativex_found %}
  • CreativeX Score Added: {{ creativex_score }} (from database)
  • {% else %}
  • ⚠️ CreativeX Score: Not found - used default (0)
  • {% endif %} ``` **Added warning section:** ```html {% if not creativex_found %}

    ⚠️ CreativeX Score Missing

    No score found for: {{ clean_filename }}

    Default Values Used: Score: 0, URL: placeholder

    To add: Upload PDF to Box folder 350605024645 and run creativex_scoring_storing.py

    {% endif %} ``` ## Default Values When no CreativeX score is found: | Field | Default Value | Purpose | |-------|---------------|---------| | Score | `0` | Indicates "not scored" but allows upload to proceed | | URL | `https://app.creativex.com/preflight/pretests` | Valid CreativeX URL (preflight section) | These defaults ensure uploads never fail due to missing CreativeX data. ## Database Query Details ### Query Used: ```sql SELECT filename, creativex_id, creativex_url, quality_score, box_file_id, full_extraction_data, extracted_at FROM creativex_scores WHERE filename = %s AND status = 'active' ORDER BY extracted_at DESC LIMIT 1 ``` ### Key Points: - ✅ Filters for `status = 'active'` → Only latest version - ✅ Orders by `extracted_at DESC` → Most recent first - ✅ `LIMIT 1` → Only one result - ✅ Returns `None` if no match found ## Email Notification Examples ### When CreativeX Score Found: ``` What Was Done: ✅ Downloaded from Box processing folder (348526703108) ✅ Loaded master metadata from database (AbCdEf) ✅ Built asset representation with 27 MVP fields ✅ Updated Description from filename ✅ Updated Language from filename ✅ Set State to "Local" ✅ CreativeX Score Added: 85 (from database) ✅ Stripped OMG Job Number and Tracking ID from filename ✅ Uploaded to DAM Final Assets folder ✅ Deleted file from Box ``` ### When CreativeX Score Missing: ``` What Was Done: ✅ Downloaded from Box processing folder (348526703108) ✅ Loaded master metadata from database (AbCdEf) ✅ Built asset representation with 27 MVP fields ✅ Updated Description from filename ✅ Updated Language from filename ✅ Set State to "Local" ⚠️ CreativeX Score: Not found - used default (0) ✅ Stripped OMG Job Number and Tracking ID from filename ✅ Uploaded to DAM Final Assets folder ✅ Deleted file from Box [Orange Warning Box] ⚠️ CreativeX Score Missing No CreativeX score found in database for: Brand_Country_Language_123456.mp4 Default Values Used: • Score: 0 • URL: https://app.creativex.com/preflight/pretests To add CreativeX score: Upload PDF report to Box folder 350605024645 and run creativex_scoring_storing.py ``` ## Filename Matching Logic ### Important: Clean Filename Used for Lookup The A2→A3 script receives files with upload components: - **Box filename:** `Brand_Country_Language_123_OMG7654321_AbCdEf.mp4` - **Clean filename:** `Brand_Country_Language_123.mp4` (stripped) The database lookup uses the **clean filename** because: 1. CreativeX PDFs are named with clean filenames 2. Upload components (OMG Job, Tracking ID) are added later in workflow 3. Database stores what's in the PDF report (original clean name) ```python clean_filename_for_lookup = parser.strip_upload_components(filename) # "Brand_Country_Language_123_OMG7654321_AbCdEf.mp4" # → "Brand_Country_Language_123.mp4" creativex_data = db.get_creativex_score_by_filename(clean_filename_for_lookup) ``` ## Testing Scenarios ### Scenario 1: File with CreativeX Score 1. Upload PDF to Box folder 350605024645 with filename: `Nutella_France_French_456.pdf` 2. Run: `python scripts/creativex_scoring_storing.py` 3. Verify in database: Score stored for `Nutella_France_French_456.mp4` 4. Agency uploads: `Nutella_France_French_456_OMG999_XyZ123.mp4` to A2→A3 folder 5. A2→A3 script: - Strips to: `Nutella_France_French_456.mp4` - Finds score in database - Uploads with actual CreativeX data - Email shows: "✅ CreativeX Score Added: 85" ### Scenario 2: File WITHOUT CreativeX Score 1. Agency uploads: `NewBrand_Italy_Italian_789_OMG888_Abc987.mp4` to A2→A3 folder 2. No PDF was ever uploaded to 350605024645 for this file 3. A2→A3 script: - Strips to: `NewBrand_Italy_Italian_789.mp4` - Database lookup returns `None` - Uses defaults: Score=0, URL=placeholder - Upload succeeds anyway - Email shows orange warning: "⚠️ CreativeX Score Missing" ## Advantages Over Box Metadata | Aspect | Old (Box Metadata) | New (Database) | |--------|-------------------|----------------| | Source | Manual entry in Box | Automatic from LlamaExtract | | Accuracy | Human error prone | AI extraction | | History | No history | Full version history | | Lookup Speed | Box API call | Fast database query | | Fallback | Would fail if missing | Graceful defaults | | Audit Trail | None | Complete with timestamps | | Scalability | Manual per file | Batch processing | ## Production Deployment Notes ### Prerequisites: 1. CreativeX scoring system deployed (see CREATIVEX_DEPLOYMENT.md) 2. Database table `creativex_scores` created 3. At least some files scored (or expect warnings for missing scores) ### No Breaking Changes: - A2→A3 workflow continues to work - Missing scores use defaults (Score: 0) - Uploads never fail due to missing CreativeX data - Email clearly indicates when defaults are used ### Recommended Workflow: 1. Download master assets (A1→A2) 2. **Upload CreativeX PDFs to folder 350605024645** 3. **Run creativex_scoring_storing.py to populate database** 4. Agency creates localized versions 5. Agency uploads to A2→A3 folder 6. A2→A3 script automatically attaches CreativeX scores ## Future Enhancements Potential additions: - Add CreativeX brand/market validation (warn if mismatch with filename) - Display version number in A2→A3 email ("Score: 85 - Version 3") - Track which files are missing scores in daily report - Auto-populate score field in Box for agency reference ## Support - **Database queries:** See CREATIVEX_DEPLOYMENT.md section "Checking Results" - **Scoring new files:** Run `python scripts/creativex_scoring_storing.py` - **Logs:** Check `logs/a2_to_a3.log` for CreativeX lookup results - **Email:** Orange warning box appears when scores are missing