Commit graph

37 commits

Author SHA1 Message Date
DJP
6c8c8ea508 Fix OMG API authorization header and private property access
Fixed two issues:
1. Removed 'Bearer' prefix from Authorization header (OMG API expects just the key)
2. Fixed private property access error (hardcoded endpoint URL instead of accessing $omgService->config)

OMG API now sends: Authorization: PeyJvcmciOiIy...
Instead of: Authorization: Bearer PeyJvcmciOiIy...

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 09:09:01 -05:00
DJP
e9a175ef5d Fix JSON parse error: disable display_errors to prevent deprecation warnings
Issue: PHP deprecation warnings from league/csv were being output as HTML
(<br /><b>...) which broke JSON parsing in browser.

Fix: Set display_errors=0 in process-csv.php while keeping log_errors=1.
Errors still logged to error_log but not output to browser.

Reverted test-upload endpoint back to process-csv.php.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 09:03:57 -05:00
DJP
b54f6af6e5 Add version marker to process-csv.php for cache troubleshooting
Added log message at start to confirm correct version is running.
This helps identify if browser is caching old JavaScript or server is serving old PHP.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:48:40 -05:00
DJP
0571ce403f Add comprehensive logging for OMG API debugging and application tracking
OMG API Debug Logging:
- Log full URL being called
- Log API key (first 20 chars for security)
- Log HTTP response code
- Log response body (first 500 chars)
- Log campaign number and business area extraction
- Log business unit mapping result

ApplicationLogger Class:
- Structured JSON logging to logs/application.log
- Track all actions: master_asset_submission, global_to_local_transform, box_upload
- Capture user email, timestamp, IP address, user agent
- Methods for reporting: getRecentLogs(), getLogsByAction(), getLogsByUser()
- Generate statistics: total actions, by user, by action, errors

Email Configuration:
- Configured SMTP via Mailgun (smtp.mailgun.org:587)
- Using twist@mail.dev.oliver.solutions
- Emails sent to logged-in user

This enables full audit trail and troubleshooting capability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:26:20 -05:00
DJP
9b8dbbf20c Enable OMG API lookup and add SMTP email support
Email Configuration:
- Added SMTP support via Mailgun (smtp.mailgun.org:587)
- EmailService now supports both Mailgun API and SMTP
- Configured to use twist@mail.dev.oliver.solutions
- Emails sent to logged-in user (SSO email or local dev email)

OMG API:
- Enabled OMG API lookup in process-csv.php
- API key configured in config.php
- Looks up business unit from campaign number
- Falls back to 'ERROR' if business unit not recognized

SMTP Implementation:
- Full SMTP protocol with AUTH LOGIN
- Proper error handling and logging
- Fallback to Mailgun API if SMTP fails

Notifications sent to user email:
- Process started notification
- Process completed notification (with file count)
- Error notifications

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:15:22 -05:00
DJP
11ebcf8dd3 Fix preview table rendering - convert PHP object to JavaScript array
Issue: PHP's iterator_to_array() returns associative array with numeric keys
which JavaScript receives as an object {1: {...}, 2: {...}}, not an array.

Fix: Convert object to array using Object.values() before rendering table.
Added to both initial preview and file selector preview.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:33:10 -05:00
DJP
b51b59af7f Add debug logging to troubleshoot preview table issue
Added console.log statements to track:
- Preview data availability
- Row count
- Headers extraction
- Table HTML generation

This will help identify why the table isn't rendering.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:32:02 -05:00
DJP
431c25fb24 Fix filename generation: properly interpolate country code variable
Changed {country} to {$country} in filename template.
Now generates correct filenames like:
- OMG1601654_GlobalACIngest_TESTING-GB_1763418477.csv
- OMG1601654_GlobalACIngest_TESTING-ES_1763418477.csv
etc.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:30:17 -05:00
DJP
53ec170702 Fix preview display and show all rows instead of just 20
Changes:
- Initial preview now displays immediately from response data
- Show ALL rows in preview table (not limited to 20)
- File selector properly switches between all 16 CSVs
- Each file shows complete data when selected

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:29:28 -05:00
DJP
79c45634fe Update README with complete Global to Local documentation
Added comprehensive documentation:
- Updated app title to 'L'Oréal OMG Assistant Global'
- Detailed Global to Local workflow (6 stages)
- Input CSV requirements and format
- ISO codes configuration (16 markets in config.php)
- Output file naming and structure
- Preview and download options
- User approval workflow
- Error handling examples for all stages
- API endpoints documentation
- Configuration sections for OMG API and Email

