fix: product worker
This commit is contained in:
parent
f4802b6991
commit
7f0d006a7c
4 changed files with 176 additions and 248 deletions
|
|
@ -5,6 +5,8 @@ import ThaiBahtText from 'thai-baht-text';
|
||||||
import { toWords } from 'number-to-words';
|
import { toWords } from 'number-to-words';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
import WorkerItem from './WorkerItem.vue';
|
||||||
|
import DeleteButton from '../button/DeleteButton.vue';
|
||||||
import { commaInput } from 'stores/utils';
|
import { commaInput } from 'stores/utils';
|
||||||
import { precisionRound } from 'src/utils/arithmetic';
|
import { precisionRound } from 'src/utils/arithmetic';
|
||||||
import TableComponents from 'components/TableComponents.vue';
|
import TableComponents from 'components/TableComponents.vue';
|
||||||
|
|
@ -15,6 +17,17 @@ import { Product, Service, Work } from 'src/stores/product-service/types';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
agentPrice: boolean;
|
agentPrice: boolean;
|
||||||
|
employeeRows?: {
|
||||||
|
foreignRefNo: string;
|
||||||
|
employeeName: string;
|
||||||
|
birthDate: string;
|
||||||
|
gender: string;
|
||||||
|
age: string;
|
||||||
|
nationality: string;
|
||||||
|
documentExpireDate: string;
|
||||||
|
imgUrl: string;
|
||||||
|
status: string;
|
||||||
|
}[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
|
|
@ -59,7 +72,9 @@ const summaryPrice = defineModel<{
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentBtnOpen = ref<boolean[]>([]);
|
const currentBtnOpen = ref<{ title: string; opened: boolean[] }[]>([
|
||||||
|
{ title: '', opened: [] },
|
||||||
|
]);
|
||||||
const finalDiscount = ref<number>(0);
|
const finalDiscount = ref<number>(0);
|
||||||
const finalDiscount4Show = ref<string>(finalDiscount.value.toString());
|
const finalDiscount4Show = ref<string>(finalDiscount.value.toString());
|
||||||
|
|
||||||
|
|
@ -104,7 +119,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'code',
|
name: 'code',
|
||||||
align: 'center',
|
align: 'left',
|
||||||
label: 'productService.group.code',
|
label: 'productService.group.code',
|
||||||
field: (v) => v.product.code,
|
field: (v) => v.product.code,
|
||||||
},
|
},
|
||||||
|
|
@ -150,12 +165,6 @@ const columns = [
|
||||||
label: 'quotation.sumPrice',
|
label: 'quotation.sumPrice',
|
||||||
field: 'sumPrice',
|
field: 'sumPrice',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'action',
|
|
||||||
align: 'left',
|
|
||||||
label: '',
|
|
||||||
field: 'action',
|
|
||||||
},
|
|
||||||
] satisfies QTableProps['columns'];
|
] satisfies QTableProps['columns'];
|
||||||
|
|
||||||
const EngBahtText = (number: number) => {
|
const EngBahtText = (number: number) => {
|
||||||
|
|
@ -167,14 +176,16 @@ const EngBahtText = (number: number) => {
|
||||||
return `${bahtText} Baht${satang ? ` and ${satangText} Satang` : ''}`;
|
return `${bahtText} Baht${satang ? ` and ${satangText} Satang` : ''}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
function openEmployeeTable(index: number) {
|
function openEmployeeTable(title: string, index: number) {
|
||||||
currentBtnOpen.value.map((_, i) => {
|
currentBtnOpen.value[0].title = title;
|
||||||
|
currentBtnOpen.value[0].opened.map((_, i) => {
|
||||||
if (i !== index) {
|
if (i !== index) {
|
||||||
currentBtnOpen.value[i] = false;
|
currentBtnOpen.value[0].opened[i] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
currentBtnOpen.value[index] = !currentBtnOpen.value[index];
|
currentBtnOpen.value[0].opened[index] =
|
||||||
|
!currentBtnOpen.value[0].opened[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -202,25 +213,29 @@ watch(
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</div>
|
</div>
|
||||||
<TableComponents
|
|
||||||
|
<q-table
|
||||||
flat
|
flat
|
||||||
bordered
|
bordered
|
||||||
hidePagination
|
hide-pagination
|
||||||
button-delete
|
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="item.product"
|
:rows="item.product"
|
||||||
:customColumn="[
|
class="full-width"
|
||||||
'name',
|
:no-data-label="$t('general.noDataTable')"
|
||||||
'amount',
|
|
||||||
'pricePerUnit',
|
|
||||||
'discount',
|
|
||||||
'tax',
|
|
||||||
'sumPrice',
|
|
||||||
'priceBeforeVat',
|
|
||||||
]"
|
|
||||||
@delete="(i) => $emit('delete', i)"
|
|
||||||
>
|
>
|
||||||
<template v-slot:body-cell-name="{ props }">
|
<template #header="{ cols }">
|
||||||
|
<q-tr style="background-color: hsla(var(--info-bg) / 0.07)">
|
||||||
|
<q-th v-for="(v, i) in cols" :key="v">
|
||||||
|
{{ $t(v.label) }}
|
||||||
|
</q-th>
|
||||||
|
<q-th auto-width />
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #body="props">
|
||||||
|
<q-tr>
|
||||||
|
<q-td class="text-center">{{ props.rowIndex + 1 }}</q-td>
|
||||||
|
<q-td>{{ props.row.product.code }}</q-td>
|
||||||
<q-td>
|
<q-td>
|
||||||
<q-avatar class="q-mr-sm" size="md">
|
<q-avatar class="q-mr-sm" size="md">
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -231,9 +246,6 @@ watch(
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
{{ props.row.product.name }}
|
{{ props.row.product.name }}
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:body-cell-amount="{ props }">
|
|
||||||
<q-td align="center">
|
<q-td align="center">
|
||||||
<q-input
|
<q-input
|
||||||
dense
|
dense
|
||||||
|
|
@ -244,9 +256,6 @@ watch(
|
||||||
v-model="props.row.amount"
|
v-model="props.row.amount"
|
||||||
/>
|
/>
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:body-cell-pricePerUnit="{ props }">
|
|
||||||
<q-td align="right">
|
<q-td align="right">
|
||||||
{{
|
{{
|
||||||
formatNumberDecimal(
|
formatNumberDecimal(
|
||||||
|
|
@ -256,9 +265,6 @@ watch(
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:body-cell-discount="{ props }">
|
|
||||||
<q-td align="center">
|
<q-td align="center">
|
||||||
<q-input
|
<q-input
|
||||||
dense
|
dense
|
||||||
|
|
@ -270,35 +276,28 @@ watch(
|
||||||
v-model="props.row.discount"
|
v-model="props.row.discount"
|
||||||
/>
|
/>
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:body-cell-priceBeforeVat="{ props }">
|
|
||||||
<q-td align="right">
|
<q-td align="right">
|
||||||
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
|
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:body-cell-tax="{ props }">
|
|
||||||
<q-td align="right">
|
<q-td align="right">
|
||||||
{{
|
{{
|
||||||
|
formatNumberDecimal(
|
||||||
precisionRound(
|
precisionRound(
|
||||||
(props.row.pricePerUnit * props.row.amount -
|
(props.row.pricePerUnit * props.row.amount -
|
||||||
props.row.discount) *
|
props.row.discount) *
|
||||||
(config?.vat || 0.07),
|
(config?.vat || 0.07),
|
||||||
|
),
|
||||||
|
2,
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:body-cell-sumPrice="{ props }">
|
|
||||||
<q-td align="right">
|
<q-td align="right">
|
||||||
{{ formatNumberDecimal(calcPrice(props.row), 2) }}
|
{{ formatNumberDecimal(calcPrice(props.row), 2) }}
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
<q-td>
|
||||||
|
<div class="row items-center full-width justify-end no-wrap">
|
||||||
<template #button="{ props }">
|
|
||||||
<q-btn
|
<q-btn
|
||||||
@click.stop="openEmployeeTable(props.rowIndex)"
|
@click.stop="openEmployeeTable(item.title, props.rowIndex)"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -308,7 +307,7 @@ watch(
|
||||||
<q-icon name="mdi-account-group-outline" />
|
<q-icon name="mdi-account-group-outline" />
|
||||||
<q-icon
|
<q-icon
|
||||||
size="xs"
|
size="xs"
|
||||||
:name="`mdi-chevron-${currentBtnOpen[props.rowIndex] ? 'down' : 'up'}`"
|
:name="`mdi-chevron-${currentBtnOpen[0].title === item.title && currentBtnOpen[0].opened[props.rowIndex] ? 'down' : 'up'}`"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
@ -324,129 +323,34 @@ watch(
|
||||||
color: hsl(var(--positive-bg));
|
color: hsl(var(--positive-bg));
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
<DeleteButton
|
||||||
|
iconOnly
|
||||||
|
@click="$emit('delete', props.rowIndex)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-td>
|
||||||
|
</q-tr>
|
||||||
|
|
||||||
|
<q-tr
|
||||||
|
v-show="
|
||||||
|
currentBtnOpen[0].title === item.title &&
|
||||||
|
currentBtnOpen[0].opened[props.rowIndex]
|
||||||
|
"
|
||||||
|
:props="props"
|
||||||
|
>
|
||||||
|
<q-td colspan="100%" style="padding: 16px">
|
||||||
|
<WorkerItem
|
||||||
|
fallback-img="/images/employee-avatar.png"
|
||||||
|
inTable
|
||||||
|
hideQuantity
|
||||||
|
:rows="employeeRows"
|
||||||
|
/>
|
||||||
|
</q-td>
|
||||||
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
</TableComponents>
|
</q-table>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row items-start">
|
|
||||||
<span
|
|
||||||
class="col row items-center justify-between q-px-md q-py-xs q-mr-lg rounded app-text-muted-2 bg-color-orange-light"
|
|
||||||
>
|
|
||||||
<span class="text-weight-bold text-caption">
|
|
||||||
{{ $t('general.totalAmount') }}
|
|
||||||
</span>
|
|
||||||
<span v-if="summary.finalPrice + Number(finalDiscount)">
|
|
||||||
{{
|
|
||||||
$i18n.locale === 'eng'
|
|
||||||
? EngBahtText(summary.finalPrice)
|
|
||||||
: ThaiBahtText(summary.finalPrice)
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div class="col column">
|
|
||||||
<div class="row q-py-xs q-pr-xs q-pl-md">
|
|
||||||
<span class="col-9 app-text-muted-2">
|
|
||||||
{{ $t('quotation.allProductPrice') }}
|
|
||||||
</span>
|
|
||||||
<q-input
|
|
||||||
dense
|
|
||||||
class="col price-tag"
|
|
||||||
readonly
|
|
||||||
outlined
|
|
||||||
input-class="text-right text-bold "
|
|
||||||
:model-value="
|
|
||||||
formatNumberDecimal(summary.finalPrice + Number(finalDiscount), 2)
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row q-py-xs q-pr-xs q-pl-md">
|
|
||||||
<span class="col-9 app-text-muted-2">
|
|
||||||
{{ $t('quotation.quotationDiscount') }}
|
|
||||||
</span>
|
|
||||||
<q-input
|
|
||||||
dense
|
|
||||||
class="col price-tag"
|
|
||||||
outlined
|
|
||||||
input-class="text-right text-bold"
|
|
||||||
:model-value="commaInput(finalDiscount.toString())"
|
|
||||||
@update:model-value="
|
|
||||||
(v) => {
|
|
||||||
if (typeof v === 'string') finalDiscount4Show = commaInput(v);
|
|
||||||
const x = parseFloat(
|
|
||||||
finalDiscount4Show && typeof finalDiscount4Show === 'string'
|
|
||||||
? finalDiscount4Show.replace(/,/g, '')
|
|
||||||
: '',
|
|
||||||
);
|
|
||||||
finalDiscount = x;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="row text-bold bg-color-orange rounded q-py-xs q-pr-xs q-pl-md items-center"
|
|
||||||
style="color: var(--surface-1)"
|
|
||||||
>
|
|
||||||
<span class="col-9">
|
|
||||||
{{ $t('general.totalAmount') }}
|
|
||||||
</span>
|
|
||||||
<q-input
|
|
||||||
dense
|
|
||||||
class="col price-tag"
|
|
||||||
outlined
|
|
||||||
readonly
|
|
||||||
input-class="text-right text-bold "
|
|
||||||
:model-value="
|
|
||||||
formatNumberDecimal(Math.max(summary.finalPrice, 0), 2)
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div
|
|
||||||
class="column q-ml-auto text-caption app-text-muted-2"
|
|
||||||
style="width: 15vw"
|
|
||||||
>
|
|
||||||
<div class="row">
|
|
||||||
{{ $t('quotation.allProductPrice') }}
|
|
||||||
<span class="q-ml-auto">
|
|
||||||
{{ formatNumberDecimal(summary.totalPrice, 2) }} ฿
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
{{ $t('general.discount') }}
|
|
||||||
<span class="q-ml-auto">
|
|
||||||
{{ formatNumberDecimal(summary.totalDiscount, 2) }} ฿
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
{{ $t('quotation.tax') }}
|
|
||||||
<span class="q-ml-auto">
|
|
||||||
{{ formatNumberDecimal(summary.vat, 2) }} ฿
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<q-separator spaced="md" />
|
|
||||||
<div class="row text-bold text-body2" style="color: var(--foreground)">
|
|
||||||
{{ $t('quotation.totalPrice') }}
|
|
||||||
<span class="q-ml-auto">
|
|
||||||
{{ formatNumberDecimal(summary.finalPrice, 2) }} ฿
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
v-if="summary.finalPrice"
|
|
||||||
class="text-caption app-text-muted-2 flex self-end"
|
|
||||||
>
|
|
||||||
({{
|
|
||||||
$i18n.locale === 'eng'
|
|
||||||
? EngBahtText(summary.finalPrice)
|
|
||||||
: ThaiBahtText(summary.finalPrice)
|
|
||||||
}})
|
|
||||||
</span> -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -495,4 +399,8 @@ watch(
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: var(--side-color);
|
background: var(--side-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(i.q-icon.mdi.mdi-alert.q-table__bottom-nodata-icon) {
|
||||||
|
color: #ffc224 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
employeeAmount: number;
|
employeeAmount: number;
|
||||||
fallbackImg?: string;
|
fallbackImg?: string;
|
||||||
|
hideQuantity?: boolean;
|
||||||
|
inTable?: boolean;
|
||||||
rows: {
|
rows: {
|
||||||
foreignRefNo: string;
|
foreignRefNo: string;
|
||||||
employeeName: string;
|
employeeName: string;
|
||||||
|
|
@ -86,6 +88,7 @@ const columns = [
|
||||||
bordered
|
bordered
|
||||||
button-delete
|
button-delete
|
||||||
img-column="employeeName"
|
img-column="employeeName"
|
||||||
|
:inTable
|
||||||
:columns
|
:columns
|
||||||
:rows
|
:rows
|
||||||
hidePagination
|
hidePagination
|
||||||
|
|
@ -118,7 +121,7 @@ const columns = [
|
||||||
</template>
|
</template>
|
||||||
</TableComponents>
|
</TableComponents>
|
||||||
|
|
||||||
<div class="row q-pt-md items-center">
|
<div v-if="!hideQuantity" class="row q-pt-md items-center">
|
||||||
<span class="q-ml-auto">
|
<span class="q-ml-auto">
|
||||||
{{ $t('general.numberOf', { msg: $t('quotation.employee') }) }}
|
{{ $t('general.numberOf', { msg: $t('quotation.employee') }) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ const props = withDefaults(
|
||||||
buttomDownload?: boolean;
|
buttomDownload?: boolean;
|
||||||
buttonDelete?: boolean;
|
buttonDelete?: boolean;
|
||||||
hidePagination?: boolean;
|
hidePagination?: boolean;
|
||||||
|
inTable?: boolean;
|
||||||
|
|
||||||
imgColumn?: string;
|
imgColumn?: string;
|
||||||
customColumn?: string[];
|
customColumn?: string[];
|
||||||
|
|
@ -52,7 +53,7 @@ defineEmits<{
|
||||||
>
|
>
|
||||||
<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: ${inTable ? '#F0FFF1' : '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 props.cols" :key="col.name" :props="props">
|
||||||
|
|
|
||||||
|
|
@ -688,6 +688,22 @@ watch(
|
||||||
|
|
||||||
<ProductItem
|
<ProductItem
|
||||||
:agent-price="agentPrice"
|
:agent-price="agentPrice"
|
||||||
|
:employeeRows="
|
||||||
|
selectedWorker.map((e: Employee) => ({
|
||||||
|
foreignRefNo: '123456789',
|
||||||
|
employeeName:
|
||||||
|
$i18n.locale === 'eng'
|
||||||
|
? `${e.firstNameEN} ${e.lastNameEN}`
|
||||||
|
: `${e.firstName} ${e.lastName}`,
|
||||||
|
birthDate: dateFormat(e.dateOfBirth),
|
||||||
|
gender: e.gender,
|
||||||
|
age: calculateAge(e.dateOfBirth),
|
||||||
|
nationality: optionStore.mapOption(e.nationality),
|
||||||
|
documentExpireDate: '1234',
|
||||||
|
imgUrl: `${baseUrl}/customer/${e.id}/image/${e.selectedImage}`,
|
||||||
|
status: e.status,
|
||||||
|
}))
|
||||||
|
"
|
||||||
@delete="toggleDeleteProduct"
|
@delete="toggleDeleteProduct"
|
||||||
v-model:groupList="productServiceTableData"
|
v-model:groupList="productServiceTableData"
|
||||||
v-model:rows="productServiceList"
|
v-model:rows="productServiceList"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue