Files
2026-05-17 05:22:06 +03:00

191 lines
9.6 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/../../inc/auth.php';
require_once __DIR__ . '/../../inc/functions.php';
$session = auth_require('owner', 'engineer');
$pdo = getDB();
$message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$id = (int)($_POST['id'] ?? 0);
$objectId = (int)($_POST['object_id'] ?? 0);
$client = trim($_POST['client_name'] ?? '');
$start = $_POST['start_date'] ?? '';
$end = $_POST['end_date'] ?? '';
$price = (float)($_POST['sla_price_monthly'] ?? 0);
$level = $_POST['service_level'] ?? 'business';
$status = $_POST['status'] ?? 'active';
$cr = $session['user_id'];
$csrf = $_POST['csrf_token'] ?? '';
if (!auth_csrf_verify($csrf)) {
$message = 'Ошибка безопасности.';
} elseif (!$objectId || !$start) {
$message = 'Объект и дата начала обязательны.';
} else {
try {
if ($id > 0) {
$stmt = $pdo->prepare("UPDATE sla_contracts SET object_id=?, client_name=?, start_date=?, end_date=?, sla_price_monthly=?, service_level=?, status=? WHERE id=?");
$stmt->execute([$objectId, $client, $start, $end ?: null, $price, $level, $status, $id]);
} else {
$stmt = $pdo->prepare("INSERT INTO sla_contracts (object_id, client_name, start_date, end_date, sla_price_monthly, service_level, status, created_by) VALUES (?,?,?,?,?,?,?,?)");
$stmt->execute([$objectId, $client, $start, $end ?: null, $price, $level, $status, $cr]);
}
$message = 'SLA контракт сохранён.';
auth_log($session['user_id'], 'sla_save', "Object: $objectId");
} catch (\PDOException $e) {
$message = 'Ошибка: ' . $e->getMessage();
}
}
}
$editSla = null;
if (isset($_GET['edit'])) {
$stmt = $pdo->prepare("SELECT * FROM sla_contracts WHERE id=?");
$stmt->execute([(int)$_GET['edit']]);
$editSla = $stmt->fetch();
}
$objectFilter = (int)($_GET['object_id'] ?? 0);
if ($objectFilter) {
$stmt = $pdo->prepare("SELECT sc.*, o.name as object_name FROM sla_contracts sc JOIN objects o ON o.id=sc.object_id WHERE sc.object_id=? ORDER BY sc.created_at DESC");
$stmt->execute([$objectFilter]);
} else {
$stmt = $pdo->query("SELECT sc.*, o.name as object_name FROM sla_contracts sc JOIN objects o ON o.id=sc.object_id ORDER BY sc.created_at DESC");
}
$contracts = $stmt->fetchAll();
$objects = $pdo->query("SELECT id, name FROM objects WHERE status IN ('active','audit') ORDER BY name")->fetchAll();
$csrf = auth_csrf_token();
require __DIR__ . '/../../inc/header.php';
?>
<div class="main-header">
<div>
<h1>SLA Контракты</h1>
<div class="breadcrumb"><a href="/service/dashboard.php">Главная</a> / SLA</div>
</div>
<button class="btn btn-primary btn-sm" onclick="openModal()" data-tooltip="Добавить SLA контракт">+ Добавить</button>
</div>
<?php if ($message): ?>
<div class="alert alert-info"><?= htmlspecialchars($message) ?></div>
<?php endif; ?>
<div class="filter-bar">
<form method="get">
<select name="object_id" onchange="this.form.submit()">
<option value="">Все объекты</option>
<?php foreach ($objects as $o): ?>
<option value="<?= $o['id'] ?>" <?= $objectFilter === $o['id'] ? 'selected' : '' ?>><?= htmlspecialchars($o['name']) ?></option>
<?php endforeach; ?>
</select>
<?php if ($objectFilter): ?><a href="sla.php" class="btn btn-secondary btn-sm" data-tooltip="Сбросить фильтр">Сброс</a><?php endif; ?>
</form>
</div>
<div class="card">
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Объект</th>
<th>Клиент</th>
<th>Уровень</th>
<th>Цена/мес</th>
<th>Период</th>
<th>Статус</th>
<th class="actions">Действия</th>
</tr>
</thead>
<tbody>
<?php if (empty($contracts)): ?>
<tr><td colspan="7" style="text-align:center;color:var(--text-muted);">Нет SLA контрактов</td></tr>
<?php endif; ?>
<?php foreach ($contracts as $c): ?>
<tr>
<td><strong><?= htmlspecialchars($c['object_name']) ?></strong></td>
<td><?= htmlspecialchars($c['client_name'] ?: '—') ?></td>
<td><span class="badge badge-<?= $c['service_level'] === 'enterprise' ? 'critical' : ($c['service_level'] === 'business' ? 'high' : 'medium') ?>"><?= $c['service_level'] ?></span></td>
<td><strong><?= fmt_money($c['sla_price_monthly']) ?></strong></td>
<td><?= date('d.m.Y', strtotime($c['start_date'])) . ($c['end_date'] ? ' — ' . date('d.m.Y', strtotime($c['end_date'])) : '') ?></td>
<td><span class="badge badge-<?= $c['status'] ?>"><?= $c['status'] ?></span></td>
<td class="actions">
<a href="?edit=<?= $c['id'] ?>" class="btn btn-secondary btn-sm" data-tooltip="Редактировать">✏️</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="modal-overlay <?= $editSla ? 'open' : '' ?>" id="slaModal">
<div class="modal">
<button class="modal-close" onclick="closeModal()">&times;</button>
<h2><?= $editSla ? 'Редактировать' : 'Добавить' ?> SLA контракт</h2>
<form method="post">
<input type="hidden" name="csrf_token" value="<?= $csrf ?>">
<input type="hidden" name="id" value="<?= $editSla['id'] ?? 0 ?>">
<div class="form-row">
<div class="form-group">
<label for="object_id">Объект *</label>
<select id="object_id" name="object_id" required>
<option value="">— выберите —</option>
<?php foreach ($objects as $o): ?>
<option value="<?= $o['id'] ?>" <?= ($editSla['object_id'] ?? 0) === $o['id'] ? 'selected' : ($objectFilter === $o['id'] ? 'selected' : '') ?>><?= htmlspecialchars($o['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="client_name">Клиент</label>
<input type="text" id="client_name" name="client_name" value="<?= htmlspecialchars($editSla['client_name'] ?? '') ?>">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="service_level">Уровень</label>
<select id="service_level" name="service_level">
<option value="start" <?= ($editSla['service_level'] ?? '') === 'start' ? 'selected' : '' ?>>Start</option>
<option value="business" <?= ($editSla['service_level'] ?? '') === 'business' ? 'selected' : '' ?>>Business</option>
<option value="enterprise" <?= ($editSla['service_level'] ?? '') === 'enterprise' ? 'selected' : '' ?>>Enterprise</option>
</select>
</div>
<div class="form-group">
<label for="sla_price_monthly">Цена в месяц (₽)</label>
<input type="number" id="sla_price_monthly" name="sla_price_monthly" step="0.01" value="<?= $editSla['sla_price_monthly'] ?? 0 ?>">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="start_date">Дата начала *</label>
<input type="date" id="start_date" name="start_date" value="<?= $editSla['start_date'] ?? '' ?>" required>
</div>
<div class="form-group">
<label for="end_date">Дата окончания</label>
<input type="date" id="end_date" name="end_date" value="<?= $editSla['end_date'] ?? '' ?>">
</div>
</div>
<div class="form-group">
<label for="status">Статус</label>
<select id="status" name="status">
<option value="active" <?= ($editSla['status'] ?? '') === 'active' ? 'selected' : '' ?>>Активен</option>
<option value="expired" <?= ($editSla['status'] ?? '') === 'expired' ? 'selected' : '' ?>>Истёк</option>
<option value="cancelled" <?= ($editSla['status'] ?? '') === 'cancelled' ? 'selected' : '' ?>>Отменён</option>
<option value="negotiation" <?= ($editSla['status'] ?? '') === 'negotiation' ? 'selected' : '' ?>>В переговорах</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
<button type="button" class="btn btn-secondary" onclick="closeModal()">Отмена</button>
</form>
</div>
</div>
<script>
function openModal() { document.getElementById('slaModal').classList.add('open'); }
function closeModal() { document.getElementById('slaModal').classList.remove('open'); window.location.href = 'sla.php'; }
</script>
<?php require __DIR__ . '/../../inc/footer.php'; ?>