Clarified that ISO codes are in config.php and fully editable.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:29:06 -05:00
DJP
df403363a9 Add file preview selector and download all functionality
Title Changes:
- App title: "L'Oréal OMG Assistant Global"
- Tab 1: "Master Global Asset Submission"
- Upload button: "Approve & Upload to OMG"

Preview Enhancements:
- Dropdown selector to preview all 16 CSV files individually
- Shows filename with ISO code (e.g., "en-GB - OMG1601654_...")
- Switch between files to view complete data for each
- Show ALL rows (not just first 20)

Download Features:
- "Download Current File" - Download the currently previewed CSV
- "Download All Files (ZIP)" - Download all 16 CSVs as a ZIP archive
- get-csv-preview.php: Endpoint to fetch any file for preview
- download-all-csv.php: Creates ZIP with all CSVs

UX Improvements:
- File selector styled with brand colors
- Clear labeling of which file is being previewed
- Easy navigation between all regional CSVs
- Test before upload with full data visibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:27:25 -05:00
DJP
82b192355c Fix syntax error: remove stray quote after comment block
Line 180 had */" which caused PHP parse error.
Changed to just */ to close comment block properly.

This was causing the 500 Internal Server Error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:19:40 -05:00
DJP
5fb6e1957d Add debug logging and fix test files
- Added error_log debugging to process-csv.php
- Fixed test-csv.php syntax (removed use statements in code)
- Created test-process2.php for step-by-step class loading test
- All service classes load successfully in tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:16:21 -05:00
DJP
0be9ddb946 Fix class namespace issues - use fully qualified class names
Removed 'use' statements outside namespace context.
Changed to fully qualified class names:
- League\Csv\Reader
- League\Csv\Writer
- Carbon\Carbon

This fixes PHP 500 errors from improper use statements.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:09:46 -05:00
DJP
7d377f635f Fix session_start timing to prevent headers already sent error
Moved session_start() to top of process-csv.php before any output.
Removed duplicate session_start() call.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:06:01 -05:00
DJP
5c6cf687a8 Update Global to Local to create 16 separate CSV files and fix PHP compatibility
Key Changes:
- Fixed CSV transformation to create 16 separate files (one per ISO code)
- Each CSV has all input rows with Language/Country replaced
- Handles Excel Sep=, prefix correctly
- Parses date format "24 Mar 2025 00:00" from sample CSV
- Skip OMG API for testing (use business unit "TESTING")
- Upload all 16 CSVs to Box folder
- Show list of all files in preview
- Download preview functionality

PHP Compatibility:
- Downgraded nesbot/carbon to ^2.0 (supports PHP 7.1+)
- Downgraded league/csv to 9.8.0 (supports PHP 7.4+)
- Now compatible with PHP 7.4-8.0 servers

Preview Enhancements:
- Shows all 16 filenames with ISO codes
- Preview table shows first file as sample
- Summary shows file count and total rows

Testing:
- Added sample CSV: Project_1601654_mediaBookings.csv
- OMG API lookup commented out (ready to enable later)
- Using "TESTING" as business unit

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:03:51 -05:00
DJP
19328d10b4 Fix PHP version requirements for server compatibility
Downgraded dependencies to support PHP 7.4+:
- nesbot/carbon: ^2.0 (PHP 7.1+)
- league/csv: 9.8.0 (PHP 7.4+)

