Repository navigation
Expand file tree
/
Copy pathreconcile_fix.php
More file actions
76 lines (63 loc) · 2.62 KB
/
Copy pathreconcile_fix.php
File metadata and controls
76 lines (63 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
/**
* Reconciliation "Auto-Fix" (posted from monthly_balances.php).
*
* Recorded bank balances (BalanceHelper) are the truth. When they differ from
* opening + income - expenses for a month, this records a balancing Income or
* Expense entry dated at month end. The entry does NOT move any bank balance
* (balance_bank_id stays NULL), it only explains the gap.
*/
require_once __DIR__ . '/autoload.php';
use App\Core\Bootstrap;
use App\Helpers\SecurityHelper;
use App\Helpers\AuditHelper;
use App\Helpers\Flash;
Bootstrap::init();
$back = BASE_URL . 'monthly_balances.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header("Location: $back");
exit();
}
SecurityHelper::verifyCsrfToken($_POST['csrf_token'] ?? '');
if (($_SESSION['permission'] ?? 'edit') === 'read_only') {
Flash::redirect($back, 'error', 'Unauthorized: Read-only access');
}
$tenant_id = (int) $_SESSION['tenant_id'];
$user_id = (int) $_SESSION['user_id'];
$action = $_POST['action'] ?? '';
$dateRaw = $_POST['date'] ?? '';
$dt = DateTime::createFromFormat('!Y-m-d', $dateRaw);
if (!$dt || $dt->format('Y-m-d') !== $dateRaw) {
Flash::redirect($back, 'error', 'Invalid date');
}
$date = $dateRaw;
$back .= '?month=' . (int) $dt->format('n') . '&year=' . (int) $dt->format('Y');
$diffRaw = $_POST['difference'] ?? '';
if (!is_numeric($diffRaw) || !is_finite((float) $diffRaw) || abs((float) $diffRaw) >= 1e12) {
Flash::redirect($back, 'error', 'Invalid difference');
}
$diff = round((float) $diffRaw, 2);
if ($action !== 'auto_fix') {
Flash::redirect($back, 'error', 'Unknown action');
}
if (abs($diff) < 0.01) {
header("Location: $back");
exit();
}
$desc = 'Reconciliation Adjustment (' . $dt->format('F Y') . ')';
try {
if ($diff > 0) {
// Surplus -> Income
$stmt = $pdo->prepare("INSERT INTO income (user_id, tenant_id, amount, description, category, income_date, currency) VALUES (?, ?, ?, ?, 'Adjustment', ?, 'AED')");
$stmt->execute([$user_id, $tenant_id, $diff, $desc, $date]);
} else {
// Missing -> Expense
$stmt = $pdo->prepare("INSERT INTO expenses (user_id, tenant_id, spent_by_user_id, amount, description, category, payment_method, expense_date, currency) VALUES (?, ?, ?, ?, ?, 'Adjustment', 'Cash', ?, 'AED')");
$stmt->execute([$user_id, $tenant_id, $user_id, abs($diff), $desc, $date]);
}
AuditHelper::log($pdo, 'reconcile_auto_fix', "$desc: $diff AED");
} catch (PDOException $e) {
error_log("Reconcile Fix Error: " . $e->getMessage());
Flash::redirect($back, 'error', 'Failed to record the adjustment.');
}
Flash::redirect($back, 'success', 'Adjustment recorded');