142 lines · 5.6 KB
Raw Download
1
<?php
2
require_once __DIR__ . '/inc/layout.php';
3
require_once __DIR__ . '/inc/report.php';
4
5
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
6
header('Pragma: no-cache');
7
header('Expires: 0');
8
9
require_login();
10
11
$error = '';
12
13
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
14
    check_csrf();
15
    $action = (string)($_POST['action'] ?? '');
16
17
    if ($action === 'email') {
18
        $to    = trim((string)($_POST['report_email'] ?? ''));
19
        $daily = isset($_POST['report_daily']);
20
        $hour  = max(0, min(23, (int)($_POST['report_hour'] ?? 7)));
21
        $send  = ($_POST['do'] ?? '') === 'send';
22
23
        if ($to !== '' && !filter_var($to, FILTER_VALIDATE_EMAIL)) {
24
            $error = 'That email address does not look valid.';
25
        } elseif (($daily || $send) && $to === '') {
26
            $error = 'Enter an email address first.';
27
        } else {
28
            setting_set('report_email', $to);
29
            setting_set('report_daily', $daily ? '1' : '0');
30
            setting_set('report_hour', (string)$hour);
31
            if ($send) {
32
                $ok = send_report_email($to, $err);
33
                setting_set('report_last_status', ($ok ? "Sent to $to" : 'FAILED: ' . $err) . ' — ' . date('Y-m-d H:i'));
34
                flash($ok ? "Report sent to $to." : "Sending failed: $err");
35
            } else {
36
                flash('Report settings saved.');
37
            }
38
            header('Location: report.php');
39
            exit;
40
        }
41
    }
42
43
    if ($action === 'import') {
44
        $f = $_FILES['csv'] ?? null;
45
        if (!$f || $f['error'] === UPLOAD_ERR_NO_FILE) {
46
            $error = 'Choose a CSV file first.';
47
        } elseif ($f['error'] !== UPLOAD_ERR_OK) {
48
            $error = 'Upload failed (error ' . (int)$f['error'] . ') — the file may exceed the server upload limit.';
49
        } elseif (!is_uploaded_file($f['tmp_name'])) {
50
            $error = 'Upload failed.';
51
        } else {
52
            try {
53
                [$ins, $upd, $skip] = import_csv($f['tmp_name'], isset($_POST['update_existing']));
54
                $msg = "Imported $ins new spool" . ($ins === 1 ? '' : 's');
55
                if ($upd) {
56
                    $msg .= ", updated $upd";
57
                }
58
                if ($skip) {
59
                    $msg .= ", skipped $skip row" . ($skip === 1 ? '' : 's') . ' (missing type or bad weights)';
60
                }
61
                flash($msg . '.');
62
                header('Location: index.php?sort=added');
63
                exit;
64
            } catch (RuntimeException $ex) {
65
                $error = $ex->getMessage();
66
            }
67
        }
68
    }
69
}
70
71
$to    = (string)($_POST['report_email'] ?? setting_get('report_email', ''));
72
$daily = $_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'email'
73
       ? isset($_POST['report_daily'])
74
       : setting_get('report_daily') === '1';
75
$hour  = max(0, min(23, (int)($_POST['report_hour'] ?? setting_get('report_hour', '7'))));
76
$status = setting_get('report_last_status');
77
78
$scheme  = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
79
$base    = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])), '/');
80
$cronUrl = $scheme . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost') . $base . '/cron.php?token=' . cron_token();
81
82
page_header('Report & CSV');
83
?>
84
<h1>Email report</h1>
85
<?php if ($error): ?>
86
<p class="error"><?= e($error) ?></p>
87
<?php endif; ?>
88
<form method="post">
89
  <?= csrf_field() ?>
90
  <input type="hidden" name="action" value="email">
91
92
  <label for="report_email">Send the report to</label>
93
  <input type="email" id="report_email" name="report_email" value="<?= e($to) ?>" placeholder="you@example.com" autocomplete="email">
94
95
  <label class="check"><input type="checkbox" name="report_daily" <?= $daily ? 'checked' : '' ?>> Email the report every morning</label>
96
97
  <label for="report_hour">Morning send time (server time)</label>
98
  <select id="report_hour" name="report_hour">
99
    <?php for ($h = 0; $h < 24; $h++): ?>
100
    <option value="<?= $h ?>" <?= $h === $hour ? 'selected' : '' ?>><?= $h ?>:00</option>
101
    <?php endfor; ?>
102
  </select>
103
104
  <div class="actions">
105
    <button name="do" value="save">Save settings</button>
106
    <button name="do" value="send" class="secondary">Save &amp; send now</button>
107
  </div>
108
  <?php if ($status): ?>
109
  <p class="muted">Last report: <?= e($status) ?></p>
110
  <?php endif; ?>
111
  <p class="muted">The report lists every spool (lowest first) with the full inventory attached as CSV.
112
    The morning email goes out on the first visit to the site after the chosen hour; for delivery at
113
    exactly that time, point a cron job or uptime monitor at:<br>
114
    <code style="overflow-wrap:anywhere"><?= e($cronUrl) ?></code></p>
115
</form>
116
117
<h1>CSV export</h1>
118
<p class="muted">Download the whole inventory as a spreadsheet-friendly CSV — also handy as a backup.</p>
119
<div class="actions">
120
  <a class="btn" href="export.php">Download CSV</a>
121
</div>
122
123
<h1>CSV import</h1>
124
<form method="post" enctype="multipart/form-data">
125
  <?= csrf_field() ?>
126
  <input type="hidden" name="action" value="import">
127
128
  <label for="csvFile">CSV file</label>
129
  <input type="file" id="csvFile" name="csv" accept=".csv,text/csv,text/plain" required>
130
131
  <label class="check"><input type="checkbox" name="update_existing" checked> Update existing spools when a row's id matches (untick to add everything as new)</label>
132
133
  <div class="actions">
134
    <button>Import CSV</button>
135
  </div>
136
  <p class="muted">The first row must be a header row. Files from the export above round-trip as-is;
137
    at minimum a <strong>type</strong> column is required — weights that are missing are assumed
138
    to be full spools. A database backup is taken before every import.</p>
139
</form>
140
<?php
141
page_footer();
142