Remove pull integration; persist push log to DB (last 50 per hotel)
- Remove TravelLine/netup-pms pull route (travelline.ts unused) - Remove pull integration section from TvWelcomePage (token field, API URL, etc.) - Migration 008: netup_push_log table (hotel_id, action, status, request/response body) - recordPush() now writes to DB in addition to in-memory buffer - getLog reads from DB so logs survive server restarts - clearLog deletes from DB - Limit enforced: 50 rows per hotel (oldest auto-deleted) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,6 @@ import housekeepingRoutes from './routes/housekeeping'
|
||||
import channelsRoutes from './routes/channels'
|
||||
import usersRoutes from './routes/users'
|
||||
import netupRoutes from './routes/netup'
|
||||
import travellineRoutes from './routes/travelline'
|
||||
|
||||
export async function buildApp() {
|
||||
const fastify = Fastify({
|
||||
@@ -74,7 +73,6 @@ export async function buildApp() {
|
||||
await fastify.register(channelsRoutes)
|
||||
await fastify.register(usersRoutes)
|
||||
await fastify.register(netupRoutes)
|
||||
await fastify.register(travellineRoutes)
|
||||
|
||||
return fastify
|
||||
}
|
||||
|
||||
@@ -1,30 +1,47 @@
|
||||
import type { FastifyPluginAsync } from 'fastify'
|
||||
import { db } from '../db'
|
||||
import { captured } from './travelline'
|
||||
|
||||
type SlugParam = { Params: { slug: string } }
|
||||
type SlugIdParam = { Params: { slug: string; id: string } }
|
||||
|
||||
// ── Push event log (check-in / check-out calls to NetUP) ─────────────────────
|
||||
export type PushEvent = {
|
||||
ts: string
|
||||
action: 'check-in' | 'check-out' | 'message'
|
||||
hotelId: string
|
||||
roomNumber: string // PMS room number
|
||||
netupRoom: string // NetUP room number
|
||||
url: string
|
||||
requestBody?: unknown // what we sent
|
||||
status: 'ok' | 'error' | 'skipped'
|
||||
httpStatus?: number
|
||||
responseBody?: string // what NetUP replied
|
||||
error?: string
|
||||
ts: string
|
||||
action: 'check-in' | 'check-out' | 'message'
|
||||
hotelId: string
|
||||
roomNumber: string
|
||||
netupRoom: string
|
||||
url: string
|
||||
requestBody?: unknown
|
||||
status: 'ok' | 'error' | 'skipped'
|
||||
httpStatus?: number
|
||||
responseBody?: string
|
||||
error?: string
|
||||
}
|
||||
const MAX_PUSH = 100
|
||||
// In-memory fallback (used before DB write completes; also keeps last 50)
|
||||
export const pushLog: PushEvent[] = []
|
||||
|
||||
function recordPush(e: PushEvent) {
|
||||
pushLog.push(e)
|
||||
if (pushLog.length > MAX_PUSH) pushLog.shift()
|
||||
if (pushLog.length > 50) pushLog.shift()
|
||||
|
||||
// Persist to DB (fire-and-forget); also enforce 50-row limit per hotel
|
||||
db.query(
|
||||
`INSERT INTO netup_push_log
|
||||
(hotel_id, ts, action, room_number, netup_room, url, request_body, status, http_status, response_body, error)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`,
|
||||
[e.hotelId, e.ts, e.action, e.roomNumber, e.netupRoom, e.url,
|
||||
e.requestBody ? JSON.stringify(e.requestBody) : null,
|
||||
e.status, e.httpStatus ?? null, e.responseBody ?? null, e.error ?? null],
|
||||
).then(() =>
|
||||
// Keep only last 50 rows per hotel
|
||||
db.query(
|
||||
`DELETE FROM netup_push_log WHERE hotel_id = $1 AND id NOT IN (
|
||||
SELECT id FROM netup_push_log WHERE hotel_id = $1 ORDER BY ts DESC LIMIT 50
|
||||
)`,
|
||||
[e.hotelId],
|
||||
)
|
||||
).catch(() => { /* best-effort */ })
|
||||
}
|
||||
|
||||
const netup: FastifyPluginAsync = async (fastify) => {
|
||||
@@ -270,13 +287,25 @@ const netup: FastifyPluginAsync = async (fastify) => {
|
||||
return reply.code(403).send({ error: 'Forbidden' })
|
||||
}
|
||||
const hotelId = await getHotelId(slug)
|
||||
// Push events filtered to this hotel
|
||||
const pushEvents = [...pushLog]
|
||||
.filter(e => e.hotelId === hotelId)
|
||||
.reverse()
|
||||
// Pull requests (from NetUP TravelLine polls) — all, no hotel filter possible
|
||||
const pullRequests = [...captured].reverse()
|
||||
return { pushEvents, pullRequests }
|
||||
const { rows } = await db.query(
|
||||
`SELECT ts, action, room_number, netup_room, url, request_body,
|
||||
status, http_status, response_body, error
|
||||
FROM netup_push_log WHERE hotel_id = $1 ORDER BY ts DESC LIMIT 50`,
|
||||
[hotelId],
|
||||
)
|
||||
const pushEvents = rows.map((r: Record<string, unknown>) => ({
|
||||
ts: (r.ts as Date).toISOString(),
|
||||
action: r.action,
|
||||
roomNumber: r.room_number,
|
||||
netupRoom: r.netup_room,
|
||||
url: r.url,
|
||||
requestBody: r.request_body,
|
||||
status: r.status,
|
||||
httpStatus: r.http_status,
|
||||
responseBody: r.response_body,
|
||||
error: r.error,
|
||||
}))
|
||||
return { pushEvents, pullRequests: [] }
|
||||
},
|
||||
)
|
||||
|
||||
@@ -289,7 +318,8 @@ const netup: FastifyPluginAsync = async (fastify) => {
|
||||
if (!canAccess(request.user.hotelSlug, request.user.role, slug)) {
|
||||
return reply.code(403).send({ error: 'Forbidden' })
|
||||
}
|
||||
captured.length = 0
|
||||
const hotelId2 = await getHotelId(slug)
|
||||
if (hotelId2) await db.query('DELETE FROM netup_push_log WHERE hotel_id = $1', [hotelId2])
|
||||
pushLog.length = 0
|
||||
return { ok: true }
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user