All files / apps/web/src/handlers/debt-intentions get-all.ts

100% Statements 12/12
100% Branches 4/4
100% Functions 9/9
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109            6x             2x 2x     2x             2x         2x     2x         2x         2x                                                   2x                                   2x 2x                                          
import type { Selectable } from "kysely";
 
import type { DB } from "~db/types.gen";
import type { MappedNullableObject } from "~utils/types";
import { authProcedure } from "~web/handlers/trpc";
 
export const procedure = authProcedure
	.meta({
		title: "Get all debt intentions",
		description:
			"Returns inbound debts from connected peers that are new or differ from the current  user's mirrored debt.",
	})
	.query(async ({ ctx }) => {
		const { database } = ctx;
		const debts = await database
			.selectFrom("peers")
			.where((eb) =>
				eb("peers.connectedUserId", "=", ctx.auth.userId).and(
					"peers.ownerUserId",
					"<>",
					ctx.auth.userId,
				),
			)
			.innerJoin("peers as reciprocalPeers", (qb) =>
				qb
					.onRef("reciprocalPeers.ownerUserId", "=", "peers.connectedUserId")
					.onRef("reciprocalPeers.connectedUserId", "=", "peers.ownerUserId"),
			)
			.innerJoin("debts as theirDebts", (qb) =>
				qb.onRef("theirDebts.peerId", "=", "peers.id"),
			)
			.leftJoin("debts as selfDebts", (qb) =>
				qb
					.onRef("theirDebts.id", "=", "selfDebts.id")
					.onRef("selfDebts.ownerUserId", "=", "peers.connectedUserId"),
			)
			.innerJoin("peers as peersMine", (qb) =>
				qb
					.onRef("peersMine.connectedUserId", "=", "theirDebts.ownerUserId")
					.onRef("peersMine.ownerUserId", "=", "peers.connectedUserId"),
			)
			.where((eb) =>
				eb.or([
					eb("selfDebts.id", "is", null),
					eb
						.or([
							eb("selfDebts.amount", "<>", eb.neg(eb.ref("theirDebts.amount"))),
							eb(
								"selfDebts.currencyCode",
								"<>",
								eb.ref("theirDebts.currencyCode"),
							),
							eb("selfDebts.timestamp", "<>", eb.ref("theirDebts.timestamp")),
						])
						.and(
							eb("selfDebts.updatedAt", "<", eb.ref("theirDebts.updatedAt")),
						),
				]),
			)
			.select([
				"theirDebts.id",
				"theirDebts.ownerUserId",
				"theirDebts.timestamp",
				"theirDebts.updatedAt",
				"theirDebts.amount",
				"theirDebts.currencyCode",
				"theirDebts.receiptId",
				"peersMine.id as peerId",
				(eb) => eb.fn.coalesce("selfDebts.note", "theirDebts.note").as("note"),
				"selfDebts.amount as selfAmount",
				"selfDebts.timestamp as selfTimestamp",
				"selfDebts.currencyCode as selfCurrencyCode",
			])
			.orderBy("theirDebts.updatedAt", "desc")
			.orderBy("theirDebts.id", "desc")
			.$narrowType<
				MappedNullableObject<
					Selectable<DB["debts"]>,
					{
						selfAmount: "amount";
						selfTimestamp: "timestamp";
						selfCurrencyCode: "currencyCode";
					}
				>
			>()
			.execute();
		return {
			items: debts.map((debt) => ({
				id: debt.id,
				peerId: debt.peerId,
				amount: -Number(debt.amount),
				currencyCode: debt.currencyCode,
				updatedAt: debt.updatedAt,
				timestamp: debt.timestamp,
				note: debt.note,
				...(debt.receiptId ? { receiptId: debt.receiptId } : {}),
				...(debt.selfAmount
					? {
							current: {
								amount: Number(debt.selfAmount),
								timestamp: debt.selfTimestamp,
								currencyCode: debt.selfCurrencyCode,
							},
						}
					: {}),
			})),
		};
	});