230 lines
11 KiB
PHP
230 lines
11 KiB
PHP
<?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);
|
|
$name = trim($_POST['name'] ?? '');
|
|
$address = trim($_POST['address'] ?? '');
|
|
$objType = trim($_POST['object_type'] ?? '');
|
|
$contact = trim($_POST['contact_person'] ?? '');
|
|
$cphone = trim($_POST['contact_phone'] ?? '');
|
|
$status = $_POST['status'] ?? 'active';
|
|
$notes = trim($_POST['notes'] ?? '');
|
|
$customerId = (int)($_POST['customer_id'] ?? 0);
|
|
$csrf = $_POST['csrf_token'] ?? '';
|
|
|
|
if (!auth_csrf_verify($csrf)) {
|
|
$message = 'Ошибка безопасности.';
|
|
} elseif ($name === '') {
|
|
$message = 'Название объекта обязательно.';
|
|
} else {
|
|
try {
|
|
if ($id > 0) {
|
|
$stmt = $pdo->prepare("UPDATE objects SET customer_id=?, name=?, address=?, object_type=?, contact_person=?, contact_phone=?, status=?, notes=? WHERE id=?");
|
|
$stmt->execute([$customerId ?: null, $name, $address, $objType, $contact, $cphone, $status, $notes, $id]);
|
|
$message = 'Объект обновлён.';
|
|
} else {
|
|
$stmt = $pdo->prepare("INSERT INTO objects (customer_id, name, address, object_type, contact_person, contact_phone, status, notes, created_by) VALUES (?,?,?,?,?,?,?,?,?)");
|
|
$stmt->execute([$customerId ?: null, $name, $address, $objType, $contact, $cphone, $status, $notes, $session['user_id']]);
|
|
$message = 'Объект создан.';
|
|
}
|
|
auth_log($session['user_id'], $id > 0 ? 'object_update' : 'object_create', "Name: $name");
|
|
} catch (\PDOException $e) {
|
|
$message = 'Ошибка: ' . $e->getMessage();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['delete']) && auth_has_role('owner')) {
|
|
$id = (int)$_GET['delete'];
|
|
if (auth_csrf_verify($_GET['csrf'] ?? '')) {
|
|
$pdo->prepare("DELETE FROM objects WHERE id=?")->execute([$id]);
|
|
$message = 'Объект удалён.';
|
|
auth_log($session['user_id'], 'object_delete', "ID: $id");
|
|
}
|
|
}
|
|
|
|
$editObj = null;
|
|
if (isset($_GET['edit'])) {
|
|
$stmt = $pdo->prepare("SELECT * FROM objects WHERE id=?");
|
|
$stmt->execute([(int)$_GET['edit']]);
|
|
$editObj = $stmt->fetch();
|
|
}
|
|
|
|
$search = trim($_GET['search'] ?? '');
|
|
$customerId = (int)($_GET['customer_id'] ?? 0);
|
|
|
|
if ($customerId > 0) {
|
|
$stmt = $pdo->prepare("
|
|
SELECT o.*, c.name as customer_name
|
|
FROM objects o
|
|
LEFT JOIN customers c ON c.id = o.customer_id
|
|
WHERE o.customer_id = ?
|
|
ORDER BY o.name
|
|
");
|
|
$stmt->execute([$customerId]);
|
|
} elseif ($search !== '') {
|
|
$stmt = $pdo->prepare("
|
|
SELECT o.*, c.name as customer_name
|
|
FROM objects o
|
|
LEFT JOIN customers c ON c.id = o.customer_id
|
|
WHERE o.name LIKE ? OR o.address LIKE ?
|
|
ORDER BY o.name
|
|
");
|
|
$stmt->execute(["%$search%", "%$search%"]);
|
|
} else {
|
|
$stmt = $pdo->query("
|
|
SELECT o.*, c.name as customer_name
|
|
FROM objects o
|
|
LEFT JOIN customers c ON c.id = o.customer_id
|
|
ORDER BY o.name
|
|
");
|
|
}
|
|
$objects = $stmt->fetchAll();
|
|
|
|
$customers = $pdo->query("SELECT id, name FROM customers WHERE status='active' ORDER BY name")->fetchAll();
|
|
|
|
$csrf = auth_csrf_token();
|
|
require __DIR__ . '/../../inc/header.php';
|
|
?>
|
|
|
|
<div class="main-header">
|
|
<div>
|
|
<h1>Объекты</h1>
|
|
<div class="breadcrumb"><a href="/service/dashboard.php">Главная</a> / Объекты</div>
|
|
</div>
|
|
<button class="btn btn-primary btn-sm" onclick="openModal()" data-tooltip="Добавить объект">+ Добавить</button>
|
|
</div>
|
|
|
|
<?php if ($message): ?>
|
|
<div class="alert alert-info"><?= htmlspecialchars($message) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<form class="search-box" method="get">
|
|
<input type="text" name="search" placeholder="Поиск объектов..." value="<?= htmlspecialchars($search) ?>">
|
|
<button type="submit" class="btn btn-primary btn-sm" data-tooltip="Поиск">Найти</button>
|
|
<?php if ($search): ?><a href="objects.php" class="btn btn-secondary btn-sm" data-tooltip="Сбросить поиск">Сброс</a><?php endif; ?>
|
|
</form>
|
|
|
|
<div class="card">
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Название</th>
|
|
<th>Клиент</th>
|
|
<th>Тип</th>
|
|
<th>Адрес</th>
|
|
<th>Статус</th>
|
|
<th>Risk Score</th>
|
|
<th>Object Index</th>
|
|
<th class="actions">Действия</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($objects)): ?>
|
|
<tr><td colspan="8" style="text-align:center;color:var(--text-muted);">Нет объектов</td></tr>
|
|
<?php endif; ?>
|
|
<?php foreach ($objects as $o): ?>
|
|
<tr>
|
|
<td><strong><?= htmlspecialchars($o['name']) ?></strong></td>
|
|
<td><?= $o['customer_name'] ? '<a href="customers.php?edit=' . (int)$o['customer_id'] . '">' . htmlspecialchars($o['customer_name']) . '</a>' : '—' ?></td>
|
|
<td><?= htmlspecialchars($o['object_type'] ?: '—') ?></td>
|
|
<td><?= htmlspecialchars($o['address'] ?: '—') ?></td>
|
|
<td><span class="badge badge-<?= $o['status'] ?>"><?= $o['status'] ?></span></td>
|
|
<td><?= $o['risk_score'] ?: '—' ?></td>
|
|
<td><strong><?= $o['object_index'] ?: '—' ?></strong></td>
|
|
<td class="actions">
|
|
<a href="?edit=<?= $o['id'] ?>" class="btn btn-secondary btn-sm" data-tooltip="Редактировать">✏️</a>
|
|
<a href="../shared/questionnaire.php?new=1" class="btn btn-secondary btn-sm" data-tooltip="Новый опросник">📝</a>
|
|
<a href="sla.php?object_id=<?= $o['id'] ?>" class="btn btn-secondary btn-sm" data-tooltip="Создать SLA">📋 SLA</a>
|
|
<a href="?delete=<?= $o['id'] ?>&csrf=<?= $csrf ?>" class="btn btn-danger btn-sm" onclick="return confirm('Удалить объект?')" data-tooltip="Удалить">🗑️</a>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-overlay <?= $editObj ? 'open' : '' ?>" id="objModal">
|
|
<div class="modal">
|
|
<button class="modal-close" onclick="closeModal()">×</button>
|
|
<h2><?= $editObj ? 'Редактировать' : 'Добавить' ?> объект</h2>
|
|
<form method="post">
|
|
<input type="hidden" name="csrf_token" value="<?= $csrf ?>">
|
|
<input type="hidden" name="id" value="<?= $editObj['id'] ?? 0 ?>">
|
|
|
|
<div class="form-group">
|
|
<label for="name">Название *</label>
|
|
<input type="text" id="name" name="name" value="<?= htmlspecialchars($editObj['name'] ?? '') ?>" required>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="customer_id">Клиент</label>
|
|
<select id="customer_id" name="customer_id">
|
|
<option value="">— Не выбран —</option>
|
|
<?php foreach ($customers as $cust): ?>
|
|
<option value="<?= $cust['id'] ?>" <?= ($editObj['customer_id'] ?? 0) == $cust['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cust['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="object_type">Тип</label>
|
|
<select id="object_type" name="object_type">
|
|
<option value="">—</option>
|
|
<?php foreach (['Гостиница','Склад','Производство','ТЦ','Офис','Бизнес-центр','Медицина','Образование','Другое'] as $t): ?>
|
|
<option value="<?= $t ?>" <?= ($editObj['object_type'] ?? '') === $t ? 'selected' : '' ?>><?= $t ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="address">Адрес</label>
|
|
<input type="text" id="address" name="address" value="<?= htmlspecialchars($editObj['address'] ?? '') ?>">
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="contact_person">Контактное лицо</label>
|
|
<input type="text" id="contact_person" name="contact_person" value="<?= htmlspecialchars($editObj['contact_person'] ?? '') ?>">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="contact_phone">Телефон</label>
|
|
<input type="text" id="contact_phone" name="contact_phone" value="<?= htmlspecialchars($editObj['contact_phone'] ?? '') ?>">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="status">Статус</label>
|
|
<select id="status" name="status">
|
|
<option value="active" <?= ($editObj['status'] ?? '') === 'active' ? 'selected' : '' ?>>Активен</option>
|
|
<option value="inactive" <?= ($editObj['status'] ?? '') === 'inactive' ? 'selected' : '' ?>>Неактивен</option>
|
|
<option value="audit" <?= ($editObj['status'] ?? '') === 'audit' ? 'selected' : '' ?>>Аудит</option>
|
|
<option value="prospective" <?= ($editObj['status'] ?? '') === 'prospective' ? 'selected' : '' ?>>Потенциальный</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="notes">Примечания</label>
|
|
<textarea id="notes" name="notes"><?= htmlspecialchars($editObj['notes'] ?? '') ?></textarea>
|
|
</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('objModal').classList.add('open'); }
|
|
function closeModal() { document.getElementById('objModal').classList.remove('open'); window.location.href = 'objects.php'; }
|
|
</script>
|
|
|
|
<?php require __DIR__ . '/../../inc/footer.php'; ?>
|