Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c1bba6b
fix: update currency & exchange rate, update base & transaction field…
iamkhanraheel Feb 5, 2026
370b469
fix: advance child table row selection as per the sanctioned amount i…
iamkhanraheel Feb 25, 2026
2b0dc14
fix: update base fields value as per the exchange rate in real time
iamkhanraheel Feb 25, 2026
a767d69
fix(Link): reload link field options when filters change
ruchamahabal Mar 5, 2026
0912671
fix: update currency in advance account filters, remove fetching defa…
iamkhanraheel Mar 6, 2026
cde96b3
fix: add currency filter in payable account of expense claim
iamkhanraheel Mar 6, 2026
f7ef13f
fix: set exchange rate to 0 if currency not set, correct typo
iamkhanraheel Mar 8, 2026
1164ff8
fix: formatting
iamkhanraheel Mar 26, 2026
604dc07
fix: currency not showing up in recent expenses
ruchamahabal Mar 30, 2026
6972cea
fix(Link): new options don't populate when search term changes
ruchamahabal Mar 30, 2026
3908367
fix: fetching exchange rate fails when expense currency changes from …
ruchamahabal Mar 30, 2026
0f9ef2b
fix: don't pass currency in expense claim tables, use doc currency
ruchamahabal Mar 30, 2026
f18d124
fix: remove all basefield conversion & label update
iamkhanraheel Mar 30, 2026
0874b5a
fix: watch for currency change only to update label, cleanup currency…
iamkhanraheel Mar 31, 2026
fd43c57
fix(expense_claim_pwa): fetch salary employee from employee master
iamkhanraheel Apr 6, 2026
6457589
fix: don't pass currency in expense advances, use doc currency
ruchamahabal Apr 6, 2026
f7ecbfa
fix: set exchange rate first, clear advances table on API response
ruchamahabal Apr 6, 2026
c49a2fb
fix(Link): options not loading once value is set
ruchamahabal Apr 6, 2026
26e5017
fix: move expenses table currency update call to onSuccess of table f…
ruchamahabal Apr 6, 2026
e6c66bb
chore: remove unused flt function
ruchamahabal Apr 6, 2026
e6dbfbd
fix: don't reload form fields on currency change
ruchamahabal Apr 6, 2026
55ddf2a
refactor: use currency conversion as a composable instead of explicit…
ruchamahabal Apr 6, 2026
e57651a
fix: apply currency filter in employee advance account on currency ch…
ruchamahabal Apr 6, 2026
cdcc2e6
fix: show correct currency in expense preview
ruchamahabal Apr 6, 2026
1a3754d
fix: pass expense claim ref to composable
ruchamahabal Apr 6, 2026
2743cad
fix: wire currency conversion labels in expense taxes
ruchamahabal Apr 6, 2026
378b0c2
fix: fields clipping in expense item entry
ruchamahabal Apr 6, 2026
8cc9b68
fix: has permission check
ruchamahabal Apr 6, 2026
7af1034
fix: Advance allocation function like before
ruchamahabal Apr 6, 2026
021bf70
fix: retain unallocated advances cards & allocated advances selection…
ruchamahabal Apr 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions frontend/src/components/ExpenseClaimItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<span>{{ claimDates }}</span>
<span class="whitespace-pre"> &middot; </span>
<span class="whitespace-nowrap">
{{ formatCurrency(props.doc.total_claimed_amount, currency) }}
{{ formatCurrency(props.doc.total_claimed_amount, props.doc.currency) }}
</span>
</div>
</div>
Expand All @@ -33,7 +33,6 @@ import { computed, inject } from "vue"
import ListItem from "@/components/ListItem.vue"
import ExpenseIcon from "@/components/icons/ExpenseIcon.vue"

import { getCompanyCurrency } from "@/data/currencies"
import { formatCurrency } from "@/utils/formatters"

const dayjs = inject("$dayjs")
Expand Down Expand Up @@ -99,7 +98,6 @@ const claimDates = computed(() => {
}
})

const currency = computed(() => getCompanyCurrency(props.doc.company))

