// Orders page JavaScript let routes = {}; let csrfToken = ''; // Initialize on page load document.addEventListener('DOMContentLoaded', function() { if (window.orderRoutes) { routes = window.orderRoutes; csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || ''; } // Attach event listener to the button instead of using inline onclick const startButton = document.getElementById('startOrderMigrationBtn'); if (startButton) { startButton.addEventListener('click', function(e) { e.preventDefault(); startOrderMigration(); }); } }); function startOrderMigration() { try { const button = document.getElementById('startOrderMigrationBtn'); if (!button) { console.error('Start order migration button not found'); alert('Error: Button not found. Please refresh the page.'); return; } const logContent = document.getElementById('orderMigrationLogContent'); if (!logContent) { console.error('Order migration log content not found'); alert('Error: Log container not found. Please refresh the page.'); return; } const originalText = button.textContent || 'Start Order Migration'; if (button) { button.disabled = true; button.textContent = 'Migrating...'; button.style.cursor = 'not-allowed'; } const progressContainer = document.getElementById('migrationProgressContainer'); // Show progress bar if (progressContainer) { progressContainer.style.display = 'block'; updateProgressBar(0, 0, 0, 0, 0, 'Starting migration...', ''); } logContent.innerHTML = '
Starting migration...
'; // Generate progress key for tracking const progressKey = 'order_migration_progress_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); let progressInterval = null; // Check if routes are available if (!routes || !routes.migrateOrders) { console.error('Order routes not available', routes); if (button) { button.disabled = false; button.textContent = originalText; button.style.cursor = 'pointer'; } alert('Error: Routes not initialized. Please refresh the page.'); return; } progressInterval = pollMigrationProgress(progressKey, button, originalText, logContent); fetch(routes.migrateOrders, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify({ dry_run: false, progress_key: progressKey }) }) .then(async response => { const contentType = response.headers.get('content-type'); // Check if response is JSON if (contentType && contentType.includes('application/json')) { return response.json(); } else { // Response is HTML (error page), get text and show error const text = await response.text(); throw new Error(`Server returned HTML instead of JSON. Status: ${response.status}. This usually means there was a server error. Check the browser console or server logs for details.`); } }) .then(data => { // Stop polling if (progressInterval) { clearInterval(progressInterval); } // Hide progress bar if (progressContainer) { progressContainer.style.display = 'none'; } if (button) { button.disabled = false; button.textContent = originalText; button.style.cursor = 'pointer'; } if (data.success) { // Update progress bar to 100% before hiding if (progressContainer) { updateProgressBar(100, data.added + data.updated, data.added + data.updated, data.added, data.updated, data.errors, 'completed', ''); } // Update order statistics updateOrderStatistics(); const successEntry = document.createElement('div'); successEntry.className = 'log-entry success'; successEntry.textContent = `✓ Migration completed! Added: ${data.added || 0}, Updated: ${data.updated || 0}, Errors: ${data.errors || 0}`; logContent.appendChild(successEntry); if (data.log && data.log.length > 0) { data.log.forEach(log => { const entry = document.createElement('div'); entry.className = 'log-entry ' + (log.includes('ERROR') ? 'error' : 'success'); entry.textContent = log; logContent.appendChild(entry); }); } const logContainer = document.getElementById('orderMigrationLogContainer'); logContainer.scrollTop = logContainer.scrollHeight; } else { const errorEntry = document.createElement('div'); errorEntry.className = 'log-entry error'; errorEntry.textContent = '✗ Migration failed: ' + (data.message || 'Unknown error'); logContent.appendChild(errorEntry); } }) .catch(error => { // Stop polling if (progressInterval) { clearInterval(progressInterval); } // Hide progress bar if (progressContainer) { progressContainer.style.display = 'none'; } if (button) { button.disabled = false; button.textContent = originalText; button.style.cursor = 'pointer'; } if (logContent) { const errorEntry = document.createElement('div'); errorEntry.className = 'log-entry error'; errorEntry.textContent = '✗ Error: ' + error.message; logContent.appendChild(errorEntry); } else { console.error('Error during migration:', error); alert('Error: ' + error.message); } }); } catch (error) { console.error('Error in startOrderMigration:', error); alert('An unexpected error occurred. Please refresh the page and try again.'); } } function pollMigrationProgress(progressKey, button, originalText, logContent) { return setInterval(() => { if (!routes.migrationProgress) { console.error('Migration progress route not available'); return; } fetch(routes.migrationProgress + '?progress_key=' + encodeURIComponent(progressKey), { method: 'GET', headers: { 'X-CSRF-TOKEN': csrfToken } }) .then(response => response.json()) .then(data => { if (data.success && data.progress) { const progress = data.progress; const percentage = progress.total > 0 ? Math.round((progress.current / progress.total) * 100) : 0; updateProgressBar( percentage, progress.current, progress.total, progress.added, progress.updated, progress.errors, progress.status, progress.current_increment_id ); } else if (data.success === false && data.message === 'Progress not found') { // Progress not found yet, migration might not have started // This is okay, just continue polling } }) .catch(error => { console.error('Error polling progress:', error); }); }, 500); // Poll every 500ms for smoother updates } function updateProgressBar(percentage, current, total, added, updated, errors, status, currentIncrementId) { const progressBar = document.getElementById('progressBar'); const progressPercentage = document.getElementById('progressPercentage'); const progressStatus = document.getElementById('progressStatus'); const currentOrder = document.getElementById('currentOrder'); const progressAdded = document.getElementById('progressAdded'); const progressUpdated = document.getElementById('progressUpdated'); const progressErrors = document.getElementById('progressErrors'); if (progressBar) { progressBar.style.width = percentage + '%'; } if (progressPercentage) { progressPercentage.textContent = percentage + '%'; } if (progressStatus) { const statusText = status === 'running' ? 'Migrating...' : status === 'completed' ? 'Migration completed!' : status === 'failed' ? 'Migration failed!' : 'Starting...'; progressStatus.textContent = statusText; } if (currentOrder) { currentOrder.textContent = currentIncrementId ? `Current: ${currentIncrementId}` : `Processing ${current} of ${total}`; } if (progressAdded) { progressAdded.textContent = added; } if (progressUpdated) { progressUpdated.textContent = updated; } if (progressErrors) { progressErrors.textContent = errors; } } function updateOrderStatistics() { if (!routes.statistics) { console.error('Statistics route not available'); return; } fetch(routes.statistics, { method: 'GET', headers: { 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.success && data.statistics) { const stats = data.statistics; const m1OrdersEl = document.getElementById('statM1Orders'); const m2OrdersEl = document.getElementById('statM2Orders'); const m1NotInM2El = document.getElementById('statM1NotInM2'); const m2NotInM1El = document.getElementById('statM2NotInM1'); if (m1OrdersEl) m1OrdersEl.textContent = stats.m1Orders; if (m2OrdersEl) m2OrdersEl.textContent = stats.m2Orders; if (m1NotInM2El) m1NotInM2El.textContent = stats.m1OrdersNotInM2; if (m2NotInM1El) m2NotInM1El.textContent = stats.m2OrdersNotInM1; } }) .catch(error => { console.error('Error updating order statistics:', error); }); } function deleteM2Order(orderId, incrementId) { const orderLabel = incrementId !== 'N/A' ? incrementId : `ID ${orderId}`; if (!confirm(`Are you sure you want to delete order "${orderLabel}"?`)) { return; } const url = routes.deleteOrder.replace(':id', orderId); fetch(url, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken } }) .then(response => response.json()) .then(data => { if (data.success) { alert('Order deleted successfully!'); location.reload(); } else { alert('Error: ' + (data.message || 'Failed to delete order')); } }) .catch(error => { alert('Error: ' + error.message); }); } // Make functions available globally window.startOrderMigration = startOrderMigration; window.deleteM2Order = deleteM2Order;