feat: payment view

This commit is contained in:
Methapon Metanipat 2024-10-28 16:44:14 +07:00
parent 639dc36d71
commit d9f8d0f971
4 changed files with 53 additions and 76 deletions

View file

@ -3,27 +3,25 @@ import { baseUrl } from 'stores/utils';
import { storeToRefs } from 'pinia';
import { useConfigStore } from 'stores/config';
import { formatNumberDecimal } from 'stores/utils';
import DialogForm from 'src/components/DialogForm.vue';
import { reactive, ref, watch } from 'vue';
import { reactive, ref } from 'vue';
import { useQuotationPayment } from 'src/stores/quotations';
import {
PaymentPayload,
Quotation,
QuotationFull,
QuotationPaymentData,
} from 'src/stores/quotations/types';
import { dateFormat } from 'src/utils/datetime';
import { QFile, QMenu } from 'quasar';
import UploadFileCard from 'src/components/upload-file/UploadFileCard.vue';
import { onMounted } from 'vue';
const configStore = useConfigStore();
const quotationPayment = useQuotationPayment();
const { data: config } = storeToRefs(configStore);
const model = defineModel<boolean>({ default: false, required: true });
const data = defineModel<Quotation | undefined>('data', { required: true });
const prop = defineProps<{ data?: Quotation | QuotationFull }>();
const fileManager =
ref<ReturnType<typeof quotationPayment.createPaymentFileManager>>();
const refQFile = ref<InstanceType<typeof QFile>[]>([]);
const refQMenu = ref<InstanceType<typeof QMenu>[]>([]);
const paymentData = ref<QuotationPaymentData[]>([]);
@ -51,7 +49,6 @@ const paymentStatusOpts = [
];
const slipFile = ref<
{
quotationId: string;
paymentId: string;
data: { name: string; progress: number; loaded: number; total: number }[];
file?: File;
@ -74,8 +71,7 @@ function pickFile(index: number) {
}
async function getSlipList(payment: QuotationPaymentData, index: number) {
if (!fileManager.value) return;
const slipList = await fileManager.value.listAttachment({
const slipList = await quotationPayment.listAttachment({
parentId: payment.id,
});
@ -106,19 +102,18 @@ async function triggerUpload(
index: number,
file?: File,
) {
if (!data.value || !fileManager.value || !file) return;
if (!file) return;
slipFile.value[index].data.push({
name: file.name,
progress: 0,
loaded: 0,
total: 0,
});
const ret = await fileManager.value.putAttachment({
const ret = await quotationPayment.putAttachment({
parentId: payment.id,
name: file.name,
file: file,
onUploadProgress: (e) => {
console.log(e);
slipFile.value[index].data[slipFile.value[index].data.length - 1] = {
name: file.name,
progress: e.progress || 0,
@ -136,14 +131,12 @@ async function triggerDelete(
name: string,
index: number,
) {
if (!data.value || !fileManager.value) return;
await fileManager.value.delAttachment({ parentId: payment.id, name });
await quotationPayment.delAttachment({ parentId: payment.id, name });
await getSlipList(payment, index);
}
function triggerViewSlip(payment: QuotationPaymentData, name: string) {
if (!data.value || !fileManager.value) return;
const url = `${baseUrl}/quotation/${data.value.id}/payment/${payment.id}/attachment/${name}`;
const url = `${baseUrl}/payment/${payment.id}/attachment/${name}`;
window.open(url, '_blank');
}
@ -168,60 +161,36 @@ function selectStatus(
async function triggerSubmit() {
submitPaymentData.value.forEach(async (p) => {
if (!data.value) return;
const payload: PaymentPayload = {
paymentStatus: p.paymentStatus,
remark: p.remark || '',
date: new Date(p.date),
amount: p.amount,
};
await quotationPayment.updateQuotationPayment(data.value.id, p.id, payload);
await quotationPayment.updateQuotationPayment(p.id, payload);
});
model.value = false;
}
watch(
() => model.value,
async (open) => {
if (!data.value) return;
if (!open) {
paymentData.value = [];
state.payExpansion = [];
slipFile.value = [];
submitPaymentData.value = [];
} else {
fileManager.value = quotationPayment.createPaymentFileManager(
data.value.id,
);
const ret = await quotationPayment.getQuotationPayment(data.value.id);
if (ret) {
paymentData.value = ret.quotationPaymentData;
slipFile.value = paymentData.value.map((v) => ({
quotationId: ret.id,
paymentId: v.id,
data: [],
}));
}
}
},
);
onMounted(async () => {
if (!prop.data) return;
const ret = await quotationPayment.getQuotationPayment(prop.data.id);
if (ret) {
paymentData.value = ret.result;
slipFile.value = paymentData.value.map((v) => ({
paymentId: v.id,
data: [],
}));
}
});
</script>
<template>
<DialogForm
:title="$t('quotation.receipt')"
v-model:modal="model"
width="65%"
:submit="() => triggerSubmit()"
<q-form
greedy
@submit.prevent
@validation-success="triggerSubmit"
class="column full-height"
v-if="data"
>
<div
v-if="data"
class="col column no-wrap"
:class="{
'q-mx-lg q-my-md': $q.screen.gt.sm,
'q-mx-md q-my-sm': !$q.screen.gt.sm,
}"
>
<div class="col column no-wrap">
<!-- PRICE DETAIL -->
<section class="bordered rounded surface-1" style="overflow: hidden">
<q-expansion-item
@ -662,7 +631,7 @@ watch(
</section>
</section>
</div>
</DialogForm>
</q-form>
</template>
<style scoped>
.bg-color-orange {

View file

@ -67,6 +67,7 @@ import { precisionRound } from 'src/utils/arithmetic';
import { useConfigStore } from 'src/stores/config';
import QuotationFormMetadata from './QuotationFormMetadata.vue';
import BadgeComponent from 'src/components/BadgeComponent.vue';
import PaymentForm from './PaymentForm.vue';
// defineProps<{
// readonly?: boolean;
@ -905,7 +906,15 @@ const view = ref<View>(View.Quotation);
/>
</div>
</div>
<template v-if="true">
<template
v-if="
view === View.Quotation ||
view === View.Accepted ||
view === View.Invoice ||
view === View.Payment ||
view === View.Receipt
"
>
<q-expansion-item
for="item-up"
id="item-up"
@ -1204,6 +1213,9 @@ const view = ref<View>(View.Quotation);
</div>
</q-expansion-item>
</template>
<template v-else>
<PaymentForm :data="quotationFormState.source" />
</template>
</div>
</section>
</article>

View file

@ -13,7 +13,6 @@ import {
QuotationStatus,
} from './types';
import { PaginationResult } from 'src/types';
import { AxiosProgressEvent } from 'axios';
import { manageAttachment } from '../utils';
@ -140,9 +139,9 @@ export const useQuotationStore = defineStore('quotation-store', () => {
export const useQuotationPayment = defineStore('quotation-payment', () => {
async function getQuotationPayment(quotationId: string) {
const res = await api.get<
Quotation & { quotationPaymentData: QuotationPaymentData[] }
>(`/quotation/${quotationId}/payment`);
const res = await api.get<PaginationResult<QuotationPaymentData>>(
`/payment/${quotationId}`,
);
if (res.status < 400) {
return res.data;
}
@ -150,12 +149,11 @@ export const useQuotationPayment = defineStore('quotation-payment', () => {
}
async function updateQuotationPayment(
quotationId: string,
paymentId: string,
payload: PaymentPayload,
) {
const res = await api.put<PaymentPayload & { id: string }>(
`/quotation/${quotationId}/payment/${paymentId}`,
`/payment/${paymentId}`,
payload,
);
if (res.status < 400) {
@ -164,16 +162,12 @@ export const useQuotationPayment = defineStore('quotation-payment', () => {
return null;
}
function createPaymentFileManager(
quotationId: string,
opts?: { onUploadProgress: (e: AxiosProgressEvent) => void },
) {
return manageAttachment(api, `quotation/${quotationId}/payment`, opts);
}
const fileManager = manageAttachment(api, `payment`);
return {
getQuotationPayment,
createPaymentFileManager,
updateQuotationPayment,
...fileManager,
};
});

View file

@ -270,6 +270,8 @@ export type QuotationFull = {
id: string;
finalPrice: number;
vat: number;
vatExcluded: number;
discount: number;
totalDiscount: number;
totalPrice: number;
urgent: boolean;
@ -283,6 +285,7 @@ export type QuotationFull = {
contactTel: string;
contactName: string;
workName: string;
workerMax: number | null;
code: string;
statusOrder: number;
status: Status;
@ -297,6 +300,7 @@ export type QuotationFull = {
| 'Canceled';
customerBranchId: string;
customerBranch: CustomerBranchRelation;
registeredBranchId: string;
registeredBranch: { id: string; name: string };
@ -372,7 +376,6 @@ export type ProductGroup = {
};
export type QuotationPaymentData = {
quotationId: string;
paymentStatus: string;
amount: number;
remark: string;
@ -393,7 +396,6 @@ export type Details = {
export type PaymentPayload = {
paymentStatus: string;
remark: string;
date: Date;
amount: number;
};