diff --git a/TalpaAPI.php b/TalpaAPI.php index 7748bbb..83152fc 100644 --- a/TalpaAPI.php +++ b/TalpaAPI.php @@ -100,17 +100,35 @@ class TalpaApi { ]); } + public function updateTransmission($transmissionId, $data) { + return $this->request('PUT', '/linearSchedule/v1/transmissions/' . $transmissionId, [ + "startDate" => $data['startDate'], + "startTime" => $data['startTime'], + "duration" => $data['duration'] + ]); + } + + public function updateEpisode($contentId, $title, $duration) { + return $this->request('PUT', '/content/v1/episodes/' . $contentId, [ + "title" => $title, + "duration" => $duration, + "department" => "Homeshopping" + ]); + } + public function deleteEpisode($contentId) { return $this->request('DELETE', '/content/v1/episodes/' . $contentId); } private function getMockResponse($endpoint, $data) { usleep(200000); - if (strpos($endpoint, '/content/v1/episodes') !== false && strpos($endpoint, 'DELETE') === false) return ["id" => "MOCK_CONT_" . time()]; + if (strpos($endpoint, '/content/v1/episodes') !== false && strpos($endpoint, 'DELETE') === false && !isset($data['title'])) return ["id" => "MOCK_CONT_" . time()]; + if (strpos($endpoint, '/content/v1/episodes') !== false && isset($data['title'])) return ["statusCode" => "200", "message" => "Episode updated"]; if (strpos($endpoint, '/content/v1/episodes') !== false) return ["statusCode" => "200", "message" => "Episode deleted"]; if (strpos($endpoint, '/mam/v1/mediaAssets') !== false && !isset($data)) return ["mediaAssetLabel" => "TEL_MOCK_" . rand(100, 999)]; if (strpos($endpoint, '/mam/v1/mediaAssets') !== false) return ["id" => "MOCK_ASSET_" . time()]; - if (strpos($endpoint, '/linearSchedule/v1/transmissions') !== false) return ["statusCode" => "201", "id" => "MOCK_TX_" . time()]; + if (strpos($endpoint, '/linearSchedule/v1/transmissions') !== false && strpos($endpoint, 'PUT') === false) return ["statusCode" => "201", "id" => "MOCK_TX_" . time()]; + if (strpos($endpoint, '/linearSchedule/v1/transmissions') !== false) return ["statusCode" => "200", "message" => "Transmission updated"]; return []; } } diff --git a/api/copy_block.php b/api/copy_block.php new file mode 100644 index 0000000..2e7f919 --- /dev/null +++ b/api/copy_block.php @@ -0,0 +1,170 @@ +load(); + +header('Content-Type: application/json'); + +try { + $db = getDbConnection(); + + // Get POST data + $input = json_decode(file_get_contents('php://input'), true); + + $sourceBlockId = $input['source_block_id'] ?? null; + $targetBlockId = $input['target_block_id'] ?? null; + $targetDate = $input['target_date'] ?? null; + + // Validate input + if (!$sourceBlockId || !$targetBlockId || !$targetDate) { + jsonResponse(['success' => false, 'error' => 'Missing required parameters'], 400); + } + + if (!isValidDate($targetDate)) { + jsonResponse(['success' => false, 'error' => 'Invalid target date format'], 400); + } + + // Start transaction + $db->beginTransaction(); + + try { + // Get source block info + $stmt = $db->prepare(" + SELECT * FROM daily_blocks WHERE id = ? + "); + $stmt->execute([$sourceBlockId]); + $sourceBlock = $stmt->fetch(); + + if (!$sourceBlock) { + throw new Exception('Source block not found'); + } + + // Get target block info + $stmt = $db->prepare(" + SELECT * FROM daily_blocks WHERE id = ? + "); + $stmt->execute([$targetBlockId]); + $targetBlock = $stmt->fetch(); + + if (!$targetBlock) { + throw new Exception('Target block not found'); + } + + // Validate that blocks are compatible (same channel) + if ($sourceBlock['channel'] !== $targetBlock['channel']) { + throw new Exception('Source and target blocks must be on the same channel'); + } + + // Get template names to compare (allows copying between different template IDs with same name) + $stmt = $db->prepare("SELECT name FROM block_templates WHERE id = ?"); + $stmt->execute([$sourceBlock['template_id']]); + $sourceTemplateName = $stmt->fetchColumn(); + + $stmt = $db->prepare("SELECT name FROM block_templates WHERE id = ?"); + $stmt->execute([$targetBlock['template_id']]); + $targetTemplateName = $stmt->fetchColumn(); + + if ($sourceTemplateName !== $targetTemplateName) { + throw new Exception('Source and target blocks must have the same template name'); + } + + // Step 1: Update target block times + $stmt = $db->prepare(" + UPDATE daily_blocks + SET actual_start_time = ?, + actual_end_time = ? + WHERE id = ? + "); + $stmt->execute([ + $sourceBlock['actual_start_time'], + $sourceBlock['actual_end_time'], + $targetBlockId + ]); + + // Step 2: Delete existing transmissions in target block + // Use the OLD target block times to find transmissions to delete + $stmt = $db->prepare(" + DELETE FROM transmissions + WHERE start_date = ? + AND channel = ? + AND start_time >= ? + AND start_time < ? + "); + $stmt->execute([ + $targetDate, + $targetBlock['channel'], + $targetBlock['actual_start_time'], + $targetBlock['actual_end_time'] ?? '23:59:59' + ]); + $deletedCount = $stmt->rowCount(); + + // Step 3: Get source transmissions + $stmt = $db->prepare(" + SELECT t.*, c.duration + FROM transmissions t + JOIN infomercials c ON t.infomercial_id = c.id + WHERE t.start_date = ? + AND t.channel = ? + AND t.start_time >= ? + AND t.start_time < ? + ORDER BY t.start_time ASC + "); + $stmt->execute([ + $sourceBlock['block_date'], + $sourceBlock['channel'], + $sourceBlock['actual_start_time'], + $sourceBlock['actual_end_time'] ?? '23:59:59' + ]); + $sourceTransmissions = $stmt->fetchAll(); + + // Step 4: Copy transmissions to target block + $copiedCount = 0; + $insertStmt = $db->prepare(" + INSERT INTO transmissions + (infomercial_id, channel, template, start_date, start_time, duration, api_status) + VALUES (?, ?, ?, ?, ?, ?, 'pending') + "); + + foreach ($sourceTransmissions as $tx) { + $insertStmt->execute([ + $tx['infomercial_id'], + $tx['channel'], + $tx['template'], + $targetDate, // Use target date + $tx['start_time'], + $tx['duration'], + ]); + $copiedCount++; + } + + // Commit transaction + $db->commit(); + + jsonResponse([ + 'success' => true, + 'message' => 'Block copied successfully', + 'copied_count' => $copiedCount, + 'deleted_count' => $deletedCount, + 'block_times_updated' => true + ]); + + } catch (Exception $e) { + $db->rollBack(); + throw $e; + } + +} catch (Exception $e) { + jsonResponse([ + 'success' => false, + 'error' => $e->getMessage() + ], 500); +} diff --git a/api/get_available_source_blocks.php b/api/get_available_source_blocks.php new file mode 100644 index 0000000..43964e0 --- /dev/null +++ b/api/get_available_source_blocks.php @@ -0,0 +1,74 @@ +load(); + +header('Content-Type: application/json'); + +try { + $db = getDbConnection(); + + // Validate input + $date = $_GET['date'] ?? null; + $channel = $_GET['channel'] ?? null; + $templateId = $_GET['template_id'] ?? null; + + if (!$date || !$channel || !$templateId) { + jsonResponse(['success' => false, 'error' => 'Missing parameters'], 400); + } + + if (!isValidDate($date)) { + jsonResponse(['success' => false, 'error' => 'Invalid date format'], 400); + } + + // Ensure blocks exist for this date + ensureDailyBlocks($db, $date, $date); + + // Get the template name from the target template + $stmt = $db->prepare("SELECT name FROM block_templates WHERE id = ?"); + $stmt->execute([$templateId]); + $targetTemplateName = $stmt->fetchColumn(); + + if (!$targetTemplateName) { + jsonResponse(['success' => false, 'error' => 'Target template not found'], 404); + } + + // Get blocks for this date and channel with matching template NAME (not ID) + // This allows copying between different template IDs that have the same name + $stmt = $db->prepare(" + SELECT + db.*, + bt.name as template_name, + COUNT(t.id) as transmission_count + FROM daily_blocks db + LEFT JOIN block_templates bt ON db.template_id = bt.id + LEFT JOIN transmissions t ON t.start_date = db.block_date + AND t.channel = db.channel + AND t.start_time >= db.actual_start_time + AND t.start_time < COALESCE(db.actual_end_time, '23:59:59') + WHERE db.block_date = ? + AND db.channel = ? + AND bt.name = ? + GROUP BY db.id + ORDER BY db.actual_start_time + "); + $stmt->execute([$date, $channel, $targetTemplateName]); + $blocks = $stmt->fetchAll(); + + jsonResponse([ + 'success' => true, + 'blocks' => $blocks + ]); + +} catch (Exception $e) { + jsonResponse(['success' => false, 'error' => $e->getMessage()], 500); +} diff --git a/api/get_block_details.php b/api/get_block_details.php new file mode 100644 index 0000000..085fea7 --- /dev/null +++ b/api/get_block_details.php @@ -0,0 +1,67 @@ +load(); + +header('Content-Type: application/json'); + +try { + $db = getDbConnection(); + + $blockId = $_GET['block_id'] ?? null; + + if (!$blockId) { + jsonResponse(['success' => false, 'error' => 'Missing block_id'], 400); + } + + // Get block info + $stmt = $db->prepare(" + SELECT db.*, bt.name as template_name + FROM daily_blocks db + LEFT JOIN block_templates bt ON db.template_id = bt.id + WHERE db.id = ? + "); + $stmt->execute([$blockId]); + $block = $stmt->fetch(); + + if (!$block) { + jsonResponse(['success' => false, 'error' => 'Block not found'], 404); + } + + // Get transmissions in this block + $stmt = $db->prepare(" + SELECT t.*, c.title, c.series_code + FROM transmissions t + JOIN infomercials c ON t.infomercial_id = c.id + WHERE t.start_date = ? + AND t.channel = ? + AND t.start_time >= ? + AND t.start_time < ? + ORDER BY t.start_time ASC + "); + $stmt->execute([ + $block['block_date'], + $block['channel'], + $block['actual_start_time'], + $block['actual_end_time'] ?? '23:59:59' + ]); + $transmissions = $stmt->fetchAll(); + + jsonResponse([ + 'success' => true, + 'block' => $block, + 'transmissions' => $transmissions + ]); + +} catch (Exception $e) { + jsonResponse(['success' => false, 'error' => $e->getMessage()], 500); +} diff --git a/api/insert_transmission_at_position.php b/api/insert_transmission_at_position.php index e18faea..c46a3ec 100644 --- a/api/insert_transmission_at_position.php +++ b/api/insert_transmission_at_position.php @@ -5,6 +5,7 @@ */ require_once __DIR__ . '/../vendor/autoload.php'; +require_once __DIR__ . '/../TalpaAPI.php'; require_once __DIR__ . '/../helpers.php'; use Dotenv\Dotenv; @@ -80,13 +81,14 @@ try { // Recalculate all start times $currentTime = $blockStartTime; + $newTransmissionId = null; foreach ($transmissions as $index => $tx) { if ($index === $position) { // Insert new transmission $stmt = $db->prepare(" - INSERT INTO transmissions - (infomercial_id, channel, template, start_date, start_time, duration, api_status) + INSERT INTO transmissions + (infomercial_id, channel, template, start_date, start_time, duration, api_status) VALUES (?, ?, 'HOME030', ?, ?, ?, 'pending') "); $stmt->execute([ @@ -96,6 +98,7 @@ try { $currentTime, $duration ]); + $newTransmissionId = $db->lastInsertId(); } else { // Update existing transmission $stmt = $db->prepare("UPDATE transmissions SET start_time = ?, api_status = 'pending' WHERE id = ?"); @@ -105,9 +108,21 @@ try { $currentTime = addTimeToTime($currentTime, $tx['duration']); } + // Sync all transmissions in the block to Talpa + $api = new TalpaApi(); + $blockUpdateResult = updateBlockTransmissionsToTalpa( + $db, + $api, + $input['date'], + $input['channel'], + $input['block_id'] + ); + jsonResponse([ 'success' => true, - 'message' => 'Transmission inserted successfully' + 'message' => 'Transmission inserted successfully', + 'new_transmission_id' => $newTransmissionId, + 'block_update' => $blockUpdateResult ]); } catch (Exception $e) { diff --git a/api/sync_block.php b/api/sync_block.php index 3426485..d387a32 100644 --- a/api/sync_block.php +++ b/api/sync_block.php @@ -43,14 +43,14 @@ $channel = $input['channel']; $debugLog[] = ['step' => 'Parameters', 'date' => $date, 'channel' => $channel]; try { - // Get all transmissions for this block that are not yet synced + // Get all transmissions for this block + // Include both new (pending) and existing (synced) transmissions $stmt = $db->prepare(" SELECT t.*, c.content_id, c.title as commercial_title FROM transmissions t JOIN infomercials c ON t.infomercial_id = c.id WHERE t.start_date = ? AND t.channel = ? - AND t.api_status != 'synced' ORDER BY t.start_time ASC "); $stmt->execute([$date, $channel]); @@ -79,7 +79,8 @@ try { $txDebug = [ 'transmission_id' => $tx['id'], 'title' => $tx['commercial_title'], - 'time' => $tx['start_time'] + 'time' => $tx['start_time'], + 'talpa_transmission_id' => $tx['talpa_transmission_id'] ]; try { @@ -94,23 +95,52 @@ try { $txDebug['request'] = $requestData; - $res = $api->createTransmission($requestData); + // Determine if this is a new transmission or an update + if (!empty($tx['talpa_transmission_id'])) { + // Update existing transmission in Talpa + $txDebug['action'] = 'update'; + $res = $api->updateTransmission($tx['talpa_transmission_id'], $requestData); + } else { + // Create new transmission in Talpa + $txDebug['action'] = 'create'; + $res = $api->createTransmission($requestData); + } $txDebug['response'] = $res; $txDebug['lastResponse'] = $api->lastResponse; // Check if sync was successful - $status = (isset($res['id']) || (isset($res['statusCode']) && $res['statusCode'] == 201)) ? 'synced' : 'error'; + $status = 'error'; + $talpaTransmissionId = $tx['talpa_transmission_id']; + + if ($txDebug['action'] === 'create') { + // For create: check for id in response + if (isset($res['id'])) { + $status = 'synced'; + $talpaTransmissionId = $res['id']; + } elseif (isset($res['statusCode']) && $res['statusCode'] == 201) { + $status = 'synced'; + $talpaTransmissionId = $res['id'] ?? $talpaTransmissionId; + } + } else { + // For update: check for success status + if (isset($res['statusCode']) && ($res['statusCode'] == 200 || $res['statusCode'] == '200')) { + $status = 'synced'; + } elseif (isset($res['message']) && strpos($res['message'], 'updated') !== false) { + $status = 'synced'; + } + } $txDebug['determined_status'] = $status; + $txDebug['talpa_transmission_id_saved'] = $talpaTransmissionId; - // Update transmission status + // Update transmission status and talpa_transmission_id $updateStmt = $db->prepare(" UPDATE transmissions - SET api_status = ?, api_response = ? + SET api_status = ?, api_response = ?, talpa_transmission_id = ? WHERE id = ? "); - $updateStmt->execute([$status, json_encode($res), $tx['id']]); + $updateStmt->execute([$status, json_encode($res), $talpaTransmissionId, $tx['id']]); if ($status === 'synced') { $syncedCount++; diff --git a/api/update_transmission.php b/api/update_transmission.php index 8c1b34b..5fb3111 100644 --- a/api/update_transmission.php +++ b/api/update_transmission.php @@ -5,6 +5,7 @@ */ require_once __DIR__ . '/../vendor/autoload.php'; +require_once __DIR__ . '/../TalpaAPI.php'; require_once __DIR__ . '/../helpers.php'; use Dotenv\Dotenv; @@ -155,9 +156,6 @@ try { } } - // Mark as pending sync if changed - $updates[] = "api_status = 'pending'"; - // Build and execute update query if (!empty($updates)) { $sql = "UPDATE transmissions SET " . implode(', ', $updates) . " WHERE id = ?"; @@ -167,13 +165,14 @@ try { $stmt->execute($params); } - // Get updated transmission + // Get updated transmission with all details including content_id $stmt = $db->prepare(" - SELECT + SELECT t.*, c.title, c.color_code, - c.series_code + c.series_code, + c.content_id FROM transmissions t JOIN infomercials c ON t.infomercial_id = c.id WHERE t.id = ? @@ -181,10 +180,54 @@ try { $stmt->execute([$input['id']]); $updated = $stmt->fetch(); + // Sync to Talpa if transmission has talpa_transmission_id + $talpaResult = null; + if (!empty($updated['talpa_transmission_id'])) { + $api = new TalpaApi(); + $talpaResult = syncTransmissionToTalpa($db, $api, $updated); + + // If sync failed, log it but don't fail the request + if (!$talpaResult['success']) { + error_log("Talpa sync failed for transmission {$updated['id']}: " . $talpaResult['error']); + } + } + + // Determine which block this transmission belongs to + $stmt = $db->prepare(" + SELECT id FROM daily_blocks + WHERE block_date = ? + AND channel = ? + AND actual_start_time <= ? + AND (actual_end_time IS NULL OR actual_end_time > ?) + LIMIT 1 + "); + $stmt->execute([ + $updated['start_date'], + $updated['channel'], + $updated['start_time'], + $updated['start_time'] + ]); + $block = $stmt->fetch(); + + // Update all other transmissions in the same block + $blockUpdateResult = null; + if ($block && !empty($updated['talpa_transmission_id'])) { + $api = new TalpaApi(); + $blockUpdateResult = updateBlockTransmissionsToTalpa( + $db, + $api, + $updated['start_date'], + $updated['channel'], + $block['id'] + ); + } + jsonResponse([ 'success' => true, 'message' => 'Transmission updated successfully', - 'transmission' => $updated + 'transmission' => $updated, + 'talpa_sync' => $talpaResult, + 'block_update' => $blockUpdateResult ]); } catch (Exception $e) { diff --git a/assets/css/custom.css b/assets/css/custom.css index 87aa5f9..2b0b756 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -3,9 +3,11 @@ */ :root { - --primary-color: #2c3e50; - --secondary-color: #34495e; - --accent-color: #3498db; + --text-color: #404040; + --brand-color: #32327D; + --accent-color: #32B4AA; + --primary-color: #32327D; + --secondary-color: #32327D; --success-color: #2ecc71; --warning-color: #f39c12; --danger-color: #e74c3c; @@ -13,12 +15,22 @@ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + color: var(--text-color); } /* Navigation */ .navbar-brand { font-weight: 600; font-size: 1.3rem; + color: var(--brand-color) !important; +} + +.navbar-dark .navbar-brand { + color: #ffffff !important; +} + +.navbar-dark { + background-color: var(--brand-color) !important; } /* Cards */ @@ -38,6 +50,10 @@ body { font-weight: 600; } +.card-header.bg-primary { + background-color: var(--brand-color) !important; +} + /* Buttons */ .btn { border-radius: 6px; @@ -50,6 +66,31 @@ body { box-shadow: 0 2px 8px rgba(0,0,0,0.15); } +.btn-primary { + background-color: var(--brand-color); + border-color: var(--brand-color); +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active { + background-color: #28286a; + border-color: #28286a; +} + +.btn-outline-primary { + color: var(--brand-color); + border-color: var(--brand-color); +} + +.btn-outline-primary:hover, +.btn-outline-primary:focus, +.btn-outline-primary:active { + background-color: var(--brand-color); + border-color: var(--brand-color); + color: #ffffff; +} + /* Tables */ .table { border-radius: 8px; @@ -461,16 +502,71 @@ body { .form-control:focus, .form-select:focus { border-color: var(--accent-color); - box-shadow: 0 0 0 0.2rem rgba(52, 152, 219, 0.25); + box-shadow: 0 0 0 0.2rem rgba(50, 180, 170, 0.25); } /* Tooltip Styling */ .tooltip-inner { - background-color: var(--primary-color); + background-color: var(--brand-color); border-radius: 4px; padding: 8px 12px; } +/* Sync Status Indicators */ +.sync-indicator { + font-size: 1.2rem; + cursor: help; + display: inline-block; + transition: transform 0.2s; +} + +.sync-indicator.sync-success { + color: #28a745; +} + +.sync-indicator.sync-pending { + color: #dc3545; +} + +.sync-indicator.sync-error { + color: #ffc107; +} + +.sync-indicator:hover { + transform: scale(1.2); +} + +/* Block Sync Status Badges */ +.block-sync-status { + font-size: 0.85rem; + padding: 0.35em 0.65em; + font-weight: 600; + border-radius: 4px; + display: inline-flex; + align-items: center; + gap: 4px; +} + +.block-sync-status.block-sync-complete { + background-color: #28a745; + color: white; +} + +.block-sync-status.block-sync-partial { + background-color: #ffc107; + color: #000; +} + +.block-sync-status.block-sync-none { + background-color: #dc3545; + color: white; +} + +.block-sync-status.block-sync-empty { + background-color: #6c757d; + color: white; +} + /* Print Styles */ @media print { .navbar, diff --git a/assets/js/calendar-init.js b/assets/js/calendar-init.js index ed57468..2b5989d 100644 --- a/assets/js/calendar-init.js +++ b/assets/js/calendar-init.js @@ -16,10 +16,28 @@ document.addEventListener('DOMContentLoaded', function() { schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', initialView: 'resourceTimeGridDay', headerToolbar: { - left: 'prev,next today', + left: 'prevDay,prev,next,nextDay today', center: 'title', right: 'resourceTimeGridDay,resourceTimeGridWeek,resourceTimelineDay' }, + customButtons: { + prevDay: { + text: '◀', + hint: 'Vorige dag', + click: function() { + calendar.getDate().setDate(calendar.getDate().getDate() - 1); + calendar.gotoDate(calendar.getDate()); + } + }, + nextDay: { + text: '▶', + hint: 'Volgende dag', + click: function() { + calendar.getDate().setDate(calendar.getDate().getDate() + 1); + calendar.gotoDate(calendar.getDate()); + } + } + }, slotDuration: '00:15:00', slotLabelInterval: '00:15:00', snapDuration: '00:01:00', diff --git a/docs/IMPLEMENTATION_SUMMARY.md b/docs/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..4eb7aa1 --- /dev/null +++ b/docs/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,307 @@ +# Transmission Synchronisatie - Implementatie Samenvatting + +## Overzicht + +Deze implementatie zorgt ervoor dat transmissions in de planning automatisch worden bijgewerkt in Talpa wanneer ze worden verplaatst. Dit geldt voor zowel de verplaatste transmission als alle andere transmissions in hetzelfde uitzendblok. + +## Geïmplementeerde Wijzigingen + +### 1. Database Migratie +**Bestand**: [`migrations/002_add_talpa_transmission_id.sql`](../migrations/002_add_talpa_transmission_id.sql) + +- Nieuwe kolom `talpa_transmission_id` toegevoegd aan `transmissions` tabel +- Index toegevoegd voor snellere lookups +- Automatische migratie van bestaande data uit `api_response` JSON + +**Uitvoeren**: +```bash +mysql -u [user] -p [database] < migrations/002_add_talpa_transmission_id.sql +``` + +### 2. TalpaAPI Uitbreiding +**Bestand**: [`TalpaAPI.php`](../TalpaAPI.php) + +**Nieuwe methode**: +```php +public function updateTransmission($transmissionId, $data) +``` + +**Functionaliteit**: +- PUT request naar `/linearSchedule/v1/transmissions/{id}` +- Update startDate, startTime en duration +- Mock response voor testing + +### 3. Sync Block Update +**Bestand**: [`api/sync_block.php`](../api/sync_block.php) + +**Wijzigingen**: +- Detecteert of transmission nieuw is (POST) of bestaand (PUT) +- Slaat `talpa_transmission_id` op na succesvolle sync +- Ondersteunt zowel create als update operaties +- Uitgebreide debug logging + +**Logica**: +``` +IF talpa_transmission_id IS NULL: + → POST nieuwe transmission + → Sla transmission_id op +ELSE: + → PUT update bestaande transmission +``` + +### 4. Helper Functies +**Bestand**: [`helpers.php`](../helpers.php) + +**Nieuwe functies**: + +#### `updateBlockTransmissionsToTalpa($db, $api, $date, $channel, $blockId)` +- Herberekent starttijden van alle transmissions in een blok +- Update lokale database +- Synchroniseert naar Talpa (PUT requests) +- Retourneert resultaat met success/failure counts + +#### `syncTransmissionToTalpa($db, $api, $transmission)` +- Sync één transmission naar Talpa +- Automatische detectie van create vs update +- Error handling en status updates +- Retourneert talpa_transmission_id + +### 5. Update Transmission +**Bestand**: [`api/update_transmission.php`](../api/update_transmission.php) + +**Nieuwe functionaliteit**: +- Direct sync naar Talpa na lokale update +- Cascade update van alle transmissions in hetzelfde blok +- Bepaalt automatisch welk blok de transmission behoort +- Retourneert sync resultaten in response + +**Flow**: +1. Update lokale transmission +2. Sync transmission naar Talpa (als talpa_transmission_id bestaat) +3. Bepaal block_id +4. Update alle andere transmissions in blok +5. Return resultaten + +### 6. Insert at Position +**Bestand**: [`api/insert_transmission_at_position.php`](../api/insert_transmission_at_position.php) + +**Nieuwe functionaliteit**: +- Herberekent starttijden na insert +- Synchroniseert hele blok naar Talpa +- Retourneert block update resultaten + +**Flow**: +1. Insert nieuwe transmission op positie +2. Herbereken alle starttijden in blok +3. Update lokale database +4. Sync hele blok naar Talpa +5. Return resultaten + +## API Response Wijzigingen + +### sync_block.php Response +```json +{ + "success": true, + "message": "Synchronisatie voltooid: 3 geslaagd, 0 mislukt", + "synced": 3, + "failed": 0, + "errors": [], + "api_calls": [ + { + "transmission_id": 1, + "action": "update", + "talpa_transmission_id": "MOCK_TX_123", + "determined_status": "synced" + } + ] +} +``` + +### update_transmission.php Response +```json +{ + "success": true, + "message": "Transmission updated successfully", + "transmission": { ... }, + "talpa_sync": { + "success": true, + "talpa_transmission_id": "MOCK_TX_123" + }, + "block_update": { + "success": true, + "updated": 2, + "failed": 0 + } +} +``` + +### insert_transmission_at_position.php Response +```json +{ + "success": true, + "message": "Transmission inserted successfully", + "new_transmission_id": 456, + "block_update": { + "success": true, + "updated": 3, + "failed": 0 + } +} +``` + +## Gebruik Scenario's + +### Scenario 1: Eerste Sync +``` +1. Maak transmissions aan in planning +2. Klik "Sync Block" +3. Transmissions krijgen talpa_transmission_id +4. Status wordt 'synced' +``` + +### Scenario 2: Transmission Verplaatsen +``` +1. Drag transmission naar nieuwe tijd +2. API update wordt getriggerd +3. Transmission wordt geüpdatet in Talpa (PUT) +4. Alle volgende transmissions in blok worden ook geüpdatet +5. Status blijft 'synced' +``` + +### Scenario 3: Insert at Position +``` +1. Insert nieuwe transmission op positie 2 +2. Nieuwe transmission wordt aangemaakt (lokaal) +3. Transmissions 2, 3, 4... worden verschoven +4. Alle bestaande transmissions worden geüpdatet in Talpa +5. Nieuwe transmission krijgt status 'pending' (nog geen talpa_transmission_id) +6. Bij volgende sync: nieuwe transmission wordt aangemaakt in Talpa +``` + +## Error Handling + +### Talpa Transmission Niet Gevonden +``` +1. PUT request faalt (404) +2. talpa_transmission_id wordt NULL +3. api_status wordt 'error' of 'pending' +4. Bij volgende sync: POST create nieuwe transmission +``` + +### Netwerk Failure +``` +1. API call faalt +2. Status blijft 'pending' +3. Error wordt gelogd in api_response +4. Bij volgende sync: retry +``` + +### Validation Errors +``` +1. Lokale validatie faalt (overlap, buiten blok) +2. Update wordt geweigerd +3. Error response naar client +4. Geen Talpa call +``` + +## Logging + +Alle API calls worden gelogd in `api_log.txt`: +``` +[2026-01-16 10:20:15] REQUEST: PUT /linearSchedule/v1/transmissions/MOCK_TX_123 | Data: {"startDate":"2026-01-20","startTime":"08:15:00","duration":"00:30:00"} +[2026-01-16 10:20:15] RESPONSE (HTTP 200): {"statusCode":"200","message":"Transmission updated"} +``` + +## Testing + +Zie [`docs/TRANSMISSION_SYNC_TESTING.md`](TRANSMISSION_SYNC_TESTING.md) voor: +- 7 gedetailleerde test scenario's +- Database verificatie queries +- API endpoint voorbeelden +- Troubleshooting guide + +## Configuratie + +### .env Settings +```env +# Talpa API +TALPA_API_BASE=https://api.talpa.nl +TALPA_TOKEN=your_token_here + +# Mock mode voor testing (geen echte API calls) +TALPA_MOCK_MODE=true +``` + +### Mock Mode +Wanneer `TALPA_MOCK_MODE=true`: +- Geen echte API calls naar Talpa +- Gesimuleerde responses met delays +- Transmission IDs: `MOCK_TX_[timestamp]` +- Altijd success responses + +## Performance + +### Overwegingen +- Elke transmission update triggert meerdere PUT requests +- Bij grote blokken (>10 transmissions): meerdere seconden +- Overweeg rate limiting bij productie gebruik + +### Optimalisaties +- Batch updates mogelijk in toekomst +- Async processing voor grote blokken +- Caching van block data + +## Rollback Plan + +Bij problemen: +```sql +-- Verwijder nieuwe kolom +ALTER TABLE transmissions DROP COLUMN talpa_transmission_id; + +-- Restore oude code files +git checkout HEAD~1 TalpaAPI.php api/sync_block.php api/update_transmission.php api/insert_transmission_at_position.php helpers.php +``` + +## Volgende Stappen + +### Optionele Verbeteringen +1. **Audit Log**: Bijhouden van alle sync operaties +2. **Retry Mechanisme**: Automatische retry bij failures +3. **Batch Updates**: Meerdere transmissions in één API call +4. **Webhooks**: Talpa notificaties bij wijzigingen +5. **Conflict Resolution**: Wat als Talpa data afwijkt van lokaal? + +### Monitoring +- Check `api_log.txt` regelmatig +- Monitor failed syncs in database +- Alert bij hoge failure rate +- Performance metrics voor API calls + +## Support + +Bij vragen of problemen: +1. Check [`plans/transmission-sync-update-plan.md`](../plans/transmission-sync-update-plan.md) voor architectuur +2. Check [`docs/TRANSMISSION_SYNC_TESTING.md`](TRANSMISSION_SYNC_TESTING.md) voor testing +3. Review `api_log.txt` voor API call details +4. Check database `api_response` kolom voor error details + +## Bestanden Overzicht + +| Bestand | Wijziging | Beschrijving | +|---------|-----------|--------------| +| [`migrations/002_add_talpa_transmission_id.sql`](../migrations/002_add_talpa_transmission_id.sql) | Nieuw | Database migratie | +| [`TalpaAPI.php`](../TalpaAPI.php) | Gewijzigd | updateTransmission() methode | +| [`api/sync_block.php`](../api/sync_block.php) | Gewijzigd | Create/Update logica | +| [`api/update_transmission.php`](../api/update_transmission.php) | Gewijzigd | Cascade updates | +| [`api/insert_transmission_at_position.php`](../api/insert_transmission_at_position.php) | Gewijzigd | Block sync | +| [`helpers.php`](../helpers.php) | Gewijzigd | Nieuwe helper functies | +| [`plans/transmission-sync-update-plan.md`](../plans/transmission-sync-update-plan.md) | Nieuw | Architectuur plan | +| [`docs/TRANSMISSION_SYNC_TESTING.md`](TRANSMISSION_SYNC_TESTING.md) | Nieuw | Testing guide | +| [`docs/IMPLEMENTATION_SUMMARY.md`](IMPLEMENTATION_SUMMARY.md) | Nieuw | Dit document | + +## Versie Informatie + +- **Implementatie Datum**: 2026-01-16 +- **Versie**: 1.0 +- **Status**: Klaar voor testing diff --git a/docs/TRANSMISSION_SYNC_TESTING.md b/docs/TRANSMISSION_SYNC_TESTING.md new file mode 100644 index 0000000..2c14c43 --- /dev/null +++ b/docs/TRANSMISSION_SYNC_TESTING.md @@ -0,0 +1,373 @@ +# Transmission Synchronisatie Testing Guide + +## Overzicht + +Dit document beschrijft hoe je de nieuwe transmission synchronisatie functionaliteit kunt testen. De implementatie zorgt ervoor dat wanneer transmissions in de planning worden verplaatst, deze automatisch worden bijgewerkt in Talpa. + +## Vereisten + +1. Database migratie uitvoeren: [`migrations/002_add_talpa_transmission_id.sql`](../migrations/002_add_talpa_transmission_id.sql) +2. Talpa API configuratie in `.env` (of MOCK_MODE enabled) +3. Bestaande infomercials in de database + +## Test Scenario's + +### Scenario 1: Nieuwe Transmission Aanmaken en Synchroniseren + +**Doel**: Verifieer dat nieuwe transmissions correct worden aangemaakt en gesynchroniseerd naar Talpa. + +**Stappen**: +1. Maak een nieuwe transmission aan via de planning interface +2. Klik op "Sync Block" voor het betreffende blok +3. Controleer de database: + ```sql + SELECT id, talpa_transmission_id, api_status + FROM transmissions + WHERE id = [transmission_id]; + ``` + +**Verwacht Resultaat**: +- `talpa_transmission_id` is gevuld met een waarde (bijv. "MOCK_TX_1234567890") +- `api_status` = 'synced' +- `api_response` bevat de Talpa response + +**Verificatie**: +- Check `api_log.txt` voor de POST request naar `/linearSchedule/v1/transmissions` +- Response moet een `id` bevatten + +--- + +### Scenario 2: Bestaande Transmission Verplaatsen + +**Doel**: Verifieer dat verplaatsen van een transmission deze en alle volgende transmissions in het blok update. + +**Setup**: +1. Maak 3 transmissions in een blok (bijv. 07:00, 07:30, 08:00) +2. Sync het blok zodat alle transmissions een `talpa_transmission_id` hebben + +**Stappen**: +1. Verplaats de tweede transmission naar een latere tijd (bijv. 07:45) +2. Gebruik de drag-and-drop functionaliteit of update API + +**Verwacht Resultaat**: +- Transmission 2 heeft nieuwe start_time (07:45) +- Transmission 3 is automatisch verschoven (08:15) +- Beide transmissions zijn geüpdatet in Talpa (PUT requests) +- `api_status` blijft 'synced' voor beide + +**Verificatie**: +```sql +SELECT id, start_time, talpa_transmission_id, api_status +FROM transmissions +WHERE start_date = '[date]' AND channel = '[channel]' +ORDER BY start_time; +``` + +Check `api_log.txt` voor: +- PUT request naar `/linearSchedule/v1/transmissions/[id]` voor transmission 2 +- PUT request voor transmission 3 + +--- + +### Scenario 3: Insert at Position + +**Doel**: Verifieer dat inserting een transmission op een specifieke positie alle volgende transmissions update. + +**Setup**: +1. Maak een blok met 3 transmissions (07:00, 07:30, 08:00) +2. Sync het blok + +**Stappen**: +1. Insert een nieuwe transmission op positie 1 (tussen eerste en tweede) +2. Gebruik de insert API endpoint + +**Verwacht Resultaat**: +- Nieuwe transmission is aangemaakt op positie 1 +- Transmissions 2 en 3 zijn verschoven +- Nieuwe transmission heeft `talpa_transmission_id` = NULL (nog niet gesynchroniseerd) +- Bestaande transmissions zijn geüpdatet in Talpa + +**Verificatie**: +```sql +SELECT id, start_time, talpa_transmission_id, api_status +FROM transmissions +WHERE start_date = '[date]' AND channel = '[channel]' +ORDER BY start_time; +``` + +Expected times: +- TX1: 07:00 (unchanged) +- NEW: 07:30 (new, no talpa_transmission_id yet) +- TX2: 08:00 (updated from 07:30) +- TX3: 08:30 (updated from 08:00) + +--- + +### Scenario 4: Re-sync na Wijzigingen + +**Doel**: Verifieer dat re-sync correct omgaat met bestaande transmissions. + +**Setup**: +1. Maak en sync een blok met transmissions +2. Verplaats enkele transmissions (zonder direct te syncen) + +**Stappen**: +1. Klik op "Sync Block" opnieuw +2. Observeer het gedrag + +**Verwacht Resultaat**: +- Transmissions met `talpa_transmission_id`: PUT update naar Talpa +- Transmissions zonder `talpa_transmission_id`: POST create naar Talpa +- Alle transmissions krijgen status 'synced' + +**Verificatie**: +Check response van sync_block.php: +```json +{ + "success": true, + "synced": 3, + "failed": 0, + "api_calls": [ + { + "transmission_id": 1, + "action": "update", + "determined_status": "synced" + }, + { + "transmission_id": 2, + "action": "create", + "determined_status": "synced" + } + ] +} +``` + +--- + +### Scenario 5: Error Handling - Talpa Transmission Niet Gevonden + +**Doel**: Verifieer dat het systeem correct omgaat met een transmission die lokaal bestaat maar niet in Talpa. + +**Setup**: +1. Maak een transmission met een fake `talpa_transmission_id` (bijv. "FAKE_ID_123") +2. Zet `api_status` op 'synced' + +**Stappen**: +1. Probeer de transmission te verplaatsen +2. Of: sync het blok opnieuw + +**Verwacht Resultaat**: +- PUT request faalt (404 of error response) +- `talpa_transmission_id` wordt NULL +- `api_status` wordt 'pending' of 'error' +- Bij volgende sync: POST create nieuwe transmission + +**Verificatie**: +```sql +SELECT id, talpa_transmission_id, api_status, api_response +FROM transmissions +WHERE id = [transmission_id]; +``` + +--- + +### Scenario 6: Overnight Block + +**Doel**: Verifieer dat transmissions in overnight blocks (bijv. 23:30 - 02:00) correct worden behandeld. + +**Setup**: +1. Maak een overnight block (SBS9 Nachtblok: 23:30 - 02:00) +2. Voeg transmissions toe die over middernacht lopen + +**Stappen**: +1. Maak transmission om 23:30 +2. Maak transmission om 00:30 +3. Sync het blok +4. Verplaats een transmission + +**Verwacht Resultaat**: +- Beide transmissions worden correct gesynchroniseerd +- Tijd berekeningen werken correct over middernacht +- Updates worden correct naar Talpa gestuurd + +--- + +### Scenario 7: Cascade Update bij Meerdere Transmissions + +**Doel**: Verifieer dat een wijziging aan één transmission alle volgende transmissions in het blok update. + +**Setup**: +1. Maak een blok met 5 transmissions (elk 30 minuten) +2. Sync het blok + +**Stappen**: +1. Verplaats transmission 2 naar 15 minuten later +2. Observeer de cascade + +**Verwacht Resultaat**: +- Transmission 2: nieuwe tijd +- Transmissions 3, 4, 5: elk 15 minuten later +- Alle 4 transmissions zijn geüpdatet in Talpa (PUT requests) + +**Verificatie**: +Check `api_log.txt` voor 4 PUT requests: +``` +PUT /linearSchedule/v1/transmissions/[id2] +PUT /linearSchedule/v1/transmissions/[id3] +PUT /linearSchedule/v1/transmissions/[id4] +PUT /linearSchedule/v1/transmissions/[id5] +``` + +--- + +## Mock Mode Testing + +Voor testen zonder echte Talpa API verbinding, zet in `.env`: +``` +TALPA_MOCK_MODE=true +``` + +Mock responses: +- **POST create**: `{"statusCode": "201", "id": "MOCK_TX_[timestamp]"}` +- **PUT update**: `{"statusCode": "200", "message": "Transmission updated"}` + +--- + +## Database Queries voor Verificatie + +### Check Sync Status van Blok +```sql +SELECT + t.id, + t.start_time, + t.talpa_transmission_id, + t.api_status, + c.title +FROM transmissions t +JOIN infomercials c ON t.infomercial_id = c.id +WHERE t.start_date = '2026-01-20' +AND t.channel = 'SBS9' +ORDER BY t.start_time; +``` + +### Check Transmissions Zonder Talpa ID +```sql +SELECT id, start_time, api_status +FROM transmissions +WHERE talpa_transmission_id IS NULL +AND api_status = 'synced'; +``` +Dit zou leeg moeten zijn - alle synced transmissions moeten een talpa_transmission_id hebben. + +### Check Failed Syncs +```sql +SELECT + t.id, + t.start_time, + t.api_status, + t.api_response, + c.title +FROM transmissions t +JOIN infomercials c ON t.infomercial_id = c.id +WHERE t.api_status = 'error' +ORDER BY t.start_date DESC, t.start_time DESC +LIMIT 10; +``` + +--- + +## API Endpoints voor Testing + +### Sync Block +```bash +curl -X POST http://localhost/api/sync_block.php \ + -H "Content-Type: application/json" \ + -d '{ + "date": "2026-01-20", + "channel": "SBS9" + }' +``` + +### Update Transmission +```bash +curl -X POST http://localhost/api/update_transmission.php \ + -H "Content-Type: application/json" \ + -d '{ + "id": 123, + "start_time": "08:15:00" + }' +``` + +### Insert at Position +```bash +curl -X POST http://localhost/api/insert_transmission_at_position.php \ + -H "Content-Type: application/json" \ + -d '{ + "infomercial_id": 5, + "channel": "SBS9", + "date": "2026-01-20", + "block_id": 10, + "position": 2 + }' +``` + +--- + +## Troubleshooting + +### Transmission blijft op 'pending' +**Oorzaak**: Sync is niet uitgevoerd of gefaald +**Oplossing**: +1. Check `api_log.txt` voor errors +2. Voer sync_block.php opnieuw uit +3. Check `api_response` kolom voor error details + +### Talpa Transmission ID is NULL na sync +**Oorzaak**: Talpa response bevat geen `id` veld +**Oplossing**: +1. Check `api_response` in database +2. Verify Talpa API response format +3. Check mock response in [`TalpaAPI.php`](../TalpaAPI.php) line 130 + +### Cascade update werkt niet +**Oorzaak**: Block ID niet correct bepaald +**Oplossing**: +1. Verify daily_blocks tabel heeft correcte data +2. Check block time ranges +3. Verify transmission valt binnen block + +### PUT request faalt met 404 +**Oorzaak**: Transmission bestaat niet (meer) in Talpa +**Oplossing**: +1. Systeem zou automatisch `talpa_transmission_id` op NULL moeten zetten +2. Re-sync maakt nieuwe transmission aan (POST) +3. Verify error handling in [`helpers.php`](../helpers.php) `syncTransmissionToTalpa()` + +--- + +## Performance Overwegingen + +Bij grote blokken (>10 transmissions): +- Elke update triggert meerdere PUT requests naar Talpa +- Overweeg batch updates of rate limiting +- Monitor `api_log.txt` voor response times + +--- + +## Volgende Stappen + +Na succesvolle testing: +1. ✅ Migratie uitvoeren op productie database +2. ✅ Backup maken voor rollback +3. ✅ Monitor eerste sync operaties +4. ✅ Check Talpa API logs voor errors +5. ✅ Verify data consistency tussen lokaal en Talpa + +--- + +## Support + +Bij problemen: +- Check [`api_log.txt`](../api_log.txt) voor API calls +- Check PHP error logs +- Review [`plans/transmission-sync-update-plan.md`](../plans/transmission-sync-update-plan.md) voor architectuur details diff --git a/helpers.php b/helpers.php index e3101ff..f18f8ec 100644 --- a/helpers.php +++ b/helpers.php @@ -385,3 +385,198 @@ function isValidDate($date) { $d = DateTime::createFromFormat('Y-m-d', $date); return $d && $d->format('Y-m-d') === $date; } + +/** + * Update all transmissions in a block to Talpa after a change + * This function recalculates start times and syncs to Talpa + * + * @param PDO $db Database connection + * @param TalpaApi $api Talpa API instance + * @param string $date Block date (Y-m-d) + * @param string $channel Channel name + * @param int $blockId Block ID + * @return array Result with success status and details + */ +function updateBlockTransmissionsToTalpa($db, $api, $date, $channel, $blockId) { + $results = [ + 'success' => true, + 'updated' => 0, + 'failed' => 0, + 'errors' => [] + ]; + + try { + // Get block info + $stmt = $db->prepare(" + SELECT actual_start_time, actual_end_time + FROM daily_blocks + WHERE id = ? + "); + $stmt->execute([$blockId]); + $block = $stmt->fetch(); + + if (!$block) { + $results['success'] = false; + $results['errors'][] = 'Block not found'; + return $results; + } + + $blockStart = $block['actual_start_time']; + $blockEnd = $block['actual_end_time'] ?? '23:59:59'; + + // Get all transmissions in this block, ordered by start time + $stmt = $db->prepare(" + SELECT t.*, c.content_id, c.duration as infomercial_duration + FROM transmissions t + JOIN infomercials c ON t.infomercial_id = c.id + WHERE t.start_date = ? + AND t.channel = ? + AND t.start_time >= ? + AND t.start_time < ? + ORDER BY t.start_time ASC + "); + $stmt->execute([$date, $channel, $blockStart, $blockEnd]); + $transmissions = $stmt->fetchAll(); + + // Recalculate start times from block start + $currentTime = $blockStart; + + foreach ($transmissions as $tx) { + // Update local start time if it changed + if ($tx['start_time'] !== $currentTime) { + $updateStmt = $db->prepare(" + UPDATE transmissions + SET start_time = ?, api_status = 'pending' + WHERE id = ? + "); + $updateStmt->execute([$currentTime, $tx['id']]); + } + + // Sync to Talpa if transmission has talpa_transmission_id + if (!empty($tx['talpa_transmission_id'])) { + try { + $requestData = [ + "startDate" => $date, + "startTime" => $currentTime, + "duration" => $tx['duration'] + ]; + + $res = $api->updateTransmission($tx['talpa_transmission_id'], $requestData); + + // Check if update was successful + $status = 'error'; + if (isset($res['statusCode']) && ($res['statusCode'] == 200 || $res['statusCode'] == '200')) { + $status = 'synced'; + $results['updated']++; + } elseif (isset($res['message']) && strpos($res['message'], 'updated') !== false) { + $status = 'synced'; + $results['updated']++; + } else { + $results['failed']++; + $results['errors'][] = [ + 'transmission_id' => $tx['id'], + 'error' => $res['message'] ?? 'Unknown error' + ]; + } + + // Update status + $updateStmt = $db->prepare(" + UPDATE transmissions + SET api_status = ?, api_response = ? + WHERE id = ? + "); + $updateStmt->execute([$status, json_encode($res), $tx['id']]); + + } catch (Exception $e) { + $results['failed']++; + $results['errors'][] = [ + 'transmission_id' => $tx['id'], + 'error' => $e->getMessage() + ]; + } + } + + // Move to next time slot + $currentTime = addTimeToTime($currentTime, $tx['duration']); + } + + } catch (Exception $e) { + $results['success'] = false; + $results['errors'][] = $e->getMessage(); + } + + return $results; +} + +/** + * Sync a single transmission to Talpa (create or update) + * + * @param PDO $db Database connection + * @param TalpaApi $api Talpa API instance + * @param array $transmission Transmission data + * @return array Result with success status and talpa_transmission_id + */ +function syncTransmissionToTalpa($db, $api, $transmission) { + $result = [ + 'success' => false, + 'talpa_transmission_id' => $transmission['talpa_transmission_id'] ?? null, + 'error' => null + ]; + + try { + $requestData = [ + "channel" => $transmission['channel'], + "template" => $transmission['template'], + "startDate" => $transmission['start_date'], + "startTime" => $transmission['start_time'], + "duration" => $transmission['duration'], + "contentId" => $transmission['content_id'] + ]; + + // Determine if this is a create or update + if (!empty($transmission['talpa_transmission_id'])) { + // Update existing transmission + $res = $api->updateTransmission($transmission['talpa_transmission_id'], $requestData); + + if (isset($res['statusCode']) && ($res['statusCode'] == 200 || $res['statusCode'] == '200')) { + $result['success'] = true; + } elseif (isset($res['message']) && strpos($res['message'], 'updated') !== false) { + $result['success'] = true; + } else { + $result['error'] = $res['message'] ?? 'Update failed'; + } + } else { + // Create new transmission + $res = $api->createTransmission($requestData); + + if (isset($res['id'])) { + $result['success'] = true; + $result['talpa_transmission_id'] = $res['id']; + } elseif (isset($res['statusCode']) && $res['statusCode'] == 201) { + $result['success'] = true; + $result['talpa_transmission_id'] = $res['id'] ?? null; + } else { + $result['error'] = $res['message'] ?? 'Create failed'; + } + } + + // Update database + $status = $result['success'] ? 'synced' : 'error'; + $updateStmt = $db->prepare(" + UPDATE transmissions + SET api_status = ?, api_response = ?, talpa_transmission_id = ? + WHERE id = ? + "); + $updateStmt->execute([ + $status, + json_encode($res), + $result['talpa_transmission_id'], + $transmission['id'] + ]); + + } catch (Exception $e) { + $result['error'] = $e->getMessage(); + } + + return $result; +} diff --git a/infomercials.php b/infomercials.php index ae2dcb9..3903399 100644 --- a/infomercials.php +++ b/infomercials.php @@ -20,6 +20,13 @@ $api = new TalpaApi(); $db = getDbConnection(); $apiLogs = []; +// Retrieve and clear refresh logs from session +session_start(); +$refreshLogs = $_SESSION['refresh_logs'] ?? null; +if ($refreshLogs) { + unset($_SESSION['refresh_logs']); +} + // Handle infomercial registration if (isset($_POST['add_commercial'])) { $apiLogs[] = ['step' => 'Start registration', 'input' => $_POST]; @@ -84,21 +91,134 @@ if (isset($_POST['add_commercial'])) { } } -// Handle media asset update -if (isset($_POST['update_media_asset'])) { - $stmt = $db->prepare(" - UPDATE infomercials - SET media_asset_label = ?, upload_status = ?, series_code = ?, color_code = ? - WHERE id = ? - "); - $stmt->execute([ - $_POST['media_asset_label'], - $_POST['upload_status'], - $_POST['series_code'] ?? null, - $_POST['color_code'], - $_POST['infomercial_id'] - ]); - header('Location: infomercials.php?success=updated'); +// Handle infomercial update (sync to Talpa) +if (isset($_POST['update_infomercial'])) { + // Get current infomercial data + $stmt = $db->prepare("SELECT content_id, title, duration FROM infomercials WHERE id = ?"); + $stmt->execute([$_POST['infomercial_id']]); + $current = $stmt->fetch(); + + if ($current && $current['content_id']) { + // Update in Talpa if title or duration changed + $titleChanged = $current['title'] !== $_POST['title']; + $durationChanged = $current['duration'] !== $_POST['duration']; + + if ($titleChanged || $durationChanged) { + $result = $api->updateEpisode( + $current['content_id'], + $_POST['title'], + $_POST['duration'] + ); + $apiLogs[] = ['call' => 'Update Episode', 'request' => [ + 'content_id' => $current['content_id'], + 'title' => $_POST['title'], + 'duration' => $_POST['duration'] + ], 'response' => $api->lastResponse]; + } + + // Update in local database + $stmt = $db->prepare(" + UPDATE infomercials + SET title = ?, duration = ?, upload_status = ?, series_code = ?, color_code = ? + WHERE id = ? + "); + $stmt->execute([ + $_POST['title'], + $_POST['duration'], + $_POST['upload_status'], + $_POST['series_code'] ?? null, + $_POST['color_code'], + $_POST['infomercial_id'] + ]); + + header('Location: infomercials.php?success=updated'); + exit; + } +} + +// Handle refresh single infomercial from Talpa +if (isset($_POST['refresh_infomercial'])) { + $stmt = $db->prepare("SELECT title, media_asset_id FROM infomercials WHERE id = ?"); + $stmt->execute([$_POST['infomercial_id']]); + $infomercial = $stmt->fetch(); + + if ($infomercial && $infomercial['media_asset_id']) { + $details = $api->getMediaAssetDetails($infomercial['media_asset_id']); + $apiLogs[] = ['call' => 'Refresh Media Asset Details', 'request' => [ + 'asset_id' => $infomercial['media_asset_id'] + ], 'response' => $api->lastResponse]; + + if (isset($details['mediaAssetLabel'])) { + $stmt = $db->prepare(" + UPDATE infomercials + SET media_asset_label = ? + WHERE id = ? + "); + $stmt->execute([ + $details['mediaAssetLabel'], + $_POST['infomercial_id'] + ]); + + header('Location: infomercials.php?success=refreshed'); + exit; + } else { + // Store failed refresh log + session_start(); + $_SESSION['refresh_logs'] = [[ + 'status' => 'failed', + 'title' => $infomercial['title'], + 'asset_id' => $infomercial['media_asset_id'], + 'error' => $api->lastResponse['message'] ?? 'Geen mediaAssetLabel gevonden in response' + ]]; + } + } + header('Location: infomercials.php?error=refresh_failed'); + exit; +} + +// Handle refresh all infomercials from Talpa +if (isset($_POST['refresh_all'])) { + $stmt = $db->query("SELECT id, title, media_asset_id FROM infomercials WHERE media_asset_id IS NOT NULL"); + $infomercials_to_refresh = $stmt->fetchAll(); + + $refreshed = 0; + $failed = 0; + $refreshLogs = []; + + foreach ($infomercials_to_refresh as $inf) { + $details = $api->getMediaAssetDetails($inf['media_asset_id']); + $apiLogs[] = ['call' => 'Refresh All - Media Asset Details', 'request' => [ + 'asset_id' => $inf['media_asset_id'] + ], 'response' => $api->lastResponse]; + + if (isset($details['mediaAssetLabel'])) { + $stmt = $db->prepare(" + UPDATE infomercials + SET media_asset_label = ? + WHERE id = ? + "); + $stmt->execute([ + $details['mediaAssetLabel'], + $inf['id'] + ]); + $refreshed++; + } else { + $failed++; + // Only log failures + $refreshLogs[] = [ + 'status' => 'failed', + 'title' => $inf['title'], + 'asset_id' => $inf['media_asset_id'], + 'error' => $api->lastResponse['message'] ?? 'Geen mediaAssetLabel gevonden in response' + ]; + } + } + + // Store logs in session for display + session_start(); + $_SESSION['refresh_logs'] = $refreshLogs; + + header("Location: infomercials.php?success=refreshed_all&count=$refreshed&failed=$failed"); exit; } @@ -185,8 +305,10 @@ $infomercials = $db->query(" 'Infomercial succesvol aangemaakt en geregistreerd bij Talpa!', - 'updated' => 'Infomercial succesvol bijgewerkt!', - 'deleted' => 'Infomercial succesvol verwijderd!' + 'updated' => 'Infomercial succesvol bijgewerkt en gesynchroniseerd naar Talpa!', + 'deleted' => 'Infomercial succesvol verwijderd!', + 'refreshed' => 'Infomercial succesvol ververst vanuit Talpa!', + 'refreshed_all' => 'Alle infomercials succesvol ververst! (' . ($_GET['count'] ?? 0) . ' gelukt' . (($_GET['failed'] ?? 0) > 0 ? ', ' . $_GET['failed'] . ' mislukt' : '') . ')' ]; echo $messages[$_GET['success']] ?? 'Actie succesvol uitgevoerd!'; ?> @@ -198,7 +320,8 @@ $infomercials = $db->query("
| Infomercial | +Asset ID | +Foutmelding | +
|---|---|---|
| = htmlspecialchars($log['title']) ?> | += htmlspecialchars($log['asset_id']) ?> |
+ + + + = htmlspecialchars($log['error']) ?> + + | +