Auto-resolve FX rate on account creation (base=1, else fetch from API)
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) <noreply@anthropic.com>
This commit is contained in:
@@ -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<string> {
|
||||
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 });
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
{#if prefix.startsWith('edit-')}
|
||||
<div>
|
||||
<label for="{prefix}-fxRate" class={labelCls}>FX Rate to Base</label>
|
||||
<input
|
||||
@@ -189,8 +190,13 @@
|
||||
placeholder="1.0 for THB, 34.5 for USD→THB"
|
||||
class={inputCls}
|
||||
/>
|
||||
<p class="mt-0.5 text-xs text-gray-400 dark:text-gray-500">1.0 if same as company currency</p>
|
||||
<p class="mt-0.5 text-xs text-gray-400 dark:text-gray-500">Auto-refreshed daily from FX API. Override here to override.</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400 self-end pb-2">
|
||||
FX rate: auto-set on create (1 if base currency, else fetched from FX API)
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if type === 'bank'}
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user