- Public page at /request for users to submit top-up requests (email + OMG job number, no auth required) - Admin "Requests" view with pending/processed/all filters - Approve with preset amounts (5M/10M/20M) or reject - Pending count badge in sidebar nav - Request data stored in JSON file (data/requests.json) - Data volume mounted for persistence across rebuilds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
72 lines
1.7 KiB
JavaScript
72 lines
1.7 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const DATA_FILE = path.join(__dirname, '..', 'data', 'requests.json');
|
|
|
|
function ensureDataDir() {
|
|
const dir = path.dirname(DATA_FILE);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
if (!fs.existsSync(DATA_FILE)) {
|
|
fs.writeFileSync(DATA_FILE, JSON.stringify([], null, 2));
|
|
}
|
|
}
|
|
|
|
function readAll() {
|
|
ensureDataDir();
|
|
const raw = fs.readFileSync(DATA_FILE, 'utf8');
|
|
return JSON.parse(raw);
|
|
}
|
|
|
|
function writeAll(data) {
|
|
ensureDataDir();
|
|
fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2));
|
|
}
|
|
|
|
function createRequest(email, omgJobNumber) {
|
|
const requests = readAll();
|
|
const request = {
|
|
id: Date.now().toString(36) + Math.random().toString(36).slice(2, 7),
|
|
email: email.trim().toLowerCase(),
|
|
omgJobNumber: omgJobNumber.trim(),
|
|
status: 'pending',
|
|
amountApproved: null,
|
|
createdAt: new Date().toISOString(),
|
|
processedAt: null,
|
|
};
|
|
requests.push(request);
|
|
writeAll(requests);
|
|
return request;
|
|
}
|
|
|
|
function getPending() {
|
|
return readAll().filter(r => r.status === 'pending');
|
|
}
|
|
|
|
function getProcessed() {
|
|
return readAll().filter(r => r.status !== 'pending');
|
|
}
|
|
|
|
function getAll() {
|
|
return readAll();
|
|
}
|
|
|
|
function updateRequest(id, status, amountApproved) {
|
|
const requests = readAll();
|
|
const idx = requests.findIndex(r => r.id === id);
|
|
if (idx === -1) return null;
|
|
requests[idx].status = status;
|
|
requests[idx].amountApproved = amountApproved || null;
|
|
requests[idx].processedAt = new Date().toISOString();
|
|
writeAll(requests);
|
|
return requests[idx];
|
|
}
|
|
|
|
module.exports = {
|
|
createRequest,
|
|
getPending,
|
|
getProcessed,
|
|
getAll,
|
|
updateRequest,
|
|
};
|