feat(stats): enhance admin and user statistics with additional metrics for revenue and user count

This commit is contained in:
2026-03-10 23:37:49 +08:00
parent 56bfdb4614
commit 984274bfb7
3 changed files with 318 additions and 84 deletions

View File

@@ -1,7 +1,7 @@
import { Hono } from "hono";
import { eq, isNull, sql } from "drizzle-orm";
import { useDrizzle } from "@/lib/db.js";
import { chargePoint, transaction, idTag } from "@/db/schema.js";
import { chargePoint, transaction, idTag, user } from "@/db/schema.js";
import type { HonoEnv } from "@/types/hono.ts";
const app = new Hono<HonoEnv>();
@@ -12,25 +12,42 @@ app.get("/", async (c) => {
const isAdmin = currentUser?.role === "admin";
if (isAdmin) {
const [totalChargePoints, onlineChargePoints, activeTransactions, totalIdTags, todayEnergy] =
await Promise.all([
db.select({ count: sql<number>`count(*)::int` }).from(chargePoint),
db
.select({ count: sql<number>`count(*)::int` })
.from(chargePoint)
.where(sql`${chargePoint.lastHeartbeatAt} > now() - interval '120 seconds'`),
db
.select({ count: sql<number>`count(*)::int` })
.from(transaction)
.where(isNull(transaction.stopTimestamp)),
db.select({ count: sql<number>`count(*)::int` }).from(idTag),
db
.select({
total: sql<number>`coalesce(sum(${transaction.stopMeterValue} - ${transaction.startMeterValue}), 0)::int`,
})
.from(transaction)
.where(sql`${transaction.stopTimestamp} >= date_trunc('day', now())`),
]);
const [
totalChargePoints,
onlineChargePoints,
activeTransactions,
totalIdTags,
todayEnergy,
todayRevenue,
totalUsers,
todayTransactions,
] = await Promise.all([
db.select({ count: sql<number>`count(*)::int` }).from(chargePoint),
db
.select({ count: sql<number>`count(*)::int` })
.from(chargePoint)
.where(sql`${chargePoint.lastHeartbeatAt} > now() - interval '120 seconds'`),
db
.select({ count: sql<number>`count(*)::int` })
.from(transaction)
.where(isNull(transaction.stopTimestamp)),
db.select({ count: sql<number>`count(*)::int` }).from(idTag),
db
.select({
total: sql<number>`coalesce(sum(${transaction.stopMeterValue} - ${transaction.startMeterValue}), 0)::int`,
})
.from(transaction)
.where(sql`${transaction.stopTimestamp} >= date_trunc('day', now())`),
db
.select({ total: sql<number>`coalesce(sum(${transaction.chargeAmount}), 0)::int` })
.from(transaction)
.where(sql`${transaction.stopTimestamp} >= date_trunc('day', now())`),
db.select({ count: sql<number>`count(*)::int` }).from(user),
db
.select({ count: sql<number>`count(*)::int` })
.from(transaction)
.where(sql`${transaction.stopTimestamp} >= date_trunc('day', now())`),
]);
return c.json({
totalChargePoints: totalChargePoints[0].count,
@@ -38,6 +55,9 @@ app.get("/", async (c) => {
activeTransactions: activeTransactions[0].count,
totalIdTags: totalIdTags[0].count,
todayEnergyWh: todayEnergy[0].total,
todayRevenue: todayRevenue[0].total,
totalUsers: totalUsers[0].count,
todayTransactions: todayTransactions[0].count,
});
}
@@ -46,7 +66,7 @@ app.get("/", async (c) => {
const userId = currentUser.id;
const [userIdTags, totalBalance, activeCount, totalTxCount] = await Promise.all([
const [userIdTags, totalBalance, activeCount, totalTxCount, todayEnergy, todayTxCount] = await Promise.all([
// Cards belonging to this user
db
.select({ count: sql<number>`count(*)::int` })
@@ -69,6 +89,24 @@ app.get("/", async (c) => {
.from(transaction)
.innerJoin(idTag, eq(transaction.idTag, idTag.idTag))
.where(eq(idTag.userId, userId)),
// Today's energy for user's cards
db
.select({
total: sql<number>`coalesce(sum(${transaction.stopMeterValue} - ${transaction.startMeterValue}), 0)::int`,
})
.from(transaction)
.innerJoin(idTag, eq(transaction.idTag, idTag.idTag))
.where(
sql`${transaction.stopTimestamp} >= date_trunc('day', now()) and ${idTag.userId} = ${userId}`,
),
// Today's completed transactions for user's cards
db
.select({ count: sql<number>`count(*)::int` })
.from(transaction)
.innerJoin(idTag, eq(transaction.idTag, idTag.idTag))
.where(
sql`${transaction.stopTimestamp} >= date_trunc('day', now()) and ${idTag.userId} = ${userId}`,
),
]);
return c.json({
@@ -76,6 +114,8 @@ app.get("/", async (c) => {
totalBalance: totalBalance[0].total,
activeTransactions: activeCount[0].count,
totalTransactions: totalTxCount[0].count,
todayEnergyWh: todayEnergy[0].total,
todayTransactions: todayTxCount[0].count,
});
});