const approvalStatus = computed(() => {
return props.doc.approval_status === "Draft" ? "Pending" : props.doc.approval_status
Expand Down
46 changes: 46 additions & 0 deletions frontend/src/components/ExpensesTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ import CustomIonModal from "@/components/CustomIonModal.vue"
import { claimTypesByID } from "@/data/claims"
import { formatCurrency } from "@/utils/formatters"

import { updateCurrencyLabels, updateBaseFieldsAmount } from "@/composables/useCurrencyConversion"

const props = defineProps({
expenseClaim: {
type: Object,
Expand Down Expand Up @@ -243,4 +245,48 @@ watch(
}
}
)

watch(
() => expensesTableFields.data,
(fields) => {
if (!fields) return

updateCurrencyLabels({
formFields: fields,
doc: props.expenseClaim,
baseFields: ["base_amount", "base_sanctioned_amount"],
transactionFields: ["amount", "sanctioned_amount"],
})
},
{ immediate: true }
)

watch(
() => [expenseItem.value.amount, expenseItem.value.sanctioned_amount],
() => {
if (expenseItem.value) {
updateBaseFieldsAmount({
doc: expenseItem.value,
fields: ['amount', 'sanctioned_amount'],
exchangeRate: props.expenseClaim.exchange_rate,
});
}
}
);

watch(
() => props.expenseClaim.exchange_rate,
(exchangeRate) => {
if (props.expenseClaim.expenses) {
props.expenseClaim.expenses.forEach(row => {
updateBaseFieldsAmount({
doc:row,
fields:['amount', 'sanctioned_amount'],
exchangeRate: exchangeRate
});
});
}
}
);

</script>
22 changes: 15 additions & 7 deletions frontend/src/components/Link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ const searchText = ref("")
const value = computed({
get: () => props.modelValue,
set: (val) => {
const newVal = (val && typeof val === "object" && val.value !== undefined) ? val.value : val
const newVal =
val && typeof val === "object" && val.value !== undefined
? val.value
: val
emit("update:modelValue", newVal || "")
},
})
Expand Down Expand Up @@ -72,20 +75,20 @@ const reloadOptions = (searchTextVal) => {
params: {
txt: searchTextVal,
doctype: props.doctype,
filters: props.filters
filters: props.filters,
},
})
options.reload()
}

const handleQueryUpdate = debounce((newQuery) => {
const val = newQuery || ""
const val = newQuery || ""

if (val === "" && props.modelValue) return
if (val === "" && props.modelValue) return

if (searchText.value === val) return
searchText.value = val
reloadOptions(val)
if (searchText.value === val) return
searchText.value = val
reloadOptions(val)
}, 300)

watch(
Expand All @@ -96,4 +99,9 @@ watch(
},
{ immediate: true }
)

watch(
() => props.filters,
() => reloadOptions(''),
)
</script>
61 changes: 61 additions & 0 deletions frontend/src/composables/useCurrencyConversion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { ref, watch } from "vue"
import { getCompanyCurrency, currencyPrecision } from "@/data/currencies"

const flt = (value, precision) => {
const num = parseFloat(value) || 0;
const targetPrecision = precision !== undefined ? precision : (currencyPrecision.data || 2);
return parseFloat(num.toFixed(targetPrecision));
};

export function updateCurrencyLabels({ formFields, doc, baseFields = [], transactionFields = []}) {
if (!formFields || !doc) return
const companyCurrency = ref("")
// fetch company currency initially or when company changes
const fetchCompanyCurrency = async () => {
if (!doc.company) return
companyCurrency.value = await getCompanyCurrency(doc.company)
}

const currencyFields = new Set([...baseFields, ...transactionFields])
const updateLabels = () => {
if (!companyCurrency.value) return

formFields.forEach((field) => {
if (!field?.fieldname) return
if (!currencyFields.has(field.fieldname)) return

if (!field._original_label && field.label) {
field._original_label = field.label.replace(/\([^\)]*\)/g, "").trim()
}
if (baseFields.includes(field.fieldname)) {
field.label = `${field._original_label} (${companyCurrency.value})`
field.hidden = doc.currency === companyCurrency.value
}
if (transactionFields.includes(field.fieldname)) {
field.label = `${field._original_label} (${doc.currency})`
}
})
}

// update labels
watch(
() => [doc.company, doc.currency],
async () => {
await fetchCompanyCurrency()
updateLabels()
},
{ immediate: true }
)

return { updateLabels, companyCurrency }
}

