feat: add seller filtering and enhance quotation forms with sellerId
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 6s

This commit is contained in:
puriphatt 2025-07-07 14:34:39 +07:00
parent f08c83c98b
commit 1e34f18366
9 changed files with 41 additions and 5 deletions

View file

@ -106,6 +106,7 @@ watch(
:persistent="isDateSelect"
>
<div class="q-pa-sm">
<slot name="prepend"></slot>
<div class="text-weight-medium">
{{ $t('general.advanceSearch') }}
</div>

View file

@ -768,6 +768,7 @@ export default {
},
quotation: {
ownOnly: 'View Own Quotation Only',
quotationDate: 'Quotation Date',
seller: 'Seller',
paymentChannels: 'Payment Channels',

View file

@ -766,6 +766,7 @@ export default {
},
quotation: {
ownOnly: 'เห็นเฉพาะใบเสนอราคาของตัวเอง',
quotationDate: 'วันที่ใบเสนอราคา',
seller: 'ผู้ขาย',
paymentChannels: 'ช่องทางชำระเงิน',

View file

@ -15,6 +15,7 @@ import { useQuotationForm } from './form';
import { hslaColors } from './constants';
import { pageTabs, columnQuotation } from './constants';
import { toCamelCase, canAccess } from 'stores/utils';
import { getUserId } from 'src/services/keycloak';
// NOTE Import Types
import { CustomerBranchCreate, CustomerType } from 'stores/customer/types';
@ -104,6 +105,7 @@ const pageState = reactive({
fieldSelected: [''],
gridView: false,
total: 0,
sellerId: '',
currentTab: 'Issued',
addModal: false,
@ -297,6 +299,7 @@ onMounted(async () => {
pageSize: quotationPageSize.value,
status: 'Issued',
urgentFirst: true,
sellerId: pageState.sellerId || undefined,
});
if (ret) {
@ -331,6 +334,7 @@ async function fetchQuotationList(mobileFetch?: boolean) {
urgentFirst: true,
startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1],
sellerId: pageState.sellerId || undefined,
});
if (ret) {
@ -406,6 +410,11 @@ async function storeDataLocal(id: string) {
window.open(url, '_blank');
}
async function filterBySellerId() {
pageState.sellerId = pageState.sellerId ? '' : getUserId();
await fetchQuotationList();
}
</script>
<template>
@ -529,7 +538,18 @@ async function storeDataLocal(id: string) {
</template>
<template v-slot:append>
<q-separator vertical inset class="q-mr-xs" />
<AdvanceSearch v-model="pageState.searchDate" />
<AdvanceSearch v-model="pageState.searchDate">
<template #prepend>
<div class="text-weight-medium q-mb-sm">
<q-checkbox
size="xs"
:model-value="!!pageState.sellerId"
@click="filterBySellerId"
/>
{{ $t('quotation.ownOnly') }}
</div>
</template>
</AdvanceSearch>
</template>
</q-input>

View file

@ -2,6 +2,7 @@
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { QSelect, useQuasar } from 'quasar';
import { getUserId } from 'src/services/keycloak';
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
import {
baseUrl,
@ -78,7 +79,6 @@ import { api } from 'src/boot/axios';
import { RouterLink, useRoute } from 'vue-router';
import { initLang, initTheme, Lang } from 'src/utils/ui';
import { convertTemplate } from 'src/utils/string-template';
import { getRole } from 'src/services/keycloak';
type Node = {
[key: string]: any;
@ -616,6 +616,7 @@ async function convertDataToFormSubmit() {
discount: quotationFormData.value.discount,
remark: quotationFormData.value.remark || '',
agentPrice: agentPrice.value,
sellerId: quotationFormData.value.sellerId,
};
newWorkerList.value = [];
@ -1015,6 +1016,7 @@ onMounted(async () => {
quotationFormData.value.customerBranchId = parsed.customerBranchId;
currentQuotationId.value = parsed.quotationId;
agentPrice.value = parsed.agentPrice;
quotationFormData.value.sellerId = getUserId();
await fetchQuotation();
await assignWorkerToSelectedWorker();
sessionData.value = parsed;
@ -1506,6 +1508,7 @@ function covertToNode() {
v-model:contactor="quotationFormData.contactName"
v-model:telephone="quotationFormData.contactTel"
v-model:due-date="quotationFormData.dueDate"
v-model:seller-id="quotationFormData.sellerId"
>
<template #issue-info>
<FormAbout
@ -2110,8 +2113,6 @@ function covertToNode() {
installmentAmount = props.row.amount;
view = View.Invoice;
console.log(code);
}
}
"

View file

@ -1,5 +1,6 @@
<script setup lang="ts">
import DatePicker from 'src/components/shared/DatePicker.vue';
import SelectUser from 'src/components/shared/select/SelectUser.vue';
defineProps<{
readonly: boolean;
@ -13,6 +14,7 @@ const contactor = defineModel<string>('contactor', { required: true });
const telephone = defineModel<string>('telephone', { required: true });
const dueDate = defineModel<Date | string>('dueDate', { required: true });
const createdAt = defineModel<Date | string>('createdAt');
const sellerId = defineModel<string>('sellerId', { required: true });
</script>
<template>
@ -95,5 +97,11 @@ const createdAt = defineModel<Date | string>('createdAt');
dense
outlined
/>
<SelectUser
:label="$t('preview.seller')"
v-model:value="sellerId"
:readonly
class="col-12 col-md-2"
/>
</div>
</template>

View file

@ -8,6 +8,7 @@ import {
QuotationPayload,
QuotationFull,
EmployeeWorker,
PayCondition,
} from 'src/stores/quotations/types';
import { Employee } from 'src/stores/employee/types';
@ -29,7 +30,7 @@ export const DEFAULT_DATA: QuotationPayload = {
payBillDate: new Date(),
paySplit: [],
paySplitCount: 0,
payCondition: 'Full',
payCondition: PayCondition.Full,
dueDate: new Date(Date.now() + 86400000),
discount: 0,
contactTel: '',
@ -40,6 +41,7 @@ export const DEFAULT_DATA: QuotationPayload = {
status: 'CREATED',
remark: '#[quotation-labor]<br/><br/>#[quotation-payment]',
agentPrice: false,
sellerId: '',
};
const DEFAULT_DATA_INVOICE: InvoicePayload = {

View file

@ -78,6 +78,7 @@ export const useQuotationStore = defineStore('quotation-store', () => {
cancelIncludeDebitNote?: boolean;
startDate?: string;
endDate?: string;
sellerId?: string;
}) {
const res = await api.get<PaginationResult<Quotation>>('/quotation', {
params,

View file

@ -356,6 +356,7 @@ export type QuotationPayload = {
_count: { worker: number };
discount?: number;
payBillDate?: Date | null;
sellerId?: string;
paySplit: {
no: number;
amount: number;