← back to Costa Rica
routes/build.js
61 lines
'use strict';
// Build / ops dashboard API — behind the basic-auth gate. One aggregate status
// endpoint for the whole build: integration live-state, data pipeline, go-live
// checklist, recent ingest runs + commits.
const express = require('express');
const { execSync } = require('child_process');
const path = require('path');
const { pool } = require('../lib/db');
const router = express.Router();
const liveState = () => ({
payment: { provider: require('../lib/payments').getProvider().name, live: require('../lib/payments').getProvider().liveMode },
whatsapp: { live: require('../lib/whatsapp').liveMode },
plaid: { live: require('../lib/plaid').liveMode, env: require('../lib/plaid').ENV },
apple: { configured: true }, // verifier always available; needs App ID capability at build
});
router.get('/status', async (_req, res) => {
const data = {};
try {
const { rows: [d] } = await pool.query(`
SELECT (SELECT count(*) FROM places) places,
(SELECT count(*) FROM places WHERE lat IS NOT NULL) geo,
(SELECT count(*) FROM places WHERE hacienda_enriched_at IS NOT NULL) hacienda,
(SELECT count(*) FROM places WHERE cedula_juridica IS NOT NULL AND hacienda_enriched_at IS NULL) hacienda_pending,
(SELECT count(*) FROM places WHERE hacienda_situacion='Inscrito') active_biz,
(SELECT count(*) FROM place_booking WHERE is_active) bookable,
(SELECT count(*) FROM bookings) bookings,
(SELECT COALESCE(SUM(platform_fee),0) FROM bookings WHERE status IN ('confirmed','completed')) revenue_minor,
(SELECT count(*) FROM app_users) users,
(SELECT count(*) FROM hosts) hosts`);
Object.assign(data, d);
} catch (e) { data.error = e.message; }
let bySource = [], runs = [], commits = [];
try { ({ rows: bySource } = await pool.query(`SELECT source, count(*) FROM places GROUP BY source ORDER BY 2 DESC LIMIT 12`)); } catch {}
try { ({ rows: runs } = await pool.query(`SELECT source, status, rows_in, rows_added, started_at, finished_at FROM ingest_runs ORDER BY id DESC LIMIT 8`)); } catch {}
try {
commits = execSync('git log --oneline -8 --format="%h|%s|%cr"', { cwd: path.join(__dirname, '..') })
.toString().trim().split('\n').map(l => { const [h, s, w] = l.split('|'); return { hash: h, subject: s, when: w }; });
} catch {}
const checklist = [
{ id: 'schema', label: 'Marketplace schema (migration 004/005)', done: true },
{ id: 'payments', label: 'Payment layer (Tilopay/ONVO, sandbox)', done: true },
{ id: 'whatsapp', label: 'WhatsApp client + webhook (sandbox)', done: true },
{ id: 'apple', label: 'Sign in with Apple (backend + app)', done: true },
{ id: 'app', label: 'Expo native app scaffold', done: true },
{ id: 'admin', label: 'Admin dashboard', done: true },
{ id: 'gate_wa', label: '🔴 GATED: Meta WABA number + token (Steve)', done: false },
{ id: 'gate_tilopay', label: '🔴 GATED: Tilopay merchant keys (Steve)', done: false },
{ id: 'gate_plaid', label: '🔴 GATED: Plaid production keys (Steve)', done: false },
{ id: 'gate_eas', label: '🔴 GATED: eas login → build/submit (Steve)', done: false },
{ id: 'gate_deploy', label: '🔴 GATED: Kamatera deploy + DNS (Steve)', done: false },
];
res.json({ ok: true, live: liveState(), data, bySource, runs, commits, checklist, ts: new Date().toISOString() });
});
module.exports = router;