Files
TaxHacker/data/stats.ts
Vasily Zubarev 0b98a2c307 (squash) init
feat: filters, settings, backups

fix: ts compile errors

feat: new dashboard, webp previews and settings

feat: use webp for pdfs

feat: use webp

fix: analyze resets old data

fix: switch to corsproxy

fix: switch to free cors

fix: max upload limit

fix: currency conversion

feat: transaction export

fix: currency conversion

feat: refactor settings actions

feat: new loader

feat: README + LICENSE

doc: update readme

doc: update readme

doc: update readme

doc: update screenshots

ci: bump prisma
2025-03-16 21:29:20 +01:00

84 lines
2.7 KiB
TypeScript

import { prisma } from "@/lib/db"
import { calcTotalPerCurrency } from "@/lib/stats"
import { Prisma } from "@prisma/client"
import { cache } from "react"
export type StatsFilters = {
dateFrom?: string
dateTo?: string
}
export type DashboardStats = {
totalIncomePerCurrency: Record<string, number>
totalExpensesPerCurrency: Record<string, number>
profitPerCurrency: Record<string, number>
invoicesProcessed: number
}
export const getDashboardStats = cache(async (filters: StatsFilters = {}): Promise<DashboardStats> => {
const where: Prisma.TransactionWhereInput = {}
if (filters.dateFrom || filters.dateTo) {
where.issuedAt = {
gte: filters.dateFrom ? new Date(filters.dateFrom) : undefined,
lte: filters.dateTo ? new Date(filters.dateTo) : undefined,
}
}
const transactions = await prisma.transaction.findMany({ where })
const totalIncomePerCurrency = calcTotalPerCurrency(transactions.filter((t) => t.type === "income"))
const totalExpensesPerCurrency = calcTotalPerCurrency(transactions.filter((t) => t.type === "expense"))
const profitPerCurrency = Object.fromEntries(
Object.keys(totalIncomePerCurrency).map((currency) => [
currency,
totalIncomePerCurrency[currency] - totalExpensesPerCurrency[currency],
])
)
const invoicesProcessed = transactions.length
return {
totalIncomePerCurrency,
totalExpensesPerCurrency,
profitPerCurrency,
invoicesProcessed,
}
})
export type ProjectStats = {
totalIncomePerCurrency: Record<string, number>
totalExpensesPerCurrency: Record<string, number>
profitPerCurrency: Record<string, number>
invoicesProcessed: number
}
export const getProjectStats = cache(async (projectId: string, filters: StatsFilters = {}) => {
const where: Prisma.TransactionWhereInput = {
projectCode: projectId,
}
if (filters.dateFrom || filters.dateTo) {
where.issuedAt = {
gte: filters.dateFrom ? new Date(filters.dateFrom) : undefined,
lte: filters.dateTo ? new Date(filters.dateTo) : undefined,
}
}
const transactions = await prisma.transaction.findMany({ where })
const totalIncomePerCurrency = calcTotalPerCurrency(transactions.filter((t) => t.type === "income"))
const totalExpensesPerCurrency = calcTotalPerCurrency(transactions.filter((t) => t.type === "expense"))
const profitPerCurrency = Object.fromEntries(
Object.keys(totalIncomePerCurrency).map((currency) => [
currency,
totalIncomePerCurrency[currency] - totalExpensesPerCurrency[currency],
])
)
const invoicesProcessed = transactions.length
return {
totalIncomePerCurrency,
totalExpensesPerCurrency,
profitPerCurrency,
invoicesProcessed,
}
})