Convert project list and detail spent to base currency via FX rate
Deploy to LXC / deploy (push) Successful in 1m57s
Validate / validate (push) Successful in 38s

Both the projects list and the project detail stats (totalApproved,
totalPending) now left-join companyAccounts and multiply expense
amounts by fxRateToBase before summing, matching the overview and
budget page fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-21 14:03:08 +07:00
parent c570019fd8
commit 06ae314b3c
2 changed files with 7 additions and 5 deletions
@@ -1,6 +1,6 @@
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import { db } from '$lib/server/db/index.js'; import { db } from '$lib/server/db/index.js';
import { projects, expenses } from '$lib/server/db/schema.js'; import { projects, expenses, companyAccounts } from '$lib/server/db/schema.js';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
export const load: PageServerLoad = async ({ parent }) => { export const load: PageServerLoad = async ({ parent }) => {
@@ -13,12 +13,13 @@ export const load: PageServerLoad = async ({ parent }) => {
description: projects.description, description: projects.description,
allocatedBudget: projects.allocatedBudget, allocatedBudget: projects.allocatedBudget,
isActive: projects.isActive, isActive: projects.isActive,
spent: sql<string>`coalesce(sum(case when ${expenses.status} = 'approved' then ${expenses.amount} else 0 end), 0)`, spent: sql<string>`coalesce(sum(case when ${expenses.status} = 'approved' then ${expenses.amount} * coalesce(${companyAccounts.fxRateToBase}, 1) else 0 end), 0)::text`,
expenseCount: sql<number>`count(${expenses.id})::int`, expenseCount: sql<number>`count(${expenses.id})::int`,
pendingCount: sql<number>`count(case when ${expenses.status} = 'pending' then 1 end)::int` pendingCount: sql<number>`count(case when ${expenses.status} = 'pending' then 1 end)::int`
}) })
.from(projects) .from(projects)
.leftJoin(expenses, eq(expenses.projectId, projects.id)) .leftJoin(expenses, eq(expenses.projectId, projects.id))
.leftJoin(companyAccounts, eq(expenses.accountId, companyAccounts.id))
.where(eq(projects.companyId, company.id)) .where(eq(projects.companyId, company.id))
.groupBy(projects.id) .groupBy(projects.id)
.orderBy(projects.name); .orderBy(projects.name);
@@ -1,7 +1,7 @@
import { error, fail } from '@sveltejs/kit'; import { error, fail } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types'; import type { Actions, PageServerLoad } from './$types';
import { db } from '$lib/server/db/index.js'; import { db } from '$lib/server/db/index.js';
import { projects, expenses, users, categories } from '$lib/server/db/schema.js'; import { projects, expenses, users, categories, companyAccounts } from '$lib/server/db/schema.js';
import { eq, and, sql } from 'drizzle-orm'; import { eq, and, sql } from 'drizzle-orm';
import { requireCompanyRole } from '$lib/server/authorization.js'; import { requireCompanyRole } from '$lib/server/authorization.js';
import { logCompanyEvent } from '$lib/server/audit.js'; import { logCompanyEvent } from '$lib/server/audit.js';
@@ -41,11 +41,12 @@ export const load: PageServerLoad = async ({ params, parent }) => {
const [stats] = await db const [stats] = await db
.select({ .select({
totalApproved: sql<string>`coalesce(sum(case when ${expenses.status} = 'approved' then ${expenses.amount} else 0 end), 0)`, totalApproved: sql<string>`coalesce(sum(case when ${expenses.status} = 'approved' then ${expenses.amount} * coalesce(${companyAccounts.fxRateToBase}, 1) else 0 end), 0)::text`,
totalPending: sql<string>`coalesce(sum(case when ${expenses.status} = 'pending' then ${expenses.amount} else 0 end), 0)`, totalPending: sql<string>`coalesce(sum(case when ${expenses.status} = 'pending' then ${expenses.amount} * coalesce(${companyAccounts.fxRateToBase}, 1) else 0 end), 0)::text`,
count: sql<number>`count(*)::int` count: sql<number>`count(*)::int`
}) })
.from(expenses) .from(expenses)
.leftJoin(companyAccounts, eq(expenses.accountId, companyAccounts.id))
.where(eq(expenses.projectId, params.projectId)); .where(eq(expenses.projectId, params.projectId));
return { project, expenses: expenseList, stats }; return { project, expenses: expenseList, stats };