feat: add support for debit notes in credit note forms and related components
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 7s

This commit is contained in:
puriphatt 2025-07-08 13:28:27 +07:00
parent 7679c076a7
commit 2b310c667d
7 changed files with 40 additions and 7 deletions

View file

@ -36,7 +36,7 @@ withDefaults(
<span
:class="{ 'link cursor-pointer': clickable }"
v-if="typeof value === 'string'"
@click="$emit('labelClick', value, null)"
@click="clickable ? $emit('labelClick', value, null) : undefined"
>
{{ value }}
<q-tooltip v-if="tooltip" :delay="500">{{ value }}</q-tooltip>

View file

@ -8,6 +8,10 @@ defineProps<{
const quotationId = defineModel<string>('quotationId', {
required: true,
});
const isDebitNote = defineModel<boolean>('isDebitNote', {
required: false,
default: false,
});
</script>
<template>
<div class="row col-12">
@ -37,6 +41,7 @@ const quotationId = defineModel<string>('quotationId', {
cancelIncludeDebitNote: true,
hasCancel: true,
}"
@selected="(v) => (isDebitNote = v.isDebitNote)"
/>
</section>
</div>

View file

@ -25,6 +25,7 @@ const { getQuotationList: getList, getQuotation: getById } = useStore();
defineEmits<{
(e: 'create'): void;
(e: 'selected', value: SelectOption): void;
}>();
type ExclusiveProps = {
@ -117,6 +118,14 @@ function setDefaultValue() {
(v: string) => !props.required || !!v || $t('form.error.required'),
]"
@filter="filter"
@update:model-value="
(v) => {
$emit(
'selected',
selectOptions.find((opt) => opt.id === v),
);
}
"
>
<template #append v-if="clearable">
<q-icon

View file

@ -4,7 +4,7 @@ import { api } from 'src/boot/axios';
import { useRoute, useRouter } from 'vue-router';
import { dateFormatJS } from 'src/utils/datetime';
import { initLang, initTheme } from 'src/utils/ui';
import { useQuotationStore } from 'src/stores/quotations';
import { QuotationFull, useQuotationStore } from 'src/stores/quotations';
import {
CreditNote,
CreditNotePaybackStatus,
@ -31,6 +31,7 @@ import {
EditButton,
UndoButton,
} from 'src/components/button';
import { DebitNote, useDebitNote } from 'src/stores/debit-note';
import { RequestWork } from 'src/stores/request-list/types';
import { storeToRefs } from 'pinia';
import useOptionStore from 'src/stores/options';
@ -42,6 +43,7 @@ import { getName } from 'src/services/keycloak';
const route = useRoute();
const router = useRouter();
const creditNote = useCreditNote();
const debitNote = useDebitNote();
const quotation = useQuotationStore();
const configStore = useConfigStore();
const { data: config } = storeToRefs(configStore);
@ -49,7 +51,7 @@ const { t } = useI18n();
const refForm = ref<InstanceType<typeof QForm>>();
const creditNoteData = ref<CreditNote>();
const quotationData = ref<CreditNote['quotation']>();
const quotationData = ref<DebitNote | QuotationFull>();
const view = ref<CreditNoteStatus | null>(null);
const fileList = ref<FileList>();
const attachmentList = ref<FileList>();
@ -286,7 +288,10 @@ async function getQuotation() {
return;
}
const ret = await quotation.getQuotation(route.query['quotationId']);
const isDebitNote = route.query['isDebitNote'] === 'true';
const ret = isDebitNote
? await debitNote.getDebitNote(route.query['quotationId'])
: await quotation.getQuotation(route.query['quotationId']);
if (!ret) return;
@ -639,6 +644,10 @@ onMounted(async () => {
</nav>
<DocumentExpansion
:noLink="
route.query['isDebitNote'] === 'true' ||
quotationData?.code.startsWith('DN')
"
readonly
:registered-branch-id="quotationData?.registeredBranchId"
:customer-id="quotationData?.customerBranchId"

View file

@ -45,6 +45,7 @@ const pageState = reactive({
.map((v) => v.name),
gridView: false,
total: 0,
isDebitNote: false,
creditDialog: false,
searchDate: [],
@ -108,13 +109,17 @@ function navigateTo(opts: {
if (opts.statusDialog === 'create') {
url.searchParams.append('quotationId', opts.quotationId || '');
url.searchParams.append('isDebitNote', pageState.isDebitNote.toString());
}
window.open(url.toString(), '_blank');
}
async function submit() {
navigateTo({ statusDialog: 'create', quotationId: pageState.quotationId });
navigateTo({
statusDialog: 'create',
quotationId: pageState.quotationId,
});
close();
}
@ -480,7 +485,10 @@ watch(
<section class="q-pa-md col full-width">
<div class="surface-1 rounded bordered q-pa-md full-height full-width">
<FormCredit v-model:quotation-id="pageState.quotationId" />
<FormCredit
v-model:quotation-id="pageState.quotationId"
v-model:is-debit-note="pageState.isDebitNote"
/>
</div>
</section>

View file

@ -6,6 +6,7 @@ import DataDisplay from 'src/components/08_request-list/DataDisplay.vue';
defineProps<{
readonly?: boolean;
noLink?: boolean;
}>();
defineEmits<{
@ -61,7 +62,7 @@ const quotationCreatedBy = defineModel<string>('quotationCreatedBy');
/>
<DataDisplay
clickable
:clickable="!noLink"
class="col-md col-6"
style="padding-inline: 20px"
:label="$t('creditNote.label.quotationCode')"

View file

@ -268,6 +268,7 @@ export type Quotation = {
updatedByUserId: string;
updatedBy: UpdatedBy;
updatedAt: string | Date;
isDebitNote?: boolean;
};
export type QuotationFull = {