// function to update base currency fields data
export function updateBaseFieldsAmount({doc, fields, exchangeRate}) {
if (!doc) return;
const excahnge_rate = flt(exchangeRate || doc.exchange_rate || 1, 9);
fields.forEach(f => {
const val = flt(flt(doc[f]) * excahnge_rate);
doc["base_" + f] = val;
});
}
10 changes: 10 additions & 0 deletions frontend/src/data/currencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,13 @@ export function getCompanyCurrencySymbol(company) {
export function getCurrencySymbol(currency) {
return currencySymbols?.data?.[currency]
}

export const currencyPrecision = createResource({
url: "frappe.client.get_single_value",
params: {
doctype: "System Settings",
field: "currency_precision"
},
auto: true,
initialData: 2
});
85 changes: 25 additions & 60 deletions frontend/src/views/employee_advance/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
<script setup>
import { IonPage, IonContent } from "@ionic/vue"
import { createResource } from "frappe-ui"
import { ref, watch, inject, computed } from "vue"
import { ref, watch, inject } from "vue"

import FormView from "@/components/FormView.vue"

import { getCompanyCurrency } from "@/data/currencies"
import { updateCurrencyLabels } from "@/composables/useCurrencyConversion"

const employee = inject("$employee")

Expand All @@ -41,10 +40,6 @@ const employeeAdvance = ref({
department: employee.data.department,
})

const companyCurrency = computed(() =>
getCompanyCurrency(employeeAdvance.value.company)
)

// get form fields
const formFields = createResource({
url: "hrms.api.get_doctype_fields",
Expand All @@ -53,41 +48,31 @@ const formFields = createResource({
const fields = getFilteredFields(data)
return applyFilters(fields)
},
onSuccess(_) {
employeeCurrency.reload()
advanceAccount.reload()
},
})
formFields.reload()

const employeeCurrency = createResource({
url: "hrms.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
params: { employee: employee.data.name },
onSuccess(data) {
employeeAdvance.value.currency = data
setExchangeRate()
},
})

const exchangeRate = createResource({
url: "erpnext.setup.utils.get_exchange_rate",
onSuccess(data) {
employeeAdvance.value.exchange_rate = data
},
})

const advanceAccount = createResource({
url: "hrms.api.get_advance_account",
params: { company: employeeAdvance.value.company },
onSuccess(data) {
employeeAdvance.value.advance_account = data
// scripts
watch(
() => [formFields.data, employeeAdvance.value.currency],
([fields, currency]) => {
if (!fields || !currency) return

updateCurrencyLabels({
formFields: fields,
doc: employeeAdvance.value,
baseFields: ["base_paid_amount"],
transactionFields: ["paid_amount"],
})
},
})
{ immediate: true }
)

// form scripts
watch(
() => employeeAdvance.value.currency,
() => setExchangeRate()
(currency) => {
if (!currency) return
formFields.reload()
}
)

// helper functions
Expand All @@ -112,40 +97,20 @@ function getFilteredFields(fields) {
function applyFilters(fields) {
return fields.map((field) => {
if (field.fieldname === "advance_account") {
let currencies = [employeeAdvance.value.currency]
if (employeeAdvance.value.currency != companyCurrency.value)
currencies.push(companyCurrency.value)

if (!employeeAdvance.value.currency) return field

field.linkFilters = {
company: employeeAdvance.value.company,
is_group: 0,
root_type: "Asset",
is_group: 0,
account_type: "Receivable",
account_currency: ["in", currencies],
account_currency: ["in", [employeeAdvance.value.currency]],
company: employeeAdvance.value.company,
}
}

return field
})
}

function setExchangeRate() {
if (!employeeAdvance.value.currency) return
const exchange_rate_field = formFields.data?.find(
(field) => field.fieldname === "exchange_rate"
)

if (employeeAdvance.value.currency === companyCurrency.value) {
employeeAdvance.value.exchange_rate = 1
exchange_rate_field.hidden = 1
} else {
exchangeRate.fetch({
from_currency: employeeAdvance.value.currency,
to_currency: companyCurrency.value,
})
exchange_rate_field.hidden = 0
}
}

function validateForm() {}
</script>
Loading
Loading