73 lines
2.1 KiB
TypeScript
73 lines
2.1 KiB
TypeScript
import { prisma } from "@/lib/prisma";
|
|
|
|
const HOUR_MS = 60 * 60 * 1000;
|
|
const DAY_MS = 24 * HOUR_MS;
|
|
|
|
export interface StaleSummary {
|
|
/** Payment MIDTRANS status AWAITING > 25 jam (lewat expiresAt) — webhook gagal? */
|
|
stalePaymentsCount: number;
|
|
/** Booking AWAITING_PAY tapi trip sudah lewat hari ini — peserta lupa bayar. */
|
|
awaitingPayPastDepartureCount: number;
|
|
/** Payout HELD tapi heldUntil sudah lebih 1 hari lewat — cron release tidak jalan? */
|
|
overduePayoutsCount: number;
|
|
/** Refund APPROVED > 7 hari belum di-process — admin lupa? */
|
|
stuckRefundsCount: number;
|
|
}
|
|
|
|
/**
|
|
* Deteksi entity yang nyangkut di state non-final terlalu lama. Dipanggil dari
|
|
* `/admin/system` page on-demand (bukan cron) supaya selalu show realtime.
|
|
*
|
|
* Threshold draft — review setelah jalan 1-2 minggu (false positive vs miss).
|
|
*/
|
|
export const systemHealthService = {
|
|
async detectStale(): Promise<StaleSummary> {
|
|
const now = new Date();
|
|
const twentyFiveHoursAgo = new Date(now.getTime() - 25 * HOUR_MS);
|
|
const oneDayAgo = new Date(now.getTime() - DAY_MS);
|
|
const sevenDaysAgo = new Date(now.getTime() - 7 * DAY_MS);
|
|
const todayStart = new Date(now);
|
|
todayStart.setUTCHours(0, 0, 0, 0);
|
|
|
|
const [
|
|
stalePayments,
|
|
awaitingPayPast,
|
|
overduePayouts,
|
|
stuckRefunds,
|
|
] = await Promise.all([
|
|
prisma.payment.count({
|
|
where: {
|
|
provider: "MIDTRANS",
|
|
status: "AWAITING",
|
|
createdAt: { lte: twentyFiveHoursAgo },
|
|
},
|
|
}),
|
|
prisma.booking.count({
|
|
where: {
|
|
status: "AWAITING_PAY",
|
|
trip: { date: { lt: todayStart } },
|
|
},
|
|
}),
|
|
prisma.payout.count({
|
|
where: {
|
|
status: "HELD",
|
|
heldUntil: { lte: oneDayAgo },
|
|
},
|
|
}),
|
|
prisma.refund.count({
|
|
where: {
|
|
status: "APPROVED",
|
|
reviewedAt: { lte: sevenDaysAgo },
|
|
},
|
|
}),
|
|
]);
|
|
|
|
return {
|
|
stalePaymentsCount: stalePayments,
|
|
awaitingPayPastDepartureCount: awaitingPayPast,
|
|
overduePayoutsCount: overduePayouts,
|
|
stuckRefundsCount: stuckRefunds,
|
|
};
|
|
},
|
|
};
|