requireAdmin(); $boardId = (int)($_GET['id'] ?? 0); $pdo = DB::connection(); $stmt = $pdo->prepare("SELECT id, name, code FROM boards WHERE id = ? LIMIT 1"); $stmt->execute([$boardId]); $board = $stmt->fetch(); if (!$board) { http_response_code(404); echo 'Доска не найдена'; return; } $stmt = $pdo->prepare(" SELECT * FROM board_sources WHERE board_id = ? AND source_type = 'google_sheet' LIMIT 1 "); $stmt->execute([$boardId]); $source = $stmt->fetch(); $stmt = $pdo->prepare(" SELECT id, code, name FROM board_fields WHERE board_id = ? AND is_active = 1 ORDER BY sort_order ASC, id ASC "); $stmt->execute([$boardId]); $customFields = $stmt->fetchAll(); $mappings = []; if ($source) { $stmt = $pdo->prepare(" SELECT target_type, target_key, source_column_name FROM board_source_mappings WHERE board_source_id = ? AND is_active = 1 "); $stmt->execute([$source['id']]); foreach ($stmt->fetchAll() as $row) { $mappings[$row['target_type'] . ':' . $row['target_key']] = $row['source_column_name']; } } $baseFields = [ ['key' => 'creator_name', 'name' => 'Постановщик'], ['key' => 'assignee_name', 'name' => 'Ответственный'], ['key' => 'name', 'name' => 'Наименование'], ['key' => 'description', 'name' => 'Описание задачи'], ['key' => 'status', 'name' => 'Статус'], ['key' => 'priority', 'name' => 'Приоритет'], ['key' => 'crm_id', 'name' => 'CRM ID'], ['key' => 'completed_flag', 'name' => 'Выполнено'], ['key' => 'task_created_at', 'name' => 'Дата постановки'], ['key' => 'planned_at', 'name' => 'Дата план'], ['key' => 'completed_at', 'name' => 'Дата факт'], ]; View::render('admin/boards/source/edit', [ 'board' => $board, 'source' => $source, 'baseFields' => $baseFields, 'customFields' => $customFields, 'mappings' => $mappings, 'user' => Auth::user(), ]); } public function save(): void { $this->requireAdmin(); $boardId = (int)($_POST['board_id'] ?? 0); $spreadsheetUrl = trim((string)($_POST['spreadsheet_url'] ?? '')); $sheetName = trim((string)($_POST['sheet_name'] ?? '')); $syncMode = trim((string)($_POST['sync_mode'] ?? 'import_export')); $isActive = isset($_POST['is_active']) ? 1 : 0; if ($boardId <= 0 || $spreadsheetUrl === '' || $sheetName === '') { $_SESSION['error'] = 'Заполни ссылку и имя вкладки'; header('Location: /admin/boards/source?id=' . $boardId); exit; } $spreadsheetId = $this->extractSpreadsheetId($spreadsheetUrl); if ($spreadsheetId === '') { $_SESSION['error'] = 'Не удалось определить Spreadsheet ID'; header('Location: /admin/boards/source?id=' . $boardId); exit; } $pdo = DB::connection(); $pdo->beginTransaction(); try { $stmt = $pdo->prepare(" SELECT id FROM board_sources WHERE board_id = ? AND source_type = 'google_sheet' LIMIT 1 "); $stmt->execute([$boardId]); $sourceId = (int)$stmt->fetchColumn(); if ($sourceId > 0) { $stmt = $pdo->prepare(" UPDATE board_sources SET spreadsheet_url = ?, source_key = ?, sheet_name = ?, sync_mode = ?, is_active = ?, updated_at = NOW() WHERE id = ? "); $stmt->execute([ $spreadsheetUrl, $spreadsheetId, $sheetName, $syncMode, $isActive, $sourceId, ]); } else { $stmt = $pdo->prepare(" INSERT INTO board_sources ( board_id, source_type, spreadsheet_url, source_key, sheet_name, sync_mode, is_active, created_at, updated_at ) VALUES (?, 'google_sheet', ?, ?, ?, ?, ?, NOW(), NOW()) "); $stmt->execute([ $boardId, $spreadsheetUrl, $spreadsheetId, $sheetName, $syncMode, $isActive, ]); $sourceId = (int)$pdo->lastInsertId(); } $stmt = $pdo->prepare("DELETE FROM board_source_mappings WHERE board_source_id = ?"); $stmt->execute([$sourceId]); $baseMappings = $_POST['mapping_base'] ?? []; if (is_array($baseMappings)) { $stmt = $pdo->prepare(" INSERT INTO board_source_mappings ( board_source_id, target_type, target_key, source_column_name, is_active, created_at, updated_at ) VALUES (?, 'base', ?, ?, 1, NOW(), NOW()) "); foreach ($baseMappings as $key => $columnName) { $columnName = trim((string)$columnName); if ($columnName === '') { continue; } $stmt->execute([$sourceId, $key, $columnName]); } } $customMappings = $_POST['mapping_custom'] ?? []; if (is_array($customMappings)) { $stmt = $pdo->prepare(" INSERT INTO board_source_mappings ( board_source_id, target_type, target_key, source_column_name, is_active, created_at, updated_at ) VALUES (?, 'custom', ?, ?, 1, NOW(), NOW()) "); foreach ($customMappings as $key => $columnName) { $columnName = trim((string)$columnName); if ($columnName === '') { continue; } $stmt->execute([$sourceId, $key, $columnName]); } } $pdo->commit(); $_SESSION['success'] = 'Интеграция Google Sheets сохранена'; } catch (\Throwable $e) { $pdo->rollBack(); $_SESSION['error'] = 'Ошибка сохранения интеграции: ' . $e->getMessage(); } header('Location: /admin/boards/source?id=' . $boardId); exit; } }