LPA-Health-V1.4-28-Feb-2026
This commit is contained in:
parent
5fae92efe8
commit
41e72d1c86
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
|
// Check if user is Super User
|
||||||
if (!isset($_SESSION["user_id"]) || ($_SESSION["user_role"] ?? '') !== 'Super User') {
|
if (!isset($_SESSION["user_id"]) || ($_SESSION["user_role"] ?? '') !== 'Super User') {
|
||||||
header("Location: login.php");
|
header("Location: login.php");
|
||||||
exit;
|
exit;
|
||||||
@ -12,6 +13,7 @@ $lpas_count = 0;
|
|||||||
$users = [];
|
$users = [];
|
||||||
$lpas = [];
|
$lpas = [];
|
||||||
$migration_history = [];
|
$migration_history = [];
|
||||||
|
$backups = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db = db();
|
$db = db();
|
||||||
@ -29,9 +31,25 @@ try {
|
|||||||
try {
|
try {
|
||||||
$migration_history = $db->query("SELECT * FROM migration_history ORDER BY executed_at DESC")->fetchAll();
|
$migration_history = $db->query("SELECT * FROM migration_history ORDER BY executed_at DESC")->fetchAll();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
// migration_history might not exist yet if installer hasn't run or table not created
|
|
||||||
$migration_history = [];
|
$migration_history = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get backups from filesystem
|
||||||
|
$backups_dir = __DIR__ . '/backups';
|
||||||
|
if (is_dir($backups_dir)) {
|
||||||
|
$backup_files = glob($backups_dir . '/backup_*.sql');
|
||||||
|
foreach ($backup_files as $file) {
|
||||||
|
$backups[] = [
|
||||||
|
'filename' => basename($file),
|
||||||
|
'size' => round(filesize($file) / 1024, 2) . ' KB',
|
||||||
|
'created_at' => filemtime($file)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// Sort by created_at descending
|
||||||
|
usort($backups, function($a, $b) {
|
||||||
|
return $b['created_at'] - $a['created_at'];
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
error_log($e->getMessage());
|
error_log($e->getMessage());
|
||||||
}
|
}
|
||||||
@ -132,8 +150,9 @@ try {
|
|||||||
<th class="ps-4">Name</th>
|
<th class="ps-4">Name</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th>Role</th>
|
<th>Role</th>
|
||||||
|
<th>Credits</th>
|
||||||
<th>Verified</th>
|
<th>Verified</th>
|
||||||
<th class="text-end pe-4">Joined</th>
|
<th class="text-end pe-4">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -146,6 +165,9 @@ try {
|
|||||||
<?php echo htmlspecialchars($u['role'] ?? 'Standard User'); ?>
|
<?php echo htmlspecialchars($u['role'] ?? 'Standard User'); ?>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="fw-bold text-primary"><?php echo (int)($u['credits'] ?? 0); ?></span>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?php if ($u['is_verified']): ?>
|
<?php if ($u['is_verified']): ?>
|
||||||
<span class="text-success small">
|
<span class="text-success small">
|
||||||
@ -155,7 +177,9 @@ try {
|
|||||||
<span class="text-muted small">No</span>
|
<span class="text-muted small">No</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end pe-4 text-muted small"><?php echo date('M d, Y', strtotime($u['created_at'])); ?></td>
|
<td class="text-end pe-4">
|
||||||
|
<button onclick="showCreditModal(<?php echo $u['id']; ?>, '<?php echo htmlspecialchars($u['name'] ?? $u['email']); ?>', <?php echo (int)($u['credits'] ?? 0); ?>)" class="btn btn-sm btn-outline-primary px-3 rounded-pill">Adjust Credits</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -217,8 +241,8 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-12 mt-5">
|
<div class="col-lg-6 mt-5">
|
||||||
<div class="card border-0 shadow-sm mb-5">
|
<div class="card border-0 shadow-sm mb-5 h-100">
|
||||||
<div class="card-header bg-white py-3 border-bottom-0">
|
<div class="card-header bg-white py-3 border-bottom-0">
|
||||||
<h5 class="fw-bold mb-0">Migration History</h5>
|
<h5 class="fw-bold mb-0">Migration History</h5>
|
||||||
</div>
|
</div>
|
||||||
@ -246,11 +270,117 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 mt-5">
|
||||||
|
<div class="card border-0 shadow-sm mb-5 h-100">
|
||||||
|
<div class="card-header bg-white py-3 border-bottom-0 d-flex justify-content-between align-items-center">
|
||||||
|
<h5 class="fw-bold mb-0">Backups</h5>
|
||||||
|
<span class="badge rounded-pill bg-light text-muted fw-normal">Last 5 kept</span>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle mb-0">
|
||||||
|
<thead class="bg-light">
|
||||||
|
<tr class="small text-uppercase tracking-wider">
|
||||||
|
<th class="ps-4">File Name</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th class="text-end pe-4">Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if (count($backups) > 0): ?>
|
||||||
|
<?php foreach ($backups as $b): ?>
|
||||||
|
<tr>
|
||||||
|
<td class="ps-4">
|
||||||
|
<div class="fw-medium small"><?php echo htmlspecialchars($b['filename']); ?></div>
|
||||||
|
<div class="text-muted" style="font-size: 0.75rem;"><?php echo date('M d, Y H:i', $b['created_at']); ?></div>
|
||||||
|
</td>
|
||||||
|
<td class="text-muted small"><?php echo $b['size']; ?></td>
|
||||||
|
<td class="text-end pe-4">
|
||||||
|
<a href="api/download_backup.php?filename=<?php echo urlencode($b['filename']); ?>" class="btn btn-sm btn-link text-primary text-decoration-none p-0">
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="me-1"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
||||||
|
Download
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="3" class="text-center py-4 text-muted small">No backups found. Backups are created automatically before migrations.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Credit Adjustment Modal -->
|
||||||
|
<div class="modal fade" id="creditModal" tabindex="-1" aria-labelledby="creditModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content border-0 shadow-lg rounded-4">
|
||||||
|
<div class="modal-header border-bottom-0 pb-0">
|
||||||
|
<h5 class="modal-title fw-bold" id="creditModalLabel">Adjust Credits</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body pt-3">
|
||||||
|
<p class="text-muted small mb-4">Adjust LPA credits for <strong id="modalUserName"></strong>. Current balance: <strong id="modalCurrentCredits"></strong></p>
|
||||||
|
|
||||||
|
<form id="creditForm">
|
||||||
|
<input type="hidden" id="modalUserId" name="user_id">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label small fw-bold text-uppercase">Action</label>
|
||||||
|
<select class="form-select rounded-3" name="action" id="creditAction">
|
||||||
|
<option value="add">Add Credits (+)</option>
|
||||||
|
<option value="set">Set Total Credits (=)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="form-label small fw-bold text-uppercase">Amount</label>
|
||||||
|
<input type="number" class="form-control rounded-3" name="credits" id="creditAmount" min="0" value="1" required>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="submit" class="btn btn-primary py-2 rounded-pill fw-bold">Update Credits</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
const creditModal = new bootstrap.Modal(document.getElementById('creditModal'));
|
||||||
|
|
||||||
|
function showCreditModal(id, name, current) {
|
||||||
|
document.getElementById('modalUserId').value = id;
|
||||||
|
document.getElementById('modalUserName').textContent = name;
|
||||||
|
document.getElementById('modalCurrentCredits').textContent = current;
|
||||||
|
document.getElementById('creditAmount').value = 1;
|
||||||
|
creditModal.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('creditForm').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const formData = new FormData(this);
|
||||||
|
|
||||||
|
fetch('api/allocate_credits.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Error: ' + data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('An unexpected error occurred.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function deleteLPA(id) {
|
function deleteLPA(id) {
|
||||||
if (confirm('Are you sure you want to delete this LPA application? This action cannot be undone.')) {
|
if (confirm('Are you sure you want to delete this LPA application? This action cannot be undone.')) {
|
||||||
fetch('api/delete_lpa.php', {
|
fetch('api/delete_lpa.php', {
|
||||||
@ -280,7 +410,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function runMigrations() {
|
function runMigrations() {
|
||||||
if (!confirm('Run database migrations? This will execute all SQL files in db/migrations/ and may take a moment.')) return;
|
if (!confirm('Run database migrations? A database backup will be created automatically before proceeding.')) return;
|
||||||
|
|
||||||
const alertBox = document.getElementById('migration-alert');
|
const alertBox = document.getElementById('migration-alert');
|
||||||
const messageEl = document.getElementById('migration-message');
|
const messageEl = document.getElementById('migration-message');
|
||||||
@ -292,9 +422,10 @@ try {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
alertBox.style.display = 'block';
|
alertBox.style.display = 'block';
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
messageEl.textContent = data.message + ' Page will reload in 2 seconds.';
|
const backupMsg = data.backup ? ` Backup created: ${data.backup}.` : '';
|
||||||
|
messageEl.textContent = data.message + backupMsg + ' Page will reload in 3 seconds.';
|
||||||
messageEl.parentElement.className = 'alert alert-success alert-dismissible fade show rounded-3 shadow-sm border-0 mb-4';
|
messageEl.parentElement.className = 'alert alert-success alert-dismissible fade show rounded-3 shadow-sm border-0 mb-4';
|
||||||
setTimeout(() => location.reload(), 2000);
|
setTimeout(() => location.reload(), 3000);
|
||||||
} else {
|
} else {
|
||||||
messageEl.textContent = 'Error: ' + data.error;
|
messageEl.textContent = 'Error: ' + data.error;
|
||||||
messageEl.parentElement.className = 'alert alert-danger alert-dismissible fade show rounded-3 shadow-sm border-0 mb-4';
|
messageEl.parentElement.className = 'alert alert-danger alert-dismissible fade show rounded-3 shadow-sm border-0 mb-4';
|
||||||
|
|||||||
39
api/allocate_credits.php
Normal file
39
api/allocate_credits.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Security: Only Super Users can allocate credits
|
||||||
|
if (!isset($_SESSION["user_id"]) || ($_SESSION["user_role"] ?? '') !== 'Super User') {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Unauthorized access.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$target_user_id = isset($_POST['user_id']) ? (int)$_POST['user_id'] : null;
|
||||||
|
$credits = isset($_POST['credits']) ? (int)$_POST['credits'] : 0;
|
||||||
|
$action = $_POST['action'] ?? 'set'; // 'set' or 'add'
|
||||||
|
|
||||||
|
if (!$target_user_id) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'User ID is required.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($action === 'add') {
|
||||||
|
$stmt = db()->prepare("UPDATE users SET credits = credits + ? WHERE id = ?");
|
||||||
|
$stmt->execute([$credits, $target_user_id]);
|
||||||
|
$message = "Successfully added $credits credits.";
|
||||||
|
} else {
|
||||||
|
$stmt = db()->prepare("UPDATE users SET credits = ? WHERE id = ?");
|
||||||
|
$stmt->execute([$credits, $target_user_id]);
|
||||||
|
$message = "Successfully set credits to $credits.";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode(['success' => true, 'message' => $message]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Database error: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Invalid request method.']);
|
||||||
|
}
|
||||||
46
api/download_backup.php
Normal file
46
api/download_backup.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Secure Backup Download API
|
||||||
|
*
|
||||||
|
* Only accessible by authenticated administrators.
|
||||||
|
*/
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Authentication and role-based access control
|
||||||
|
if (!isset($_SESSION['user_id']) || !isset($_SESSION['role']) || $_SESSION['role'] !== 'admin') {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['error' => 'Forbidden: Only administrators can access this resource.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input validation
|
||||||
|
if (!isset($_GET['filename'])) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Bad Request: Filename is required.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = basename($_GET['filename']); // Prevent directory traversal
|
||||||
|
$backups_dir = realpath(__DIR__ . '/../backups');
|
||||||
|
$filepath = "{$backups_dir}/{$filename}";
|
||||||
|
|
||||||
|
// Security check: ensure the file exists and is within the backups directory
|
||||||
|
if (!$backups_dir || !file_exists($filepath) || strpos(realpath($filepath), $backups_dir) !== 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
echo json_encode(['error' => 'Not Found: Backup file not found or access denied.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine content type
|
||||||
|
header('Content-Description: File Transfer');
|
||||||
|
header('Content-Type: application/sql');
|
||||||
|
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||||
|
header('Expires: 0');
|
||||||
|
header('Cache-Control: must-revalidate');
|
||||||
|
header('Pragma: public');
|
||||||
|
header('Content-Length: ' . filesize($filepath));
|
||||||
|
|
||||||
|
// Stream the file for download
|
||||||
|
readfile($filepath);
|
||||||
|
exit;
|
||||||
@ -8,23 +8,27 @@ if (!isset($_SESSION["user_id"]) || ($_SESSION["user_role"] ?? '') !== 'Super Us
|
|||||||
}
|
}
|
||||||
|
|
||||||
require_once '../db/config.php';
|
require_once '../db/config.php';
|
||||||
|
require_once '../db/backup_helper.php';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db = db();
|
$db = db();
|
||||||
|
|
||||||
// 1. Ensure migration_history table exists
|
// 1. Perform database backup before migrations
|
||||||
|
$backup_info = backup_db();
|
||||||
|
|
||||||
|
// 2. Ensure migration_history table exists
|
||||||
$db->exec("CREATE TABLE IF NOT EXISTS migration_history (
|
$db->exec("CREATE TABLE IF NOT EXISTS migration_history (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
filename VARCHAR(255) NOT NULL UNIQUE,
|
filename VARCHAR(255) NOT NULL UNIQUE,
|
||||||
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;");
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;");
|
||||||
|
|
||||||
// 2. Scan migrations directory
|
// 3. Scan migrations directory
|
||||||
$migrations_dir = __DIR__ . '/../db/migrations/';
|
$migrations_dir = __DIR__ . '/../db/migrations/';
|
||||||
$migration_files = glob($migrations_dir . '*.sql');
|
$migration_files = glob($migrations_dir . '*.sql');
|
||||||
sort($migration_files);
|
sort($migration_files);
|
||||||
|
|
||||||
// 3. Get list of already executed migrations
|
// 4. Get list of already executed migrations
|
||||||
$stmt = $db->query("SELECT filename FROM migration_history");
|
$stmt = $db->query("SELECT filename FROM migration_history");
|
||||||
$executed_migrations = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
$executed_migrations = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||||
|
|
||||||
@ -56,7 +60,8 @@ try {
|
|||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => "Migration process complete.",
|
'message' => "Backup and migration process complete.",
|
||||||
|
'backup' => $backup_info['filename'],
|
||||||
'executed' => $executed_count,
|
'executed' => $executed_count,
|
||||||
'skipped' => $skipped_count,
|
'skipped' => $skipped_count,
|
||||||
'new_migrations' => $new_migrations
|
'new_migrations' => $new_migrations
|
||||||
@ -64,6 +69,6 @@ try {
|
|||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'error' => 'Migration failed: ' . $e->getMessage()
|
'error' => 'Migration/Backup failed: ' . $e->getMessage()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,10 +121,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$stmt->execute([$lpa_type, $donor_name, $other_names, $donor_dob, $customer_email, $address1, $address2, $town, $postcode, $user_id, $lpa_id]);
|
$stmt->execute([$lpa_type, $donor_name, $other_names, $donor_dob, $customer_email, $address1, $address2, $town, $postcode, $user_id, $lpa_id]);
|
||||||
$id = $lpa_id;
|
$id = $lpa_id;
|
||||||
} else {
|
} else {
|
||||||
|
// Create new - CHECK CREDITS
|
||||||
|
$userCheck = db()->prepare("SELECT credits FROM users WHERE id = ?");
|
||||||
|
$userCheck->execute([$user_id]);
|
||||||
|
$userData = $userCheck->fetch();
|
||||||
|
|
||||||
|
if (!$userData || (int)$userData['credits'] < 1) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'You do not have enough credits to start a new LPA application. Please contact your administrator.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
// Create new
|
// Create new
|
||||||
$stmt = db()->prepare("INSERT INTO lpa_applications (practice_id, user_id, lpa_type, donor_name, other_names, donor_dob, customer_email, donor_address_line1, donor_address_line2, donor_town, donor_postcode, step_reached) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO lpa_applications (practice_id, user_id, lpa_type, donor_name, other_names, donor_dob, customer_email, donor_address_line1, donor_address_line2, donor_town, donor_postcode, step_reached) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([1, $user_id, $lpa_type, $donor_name, $other_names, $donor_dob, $customer_email, $address1, $address2, $town, $postcode, 1]);
|
$stmt->execute([1, $user_id, $lpa_type, $donor_name, $other_names, $donor_dob, $customer_email, $address1, $address2, $town, $postcode, 1]);
|
||||||
$id = db()->lastInsertId();
|
$id = db()->lastInsertId();
|
||||||
|
|
||||||
|
// DECREMENT CREDITS
|
||||||
|
$updateCredits = db()->prepare("UPDATE users SET credits = credits - 1 WHERE id = ?");
|
||||||
|
$updateCredits->execute([$user_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'id' => (int)$id, 'next_step' => 2, 'message' => 'Step 1 saved successfully.']);
|
echo json_encode(['success' => true, 'id' => (int)$id, 'next_step' => 2, 'message' => 'Step 1 saved successfully.']);
|
||||||
|
|||||||
15
apply.php
15
apply.php
@ -12,6 +12,19 @@ $project_name = $_SERVER['PROJECT_NAME'] ?? 'LPA Online';
|
|||||||
$step = isset($_GET['step']) ? (int)$_GET['step'] : 1;
|
$step = isset($_GET['step']) ? (int)$_GET['step'] : 1;
|
||||||
$lpa_id = isset($_GET['id']) ? (int)$_GET['id'] : null;
|
$lpa_id = isset($_GET['id']) ? (int)$_GET['id'] : null;
|
||||||
|
|
||||||
|
// If starting a NEW LPA (Step 1, no ID), check for credits
|
||||||
|
if ($step === 1 && !$lpa_id) {
|
||||||
|
$credits_stmt = db()->prepare("SELECT credits FROM users WHERE id = ?");
|
||||||
|
$credits_stmt->execute([$user_id]);
|
||||||
|
$credits = (int)$credits_stmt->fetchColumn();
|
||||||
|
|
||||||
|
if ($credits < 1) {
|
||||||
|
// Redirect back to dashboard with error
|
||||||
|
header("Location: dashboard.php?error=no_credits");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$lpa_data = null;
|
$lpa_data = null;
|
||||||
if ($lpa_id) {
|
if ($lpa_id) {
|
||||||
$stmt = db()->prepare("SELECT * FROM lpa_applications WHERE id = ?");
|
$stmt = db()->prepare("SELECT * FROM lpa_applications WHERE id = ?");
|
||||||
@ -1020,7 +1033,7 @@ foreach ($notified_persons as $np) {
|
|||||||
|
|
||||||
<div class="mt-5 d-flex justify-content-between align-items-center">
|
<div class="mt-5 d-flex justify-content-between align-items-center">
|
||||||
<a href="apply.php?step=11&id=<?php echo $lpa_id; ?>" class="btn btn-link text-decoration-none text-muted p-0">Back to Step 11</a>
|
<a href="apply.php?step=11&id=<?php echo $lpa_id; ?>" class="btn btn-link text-decoration-none text-muted p-0">Back to Step 11</a>
|
||||||
<button type="submit" class="btn btn-primary btn-lg px-5">Continue to Step 13</button>
|
<button type="submit" class="btn btn-primary btn-lg px-5">Continue to Step 12</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<?php elseif ($step === 13): ?>
|
<?php elseif ($step === 13): ?>
|
||||||
|
|||||||
280
backups/backup_2026-03-01_00-59-10.sql
Normal file
280
backups/backup_2026-03-01_00-59-10.sql
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/*M!999999\- enable the sandbox mode */
|
||||||
|
-- MariaDB dump 10.19 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64)
|
||||||
|
--
|
||||||
|
-- Host: 127.0.0.1 Database: app_37684
|
||||||
|
-- ------------------------------------------------------
|
||||||
|
-- Server version 10.11.14-MariaDB-0+deb12u2
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!40101 SET NAMES utf8mb4 */;
|
||||||
|
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||||
|
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||||
|
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||||
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `lpa_applications`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `lpa_applications`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `lpa_applications` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`practice_id` int(11) DEFAULT 1,
|
||||||
|
`user_id` int(11) DEFAULT NULL,
|
||||||
|
`customer_email` varchar(255) DEFAULT NULL,
|
||||||
|
`lpa_type` enum('Health & Welfare','Property & Financial') NOT NULL,
|
||||||
|
`donor_name` varchar(255) DEFAULT NULL,
|
||||||
|
`other_names` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_dob` date DEFAULT NULL,
|
||||||
|
`donor_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_town` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`donor_phone` varchar(20) DEFAULT NULL,
|
||||||
|
`status` enum('draft','completed') DEFAULT 'draft',
|
||||||
|
`step_reached` int(11) DEFAULT 1,
|
||||||
|
`attorney_decision_type` varchar(255) DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||||
|
`life_sustaining_treatment` enum('Option A','Option B') DEFAULT NULL,
|
||||||
|
`witness_title` varchar(20) DEFAULT NULL,
|
||||||
|
`witness_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`preferences` text DEFAULT NULL,
|
||||||
|
`instructions` text DEFAULT NULL,
|
||||||
|
`certificate_provider_title` varchar(20) DEFAULT NULL,
|
||||||
|
`certificate_provider_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`registration_who` varchar(20) DEFAULT NULL,
|
||||||
|
`registering_attorneys_ids` text DEFAULT NULL,
|
||||||
|
`correspondence_who` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_attorney_id` int(11) DEFAULT NULL,
|
||||||
|
`correspondence_title` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_company_name` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_contact_preference` varchar(50) DEFAULT NULL,
|
||||||
|
`correspondence_phone` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_email` varchar(255) DEFAULT NULL,
|
||||||
|
`payment_method` varchar(20) DEFAULT NULL,
|
||||||
|
`payment_phone` varchar(20) DEFAULT NULL,
|
||||||
|
`reduced_fee_eligibility` varchar(10) DEFAULT NULL,
|
||||||
|
`is_repeat_application` tinyint(1) DEFAULT 0,
|
||||||
|
`repeat_case_number` varchar(50) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `fk_user_id` (`user_id`),
|
||||||
|
CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `lpa_applications`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `lpa_applications` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `lpa_applications` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `lpa_applications` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `lpa_attorneys`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `lpa_attorneys`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `lpa_attorneys` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`lpa_id` int(11) NOT NULL,
|
||||||
|
`type` enum('primary','replacement') DEFAULT 'primary',
|
||||||
|
`title` varchar(20) DEFAULT NULL,
|
||||||
|
`first_name` varchar(255) NOT NULL,
|
||||||
|
`last_name` varchar(255) NOT NULL,
|
||||||
|
`email` varchar(255) NOT NULL,
|
||||||
|
`dob` date NOT NULL,
|
||||||
|
`address_line1` varchar(255) NOT NULL,
|
||||||
|
`address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`town` varchar(255) NOT NULL,
|
||||||
|
`postcode` varchar(20) NOT NULL,
|
||||||
|
`relationship` varchar(100) DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`witness_title` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_postcode` varchar(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `lpa_id` (`lpa_id`),
|
||||||
|
CONSTRAINT `lpa_attorneys_ibfk_1` FOREIGN KEY (`lpa_id`) REFERENCES `lpa_applications` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `lpa_attorneys`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `lpa_attorneys` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `lpa_attorneys` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `lpa_attorneys` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `lpa_notified_persons`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `lpa_notified_persons`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `lpa_notified_persons` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`application_id` int(11) NOT NULL,
|
||||||
|
`title` varchar(20) DEFAULT NULL,
|
||||||
|
`first_name` varchar(100) DEFAULT NULL,
|
||||||
|
`last_name` varchar(100) DEFAULT NULL,
|
||||||
|
`address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `lpa_notified_persons`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `lpa_notified_persons` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `lpa_notified_persons` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `lpa_notified_persons` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `migration_history`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `migration_history`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `migration_history` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`filename` varchar(255) NOT NULL,
|
||||||
|
`executed_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `filename` (`filename`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `migration_history`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `migration_history` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `migration_history` DISABLE KEYS */;
|
||||||
|
INSERT INTO `migration_history` VALUES
|
||||||
|
(1,'01_create_users_table.sql','2026-03-01 00:57:47'),
|
||||||
|
(2,'02_update_users_for_signup.sql','2026-03-01 00:57:47'),
|
||||||
|
(3,'03_add_reset_password_fields.sql','2026-03-01 00:57:47'),
|
||||||
|
(4,'04_add_role_column.sql','2026-03-01 00:57:47'),
|
||||||
|
(5,'05_add_user_id_to_lpa_applications.sql','2026-03-01 00:57:47'),
|
||||||
|
(6,'06_create_migration_history_table.sql','2026-03-01 00:57:47');
|
||||||
|
/*!40000 ALTER TABLE `migration_history` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `practices`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `practices`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `practices` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`slug` varchar(100) NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `slug` (`slug`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `practices`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `practices` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `practices` DISABLE KEYS */;
|
||||||
|
INSERT INTO `practices` VALUES
|
||||||
|
(1,'Elite Estate Planning','elite-estate','2026-02-28 17:36:29');
|
||||||
|
/*!40000 ALTER TABLE `practices` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `users`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) DEFAULT NULL,
|
||||||
|
`email` varchar(255) NOT NULL,
|
||||||
|
`password` varchar(255) NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`is_verified` tinyint(1) DEFAULT 0,
|
||||||
|
`verification_token` varchar(64) DEFAULT NULL,
|
||||||
|
`role` enum('Standard User','Super User') DEFAULT 'Standard User',
|
||||||
|
`reset_token` varchar(64) DEFAULT NULL,
|
||||||
|
`reset_expires_at` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `email` (`email`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `users` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `users` DISABLE KEYS */;
|
||||||
|
INSERT INTO `users` VALUES
|
||||||
|
(1,NULL,'test@example.com','$2y$10$xeVgbO3f09/R4FF0bEwqSeTH3bdNp1CcDLE6R27Slc6yNBHK8Cxq.','2026-02-28 23:23:36',1,NULL,'Standard User',NULL,NULL),
|
||||||
|
(3,'Admin','advice@estateguardians.co.uk','$2y$10$.vu3rXV4RHCa4JIs2GVa/OJvfe4c2dhLOgb60Uw0boPHRCVeDKtq6','2026-03-01 00:00:01',1,NULL,'Super User',NULL,NULL),
|
||||||
|
(4,'Neel Shah (Profitise)','neel@profitise.co','$2y$10$332.cCj/4WY6.1r6aPQe1ed4QBwl4AYODFtiEeHymgCrvVapiU956','2026-03-01 00:16:28',1,NULL,'Standard User',NULL,NULL),
|
||||||
|
(5,'Neel Shah','neel@neel.me.uk','$2y$10$6.jb/U/rjKYfXJSwzfdmquJBqjij.RDqlhYKmZNnELnNgyA635u0.','2026-03-01 00:36:13',1,NULL,'Standard User',NULL,NULL),
|
||||||
|
(6,'Cogent FS','cogentfs@gmail.com','$2y$10$g23tK9toSrpgqQKXF7902eK7P5Hg98VtYZd4lB4O1Vpi/XtY.KlEq','2026-03-01 00:39:16',1,NULL,'Standard User',NULL,NULL);
|
||||||
|
/*!40000 ALTER TABLE `users` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||||
|
|
||||||
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
|
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
|
-- Dump completed on 2026-03-01 0:59:11
|
||||||
280
backups/backup_2026-03-01_01-03-59.sql
Normal file
280
backups/backup_2026-03-01_01-03-59.sql
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/*M!999999\- enable the sandbox mode */
|
||||||
|
-- MariaDB dump 10.19 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64)
|
||||||
|
--
|
||||||
|
-- Host: 127.0.0.1 Database: app_37684
|
||||||
|
-- ------------------------------------------------------
|
||||||
|
-- Server version 10.11.14-MariaDB-0+deb12u2
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!40101 SET NAMES utf8mb4 */;
|
||||||
|
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||||
|
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||||
|
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||||
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `lpa_applications`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `lpa_applications`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `lpa_applications` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`practice_id` int(11) DEFAULT 1,
|
||||||
|
`user_id` int(11) DEFAULT NULL,
|
||||||
|
`customer_email` varchar(255) DEFAULT NULL,
|
||||||
|
`lpa_type` enum('Health & Welfare','Property & Financial') NOT NULL,
|
||||||
|
`donor_name` varchar(255) DEFAULT NULL,
|
||||||
|
`other_names` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_dob` date DEFAULT NULL,
|
||||||
|
`donor_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_town` varchar(255) DEFAULT NULL,
|
||||||
|
`donor_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`donor_phone` varchar(20) DEFAULT NULL,
|
||||||
|
`status` enum('draft','completed') DEFAULT 'draft',
|
||||||
|
`step_reached` int(11) DEFAULT 1,
|
||||||
|
`attorney_decision_type` varchar(255) DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||||
|
`life_sustaining_treatment` enum('Option A','Option B') DEFAULT NULL,
|
||||||
|
`witness_title` varchar(20) DEFAULT NULL,
|
||||||
|
`witness_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`preferences` text DEFAULT NULL,
|
||||||
|
`instructions` text DEFAULT NULL,
|
||||||
|
`certificate_provider_title` varchar(20) DEFAULT NULL,
|
||||||
|
`certificate_provider_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`certificate_provider_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`registration_who` varchar(20) DEFAULT NULL,
|
||||||
|
`registering_attorneys_ids` text DEFAULT NULL,
|
||||||
|
`correspondence_who` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_attorney_id` int(11) DEFAULT NULL,
|
||||||
|
`correspondence_title` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_company_name` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`correspondence_postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_contact_preference` varchar(50) DEFAULT NULL,
|
||||||
|
`correspondence_phone` varchar(20) DEFAULT NULL,
|
||||||
|
`correspondence_email` varchar(255) DEFAULT NULL,
|
||||||
|
`payment_method` varchar(20) DEFAULT NULL,
|
||||||
|
`payment_phone` varchar(20) DEFAULT NULL,
|
||||||
|
`reduced_fee_eligibility` varchar(10) DEFAULT NULL,
|
||||||
|
`is_repeat_application` tinyint(1) DEFAULT 0,
|
||||||
|
`repeat_case_number` varchar(50) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `fk_user_id` (`user_id`),
|
||||||
|
CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `lpa_applications`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `lpa_applications` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `lpa_applications` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `lpa_applications` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `lpa_attorneys`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `lpa_attorneys`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `lpa_attorneys` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`lpa_id` int(11) NOT NULL,
|
||||||
|
`type` enum('primary','replacement') DEFAULT 'primary',
|
||||||
|
`title` varchar(20) DEFAULT NULL,
|
||||||
|
`first_name` varchar(255) NOT NULL,
|
||||||
|
`last_name` varchar(255) NOT NULL,
|
||||||
|
`email` varchar(255) NOT NULL,
|
||||||
|
`dob` date NOT NULL,
|
||||||
|
`address_line1` varchar(255) NOT NULL,
|
||||||
|
`address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`town` varchar(255) NOT NULL,
|
||||||
|
`postcode` varchar(20) NOT NULL,
|
||||||
|
`relationship` varchar(100) DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`witness_title` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_first_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_last_name` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`witness_postcode` varchar(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `lpa_id` (`lpa_id`),
|
||||||
|
CONSTRAINT `lpa_attorneys_ibfk_1` FOREIGN KEY (`lpa_id`) REFERENCES `lpa_applications` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `lpa_attorneys`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `lpa_attorneys` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `lpa_attorneys` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `lpa_attorneys` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `lpa_notified_persons`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `lpa_notified_persons`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `lpa_notified_persons` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`application_id` int(11) NOT NULL,
|
||||||
|
`title` varchar(20) DEFAULT NULL,
|
||||||
|
`first_name` varchar(100) DEFAULT NULL,
|
||||||
|
`last_name` varchar(100) DEFAULT NULL,
|
||||||
|
`address_line1` varchar(255) DEFAULT NULL,
|
||||||
|
`address_line2` varchar(255) DEFAULT NULL,
|
||||||
|
`address_line3` varchar(255) DEFAULT NULL,
|
||||||
|
`postcode` varchar(20) DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `lpa_notified_persons`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `lpa_notified_persons` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `lpa_notified_persons` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `lpa_notified_persons` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `migration_history`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `migration_history`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `migration_history` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`filename` varchar(255) NOT NULL,
|
||||||
|
`executed_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `filename` (`filename`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `migration_history`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `migration_history` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `migration_history` DISABLE KEYS */;
|
||||||
|
INSERT INTO `migration_history` VALUES
|
||||||
|
(1,'01_create_users_table.sql','2026-03-01 00:57:47'),
|
||||||
|
(2,'02_update_users_for_signup.sql','2026-03-01 00:57:47'),
|
||||||
|
(3,'03_add_reset_password_fields.sql','2026-03-01 00:57:47'),
|
||||||
|
(4,'04_add_role_column.sql','2026-03-01 00:57:47'),
|
||||||
|
(5,'05_add_user_id_to_lpa_applications.sql','2026-03-01 00:57:47'),
|
||||||
|
(6,'06_create_migration_history_table.sql','2026-03-01 00:57:47');
|
||||||
|
/*!40000 ALTER TABLE `migration_history` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `practices`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `practices`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `practices` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`slug` varchar(100) NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `slug` (`slug`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `practices`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `practices` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `practices` DISABLE KEYS */;
|
||||||
|
INSERT INTO `practices` VALUES
|
||||||
|
(1,'Elite Estate Planning','elite-estate','2026-02-28 17:36:29');
|
||||||
|
/*!40000 ALTER TABLE `practices` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `users`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) DEFAULT NULL,
|
||||||
|
`email` varchar(255) NOT NULL,
|
||||||
|
`password` varchar(255) NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`is_verified` tinyint(1) DEFAULT 0,
|
||||||
|
`verification_token` varchar(64) DEFAULT NULL,
|
||||||
|
`role` enum('Standard User','Super User') DEFAULT 'Standard User',
|
||||||
|
`reset_token` varchar(64) DEFAULT NULL,
|
||||||
|
`reset_expires_at` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `email` (`email`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `users` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `users` DISABLE KEYS */;
|
||||||
|
INSERT INTO `users` VALUES
|
||||||
|
(1,NULL,'test@example.com','$2y$10$xeVgbO3f09/R4FF0bEwqSeTH3bdNp1CcDLE6R27Slc6yNBHK8Cxq.','2026-02-28 23:23:36',1,NULL,'Standard User',NULL,NULL),
|
||||||
|
(3,'Admin','advice@estateguardians.co.uk','$2y$10$.vu3rXV4RHCa4JIs2GVa/OJvfe4c2dhLOgb60Uw0boPHRCVeDKtq6','2026-03-01 00:00:01',1,NULL,'Super User',NULL,NULL),
|
||||||
|
(4,'Neel Shah (Profitise)','neel@profitise.co','$2y$10$332.cCj/4WY6.1r6aPQe1ed4QBwl4AYODFtiEeHymgCrvVapiU956','2026-03-01 00:16:28',1,NULL,'Standard User',NULL,NULL),
|
||||||
|
(5,'Neel Shah','neel@neel.me.uk','$2y$10$6.jb/U/rjKYfXJSwzfdmquJBqjij.RDqlhYKmZNnELnNgyA635u0.','2026-03-01 00:36:13',1,NULL,'Standard User',NULL,NULL),
|
||||||
|
(6,'Cogent FS','cogentfs@gmail.com','$2y$10$g23tK9toSrpgqQKXF7902eK7P5Hg98VtYZd4lB4O1Vpi/XtY.KlEq','2026-03-01 00:39:16',1,NULL,'Standard User',NULL,NULL);
|
||||||
|
/*!40000 ALTER TABLE `users` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||||
|
|
||||||
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
|
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
|
-- Dump completed on 2026-03-01 1:03:59
|
||||||
@ -9,8 +9,15 @@ $project_name = $_SERVER['PROJECT_NAME'] ?? 'LPA Online';
|
|||||||
$user_id = $_SESSION["user_id"];
|
$user_id = $_SESSION["user_id"];
|
||||||
|
|
||||||
$lpas = [];
|
$lpas = [];
|
||||||
|
$user_credits = 0;
|
||||||
try {
|
try {
|
||||||
$stmt = db()->prepare("SELECT * FROM lpa_applications WHERE user_id = ? ORDER BY created_at DESC");
|
$db = db();
|
||||||
|
// Get user credits
|
||||||
|
$user_stmt = $db->prepare("SELECT credits FROM users WHERE id = ?");
|
||||||
|
$user_stmt->execute([$user_id]);
|
||||||
|
$user_credits = $user_stmt->fetchColumn() ?: 0;
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT * FROM lpa_applications WHERE user_id = ? ORDER BY created_at DESC");
|
||||||
$stmt->execute([$user_id]);
|
$stmt->execute([$user_id]);
|
||||||
$lpas = $stmt->fetchAll();
|
$lpas = $stmt->fetchAll();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
@ -49,13 +56,27 @@ try {
|
|||||||
<h1 class="h3 fw-bold mb-1">Your Applications</h1>
|
<h1 class="h3 fw-bold mb-1">Your Applications</h1>
|
||||||
<p class="text-muted small mb-0">Track and manage your Lasting Powers of Attorney progress.</p>
|
<p class="text-muted small mb-0">Track and manage your Lasting Powers of Attorney progress.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto d-flex align-items-center">
|
||||||
|
<div class="me-4 text-end">
|
||||||
|
<span class="text-muted small d-block mb-0 text-uppercase tracking-wider fw-bold">Available Credits</span>
|
||||||
|
<h4 class="fw-bold mb-0 text-primary"><?php echo (int)$user_credits; ?> <span class="text-muted h6 fw-normal">LPA<?php echo $user_credits != 1 ? 's' : ''; ?></span></h4>
|
||||||
|
</div>
|
||||||
<?php if (count($lpas) > 0): ?>
|
<?php if (count($lpas) > 0): ?>
|
||||||
<a href="/apply.php" class="btn btn-outline-primary px-4 rounded-pill">New Application</a>
|
<a href="/apply.php" class="btn btn-outline-primary px-4 rounded-pill">New Application</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if (isset($_GET['error']) && $_GET['error'] === 'no_credits'): ?>
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show border-0 shadow-sm mb-4" role="alert">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="me-2"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
|
||||||
|
<span><strong>Insufficient Credits:</strong> You do not have enough credits to start a new LPA application. Please contact your administrator to allocate more credits.</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (isset($_GET['completed_step'])): ?>
|
<?php if (isset($_GET['completed_step'])): ?>
|
||||||
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert">
|
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
|
|||||||
82
db/backup_helper.php
Normal file
82
db/backup_helper.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Database Backup Helper
|
||||||
|
*
|
||||||
|
* Provides functionality to back up the current database to the /backups directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function backup_db() {
|
||||||
|
// Determine path to backups directory (relative to db/config.php's folder)
|
||||||
|
$backups_dir = realpath(__DIR__ . '/../backups');
|
||||||
|
|
||||||
|
// Ensure the backups directory exists
|
||||||
|
if (!$backups_dir) {
|
||||||
|
$backups_dir = __DIR__ . '/../backups';
|
||||||
|
if (!is_dir($backups_dir)) {
|
||||||
|
if (!mkdir($backups_dir, 0775, true)) {
|
||||||
|
throw new Exception("Could not create backups directory: $backups_dir");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$backups_dir = realpath($backups_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load DB config if not already loaded (might be called from various places)
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
$timestamp = date('Y-m-d_H-i-s');
|
||||||
|
$filename = "backup_{$timestamp}.sql";
|
||||||
|
$filepath = "{$backups_dir}/{$filename}";
|
||||||
|
|
||||||
|
// Use mysqldump to create the backup
|
||||||
|
$command = sprintf(
|
||||||
|
'mysqldump --host=%s --user=%s --password=%s %s > %s 2>&1',
|
||||||
|
escapeshellarg(DB_HOST),
|
||||||
|
escapeshellarg(DB_USER),
|
||||||
|
escapeshellarg(DB_PASS),
|
||||||
|
escapeshellarg(DB_NAME),
|
||||||
|
escapeshellarg($filepath)
|
||||||
|
);
|
||||||
|
|
||||||
|
$output = [];
|
||||||
|
$return_var = null;
|
||||||
|
exec($command, $output, $return_var);
|
||||||
|
|
||||||
|
if ($return_var !== 0) {
|
||||||
|
$error_msg = implode("\n", $output);
|
||||||
|
throw new Exception("Database backup failed with exit code {$return_var}: " . $error_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatic cleanup: keep only the last 5 backups
|
||||||
|
cleanup_backups($backups_dir, 5);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'filename' => $filename,
|
||||||
|
'filepath' => $filepath,
|
||||||
|
'size' => filesize($filepath)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup old backups, keeping only the most recent $keep_count files.
|
||||||
|
*
|
||||||
|
* @param string $backups_dir Path to backups directory
|
||||||
|
* @param int $keep_count Number of backups to retain
|
||||||
|
*/
|
||||||
|
function cleanup_backups($backups_dir, $keep_count = 5) {
|
||||||
|
$files = glob("{$backups_dir}/backup_*.sql");
|
||||||
|
|
||||||
|
// Sort by modification time (newest first)
|
||||||
|
usort($files, function($a, $b) {
|
||||||
|
return filemtime($b) - filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove files beyond the keep count
|
||||||
|
if (count($files) > $keep_count) {
|
||||||
|
$files_to_remove = array_slice($files, $keep_count);
|
||||||
|
foreach ($files_to_remove as $file) {
|
||||||
|
if (is_file($file)) {
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
db/migrations/07_add_credits_to_users.sql
Normal file
2
db/migrations/07_add_credits_to_users.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-- Add credits column to users table
|
||||||
|
ALTER TABLE users ADD COLUMN credits INT DEFAULT 0;
|
||||||
Loading…
x
Reference in New Issue
Block a user