Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 3 additions & 7 deletions frontend/src/components/ExpenseAdvancesTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<div class="flex flex-row items-start gap-3">
<FormControl
type="checkbox"
class="mt-[0.5px]"
class="mt-[1.5px]"
v-model="advance.selected"
:disabled="isReadOnly"
/>
Expand All @@ -34,7 +34,7 @@
<div class="text-xs font-normal text-gray-500">
{{ __("{0}: {1}", [
__("Unclaimed Amount"),
formatCurrency(advance.unclaimed_amount, currency),
formatCurrency(advance.unclaimed_amount, expenseClaim.currency),
]) }}
</div>
</div>
Expand Down Expand Up @@ -74,17 +74,13 @@ const props = defineProps({
type: Object,
required: true,
},
currency: {
type: String,
required: true,
},
isReadOnly: {
type: Boolean,
default: false,
},
})

const currencySymbol = computed(() => getCurrencySymbol(props.currency))
const currencySymbol = computed(() => getCurrencySymbol(props.expenseClaim.currency))

function toggleAdvanceSelection(advance) {
if (props.isReadOnly) return
Expand Down
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
8 changes: 3 additions & 5 deletions frontend/src/components/ExpenseItems.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
{{
__("{0}: {1}", [
__("Sanctioned"),
formatCurrency(item.sanctioned_amount || 0, currency),
formatCurrency(item.sanctioned_amount || 0, doc.currency),
])
}}
</span>
Expand All @@ -33,7 +33,7 @@
</div>
</div>
<span class="text-gray-700 font-normal rounded text-base">
{{ formatCurrency(item.amount, currency) }}
{{ formatCurrency(item.amount, doc.currency) }}
</span>
</div>
</div>
Expand All @@ -42,9 +42,8 @@
</template>

<script setup>
import { computed, inject } from "vue"
import { inject } from "vue"
import { getCompanyCurrency } from "@/data/currencies"
import { formatCurrency } from "@/utils/formatters"
const props = defineProps({
Expand All @@ -55,5 +54,4 @@ const props = defineProps({
})
const dayjs = inject("$dayjs")
const currency = computed(() => getCompanyCurrency(props.doc.company))
</script>
20 changes: 12 additions & 8 deletions frontend/src/components/ExpenseTaxesTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<h2 class="text-base font-semibold text-gray-800">{{ __("Taxes & Charges") }} </h2>
<div class="flex flex-row gap-3 items-center">
<span class="text-base font-semibold text-gray-800">
{{ formatCurrency(expenseClaim.total_taxes_and_charges, currency) }}
{{ formatCurrency(expenseClaim.total_taxes_and_charges, expenseClaim.currency) }}
</span>
<Button
v-if="!isReadOnly"
Expand Down Expand Up @@ -35,17 +35,17 @@
{{ item.account_head }}
</div>
<div class="text-xs font-normal text-gray-500">
<span> Rate: {{ formatCurrency(item.rate, currency) }} </span>
<span> Rate: {{ formatCurrency(item.rate, expenseClaim.currency) }} </span>
<span class="whitespace-pre"> &middot; </span>
<span class="whitespace-nowrap">
Amount: {{ formatCurrency(item.tax_amount, currency) }}
Amount: {{ formatCurrency(item.tax_amount, expenseClaim.currency) }}
</span>
</div>
</div>
</div>
<div class="flex flex-row justify-end items-center gap-2">
<span class="text-gray-700 font-normal rounded text-base">
{{ formatCurrency(item.total, currency) }}
{{ formatCurrency(item.total, expenseClaim.currency) }}
</span>
<FeatherIcon name="chevron-right" class="h-5 w-5 text-gray-500" />
</div>
Expand Down Expand Up @@ -134,16 +134,13 @@ import EmptyState from "@/components/EmptyState.vue"
import CustomIonModal from "@/components/CustomIonModal.vue"

import { formatCurrency } from "@/utils/formatters"
import { useCurrencyConversion } from "@/composables/useCurrencyConversion"

const props = defineProps({
expenseClaim: {
type: Object,
required: true,
},
currency: {
type: String,
required: true,
},
isReadOnly: {
type: Boolean,
default: false,
Expand Down Expand Up @@ -215,6 +212,13 @@ const taxesTableFields = createResource({
})
taxesTableFields.reload()

const expenseClaimRef = computed(() => props.expenseClaim)
useCurrencyConversion(
taxesTableFields,
expenseClaimRef,
["tax_amount", "total"]
)

const modalTitle = computed(() => {
if (props.isReadOnly) return __("Expense Tax")

Expand Down
23 changes: 14 additions & 9 deletions frontend/src/components/ExpensesTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<h2 class="text-base font-semibold text-gray-800">{{ __("Expenses") }} </h2>
<div class="flex flex-row gap-3 items-center">
<span class="text-base font-semibold text-gray-800">
{{ formatCurrency(expenseClaim.total_claimed_amount, currency) }}
{{ formatCurrency(expenseClaim.total_claimed_amount, expenseClaim.currency) }}
</span>
<Button
v-if="!isReadOnly"
Expand Down Expand Up @@ -40,7 +40,7 @@
{{
__("{0}: {1}", [
__("Sanctioned"),
formatCurrency(item.sanctioned_amount || 0, currency),
formatCurrency(item.sanctioned_amount || 0, expenseClaim.currency),
])
}}
</span>
Expand All @@ -53,7 +53,7 @@
</div>
<div class="flex flex-row justify-end items-center gap-2">
<span class="text-gray-700 font-normal rounded text-base">
{{ formatCurrency(item.amount, currency) }}
{{ formatCurrency(item.amount, expenseClaim.currency) }}
</span>
<FeatherIcon name="chevron-right" class="h-5 w-5 text-gray-500" />
</div>
Expand All @@ -75,7 +75,7 @@
</span>
</div>
<div class="w-full flex flex-col items-center justify-center gap-5 p-4 max-h-[80vh]">
<div class="flex flex-col w-full space-y-4 overflow-y-auto">
<div class="flex flex-col w-full space-y-4 overflow-y-auto px-0.5">
<FormField
v-for="field in expensesTableFields.data"
:key="field.fieldname"
Expand Down Expand Up @@ -140,15 +140,13 @@ import CustomIonModal from "@/components/CustomIonModal.vue"
import { claimTypesByID } from "@/data/claims"
import { formatCurrency } from "@/utils/formatters"

import { useCurrencyConversion } from "@/composables/useCurrencyConversion"

const props = defineProps({
expenseClaim: {
type: Object,
required: true,
},
currency: {
type: String,
required: true,
},
isReadOnly: {
type: Boolean,
default: false,
Expand Down Expand Up @@ -201,12 +199,19 @@ const expensesTableFields = createResource({
url: "hrms.api.get_doctype_fields",
params: { doctype: "Expense Claim Detail" },
transform(data) {
const excludeFields = ["description_sb", "amounts_sb"]
const excludeFields = ["description_sb", "amounts_sb", "base_amount", "base_sanctioned_amount"]
return data.filter((field) => !excludeFields.includes(field.fieldname))
},
})
expensesTableFields.reload()

const expenseClaimRef = computed(() => props.expenseClaim)
useCurrencyConversion(
expensesTableFields,
expenseClaimRef,
["amount", "sanctioned_amount"]
)

const modalTitle = computed(() => {
if (props.isReadOnly) return __("Expense Item")

Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/FormView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ const props = defineProps({
default: false,
},
})
const emit = defineEmits(["validateForm", "update:modelValue"])
const emit = defineEmits(["validateForm", "update:modelValue", "formReloaded"])
const router = useRouter()
const { downloadPDF } = useDownloadPDF()

Expand Down Expand Up @@ -553,7 +553,6 @@ const docList = createListResource({
const documentResource = createDocumentResource({
doctype: props.doctype,
name: props.id,
fields: "*",
setValue: {
onSuccess() {
toast({
Expand Down Expand Up @@ -674,7 +673,7 @@ async function handleDocUpdate(action) {
} else if (action == "cancel") {
params.docstatus = 2
}

await documentResource.setValue.submit(params)
await documentResource.get.promise
resetForm()
Expand Down Expand Up @@ -720,6 +719,7 @@ function resetForm() {
nextTick(() => {
isFormDirty.value = false
isFormUpdated.value = true
emit("formReloaded")
})
}
function handleDownload() {
Expand Down
27 changes: 16 additions & 11 deletions frontend/src/components/Link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ const searchText = ref("")
const value = computed({
get: () => props.modelValue,
set: (val) => {
const newVal = (val && typeof val === "object" && val.value !== undefined) ? val.value : val
emit("update:modelValue", newVal || "")
if (typeof val === "string") {
emit("update:modelValue", val)
} else {
emit("update:modelValue", val?.value || "")
}
},
})

Expand Down Expand Up @@ -72,28 +75,30 @@ const reloadOptions = (searchTextVal) => {
params: {
txt: searchTextVal,
doctype: props.doctype,
filters: props.filters
filters: props.filters,
},
})
options.reload()
}

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

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

if (searchText.value === val) return
searchText.value = val
reloadOptions(val)
const val = newQuery || ""
if (searchText.value === val) return
searchText.value = val
reloadOptions(val)
}, 300)

watch(
() => props.doctype,
() => {
if (!props.doctype || props.doctype === options.doctype) return
reloadOptions(props.modelValue)
reloadOptions("")
},
{ immediate: true }
)

watch(
() => props.filters,
() => reloadOptions(''),
)
</script>
2 changes: 1 addition & 1 deletion frontend/src/components/ListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ const documents = createResource({

const createPermission = createResource({
url: "frappe.client.has_permission",
params: { doctype: props.doctype, docname: null, perm_type: "create" },
params: { doctype: props.doctype, docname: "", perm_type: "create" },
auto: true,
})

Expand Down
41 changes: 41 additions & 0 deletions frontend/src/composables/useCurrencyConversion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { watch } from "vue"

export function useCurrencyConversion(formFields, docRef, fieldsToConvert = []) {
/**
* Accepts a formFields resource, a doc ref and an array of fieldnames which are currency fields and need to have the currency in their label
* Watches and updates the labels of the currency fields to include the currency in labels
*/
const currencyFields = new Set([...fieldsToConvert])

const updateLabels = () => {
formFields.data?.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 (currencyFields.has(field.fieldname)) {
field.label = `${field._original_label} (${docRef.value.currency})`
}
})
}

watch(
() => docRef.value?.currency,
() => {
updateLabels()
},
{ immediate: true }
)

watch(
() => formFields.data,
() => {
updateLabels()
},
{ deep: true, immediate: true }
)

return { updateLabels }
}
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
});
Loading
Loading