Skip to content

Always fetch FX rate by expense date (remove UTC “today” path and latest fallback)#4

Merged
ClementLSW merged 1 commit into
mainfrom
copilot/update-fetch-exchange-rate-date
May 26, 2026
Merged

Always fetch FX rate by expense date (remove UTC “today” path and latest fallback)#4
ClementLSW merged 1 commit into
mainfrom
copilot/update-fetch-exchange-rate-date

Conversation

Copilot AI commented May 26, 2026

Copy link
Copy Markdown
Contributor

Late-night SGT entries could be treated as “today” via a UTC date check, causing live-rate fetches instead of the expense-date rate. This updates FX retrieval to always use an explicit expense date, removing time-zone-dependent branching.

  • Exchange rate utility: date-only fetch path

    • Replaced src/lib/exchangeRate.js with a single explicit-date implementation against Frankfurter (/v1/{date}?from=&to=).
    • Removed /latest behavior, retry/fallback logic, and related helper paths.
    • Kept same-currency fast path, now returning the provided date.
  • AddExpense FX effect: remove UTC “isToday” logic

    • fetchExchangeRate(...) now always receives expenseDate.
    • Removed is_historical from fx.error logging payload (no longer meaningful after date-only behavior).
  • Loading-state correctness

    • Early guard now clears loading before returning to prevent a stuck spinner.
    • finally now always clears loading, independent of cancellation flag.
const result = await fetchExchangeRate(
  expenseCurrency,
  groupCurrency,
  expenseDate,
)

Agent-Logs-Url: https://github.com/ClementLSW/osps/sessions/7f23da57-fd59-4ff9-8e7d-b17be954e069

Co-authored-by: ClementLSW <24468433+ClementLSW@users.noreply.github.com>
@netlify

netlify Bot commented May 26, 2026

Copy link
Copy Markdown

Deploy Preview for omoneypmoney ready!

Name Link
🔨 Latest commit bd7a55c
🔍 Latest deploy log https://app.netlify.com/projects/omoneypmoney/deploys/6a15d0d8cb2edf0008f01e54
😎 Deploy Preview https://deploy-preview-4--omoneypmoney.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ClementLSW ClementLSW requested a review from Copilot May 26, 2026 16:57
@ClementLSW ClementLSW marked this pull request as ready for review May 26, 2026 16:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates foreign-exchange rate retrieval to always fetch a rate for the explicit expense date (removing the previous UTC “today” branching), and adjusts the AddExpense FX effect/loading behavior accordingly.

Changes:

  • Updated the AddExpense FX useEffect to always pass expenseDate into fetchExchangeRate and simplified the FX error logging payload.
  • Replaced the exchange-rate utility implementation with a single explicit-date fetch against https://api.frankfurter.dev/v1/{date}?from=&to=.
  • Adjusted FX loading-state handling to clear loading on early-guard returns and in finally.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/pages/AddExpense.jsx Always fetches FX by expenseDate, updates loading-state behavior, and simplifies FX error logging payload.
src/lib/exchangeRate.js Replaces prior multi-path FX fetching with a single explicit-date Frankfurter fetch and same-currency fast path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/pages/AddExpense.jsx
if (!cancelled) toast.error('Could not fetch exchange rate')
} finally {
if (!cancelled) setRateLoading(false)
setRateLoading(false)
Comment thread src/pages/AddExpense.jsx
useEffect(() => {
const groupCurrency = group?.currency || 'SGD'
if (!expenseCurrency || expenseCurrency === groupCurrency || manualRate) return
if (!expenseCurrency || expenseCurrency === groupCurrency || manualRate) {
Comment thread src/lib/exchangeRate.js
Comment on lines 14 to 20
export async function fetchExchangeRate(from, to, date) {
if (from === to) {
return {
from,
to,
rate: 1,
date: date || new Date().toISOString().slice(0, 10),
fetchedAt: new Date().toISOString(),
}
return { from, to, rate: 1, date, fetchedAt: new Date().toISOString() }
}

// First attempt
try {
return await _fetchOnce(from, to, date)
} catch (err) {
// Only retry /latest — historical dates don't have publish window issues
if (date) throw err

const yesterday = new Date()
yesterday.setUTCDate(yesterday.getUTCDate() - 1)
const fallbackDate = yesterday.toISOString().slice(0, 10)

const result = await _fetchOnce(from, to, fallbackDate)
return { ...result, usedFallbackDate: true }
}
}

async function _fetchOnce(from, to, date) {
const params = new URLSearchParams({ from, to })
if (date) params.set('date', date)

const res = await fetch(`/api/exchange-rate?${params}`)
const res = await fetch(`${BASE_URL}/${date}?from=${from}&to=${to}`)

Comment thread src/lib/exchangeRate.js
Comment on lines +19 to 23
const res = await fetch(`${BASE_URL}/${date}?from=${from}&to=${to}`)

if (!res.ok) {
const body = await res.json().catch(() => ({}))
const err = new Error(body.error || `Exchange rate fetch failed: ${res.status}`)
const err = new Error(`Exchange rate fetch failed: ${res.status}`)
err.status = res.status
@ClementLSW ClementLSW merged commit 21fb9cf into main May 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants