259 lines
8.3 KiB
PHP
259 lines
8.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controllers;
|
|
|
|
use App\Core\Auth;
|
|
use App\Core\DB;
|
|
use App\Core\View;
|
|
|
|
class AdminBoardSourceController
|
|
{
|
|
private function requireAdmin(): void
|
|
{
|
|
if (!Auth::check()) {
|
|
header('Location: /login');
|
|
exit;
|
|
}
|
|
|
|
$user = Auth::user();
|
|
|
|
if ((int)($user['is_admin'] ?? 0) !== 1) {
|
|
http_response_code(403);
|
|
echo 'Доступ запрещен';
|
|
exit;
|
|
}
|
|
}
|
|
|
|
private function extractSpreadsheetId(string $url): string
|
|
{
|
|
if (preg_match('~/spreadsheets/d/([a-zA-Z0-9-_]+)~', $url, $matches)) {
|
|
return $matches[1];
|
|
}
|
|
|
|
return trim($url);
|
|
}
|
|
|
|
public function edit(): void
|
|
{
|
|
$this->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;
|
|
}
|
|
} |