refactor: quotation role check

This commit is contained in:
puriphatt 2025-07-03 15:17:37 +07:00
parent d880e1a1c5
commit 2269038e11
4 changed files with 34 additions and 21 deletions

View file

@ -19,6 +19,7 @@ const props = withDefaults(
page?: number;
pageSize?: number;
hideBtnPreview?: boolean;
hideAction?: boolean;
}>(),
{
row: () => [],
@ -149,6 +150,7 @@ defineEmits<{
/>
<KebabAction
v-if="!hideAction"
:idName="`btn-kebab-${props.row.workName}`"
status="'ACTIVE'"
hide-toggle

View file

@ -14,7 +14,7 @@ import useMyBranch from 'stores/my-branch';
import { useQuotationForm } from './form';
import { hslaColors } from './constants';
import { pageTabs, columnQuotation } from './constants';
import { toCamelCase } from 'stores/utils';
import { toCamelCase, canAccess } from 'stores/utils';
// NOTE Import Types
import { CustomerBranchCreate, CustomerType } from 'stores/customer/types';
@ -413,6 +413,7 @@ async function storeDataLocal(id: string) {
hide-icon
style="z-index: 999"
@click.stop="triggerAddQuotationDialog"
v-if="canAccess('related', 'edit')"
/>
<div class="column full-height no-wrap">
@ -647,12 +648,20 @@ async function storeDataLocal(id: string) {
class="col surface-2 flex items-center justify-center"
>
<NoData
v-if="pageState.inputSearch || pageState.currentTab !== 'Issued'"
v-if="
pageState.inputSearch ||
!canAccess('related', 'edit') ||
pageState.currentTab !== 'Issued'
"
:not-found="!!pageState.inputSearch"
/>
<CreateButton
v-if="!pageState.inputSearch && pageState.currentTab === 'Issued'"
v-if="
!pageState.inputSearch &&
pageState.currentTab === 'Issued' &&
canAccess('related', 'edit')
"
@click="triggerAddQuotationDialog"
label="general.add"
:i18n-args="{ text: $t('quotation.title') }"
@ -675,6 +684,7 @@ async function storeDataLocal(id: string) {
"
>
<TableQuotation
:hide-action="!canAccess('related', 'edit')"
:page="quotationPage"
:page-size="quotationPageSize"
:columns="columnQuotation"
@ -708,6 +718,7 @@ async function storeDataLocal(id: string) {
<QuotationCard
class="col"
hide-kebab-delete
:hide-action="!canAccess('related', 'edit')"
:hide-kebab-edit="!(pageState.currentTab === 'Issued')"
:hide-preview="pageState.currentTab === 'PaymentSuccess'"
:urgent="item.row.urgent"

View file

@ -29,6 +29,7 @@ const { data: config } = storeToRefs(configStore);
const prop = defineProps<{
data?: Quotation | QuotationFull | DebitNote;
readonly?: boolean;
isDebitNote?: boolean;
}>();
@ -521,6 +522,7 @@ onMounted(async () => {
<div class="q-ml-auto row" style="gap: 10px">
<q-btn
:disable="readonly"
id="btn-payment"
@click.stop
unelevated
@ -547,7 +549,11 @@ onMounted(async () => {
<span>
{{ $t(`quotation.receiptDialog.${p.paymentStatus}`) }}
</span>
<q-icon name="mdi-chevron-down" class="q-pl-xs" />
<q-icon
v-if="!readonly"
name="mdi-chevron-down"
class="q-pl-xs"
/>
<q-menu
ref="refQMenu"
fit
@ -634,6 +640,7 @@ onMounted(async () => {
})
}}
<q-btn
v-if="!readonly"
unelevated
id="btn-upload-file"
:label="$t('general.upload')"
@ -762,10 +769,10 @@ onMounted(async () => {
}
:deep(
.q-expansion-item
.q-item.q-item-type.row.no-wrap.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable
.q-focus-helper
) {
.q-expansion-item
.q-item.q-item-type.row.no-wrap.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable
.q-focus-helper
) {
visibility: hidden;
}
</style>

View file

@ -8,6 +8,7 @@ import {
dialogCheckData,
dialogWarningClose,
formatNumberDecimal,
canAccess,
} from 'stores/utils';
import { ProductTree, quotationProductTree } from './utils';
@ -213,17 +214,6 @@ const attachmentData = ref<
url?: string;
}[]
>([]);
const hideBtnApproveInvoice = computed(() => {
const role = getRole();
const allowedRoles = [
'system',
'head_of_admin',
'admin',
'head_of_accountant',
'accountant',
];
return !role || !role.some((r) => allowedRoles.includes(r));
});
const getToolbarConfig = computed(() => {
const toolbar = [['left', 'center', 'justify'], ['toggle'], ['clip']];
@ -1746,7 +1736,7 @@ function covertToNode() {
:readonly="
{
quotation: quotationFormState.mode !== 'edit',
invoice: false,
invoice: !canAccess('related', 'edit'),
accepted: true,
}[view]
"
@ -1950,6 +1940,7 @@ function covertToNode() {
view !== View.Receipt &&
view !== View.Complete
"
:readonly="!canAccess('related', 'edit')"
:data="quotationFormState.source"
v-model:first-code-payment="firstCodePayment"
@fetch-status="
@ -2281,6 +2272,7 @@ function covertToNode() {
class="q-ml-sm"
v-if="
view === View.Accepted &&
canAccess('related', 'edit') &&
quotationFormData.quotationStatus === 'Issued'
"
>
@ -2320,6 +2312,7 @@ function covertToNode() {
class="q-ml-sm"
v-if="
view === View.Invoice &&
canAccess('related', 'edit') &&
((quotationFormData.quotationStatus !== 'PaymentPending' &&
quotationFormData.payCondition !== 'Full') ||
quotationFormData.quotationStatus === 'Accepted') &&
@ -2327,7 +2320,6 @@ function covertToNode() {
"
>
<MainButton
v-if="!hideBtnApproveInvoice"
solid
icon="mdi-account-multiple-check-outline"
color="207 96% 32%"
@ -2347,6 +2339,7 @@ function covertToNode() {
style="gap: var(--size-2)"
v-if="
(view === View.Quotation &&
canAccess('related', 'edit') &&
(quotationFormData.quotationStatus === 'Issued' ||
quotationFormData.quotationStatus === 'Expired')) ||
!quotationFormData.quotationStatus