All files / apps/web/src/handlers/currency top.ts

100% Statements 12/12
100% Branches 2/2
100% Functions 5/5
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90                6x                                     4x     4x   2x               2x                     2x   2x                   2x             2x         2x         2x 3x                
import { z } from "zod";
 
import {
	getOwnReceipts,
	getParticipantsReceipts,
} from "~web/handlers/receipts/utils";
import { authProcedure } from "~web/handlers/trpc";
 
export const procedure = authProcedure
	.meta({
		title: "Get top currencies",
		description:
			"Returns the currencies used most in the last month across the  user's receipts or debts, ordered by usage count.",
	})
	.input(
		z.strictObject({
			options: z.discriminatedUnion("type", [
				z.strictObject({
					type: z.literal("receipts"),
				}),
				z.strictObject({
					type: z.literal("debts"),
				}),
			]),
		}),
	)
	.query(async ({ input, ctx }) => {
		const minimalTimestamp = Temporal.Now.plainDateISO().subtract({
			months: 1,
		});
		switch (input.options.type) {
			case "debts":
				return {
					items: await ctx.database
						.selectFrom("debts")
						.select([
							"currencyCode",
							ctx.database.fn.count<number>("id").as("count"),
						])
						.where((eb) =>
							eb("timestamp", ">", minimalTimestamp).and(
								"debts.ownerUserId",
								"=",
								ctx.auth.userId,
							),
						)
						.groupBy("currencyCode")
						.orderBy("count", "desc")
						.execute(),
				};
			case "receipts": {
				const topCurrenciesResult = await ctx.database
					.with("mergedReceipts", () => {
						const participantReceipts = getParticipantsReceipts(
							ctx.database,
							ctx.auth.userId,
						)
							.select([
								"receipts.currencyCode",
								ctx.database.fn.count<number>("receipts.id").as("count"),
							])
							.where("issued", ">", minimalTimestamp)
							.groupBy("receipts.currencyCode");
						const ownerReceipts = getOwnReceipts(ctx.database, ctx.auth.userId)
							.select([
								"receipts.currencyCode",
								ctx.database.fn.count<number>("receipts.id").as("count"),
							])
							.where("issued", ">", minimalTimestamp)
							.groupBy("receipts.currencyCode");
						return participantReceipts.unionAll(ownerReceipts);
					})
					.selectFrom("mergedReceipts")
					.select([
						"currencyCode",
						(eb) => eb.fn.sum<string>("count").as("count"),
					])
					.groupBy("currencyCode")
					.orderBy("count", "desc")
					.execute();
				return {
					items: topCurrenciesResult.map(({ currencyCode, count }) => ({
						currencyCode,
						count: Number(count),
					})),
				};
			}
		}
	});