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 { storeToRefs } from 'pinia';
|
||||
|
||||
import WorkerItem from './WorkerItem.vue';
|
||||
import DeleteButton from '../button/DeleteButton.vue';
|
||||
import { commaInput } from 'stores/utils';
|
||||
import { precisionRound } from 'src/utils/arithmetic';
|
||||
import TableComponents from 'components/TableComponents.vue';
|
||||
|
|
@ -15,6 +17,17 @@ import { Product, Service, Work } from 'src/stores/product-service/types';
|
|||
|
||||
defineProps<{
|
||||
agentPrice: boolean;
|
||||
employeeRows?: {
|
||||
foreignRefNo: string;
|
||||
employeeName: string;
|
||||
birthDate: string;
|
||||
gender: string;
|
||||
age: string;
|
||||
nationality: string;
|
||||
documentExpireDate: string;
|
||||
imgUrl: string;
|
||||
status: string;
|
||||
}[];
|
||||
}>();
|
||||
|
||||
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 finalDiscount4Show = ref<string>(finalDiscount.value.toString());
|
||||
|
||||
|
|
@ -104,7 +119,7 @@ const columns = [
|
|||
},
|
||||
{
|
||||
name: 'code',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
label: 'productService.group.code',
|
||||
field: (v) => v.product.code,
|
||||
},
|
||||
|
|
@ -150,12 +165,6 @@ const columns = [
|
|||
label: 'quotation.sumPrice',
|
||||
field: 'sumPrice',
|
||||
},
|
||||
{
|
||||
name: 'action',
|
||||
align: 'left',
|
||||
label: '',
|
||||
field: 'action',
|
||||
},
|
||||
] satisfies QTableProps['columns'];
|
||||
|
||||
const EngBahtText = (number: number) => {
|
||||
|
|
@ -167,14 +176,16 @@ const EngBahtText = (number: number) => {
|
|||
return `${bahtText} Baht${satang ? ` and ${satangText} Satang` : ''}`;
|
||||
};
|
||||
|
||||
function openEmployeeTable(index: number) {
|
||||
currentBtnOpen.value.map((_, i) => {
|
||||
function openEmployeeTable(title: string, index: number) {
|
||||
currentBtnOpen.value[0].title = title;
|
||||
currentBtnOpen.value[0].opened.map((_, i) => {
|
||||
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(
|
||||
|
|
@ -202,251 +213,144 @@ watch(
|
|||
</q-avatar>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<TableComponents
|
||||
|
||||
<q-table
|
||||
flat
|
||||
bordered
|
||||
hidePagination
|
||||
button-delete
|
||||
hide-pagination
|
||||
:columns="columns"
|
||||
:rows="item.product"
|
||||
:customColumn="[
|
||||
'name',
|
||||
'amount',
|
||||
'pricePerUnit',
|
||||
'discount',
|
||||
'tax',
|
||||
'sumPrice',
|
||||
'priceBeforeVat',
|
||||
]"
|
||||
@delete="(i) => $emit('delete', i)"
|
||||
class="full-width"
|
||||
:no-data-label="$t('general.noDataTable')"
|
||||
>
|
||||
<template v-slot:body-cell-name="{ props }">
|
||||
<q-td>
|
||||
<q-avatar class="q-mr-sm" size="md">
|
||||
<q-icon
|
||||
class="full-width full-height"
|
||||
name="mdi-shopping-outline"
|
||||
:style="`color: var(--teal-10); background: hsla(var(--teal-${$q.dark.isActive ? '8' : '10'}-hsl)/0.15)`"
|
||||
<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-avatar class="q-mr-sm" size="md">
|
||||
<q-icon
|
||||
class="full-width full-height"
|
||||
name="mdi-shopping-outline"
|
||||
:style="`color: var(--teal-10); background: hsla(var(--teal-${$q.dark.isActive ? '8' : '10'}-hsl)/0.15)`"
|
||||
/>
|
||||
</q-avatar>
|
||||
{{ props.row.product.name }}
|
||||
</q-td>
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
min="0"
|
||||
v-model="props.row.amount"
|
||||
/>
|
||||
</q-avatar>
|
||||
{{ props.row.product.name }}
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-amount="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
min="0"
|
||||
v-model="props.row.amount"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-pricePerUnit="{ props }">
|
||||
<q-td align="right">
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
props.row.pricePerUnit +
|
||||
props.row.pricePerUnit * (config?.vat || 0.07),
|
||||
2,
|
||||
)
|
||||
}}
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-discount="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
min="0"
|
||||
outlined
|
||||
input-class="text-right"
|
||||
type="number"
|
||||
style="width: 90px"
|
||||
v-model="props.row.discount"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-priceBeforeVat="{ props }">
|
||||
<q-td align="right">
|
||||
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-tax="{ props }">
|
||||
<q-td align="right">
|
||||
{{
|
||||
precisionRound(
|
||||
(props.row.pricePerUnit * props.row.amount -
|
||||
props.row.discount) *
|
||||
(config?.vat || 0.07),
|
||||
)
|
||||
}}
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-sumPrice="{ props }">
|
||||
<q-td align="right">
|
||||
{{ formatNumberDecimal(calcPrice(props.row), 2) }}
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template #button="{ props }">
|
||||
<q-btn
|
||||
@click.stop="openEmployeeTable(props.rowIndex)"
|
||||
dense
|
||||
flat
|
||||
size="sm"
|
||||
class="rounded q-mr-xs"
|
||||
>
|
||||
<div class="row items-center no-wrap">
|
||||
<q-icon name="mdi-account-group-outline" />
|
||||
<q-icon
|
||||
size="xs"
|
||||
:name="`mdi-chevron-${currentBtnOpen[props.rowIndex] ? 'down' : 'up'}`"
|
||||
</q-td>
|
||||
<q-td align="right">
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
props.row.pricePerUnit +
|
||||
props.row.pricePerUnit * (config?.vat || 0.07),
|
||||
2,
|
||||
)
|
||||
}}
|
||||
</q-td>
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
min="0"
|
||||
outlined
|
||||
input-class="text-right"
|
||||
type="number"
|
||||
style="width: 90px"
|
||||
v-model="props.row.discount"
|
||||
/>
|
||||
</div>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
icon="mdi-monitor"
|
||||
size="sm"
|
||||
class="rounded q-mr-xs"
|
||||
padding="4px 8px"
|
||||
dense
|
||||
flat
|
||||
style="
|
||||
background-color: hsla(var(--positive-bg) / 0.1);
|
||||
color: hsl(var(--positive-bg));
|
||||
</q-td>
|
||||
<q-td align="right">
|
||||
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
|
||||
</q-td>
|
||||
<q-td align="right">
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
precisionRound(
|
||||
(props.row.pricePerUnit * props.row.amount -
|
||||
props.row.discount) *
|
||||
(config?.vat || 0.07),
|
||||
),
|
||||
2,
|
||||
)
|
||||
}}
|
||||
</q-td>
|
||||
<q-td align="right">
|
||||
{{ formatNumberDecimal(calcPrice(props.row), 2) }}
|
||||
</q-td>
|
||||
<q-td>
|
||||
<div class="row items-center full-width justify-end no-wrap">
|
||||
<q-btn
|
||||
@click.stop="openEmployeeTable(item.title, props.rowIndex)"
|
||||
dense
|
||||
flat
|
||||
size="sm"
|
||||
class="rounded q-mr-xs"
|
||||
>
|
||||
<div class="row items-center no-wrap">
|
||||
<q-icon name="mdi-account-group-outline" />
|
||||
<q-icon
|
||||
size="xs"
|
||||
:name="`mdi-chevron-${currentBtnOpen[0].title === item.title && currentBtnOpen[0].opened[props.rowIndex] ? 'down' : 'up'}`"
|
||||
/>
|
||||
</div>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
icon="mdi-monitor"
|
||||
size="sm"
|
||||
class="rounded q-mr-xs"
|
||||
padding="4px 8px"
|
||||
dense
|
||||
flat
|
||||
style="
|
||||
background-color: hsla(var(--positive-bg) / 0.1);
|
||||
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>
|
||||
</TableComponents>
|
||||
</q-table>
|
||||
</section>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
|
|
@ -495,4 +399,8 @@ watch(
|
|||
bottom: 0;
|
||||
background: var(--side-color);
|
||||
}
|
||||
|
||||
:deep(i.q-icon.mdi.mdi-alert.q-table__bottom-nodata-icon) {
|
||||
color: #ffc224 !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ withDefaults(
|
|||
defineProps<{
|
||||
employeeAmount: number;
|
||||
fallbackImg?: string;
|
||||
hideQuantity?: boolean;
|
||||
inTable?: boolean;
|
||||
rows: {
|
||||
foreignRefNo: string;
|
||||
employeeName: string;
|
||||
|
|
@ -86,6 +88,7 @@ const columns = [
|
|||
bordered
|
||||
button-delete
|
||||
img-column="employeeName"
|
||||
:inTable
|
||||
:columns
|
||||
:rows
|
||||
hidePagination
|
||||
|
|
@ -118,7 +121,7 @@ const columns = [
|
|||
</template>
|
||||
</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">
|
||||
{{ $t('general.numberOf', { msg: $t('quotation.employee') }) }}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ const props = withDefaults(
|
|||
buttomDownload?: boolean;
|
||||
buttonDelete?: boolean;
|
||||
hidePagination?: boolean;
|
||||
inTable?: boolean;
|
||||
|
||||
imgColumn?: string;
|
||||
customColumn?: string[];
|
||||
|
|
@ -52,7 +53,7 @@ defineEmits<{
|
|||
>
|
||||
<template v-slot:header="props">
|
||||
<q-tr
|
||||
style="background-color: hsla(var(--info-bg) / 0.07)"
|
||||
:style="`background-color: ${inTable ? '#F0FFF1' : 'hsla(var(--info-bg) / 0.07'} `"
|
||||
:props="props"
|
||||
>
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||
|
|
|
|||
|
|
@ -688,6 +688,22 @@ watch(
|
|||
|
||||
<ProductItem
|
||||
: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"
|
||||
v-model:groupList="productServiceTableData"
|
||||
v-model:rows="productServiceList"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue