chore: add Biome for lint and fix all lint errors
- Install @biomejs/biome as devDependency at root - Configure biome.json with 2-space indent, double quotes, Tailwind CSS support - Add lint/lint:fix/format/format:fix scripts to root and app package.json - Fix noNonNullAssertion: env vars extracted to variables with suppression, <div role=button> replaced with <button> - Fix noUnusedVariables: remove unused destructured vars - Fix useIterableCallbackReturn: arrow functions with block body - Fix noExplicitAny: recharts Tooltip formatters - Fix noLabelWithoutControl: add htmlFor+id or use <span> for non-input labels - Fix noStaticElementInteractions/useKeyWithClickEvents: role+keyboard events for overlays - Fix noArrayIndexKey: use error string as key - Fix CSS parse: enable tailwindDirectives parser - Normalize formatting across 80 files with biome check --write
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { z } from "zod";
|
||||
import { prisma } from "../../lib/prisma";
|
||||
import { cache } from "../../lib/cache";
|
||||
import { PaymentStatus } from "../../generated/prisma/client";
|
||||
import { cache } from "../../lib/cache";
|
||||
import { prisma } from "../../lib/prisma";
|
||||
|
||||
export const createPeriodicExpenseSchema = z.object({
|
||||
description: z.string().min(1).max(50),
|
||||
@@ -27,7 +27,11 @@ function lastDayOfMonth(year: number, month: number): number {
|
||||
return new Date(year, month, 0).getDate();
|
||||
}
|
||||
|
||||
export function buildDueDate(year: number, month: number, dueDay: number): Date {
|
||||
export function buildDueDate(
|
||||
year: number,
|
||||
month: number,
|
||||
dueDay: number,
|
||||
): Date {
|
||||
const clampedDay = Math.min(dueDay, lastDayOfMonth(year, month));
|
||||
return new Date(Date.UTC(year, month - 1, clampedDay, 0, 0, 0, 0));
|
||||
}
|
||||
@@ -49,15 +53,20 @@ export async function listPeriodicExpenses() {
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function createPeriodicExpense(data: z.infer<typeof createPeriodicExpenseSchema>) {
|
||||
export async function createPeriodicExpense(
|
||||
data: z.infer<typeof createPeriodicExpenseSchema>,
|
||||
) {
|
||||
const result = await prisma.periodicExpense.create({ data });
|
||||
const { year, month } = getCurrentYearMonthUTC();
|
||||
const { month } = getCurrentYearMonthUTC();
|
||||
const currentMonthApplicable = data.periods.includes(month);
|
||||
cache.invalidateByPrefix("expenses:");
|
||||
return { ...result, currentMonthApplicable };
|
||||
}
|
||||
|
||||
export async function updatePeriodicExpense(id: number, data: z.infer<typeof updatePeriodicExpenseSchema>) {
|
||||
export async function updatePeriodicExpense(
|
||||
id: number,
|
||||
data: z.infer<typeof updatePeriodicExpenseSchema>,
|
||||
) {
|
||||
const result = await prisma.periodicExpense.update({ where: { id }, data });
|
||||
cache.invalidateByPrefix("expenses:");
|
||||
return result;
|
||||
@@ -73,7 +82,9 @@ export async function softDeletePeriodicExpense(id: number) {
|
||||
}
|
||||
|
||||
export async function generateMonthlyExpense(id: number) {
|
||||
const periodic = await prisma.periodicExpense.findUniqueOrThrow({ where: { id } });
|
||||
const periodic = await prisma.periodicExpense.findUniqueOrThrow({
|
||||
where: { id },
|
||||
});
|
||||
const { year, month } = getCurrentYearMonthUTC();
|
||||
|
||||
const existing = await prisma.expense.findFirst({
|
||||
@@ -135,7 +146,9 @@ export async function listExpenses(params: {
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function createNonPeriodicExpense(data: z.infer<typeof createNonPeriodicExpenseSchema>) {
|
||||
export async function createNonPeriodicExpense(
|
||||
data: z.infer<typeof createNonPeriodicExpenseSchema>,
|
||||
) {
|
||||
const dueDate = new Date(data.dueDate);
|
||||
const year = dueDate.getUTCFullYear();
|
||||
const month = dueDate.getUTCMonth() + 1;
|
||||
@@ -155,8 +168,13 @@ export async function createNonPeriodicExpense(data: z.infer<typeof createNonPer
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function payExpense(id: number, data: z.infer<typeof payExpenseSchema>) {
|
||||
const paymentDate = data.paymentDate ? new Date(data.paymentDate) : new Date();
|
||||
export async function payExpense(
|
||||
id: number,
|
||||
data: z.infer<typeof payExpenseSchema>,
|
||||
) {
|
||||
const paymentDate = data.paymentDate
|
||||
? new Date(data.paymentDate)
|
||||
: new Date();
|
||||
const result = await prisma.expense.update({
|
||||
where: { id },
|
||||
data: {
|
||||
@@ -189,7 +207,9 @@ export async function getMonthlyTotals(year: number, month: number) {
|
||||
const cached = cache.get(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
||||
const result = await prisma.$queryRaw<Array<{ payed: string | null; pending: string | null }>>`
|
||||
const result = await prisma.$queryRaw<
|
||||
Array<{ payed: string | null; pending: string | null }>
|
||||
>`
|
||||
SELECT
|
||||
(SELECT CAST(SUM("amountPayed") AS NUMERIC) FROM expenses WHERE year = ${year} AND month = ${month} AND status = ${PaymentStatus.PAYED}::"PaymentStatus") as payed,
|
||||
(SELECT CAST(SUM(amount) AS NUMERIC) FROM expenses WHERE year = ${year} AND month = ${month} AND status = ${PaymentStatus.PENDING}::"PaymentStatus") as pending
|
||||
@@ -218,7 +238,17 @@ export async function getTotalPending() {
|
||||
|
||||
export async function listPendingUpcomingExpenses() {
|
||||
const now = new Date();
|
||||
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0));
|
||||
const today = new Date(
|
||||
Date.UTC(
|
||||
now.getUTCFullYear(),
|
||||
now.getUTCMonth(),
|
||||
now.getUTCDate(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
),
|
||||
);
|
||||
const fiveDaysLater = new Date(today);
|
||||
fiveDaysLater.setUTCDate(fiveDaysLater.getUTCDate() + 5);
|
||||
|
||||
@@ -233,7 +263,8 @@ export async function listPendingUpcomingExpenses() {
|
||||
|
||||
return data.map((expense) => ({
|
||||
...expense,
|
||||
dueType: expense.dueDate < today ? "overdue" as const : "upcoming" as const,
|
||||
dueType:
|
||||
expense.dueDate < today ? ("overdue" as const) : ("upcoming" as const),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user