Add effective-date transaction filtering and bulk selection

This commit is contained in:
2026-06-15 21:38:25 +02:00
parent 1c88d12f0d
commit 238a30ae0c
12 changed files with 668 additions and 28 deletions

View File

@@ -41,6 +41,7 @@ export const list = query({
categoryIds: v.optional(v.array(v.id("categories"))),
withoutCategory: v.optional(v.boolean()),
accountId: v.optional(v.id("accounts")),
basis: v.optional(v.union(v.literal("effective"), v.literal("booking"))),
type: v.optional(v.union(v.literal("einnahme"), v.literal("ausgabe"))),
pendingOnly: v.optional(v.boolean()),
},
@@ -51,6 +52,9 @@ export const list = query({
}),
handler: async (ctx, args) => {
const userId = await requireUserId(ctx);
const basis = args.basis ?? "booking";
const fromMonth = args.from?.slice(0, 7);
const toMonth = args.to?.slice(0, 7);
let q;
if (args.search) {
@@ -60,21 +64,77 @@ export const list = query({
sq.search("description", args.search!).eq("userId", userId),
);
} else {
q = ctx.db
.query("transactions")
.withIndex("by_user_booking", (iq) => {
if (args.from && args.to) {
return iq.eq("userId", userId).gte("bookingDate", args.from).lte("bookingDate", args.to);
}
if (args.from) {
return iq.eq("userId", userId).gte("bookingDate", args.from);
}
if (args.to) {
return iq.eq("userId", userId).lte("bookingDate", args.to);
}
return iq.eq("userId", userId);
})
.order("desc");
if (basis === "effective") {
q = ctx.db
.query("transactions")
.withIndex("by_user_effmonth", (iq) => {
if (fromMonth && toMonth) {
return iq.eq("userId", userId).gte("effectiveMonth", fromMonth).lte("effectiveMonth", toMonth);
}
if (fromMonth) {
return iq.eq("userId", userId).gte("effectiveMonth", fromMonth);
}
if (toMonth) {
return iq.eq("userId", userId).lte("effectiveMonth", toMonth);
}
return iq.eq("userId", userId);
})
.order("desc");
} else {
q = ctx.db
.query("transactions")
.withIndex("by_user_booking", (iq) => {
if (args.from && args.to) {
return iq.eq("userId", userId).gte("bookingDate", args.from).lte("bookingDate", args.to);
}
if (args.from) {
return iq.eq("userId", userId).gte("bookingDate", args.from);
}
if (args.to) {
return iq.eq("userId", userId).lte("bookingDate", args.to);
}
return iq.eq("userId", userId);
})
.order("desc");
}
}
if (args.search) {
if (basis === "effective") {
if (fromMonth) {
const fallbackFrom = `${fromMonth}-01`;
q = q.filter((f) =>
f.or(
f.gte(f.field("effectiveMonth"), fromMonth),
f.and(
f.eq(f.field("effectiveMonth"), undefined),
f.gte(f.field("bookingDate"), fallbackFrom),
),
),
);
}
if (toMonth) {
const fallbackTo = `${toMonth}-31`;
q = q.filter((f) =>
f.or(
f.lte(f.field("effectiveMonth"), toMonth),
f.and(
f.eq(f.field("effectiveMonth"), undefined),
f.lte(f.field("bookingDate"), fallbackTo),
),
),
);
}
} else {
if (args.from) {
const from = args.from;
q = q.filter((f) => f.gte(f.field("bookingDate"), from));
}
if (args.to) {
const to = args.to;
q = q.filter((f) => f.lte(f.field("bookingDate"), to));
}
}
}
if (args.pendingOnly) {