Files
web/app/components/transaction/ChangeCustomerModal.vue
2026-05-05 11:06:49 +07:00

231 lines
7.0 KiB
Vue

<script setup>
import { useStore } from "~/stores/index";
import { useAdvancedWorkflow } from "~/composables/useAdvancedWorkflow";
import Contract from "~/components/application/Contract.vue";
import Datepicker from "~/components/datepicker/Datepicker.vue";
import dayjs from "dayjs";
const props = defineProps({
transactionId: Number,
});
const emit = defineEmits(["close", "modalevent"]);
const { $getdata, $snackbar } = useNuxtApp();
const store = useStore();
const { updateTransactionCustomer, isLoading } = useAdvancedWorkflow();
const transaction = ref(null);
const currentCustomer = ref(null);
const newCustomer = ref(null);
const workflowResult = ref(null);
const showContract = ref(false);
const contractId = ref(null);
// Contract Date
const initialContractDate = dayjs().format("YYYY-MM-DD");
const contractDate = ref(initialContractDate);
const dateRecord = ref({ contractDate: initialContractDate });
const customerViewAddon = {
component: "customer/CustomerView",
width: "70%",
height: "600px",
title: "Chi tiết khách hàng",
};
const customerViewAdd = {
component: "customer/CustomerInfo2",
width: "60%",
height: "auto",
title: "Chỉnh sửa khách hàng",
};
onMounted(async () => {
if (props.transactionId) {
transaction.value = await $getdata("transaction", { id: props.transactionId }, undefined, true);
if (transaction.value && transaction.value.customer) {
currentCustomer.value = await $getdata("customer", { id: transaction.value.customer }, undefined, true);
}
}
});
function updateContractDate(newDate) {
contractDate.value = newDate;
dateRecord.value.contractDate = newDate;
}
function updateTransactionCustomerDisplay(result) {
if (result?.success) {
const contract = result?.contract;
if (contract && contract.id) {
$snackbar(`Đổi khách hàng thành công. Hợp đồng mới được tạo với ID: ${contract.id}`, { type: "is-success" });
contractId.value = contract.id;
showContract.value = true;
}
}
}
async function confirmChangeCustomer() {
if (!newCustomer.value) {
$snackbar("Vui lòng chọn khách hàng mới.", { type: "is-warning" });
return;
}
workflowResult.value = null;
try {
const result = await updateTransactionCustomer(props.transactionId, newCustomer.value.id, contractDate.value);
workflowResult.value = result;
updateTransactionCustomerDisplay(result);
} catch (error) {
console.error("Workflow execution error:", error);
$snackbar("Có lỗi xảy ra khi thực thi workflow.", { type: "is-danger" });
}
}
</script>
<template>
<div v-if="!showContract">
<div v-if="transaction && currentCustomer">
<h3 class="fsb-18 mb-3"> giao dịch: {{ transaction.code }}</h3>
<div class="mb-4">
<h4 class="is-size-6 has-text-weight-bold mb-2">Khách hàng hiện tại</h4>
<div class="is-flex is-flex-wrap-wrap is-gap-4">
<div>
<p class="has-text-grey is-size-7"></p>
<p class="is-size-6">{{ currentCustomer.code }}</p>
</div>
<div>
<p class="has-text-grey is-size-7">Tên</p>
<p class="is-size-6">
{{ currentCustomer.name || currentCustomer.fullname }}
</p>
</div>
<div>
<p class="has-text-grey is-size-7">Loại</p>
<p class="is-size-6">
<span
class="tag"
:class="currentCustomer.type === 1 ? 'is-info' : 'is-warning'"
>{{ currentCustomer.type === 1 ? "Cá nhân" : "Tổ chức" }}</span
>
</p>
</div>
<div>
<p class="has-text-grey is-size-7">Điện thoại</p>
<p class="is-size-6">{{ currentCustomer.phone }}</p>
</div>
<div>
<p class="has-text-grey is-size-7">Email</p>
<p class="is-size-6">{{ currentCustomer.email }}</p>
</div>
</div>
</div>
<div class="field mb-3">
<label class="label">Chọn khách hàng mới<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<SearchBox
v-bind="{
api: 'customer',
field: 'label',
searchfield: ['code', 'fullname', 'phone', 'legal_code'],
column: ['code', 'fullname', 'phone', 'legal_code'],
first: true,
viewaddon: customerViewAddon,
addon: customerViewAdd,
placeholder: 'Tìm khách hàng theo mã, tên, số điện thoại hoặc CMND',
}"
@option="
(customer) => {
newCustomer = customer;
}
"
/>
</div>
</div>
<div
v-if="newCustomer"
class="mb-4"
>
<h4 class="is-size-6 has-text-weight-bold mb-2">Khách hàng mới được chọn</h4>
<div class="is-flex is-flex-wrap-wrap is-gap-4">
<div>
<p class="has-text-grey is-size-7">Mã</p>
<p class="is-size-6">{{ newCustomer.code }}</p>
</div>
<div>
<p class="has-text-grey is-size-7">Tên</p>
<p class="is-size-6">
{{ newCustomer.name || newCustomer.fullname }}
</p>
</div>
<div>
<p class="has-text-grey is-size-7">Loại</p>
<p class="is-size-6">
<span
class="tag"
:class="newCustomer.type === 1 ? 'is-info' : 'is-warning'"
>{{ newCustomer.type === 1 ? "Cá nhân" : "Tổ chức" }}</span
>
</p>
</div>
<div>
<p class="has-text-grey is-size-7">Điện thoại</p>
<p class="is-size-6">{{ newCustomer.phone }}</p>
</div>
<div>
<p class="has-text-grey is-size-7">Email</p>
<p class="is-size-6">{{ newCustomer.email }}</p>
</div>
</div>
</div>
<div class="field mb-4">
<label class="label">Ngày ký hợp đồng mới<b class="ml-1 has-text-danger">*</b></label>
<div
class="control"
style="max-width: 200px"
>
<Datepicker
:record="dateRecord"
attr="contractDate"
@date="updateContractDate"
position="is-top-left"
/>
</div>
</div>
<div class="is-flex is-justify-content-flex-end is-gap-2">
<button
class="button"
@click="$emit('close')"
>
Hủy
</button>
<button
class="button is-primary"
:disabled="!newCustomer"
:class="{ 'is-loading': isLoading }"
@click="confirmChangeCustomer"
>
Xác nhận
</button>
</div>
</div>
<div
v-else
class="is-flex is-justify-content-center is-align-items-center"
style="min-height: 200px"
>
<div class="loader"></div>
</div>
</div>
<div v-else>
<Contract :contractId="contractId" />
</div>
</template>