feat: add separate price vat calc

This commit is contained in:
Methapon2001 2025-01-28 09:44:18 +07:00
parent ef81a93690
commit 310464f834
7 changed files with 344 additions and 280 deletions

View file

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { formatNumberDecimal, commaInput } from 'stores/utils'; import { formatNumberDecimal, commaInput } from 'stores/utils';
import { QTableProps } from 'quasar'; import { QTableProps, QTableSlots } from 'quasar';
import { calculatePrice } from 'src/utils/arithmetic'; import { calculatePrice } from 'src/utils/arithmetic';
const serviceCharge = defineModel<number>('serviceCharge'); const serviceCharge = defineModel<number>('serviceCharge');
@ -9,24 +9,48 @@ const agentPrice = defineModel<number>('agentPrice');
const price = defineModel<number>('price'); const price = defineModel<number>('price');
const vatIncluded = defineModel<boolean>('vatIncluded'); const vatIncluded = defineModel<boolean>('vatIncluded');
const calcVat = defineModel<boolean>('calcVat'); const calcVat = defineModel<boolean>('calcVat');
const agentPriceVatIncluded = defineModel<boolean>('agentPriceVatIncluded');
const agentPriceCalcVat = defineModel<boolean>('agentPriceCalcVat');
const serviceChargeVatIncluded = defineModel<boolean>(
'serviceChargeVatIncluded',
);
const serviceChargeCalcVat = defineModel<boolean>('serviceChargeCalcVat');
const price4Show = ref<string>(commaInput(price.value?.toString() || '0')); const formattedPrice = ref<string>(commaInput(price.value?.toString() || '0'));
const agentPrice4Show = ref<string>( const formattedAgentPrice = ref<string>(
commaInput(agentPrice.value?.toString() || '0'), commaInput(agentPrice.value?.toString() || '0'),
); );
const serviceCharge4Show = ref<string>( const formattedServiceCharge = ref<string>(
commaInput(serviceCharge.value?.toString() || '0'), commaInput(serviceCharge.value?.toString() || '0'),
); );
const column = [ type RowData = {
pricePerUnit: number;
calcVat: boolean;
vatIncluded: boolean;
};
const columns = [
{ {
name: 'label', name: 'label',
align: 'center', align: 'left',
label: 'productService.product.priceInformation', label: 'productService.product.priceInformation',
field: 'label', field: 'label',
}, },
{ {
name: 'pricePerUnit', name: '#calcVat',
align: 'center',
label: 'general.calculateVat',
field: '#calcVat',
},
{
name: '#vatIncluded',
align: 'center',
label: 'productService.product.vatIncluded',
field: '#vatIncluded',
},
{
name: '#pricePerUnit',
align: 'center', align: 'center',
label: 'quotation.pricePerUnit', label: 'quotation.pricePerUnit',
field: 'pricePerUnit', field: 'pricePerUnit',
@ -35,54 +59,77 @@ const column = [
name: 'beforeVat', name: 'beforeVat',
align: 'right', align: 'right',
label: 'quotation.priceBeforeVat', label: 'quotation.priceBeforeVat',
field: 'beforeVat', field: (data: RowData) =>
formatNumberDecimal(
calculatePrice({
output: 'beforeVat',
vatIncluded: data.vatIncluded,
price: data.pricePerUnit || 0,
}),
2,
),
}, },
{ {
name: 'vat', name: 'vat',
align: 'right', align: 'right',
label: 'general.vat', label: 'general.vat',
field: 'vat', field: (data: RowData) =>
formatNumberDecimal(
calculatePrice({
output: 'vat',
calcVat: data.calcVat,
price: Number(
formatNumberDecimal(
calculatePrice({
output: 'beforeVat',
vatIncluded: data.vatIncluded,
price: data.pricePerUnit,
}),
2,
).replaceAll(',', ''),
),
}),
2,
),
}, },
{ {
name: 'total', name: 'total',
align: 'right', align: 'right',
label: 'quotation.sumPrice', label: 'quotation.sumPrice',
field: 'total', field: (data: RowData) =>
formatNumberDecimal(
calculatePrice({
output: 'total',
vat: 0.07,
price: data.pricePerUnit,
}) +
(!data.vatIncluded
? calculatePrice({
output: 'vat',
calcVat: data.calcVat,
price: data.pricePerUnit,
})
: 0),
2,
),
}, },
] as const satisfies QTableProps['columns']; ] as QTableProps['columns'];
const row = [ watch([calcVat, agentPriceCalcVat, serviceChargeCalcVat], () => {
{ if (calcVat.value === false) {
label: 'productService.product.salePrice', vatIncluded.value = false;
beforeVat: 0, }
vat: 0, if (agentPriceCalcVat.value === false) {
total: 0, agentPriceVatIncluded.value = false;
}, }
{ if (serviceChargeCalcVat.value === false) {
label: 'productService.product.agentPrice', serviceChargeVatIncluded.value = false;
beforeVat: 0, }
vat: 0,
total: 0,
},
{
label: 'productService.product.processingPrice',
beforeVat: 0,
vat: 0,
total: 0,
},
] as const satisfies QTableProps['rows'];
watch(calcVat, () => {
if (calcVat.value === false) vatIncluded.value = false;
}); });
withDefaults( withDefaults(
defineProps<{ defineProps<{
dense?: boolean;
outlined?: boolean;
readonly?: boolean; readonly?: boolean;
separator?: boolean;
isType?: boolean;
priceDisplay?: { priceDisplay?: {
price: boolean; price: boolean;
agentPrice: boolean; agentPrice: boolean;
@ -115,255 +162,237 @@ withDefaults(
{{ $t('productService.product.priceInformation') }} {{ $t('productService.product.priceInformation') }}
</span> </span>
</div> </div>
<section class="q-pr-md">
<input
id="input-calc-vat"
type="checkbox"
v-model="calcVat"
:disabled="readonly"
/>
<label
class="q-pl-sm"
for="input-calc-vat"
:style="{ opacity: readonly ? '.5' : undefined }"
>
{{ $t('general.calculateVat') }}
</label>
</section>
<div
class="surface-3 q-px-sm q-py-xs row text-caption app-text-muted"
style="border-radius: var(--radius-3)"
v-if="calcVat"
>
<span
id="btn-include-vat"
for="btn-include-vat"
class="q-px-sm q-mr-lg rounded cursor-pointer"
:class="{
dark: $q.dark.isActive,
'active-addr': vatIncluded,
'cursor-not-allowed': readonly,
}"
@click="readonly ? '' : (vatIncluded = true)"
>
{{ $t('productService.product.vatIncluded') }}
</span>
<span
id="btn-no-include-vat"
for="btn-no-include-vat"
class="q-px-sm rounded cursor-pointer"
:class="{
dark: $q.dark.isActive,
'active-addr': !vatIncluded,
'cursor-not-allowed': readonly,
}"
@click="readonly ? '' : (vatIncluded = false)"
>
{{ $t('productService.product.vatExcluded') }}
</span>
</div>
</div> </div>
<div class="col-12 full-width"> <div class="col-12 full-width">
<q-table <q-table
:columns="column"
:rows="row"
:rows-per-page-options="[0]" :rows-per-page-options="[0]"
:rows="[
{
label: $t('productService.product.salePrice'),
pricePerUnit: price,
calcVat,
vatIncluded,
},
{
label: $t('productService.product.agentPrice'),
calcVat: agentPriceCalcVat,
vatIncluded: agentPriceVatIncluded,
pricePerUnit: agentPrice,
},
{
label: $t('productService.product.processingPrice'),
calcVat: serviceChargeCalcVat,
vatIncluded: serviceChargeVatIncluded,
pricePerUnit: serviceCharge,
},
]"
:columns
hide-bottom
bordered bordered
flat flat
hide-pagination hide-pagination
selection="multiple"
class="full-width" class="full-width"
:no-data-label="$t('general.noDataTable')"
> >
<template v-slot:header="props"> <template v-slot:header="props">
<q-tr <q-tr
style="background-color: hsla(var(--info-bg) / 0.07)" style="background-color: hsla(var(--info-bg) / 0.07)"
:props="props" :props="props"
> >
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-th v-for="col in columns" :key="col.name" :props="props">
{{ col.label && $t(col.label) }} <template v-if="!!col.label">
{{ $t(col.label) }}
</template>
</q-th> </q-th>
</q-tr> </q-tr>
</template> </template>
<template v-slot:body="props"> <template
<q-tr> v-slot:body="props: {
<q-td>{{ $t(props.row.label) }}</q-td> row: RowData;
<q-td class="text-right" style="width: 15%"> } & Omit<Parameters<QTableSlots['body']>[0], 'row'>"
<q-input >
v-if="priceDisplay?.price && props.rowIndex === 0" <q-tr :class="{ dark: $q.dark.isActive }" class="text-center">
id="input-price" <q-td v-for="(col, i) in columns" :align="col.align" :key="i">
for="input-price" <!-- NOTE: custom column will starts with # -->
:dense="dense" <template v-if="!col.name.startsWith('#')">
outlined <span
:readonly="readonly" v-if="col.name === 'total'"
:borderless="readonly" class="text-weight-bold"
hide-bottom-space :class="{
input-class="text-right" ['tags-color-orange']: props.rowIndex === 0,
:model-value="price4Show" ['tags-color-purple']: props.rowIndex === 1,
@blur=" ['tags-color-pink']: props.rowIndex === 2,
() => { ['dark']: $q.dark.isActive,
price = Number(price4Show.replace(/,/g, '')); }"
if (price % 1 === 0) { >
const [, dec] = price4Show.split('.'); {{
if (!dec) { typeof col.field === 'string'
price4Show += '.00'; ? props.row[col.field as keyof RowData]
: col.field(props.row)
}}
</span>
<template v-else>
{{
typeof col.field === 'string'
? props.row[col.field as keyof RowData]
: col.field(props.row)
}}
</template>
</template>
<template v-if="col.name === '#calcVat'">
<q-checkbox
v-if="priceDisplay?.price && props.rowIndex === 0"
v-model="calcVat"
size="xs"
/>
<q-checkbox
v-if="priceDisplay?.agentPrice && props.rowIndex === 1"
v-model="agentPriceCalcVat"
size="xs"
/>
<q-checkbox
v-if="priceDisplay?.serviceCharge && props.rowIndex === 2"
v-model="serviceChargeCalcVat"
size="xs"
/>
</template>
<template v-if="col.name === '#vatIncluded'">
<q-select
:options="[
{ label: $t('general.included'), value: true },
{ label: $t('general.notIncluded'), value: false },
]"
v-if="priceDisplay?.price && props.rowIndex === 0"
map-options
emit-value
flat
outlined
dense
v-model="vatIncluded"
></q-select>
<q-select
:options="[
{ label: $t('general.included'), value: true },
{ label: $t('general.notIncluded'), value: false },
]"
v-if="priceDisplay?.agentPrice && props.rowIndex === 1"
map-options
emit-value
flat
outlined
dense
v-model="agentPriceVatIncluded"
></q-select>
<q-select
:options="[
{ label: $t('general.included'), value: true },
{ label: $t('general.notIncluded'), value: false },
]"
v-if="priceDisplay?.serviceCharge && props.rowIndex === 2"
map-options
emit-value
flat
outlined
dense
v-model="serviceChargeVatIncluded"
></q-select>
</template>
<template v-if="col.name === '#pricePerUnit'">
<q-input
v-if="priceDisplay?.price && props.rowIndex === 0"
id="input-price"
for="input-price"
dense
outlined
hide-bottom-space
input-class="text-right"
:readonly
:borderless="readonly"
:model-value="formattedPrice"
@blur="
() => {
price = Number(formattedPrice.replace(/,/g, ''));
if (price % 1 === 0 && !formattedPrice.split('.').at(1)) {
formattedPrice += '.00';
} }
} }
} "
" @update:model-value="
@update:model-value=" (v) => {
(v) => { formattedPrice = commaInput(
price4Show = commaInput(v?.toString() || '0', 'string'); v?.toString() || '0',
} 'string',
" );
/> }
<q-input "
v-if="priceDisplay?.agentPrice && props.rowIndex === 1" />
id="input-agent-price" <q-input
for="input-agent-price" v-if="priceDisplay?.agentPrice && props.rowIndex === 1"
:dense="dense" id="input-agent-price"
outlined for="input-agent-price"
:readonly="readonly" dense
:borderless="readonly" outlined
hide-bottom-space hide-bottom-space
input-class="text-right" input-class="text-right"
:model-value="agentPrice4Show" :readonly
@blur=" :borderless="readonly"
() => { :model-value="formattedAgentPrice"
agentPrice = Number(agentPrice4Show.replace(/,/g, '')); @blur="
if (agentPrice % 1 === 0) { () => {
const [, dec] = agentPrice4Show.split('.'); agentPrice = Number(formattedPrice.replace(/,/g, ''));
if (!dec) { if (
agentPrice4Show += '.00'; agentPrice % 1 === 0 &&
!formattedAgentPrice.split('.').at(1)
) {
formattedAgentPrice += '.00';
} }
} }
} "
" @update:model-value="
@update:model-value=" (v) => {
(v) => { formattedAgentPrice = commaInput(
agentPrice4Show = commaInput( v?.toString() || '0',
v?.toString() || '0', 'string',
'string', );
); }
} "
" />
/> <q-input
<q-input v-if="priceDisplay?.serviceCharge && props.rowIndex === 2"
v-if="priceDisplay?.serviceCharge && props.rowIndex === 2" id="input-service-charge"
id="input-service-charge" for="input-service-charge"
for="input-service-charge" dense
:dense="dense" outlined
outlined input-class="text-right"
:readonly="readonly" hide-bottom-space
:borderless="readonly" :readonly
input-class="text-right" :borderless="readonly"
hide-bottom-space :model-value="formattedServiceCharge"
:model-value="serviceCharge4Show" @blur="
@blur=" () => {
() => { serviceCharge = Number(
serviceCharge = Number( formattedServiceCharge.replace(/,/g, ''),
serviceCharge4Show.replace(/,/g, ''), );
); if (
if (serviceCharge % 1 === 0) { serviceCharge % 1 === 0 &&
const [, dec] = serviceCharge4Show.split('.'); !formattedServiceCharge.split('.').at(1)
if (!dec) { ) {
serviceCharge4Show += '.00'; formattedServiceCharge += '.00';
} }
} }
} "
" @update:model-value="
@update:model-value=" (v) => {
(v) => { formattedServiceCharge = commaInput(
serviceCharge4Show = commaInput( v?.toString() || '0',
v?.toString() || '0', 'string',
'string', );
); }
} "
" />
/> </template>
</q-td>
<q-td class="text-right" style="width: 15%">
{{
formatNumberDecimal(
calculatePrice({
output: 'beforeVat',
vatIncluded: vatIncluded,
price:
(props.rowIndex === 0
? price
: props.rowIndex === 1
? agentPrice
: serviceCharge) || 0,
}),
2,
)
}}
</q-td>
<q-td class="text-right" style="width: 15%">
{{
formatNumberDecimal(
calculatePrice({
output: 'vat',
calcVat: calcVat,
price: Number(
formatNumberDecimal(
calculatePrice({
output: 'beforeVat',
vatIncluded: vatIncluded,
price:
(props.rowIndex === 0
? price
: props.rowIndex === 1
? agentPrice
: serviceCharge) || 0,
}),
2,
).replaceAll(',', ''),
),
}),
2,
)
}}
</q-td>
<q-td class="text-right" style="width: 15%">
<span
class="text-weight-bold"
:class="{
'tags-color-orange': props.rowIndex === 0,
'tags-color-purple': props.rowIndex === 1,
'tags-color-pink': props.rowIndex === 2,
dark: $q.dark.isActive,
}"
>
{{
formatNumberDecimal(
calculatePrice({
output: 'total',
vat: 0.03,
price:
(props.rowIndex === 0
? price
: props.rowIndex === 1
? agentPrice
: serviceCharge) || 0,
}) +
(!vatIncluded
? calculatePrice({
output: 'vat',
calcVat: calcVat,
price:
(props.rowIndex === 0
? price
: props.rowIndex === 1
? agentPrice
: serviceCharge) || 0,
})
: 0),
2,
)
}}
</span>
</q-td> </q-td>
</q-tr> </q-tr>
</template> </template>
@ -373,16 +402,6 @@ withDefaults(
</template> </template>
<style scoped> <style scoped>
.active-addr {
color: hsl(var(--info-bg));
background-color: hsla(var(--info-bg) / 0.1);
border-radius: var(--radius-3);
&.dark {
background-color: var(--surface-1);
}
}
.tags-color-orange { .tags-color-orange {
color: var(--orange-5); color: var(--orange-5);
} }

View file

@ -64,7 +64,7 @@ function calcPrice(c: (typeof rows.value)[number]) {
const finalPriceNoVat = finalPriceWithVat / (1 + (config.value?.vat || 0.07)); const finalPriceNoVat = finalPriceWithVat / (1 + (config.value?.vat || 0.07));
const price = finalPriceNoVat * c.amount - c.discount; const price = finalPriceNoVat * c.amount - c.discount;
const vat = c.product.calcVat const vat = c.product[props.agentPrice ? 'agentPriceCalcVat' : 'calcVat']
? (finalPriceNoVat * c.amount - c.discount) * (config.value?.vat || 0.07) ? (finalPriceNoVat * c.amount - c.discount) * (config.value?.vat || 0.07)
: 0; : 0;
return precisionRound(price + vat); return precisionRound(price + vat);
@ -387,7 +387,9 @@ watch(
{{ {{
formatNumberDecimal( formatNumberDecimal(
props.row.pricePerUnit + props.row.pricePerUnit +
(props.row.product.calcVat (props.row.product[
agentPrice ? 'agentPriceCalcVat' : 'calcVat'
]
? props.row.pricePerUnit * (config?.vat || 0.07) ? props.row.pricePerUnit * (config?.vat || 0.07)
: 0), : 0),
2, 2,

View file

@ -1014,6 +1014,10 @@ const currentNoAction = ref(false);
const prevProduct = ref<ProductCreate>({ const prevProduct = ref<ProductCreate>({
expenseType: '', expenseType: '',
vatIncluded: true, vatIncluded: true,
agentPriceVatIncluded: true,
agentPriceCalcVat: true,
serviceChargeVatIncluded: true,
serviceChargeCalcVat: true,
productGroupId: '', productGroupId: '',
remark: '', remark: '',
serviceCharge: 0, serviceCharge: 0,
@ -1050,6 +1054,10 @@ async function assignFormDataProduct(data: Product) {
status: data.status, status: data.status,
expenseType: data.expenseType, expenseType: data.expenseType,
vatIncluded: data.vatIncluded, vatIncluded: data.vatIncluded,
serviceChargeCalcVat: data.serviceChargeCalcVat,
serviceChargeVatIncluded: data.serviceChargeVatIncluded,
agentPriceCalcVat: data.agentPriceCalcVat,
agentPriceVatIncluded: data.agentPriceVatIncluded,
selectedImage: data.selectedImage, selectedImage: data.selectedImage,
document: data.document, document: data.document,
shared: data.shared, shared: data.shared,
@ -1086,6 +1094,10 @@ function clearFormProduct() {
expenseType: '', expenseType: '',
calcVat: true, calcVat: true,
vatIncluded: true, vatIncluded: true,
agentPriceCalcVat: true,
agentPriceVatIncluded: true,
serviceChargeCalcVat: true,
serviceChargeVatIncluded: true,
shared: false, shared: false,
}; };
imageProduct.value = undefined; imageProduct.value = undefined;
@ -3900,7 +3912,12 @@ watch(
v-model:service-charge="formProduct.serviceCharge" v-model:service-charge="formProduct.serviceCharge"
v-model:vat-included="formProduct.vatIncluded" v-model:vat-included="formProduct.vatIncluded"
v-model:calc-vat="formProduct.calcVat" v-model:calc-vat="formProduct.calcVat"
dense v-model:agent-price-vat-included="formProduct.agentPriceVatIncluded"
v-model:agent-price-calc-vat="formProduct.agentPriceCalcVat"
v-model:service-charge-vat-included="
formProduct.serviceChargeVatIncluded
"
v-model:service-charge-calc-vat="formProduct.serviceChargeCalcVat"
/> />
<FormDocument <FormDocument
v-if="productTab === 3" v-if="productTab === 3"
@ -4109,7 +4126,12 @@ watch(
v-model:service-charge="formProduct.serviceCharge" v-model:service-charge="formProduct.serviceCharge"
v-model:vat-included="formProduct.vatIncluded" v-model:vat-included="formProduct.vatIncluded"
v-model:calc-vat="formProduct.calcVat" v-model:calc-vat="formProduct.calcVat"
dense v-model:agent-price-vat-included="formProduct.agentPriceVatIncluded"
v-model:agent-price-calc-vat="formProduct.agentPriceCalcVat"
v-model:service-charge-vat-included="
formProduct.serviceChargeVatIncluded
"
v-model:service-charge-calc-vat="formProduct.serviceChargeCalcVat"
:priceDisplay="priceDisplay" :priceDisplay="priceDisplay"
/> />
<FormDocument <FormDocument

View file

@ -251,10 +251,13 @@ function getPrice(
const vat = const vat =
(finalPriceNoVat * c.amount - c.discount) * (config.value?.vat || 0.07); (finalPriceNoVat * c.amount - c.discount) * (config.value?.vat || 0.07);
const calcVat =
c.product[agentPrice.value ? 'agentPriceCalcVat' : 'calcVat'];
a.totalPrice = precisionRound(a.totalPrice + price); a.totalPrice = precisionRound(a.totalPrice + price);
a.totalDiscount = precisionRound(a.totalDiscount + Number(c.discount)); a.totalDiscount = precisionRound(a.totalDiscount + Number(c.discount));
a.vat = c.product.calcVat ? precisionRound(a.vat + vat) : a.vat; a.vat = calcVat ? precisionRound(a.vat + vat) : a.vat;
a.vatExcluded = c.product.calcVat a.vatExcluded = calcVat
? a.vatExcluded ? a.vatExcluded
: precisionRound(a.vatExcluded + price); : precisionRound(a.vatExcluded + price);
a.finalPrice = precisionRound( a.finalPrice = precisionRound(

View file

@ -260,7 +260,11 @@ function mapNode() {
const price = prop.agentPrice const price = prop.agentPrice
? p.product.agentPrice ? p.product.agentPrice
: p.product.price; : p.product.price;
const pricePerUnit = p.product.vatIncluded const pricePerUnit = (
prop.agentPrice
? p.product.agentPriceVatIncluded
: p.product.vatIncluded
)
? precisionRound(price / (1 + (config.value?.vat || 0.07))) ? precisionRound(price / (1 + (config.value?.vat || 0.07)))
: price; : price;
productCount.value++; productCount.value++;
@ -334,7 +338,9 @@ function mapNode() {
}; };
} else { } else {
const price = prop.agentPrice ? v.raw.agentPrice : v.raw.price; const price = prop.agentPrice ? v.raw.agentPrice : v.raw.price;
const pricePerUnit = v.raw.vatIncluded const pricePerUnit = (
prop.agentPrice ? v.raw.agentPriceVatIncluded : v.raw.vatIncluded
)
? precisionRound(price / (1 + (config.value?.vat || 0.07))) ? precisionRound(price / (1 + (config.value?.vat || 0.07)))
: price; : price;
productCount.value++; productCount.value++;

View file

@ -160,6 +160,10 @@ export interface Product {
calcVat: boolean; calcVat: boolean;
expenseType: string; expenseType: string;
vatIncluded: boolean; vatIncluded: boolean;
agentPriceVatIncluded: boolean;
agentPriceCalcVat: boolean;
serviceChargeVatIncluded: boolean;
serviceChargeCalcVat: boolean;
remark: string; remark: string;
updatedAt: string; updatedAt: string;
updatedBy: UpdatedBy; updatedBy: UpdatedBy;
@ -189,8 +193,12 @@ export interface ProductCreate {
productGroupId: string; productGroupId: string;
remark: string; remark: string;
serviceCharge: number; serviceCharge: number;
serviceChargeCalcVat: boolean;
serviceChargeVatIncluded: boolean;
calcVat?: boolean; calcVat?: boolean;
agentPrice: number; agentPrice: number;
agentPriceCalcVat: boolean;
agentPriceVatIncluded: boolean;
price: number; price: number;
process: number; process: number;
detail: string; detail: string;

View file

@ -143,6 +143,10 @@ export type ProductRelation = {
serviceCharge: number; serviceCharge: number;
vatIncluded: boolean; vatIncluded: boolean;
calcVat: boolean; calcVat: boolean;
agentPriceVatIncluded: boolean;
agentPriceCalcVat: boolean;
serviceChargeVatIncluded: boolean;
serviceChargeCalcVat: boolean;
expenseType: string; expenseType: string;
status: Status; status: Status;
statusOrder: number; statusOrder: number;