This ensures the application works on servers with PHP 7.4-8.0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 16:51:27 -05:00
DJP
d31f394ad5 Add Global to Local CSV transformation frontend with visual progress tracking
Created Complete Tab System:
- header.php: Shared navigation between Asset Submission and Global to Local tabs
- global-to-local.php: Upload page with drag & drop, progress tracker, preview
- global-to-local.js: Frontend logic for upload, processing, preview, and Box upload

Visual Progress System:
- 6-stage progress tracker with icons and status (⏸️ pending, 🔄 processing,  success, ⚠️ warning,  error)
- Real-time status updates for each stage
- Detailed error cards with actionable messages
- Warning cards for data quality issues
- Success cards with completion info

Features:
- Drag & drop CSV upload with file size validation
- Step-by-step progress visualization
- Error reporting at each stage (upload, parse, campaign, OMG API, business unit, transform)
- CSV preview table (first 50 rows) before Box upload
- Download preview CSV before committing
- User approval required before Box upload
- Summary cards showing input/output counts, campaign, business unit

Error Handling:
- File validation errors (wrong type, too large, empty)
- CSV parsing errors (malformed, wrong columns)
- Campaign extraction errors (invalid filename)
- OMG API errors (404, timeout, auth failure)
- Business unit mapping errors (unrecognized brands)
- Date transformation errors (invalid formats)
- Box upload errors (permissions, folder issues)

UI Enhancements:
- Tab navigation with active state highlighting
- Professional error cards with details and actions
- Responsive design for mobile/desktop
- Maintains black/yellow L'Oréal brand colors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 16:48:43 -05:00
DJP
80b170a735 Add Global to Local CSV transformation backend
Services Created:
- OMGService.php: OMG API integration with detailed error handling
- CSVTransformer.php: CSV parsing and transformation logic
- EmailService.php: Mailgun email notifications
- process-csv.php: Multi-stage CSV processing with progress tracking
- upload-to-box.php: Box upload with approval workflow

Features:
- Comprehensive validation at each stage (upload, parse, campaign, API, transform)
- Detailed error reporting with actionable messages
- Warning system for non-critical issues
- Progress tracking through all stages
- Session-based CSV storage for preview before upload
- Date transformation (parse + add 1 month per blueprint)
- 16x market multiplication per ISO codes
- Business unit mapping per Make.com blueprint logic

Dependencies Added:
- league/csv for CSV parsing
- nesbot/carbon for date manipulation

Configuration:
- Added global_to_local settings (ISO codes, business unit map)
- Added omg_api settings (placeholder for API key)
- Added email settings (Mailgun placeholders)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 16:44:48 -05:00
DJP
384c37be3e Expand README with comprehensive workflow documentation
Added detailed sections:
- Workflow Overview and Purpose
- Box folder structure requirements with visual diagram
- Complete data extraction breakdown (Box API, User Input, System)
- Step-by-step workflow (7 detailed steps)
- Data flow diagram
- Example webhook payload with full structure
- What happens after submission
- Comprehensive error handling documentation

This provides complete understanding of how the application extracts and processes campaign asset metadata.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:51:46 -05:00
DJP
e19ec94b76 Simplify .htaccess - remove vendor blocking
- Removed vendor directory blocking (was breaking require_once)
- Keep critical protections: JWT config, config.php, hidden files
- More targeted JSON file blocking (config/composer only)
- Allow vendor directory to be accessed by PHP

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:42:11 -05:00
DJP
35e959bbf7 Add comprehensive .htaccess security configuration
Protected files:
- Box JWT config (43984435_*_config.json)
- All JSON files
- config.php and composer files
- vendor directory
- Hidden files (.git, .env, etc.)
- Log and backup files
- README and documentation

