From 837611676525678d7435f07a76cc8bf89f97af9c Mon Sep 17 00:00:00 2001 From: grabowski Date: Mon, 20 Apr 2026 15:57:08 +0700 Subject: [PATCH] Auto-resolve FX rate on account creation (base=1, else fetch from API) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Account creation no longer requires the user to enter an FX rate. On create: - If account currency == company base → fxRateToBase = 1 - Otherwise → fetchRate(accountCurrency, baseCurrency) from the fawazahmed0 FX API (same helper the daily scheduler uses) - Fallback to 1 if API call fails The manual override field is still shown on the edit form for admin corrections, and the daily scheduler keeps it fresh. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../[companyId]/accounts/+page.server.ts | 24 ++++++++++++- .../[companyId]/accounts/+page.svelte | 34 +++++++++++-------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/routes/(app)/companies/[companyId]/accounts/+page.server.ts b/src/routes/(app)/companies/[companyId]/accounts/+page.server.ts index d0a162b..5f4dad3 100644 --- a/src/routes/(app)/companies/[companyId]/accounts/+page.server.ts +++ b/src/routes/(app)/companies/[companyId]/accounts/+page.server.ts @@ -2,6 +2,7 @@ import { error, fail } from '@sveltejs/kit'; import type { Actions, PageServerLoad } from './$types'; import { db } from '$lib/server/db/index.js'; import { + companies, companyAccounts, companyAccountTransactions, externalAccounts @@ -13,8 +14,26 @@ import { postTransfer, type CompanyAccountTxnType } from '$lib/server/accounts/ledger.js'; +import { fetchRate } from '$lib/server/fx/index.js'; import { and, asc, eq, isNull, sql } from 'drizzle-orm'; +async function resolveFxRate(companyId: string, accountCurrency: string): Promise { + const [company] = await db + .select({ currency: companies.currency }) + .from(companies) + .where(eq(companies.id, companyId)) + .limit(1); + const base = company?.currency ?? 'THB'; + if (accountCurrency.toUpperCase() === base.toUpperCase()) return '1'; + try { + const rate = await fetchRate(accountCurrency, base); + if (rate !== null && rate > 0) return rate.toFixed(8); + } catch { + // fall through + } + return '1'; +} + const MANUAL_TXN_TYPES = ['deposit', 'adjustment'] as const; type ManualTxnType = (typeof MANUAL_TXN_TYPES)[number]; @@ -281,6 +300,9 @@ export const actions: Actions = { const openingBalanceDate = parseDate(fd.get('openingBalanceDate')) ?? new Date(); + // Auto-determine FX rate: 1 for base currency, API rate otherwise + const fxRateToBase = await resolveFxRate(params.companyId, f.currency); + const inserted = await db.transaction(async (tx) => { const [row] = await tx .insert(companyAccounts) @@ -306,7 +328,7 @@ export const actions: Actions = { creditLimit: f.creditLimit, statementCloseDay: f.statementCloseDay, paymentDueDay: f.paymentDueDay, - fxRateToBase: f.fxRateToBase, + fxRateToBase, externalAccountId: f.externalAccountId }) .returning({ id: companyAccounts.id }); diff --git a/src/routes/(app)/companies/[companyId]/accounts/+page.svelte b/src/routes/(app)/companies/[companyId]/accounts/+page.svelte index 7660860..c00c142 100644 --- a/src/routes/(app)/companies/[companyId]/accounts/+page.svelte +++ b/src/routes/(app)/companies/[companyId]/accounts/+page.svelte @@ -177,20 +177,26 @@ class={inputCls} /> -
- - -

1.0 if same as company currency

-
+ {#if prefix.startsWith('edit-')} +
+ + +

Auto-refreshed daily from FX API. Override here to override.

+
+ {:else} +
+ FX rate: auto-set on create (1 if base currency, else fetched from FX API) +
+ {/if} {#if type === 'bank'}