From 5c58953820513ed832012c24a3125353c9b3c9e3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:12:07 +0700 Subject: [PATCH] feat: add payment stats by month --- src/controllers/00-stats-controller.ts | 53 ++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/controllers/00-stats-controller.ts b/src/controllers/00-stats-controller.ts index 92193fe..6db8ca4 100644 --- a/src/controllers/00-stats-controller.ts +++ b/src/controllers/00-stats-controller.ts @@ -13,6 +13,7 @@ import { createPermCondition } from "../services/permission"; import { RequestWithUser } from "../interfaces/user"; import { PaymentStatus } from "../generated/kysely/types"; import { precisionRound } from "../utils/arithmetic"; +import dayjs from "dayjs"; const permissionCondCompany = createPermCondition((_) => true); @@ -411,4 +412,56 @@ export class StatsController extends Controller { { income: 0, expenses: 0, netProfit: 0 }, ); } + + @Get("payment") + async invoice( + @Request() req: RequestWithUser, + @Query() startDate?: Date, + @Query() endDate?: Date, + ) { + if (!startDate && !endDate) { + startDate = dayjs(new Date()).subtract(12, "months").startOf("month").toDate(); + endDate = dayjs(new Date()).endOf("months").toDate(); + } + + if (!startDate && endDate) { + startDate = dayjs(endDate).subtract(12, "months").startOf("month").toDate(); + } + + if (startDate && !endDate) { + endDate = dayjs(new Date()).endOf("month").toDate(); + } + + const data = await prisma.$transaction(async (tx) => { + const months: Date[] = []; + + while (startDate! < endDate!) { + months.push(startDate!); + startDate = dayjs(startDate).startOf("month").add(1, "month").toDate(); + } + + return await Promise.all( + months.map(async (v) => { + const date = dayjs(v); + return { + month: date.format("MM"), + year: date.format("YYYY"), + data: await tx.payment + .groupBy({ + _sum: { amount: true }, + where: { createdAt: { gte: v, lte: date.endOf("month").toDate() } }, + by: "paymentStatus", + }) + .then((v) => + v.reduce>>((a, c) => { + a[c.paymentStatus] = c._sum.amount || 0; + return a; + }, {}), + ), + }; + }), + ); + }); + return data; + } }