Security features:
- Prevent directory browsing
- Security headers (X-Frame-Options, XSS Protection, etc.)
- HTTPS redirect (commented out, enable in production)
- Compression and caching for performance
- PHP security settings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:40:00 -05:00
DJP
47b0615c3a Fix grandparent logic: properly get folder two levels up
Structure: Campaign Number → CAMPAIGN_ASSETS → SUPPLIED_ASSETS
- Changed to fetch parent, then parent's parent (proper two levels up)
- Previous logic was using path_collection which showed CAMPAIGN_ASSETS
- Now correctly retrieves the campaign number folder
- Uses two separate API calls to traverse up the hierarchy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:22:06 -05:00
DJP
ef7ffedc94 Fix Master Campaign Number to use parent folder (one level up)
Changed from grandparent (two levels up) to parent (one level up).
- Renamed getGrandparentFolder() to getParentFolder()
- Uses folder's direct parent instead of path_collection traversal
- Master Campaign Number should now show the campaign number folder
- Updated validate-box.php to use 'parent' instead of 'grandparent'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:20:39 -05:00
DJP
9923ec24a0 Fix Lookup button alignment and layout
- Changed align-items to stretch for proper vertical alignment
- Added flex: 1 to input for proper width distribution
- Added flex-shrink: 0 to button to prevent shrinking
- Increased min-width to 120px for 'Looking up...' text
- Fixed transform on disabled state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:14:45 -05:00
DJP
7cde92694c Add validation: folder must be named SUPPLIED_ASSETS
- Check folder name immediately after fetching folder info
- Stop processing if folder name is not SUPPLIED_ASSETS (case-insensitive)
- Return clear error message with actual folder name
- Prevents unnecessary API calls for invalid folders

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:12:37 -05:00
DJP
073f148cec Use correct Make.com API key header: x-make-apikey
Changed from custom header to Make.com's official API key header format.
Reference: https://apps.make.com/gateway

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:02:18 -05:00
DJP
3aeeae7401 Remove custom API key header for Make.com webhook
Make.com webhooks use the URL itself as authentication, not custom headers.
Removed 'Loreal-Webhook' header - only sending Content-Type: application/json.
Added payload logging for debugging.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:00:01 -05:00
DJP
70a4d26d9b Fix 401 error: Don't pass webhook status code to client
Issue: When webhook returned 401, PHP was setting http_response_code(401)
which made the browser think the PHP endpoint was unauthorized.

Fix: Always return 200 to client, but indicate webhook failure in JSON response.
Added detailed logging of webhook failures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:58:10 -05:00
DJP
f70fe30ea2 Show user email in header for both SSO and local modes
- Display user email in top right of header bar
- Update header layout with flexbox
- Show email in yellow (#FFC407) color
- Always visible regardless of SSO mode

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:55:54 -05:00
DJP
d11bdc634a Add debug logging to troubleshoot 401 error
- Enable display_errors for debugging
- Add SSO status logging
- Add detailed error information in response
- Log authentication user details

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:54:06 -05:00
DJP
d6c44ef3ad Fix webhook API key header name for Make.com
Changed from 'X-API-Key' to 'Loreal-Webhook' header to match Make.com webhook expectations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:50:58 -05:00
DJP
b412356b4b Add Lookup button and nested folder contents display
Features:
- Added "Lookup" button to trigger Box ID validation manually
- No automatic validation on typing - user must click Lookup
- Recursive folder contents fetching (3 levels deep)
- Collapsible nested folder display with expand/collapse buttons
- Visual hierarchy with indentation and folder icons
- Shows all files within nested folders
- Updated UI with better folder/file organization

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:48:25 -05:00
DJP
1a88a06d54 Add comprehensive README documentation 2025-11-17 14:45:40 -05:00
DJP
110bd68fdb Resolve .gitignore merge conflict 2025-11-17 14:44:46 -05:00
DJP
dbf7090d09 Initial commit: L'Oréal Box Asset Submission Form
- Set up PHP application with Composer and JWT library
- Implemented SSO authentication with local dev mode
- Created Box API service for folder validation
- Built two-column form interface (form + preview)
- Added real-time Box ID validation with AJAX
- Integrated webhook submission with status response
- Auto-populate Master Campaign Number from Box folder hierarchy
- Responsive design with Montserrat font and black/yellow theme

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:43:36 -05:00
Dave Porter
bd7d07fd84 Initial commit 2025-11-17 19:38:53 +00:00