Initial commit
This commit is contained in:
783
app/components/customer/CustomerInfo.vue
Normal file
783
app/components/customer/CustomerInfo.vue
Normal file
@@ -0,0 +1,783 @@
|
||||
<template v-if="isLoaded">
|
||||
<div v-if="record && isLoaded">
|
||||
<div class="columns is-multiline mx-0">
|
||||
<div :class="`column is-2 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("custcode")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input has-text-black"
|
||||
disabled
|
||||
type="text"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.code">{{ errors.code }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-4 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("name")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="" />
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.fullname">
|
||||
{{ errors.fullname }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("phone_number")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<InputPhone
|
||||
v-bind="{ record: record, attr: 'phone', placeholder: '' }"
|
||||
@phone="selected('phone', $event)"
|
||||
>
|
||||
</InputPhone>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.phone">
|
||||
{{ errors.phone }}
|
||||
<a
|
||||
class="has-text-primary"
|
||||
v-if="existedCustomer"
|
||||
@click="showCustomer()"
|
||||
>Chi tiết</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label">Email</label>
|
||||
<div class="control">
|
||||
<InputEmail
|
||||
v-bind="{ record: record, attr: 'email', placeholder: '' }"
|
||||
@email="selected('email', $event)"
|
||||
>
|
||||
</InputEmail>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.email">{{ errors.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("gender")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
vdata: store.sex,
|
||||
api: 'sex',
|
||||
field: isVietnamese ? 'name' : 'en',
|
||||
column: ['name', 'en'],
|
||||
first: true,
|
||||
optionid: record.sex,
|
||||
}"
|
||||
@option="selected('sex', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("birth_date")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<Datepicker
|
||||
v-bind="{ record: record, attr: 'dob', maxdate: new Date() }"
|
||||
@date="selected('dob', $event)"
|
||||
>
|
||||
</Datepicker>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.dob">{{ errors.dob }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("country")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
vdata: store.country,
|
||||
api: 'country',
|
||||
field: isVietnamese ? 'name' : 'en',
|
||||
column: ['name', 'en'],
|
||||
first: true,
|
||||
optionid: record.country,
|
||||
}"
|
||||
@option="selected('country', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("province")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.province"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("district")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.district"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-4 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("address")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.address"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.address"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-5 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label">{{
|
||||
dataLang && findFieldName("company")[lang]
|
||||
}}</label>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'company',
|
||||
field: 'fullname',
|
||||
column: ['fullname'],
|
||||
first: true,
|
||||
optionid: record.company,
|
||||
addon: companyAddon,
|
||||
viewaddon: companyviewAddon,
|
||||
}"
|
||||
@option="selected('company', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="`column is-3 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("personal_id")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
vdata: store.legaltype,
|
||||
api: 'legaltype',
|
||||
field: isVietnamese ? 'name' : 'en',
|
||||
column: ['name', 'en'],
|
||||
first: true,
|
||||
optionid: record.legal_type,
|
||||
}"
|
||||
@option="selected('legal_type', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("idnum")[lang] }}
|
||||
<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.legal_code"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.legal_code">
|
||||
{{ errors.legal_code }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-2 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("issued_date")[lang] }}
|
||||
<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<Datepicker
|
||||
v-bind="{
|
||||
record: record,
|
||||
attr: 'issued_date',
|
||||
maxdate: new Date(),
|
||||
position: 'is-top-left',
|
||||
}"
|
||||
@date="selected('issued_date', $event)"
|
||||
></Datepicker>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.issued_date">
|
||||
{{ errors.issued_date }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-4 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>{{ dataLang && findFieldName("issued_place")[lang] }}
|
||||
<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.issued_place"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.issued_place"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 px-0 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label">Zalo</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.zalo"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`column is-3 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label">Facebook</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.facebook"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="`column px-0 is-6 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<div class="field">
|
||||
<label class="label">{{
|
||||
dataLang && findFieldName("note")[lang]
|
||||
}}</label>
|
||||
<div class="control">
|
||||
<textarea
|
||||
class="textarea"
|
||||
:placeholder="isVietnamese ? 'Nhập ghi chú...' : 'Enter note...'"
|
||||
v-model="record.note"
|
||||
rows="1"
|
||||
></textarea>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.note">{{ errors.note }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4 mt-5">
|
||||
<Caption
|
||||
v-bind="{
|
||||
title: findFieldName('related_person')[lang],
|
||||
type: 'has-text-warning',
|
||||
}"
|
||||
></Caption>
|
||||
</div>
|
||||
<div class="columns mb-0 mx-0" v-for="(v, i) in people">
|
||||
<div :class="`column is-7 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<label class="label" v-if="i === 0"
|
||||
>{{ findFieldName("select")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
position: 'top',
|
||||
api: 'people',
|
||||
field: 'label',
|
||||
column: ['code', 'fullname', 'phone'],
|
||||
first: true,
|
||||
optionid: v.people,
|
||||
addon: peopleAddon,
|
||||
viewaddon: peopleviewAddon,
|
||||
position: 'is-top-left',
|
||||
}"
|
||||
@option="selectPeople($event, v, i)"
|
||||
>
|
||||
</SearchBox>
|
||||
<p class="help is-danger" v-if="v.error">{{ v.error }}</p>
|
||||
</div>
|
||||
<div :class="`column is-3 ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<label class="label" v-if="i === 0"
|
||||
>{{ findFieldName("relationship")[lang]
|
||||
}}<b class="ml-1 has-text-danger">*</b></label
|
||||
>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
vdata: store.relation,
|
||||
position: 'top',
|
||||
api: 'relation',
|
||||
field: store.lang === 'en' ? 'en' : 'name',
|
||||
column: ['code', 'name', 'en'],
|
||||
first: true,
|
||||
optionid: v.relation,
|
||||
position: 'is-top-left',
|
||||
}"
|
||||
@option="selectRelation($event, v, i)"
|
||||
>
|
||||
</SearchBox>
|
||||
</div>
|
||||
<div :class="`column ${viewport === 1 ? 'px-0 pb-1' : ''}`">
|
||||
<label class="label" v-if="i === 0"
|
||||
>{{ findFieldName("addmore")[lang] }}...</label
|
||||
>
|
||||
<button class="button px-2 is-dark mr-3" @click="add()">
|
||||
<SvgIcon
|
||||
v-bind="{ name: 'add1.png', type: 'white', size: 20 }"
|
||||
></SvgIcon>
|
||||
</button>
|
||||
<button class="button px-2 is-warning" @click="remove(v, i)">
|
||||
<SvgIcon
|
||||
v-bind="{ name: 'bin1.svg', type: 'white', size: 20 }"
|
||||
></SvgIcon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<button class="button is-primary has-text-white" @click="update()">
|
||||
{{ store.lang === "en" ? "Save" : "Lưu lại" }}
|
||||
</button>
|
||||
</div>
|
||||
<Modal
|
||||
@close="showmodal = undefined"
|
||||
v-bind="showmodal"
|
||||
v-if="showmodal"
|
||||
></Modal>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, defineEmits } from "vue";
|
||||
import { useNuxtApp } from "#app";
|
||||
import InputPhone from "~/components/common/InputPhone";
|
||||
import InputEmail from "~/components/common/InputEmail";
|
||||
import SearchBox from "~/components/SearchBox";
|
||||
import Datepicker from "~/components/datepicker/Datepicker";
|
||||
import { useStore } from "@/stores/index";
|
||||
const emit = defineEmits(["close", "update"]);
|
||||
const nuxtApp = useNuxtApp();
|
||||
const {
|
||||
$getdata,
|
||||
$updateapi,
|
||||
$insertapi,
|
||||
$empty,
|
||||
$errPhone,
|
||||
$resetNull,
|
||||
$snackbar,
|
||||
$copy,
|
||||
$dayjs,
|
||||
} = nuxtApp;
|
||||
var props = defineProps({
|
||||
pagename: String,
|
||||
row: Object,
|
||||
application: Object,
|
||||
});
|
||||
|
||||
console.log("props", props);
|
||||
|
||||
const store = useStore();
|
||||
const lang = computed(() => store.lang);
|
||||
const isVietnamese = computed(() => lang.value === "vi");
|
||||
const dataLang = ref(store.common);
|
||||
var viewport = store.viewport;
|
||||
var errors = ref({});
|
||||
var record = ref({});
|
||||
const isLoaded = ref(false);
|
||||
const dataCustomer = ref(props.row);
|
||||
|
||||
if (!props.row && props.application) {
|
||||
//create customer by copying information form application
|
||||
let copy = $copy(props.application);
|
||||
let image = await $getdata("applicationfile", {
|
||||
ref: copy.id,
|
||||
file__doc_type__code__in: ["cccd-mt", "cccd-ms", "avatar"],
|
||||
});
|
||||
copy.image = image.map((v) => v.file);
|
||||
delete copy.id;
|
||||
dataCustomer.value = copy;
|
||||
}
|
||||
|
||||
// const formData = ref({
|
||||
// // fullname: dataCustomer.value.fullname || "",
|
||||
// phone: dataCustomer.value.phone || "",
|
||||
// email: dataCustomer.value.email || "",
|
||||
// dob: dataCustomer.value.dob || null,
|
||||
// country: dataCustomer.value.country || 1,
|
||||
// province: dataCustomer.value.province || null,
|
||||
// district: dataCustomer.value.district || "",
|
||||
// address: dataCustomer.value.address || "",
|
||||
// sex: dataCustomer.value.sex || 1,
|
||||
// note: dataCustomer.value.note || "",
|
||||
// legal_type: dataCustomer.value.legal_type || null,
|
||||
// legal_code: dataCustomer.value.legal_code || "",
|
||||
// issued_date: dataCustomer.value.issue_date || null,
|
||||
// issued_place: dataCustomer.value.issue_place || "",
|
||||
// branch: dataCustomer.value.branch || null,
|
||||
// user: dataCustomer.value.user || null,
|
||||
// collaborator: dataCustomer.value.collaborator || null,
|
||||
// updater: dataCustomer.value.updater || store.login.id,
|
||||
// creator: store.login.id,
|
||||
// image: dataCustomer.value.image || null,
|
||||
// });
|
||||
|
||||
var showmodal = ref();
|
||||
var existedCustomer = undefined;
|
||||
var people = ref([]);
|
||||
var peopleAddon = {
|
||||
component: "people/People",
|
||||
with: "65%",
|
||||
height: "600px",
|
||||
title: store.lang === "en" ? "Related persion" : "Người liên quan",
|
||||
};
|
||||
var peopleviewAddon = {
|
||||
component: "people/People",
|
||||
width: "65%",
|
||||
height: "600px",
|
||||
title: store.lang === "en" ? "Related person" : "Người liên quan",
|
||||
};
|
||||
var companyAddon = {
|
||||
component: "customer/Company",
|
||||
with: "55%",
|
||||
height: "400px",
|
||||
title: store.lang === "en" ? "Company" : "Công ty",
|
||||
};
|
||||
var companyviewAddon = {
|
||||
component: "customer/Company",
|
||||
width: "55%",
|
||||
height: "400px",
|
||||
title: store.lang === "en" ? "Company" : "Công ty",
|
||||
};
|
||||
|
||||
async function initData() {
|
||||
try {
|
||||
if (dataCustomer.value.customer) {
|
||||
record.value = { ...dataCustomer.value.customer, ...formData.value };
|
||||
people.value = [{}];
|
||||
} else if (dataCustomer.value.id) {
|
||||
record.value = props.row;
|
||||
let rows = await $getdata("customerpeople", {
|
||||
customer: dataCustomer.value.id,
|
||||
});
|
||||
people.value = rows.length > 0 ? rows : [{}];
|
||||
} else {
|
||||
const customerCode = await $getdata("getcodeCustomer");
|
||||
record.value = { ...formData.value, code: customerCode };
|
||||
isLoaded.value = true;
|
||||
people.value = [{}];
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error in initData:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function findFieldName(code) {
|
||||
const field = dataLang.value.find((item) => item.code === code);
|
||||
return field || { vi: "Không tìm thấy trường", en: "Field not found" };
|
||||
}
|
||||
|
||||
function showCustomer() {
|
||||
showmodal.value = {
|
||||
component: "customer/CustomerView",
|
||||
width: "60%",
|
||||
height: "600px",
|
||||
title: store.lang === "en" ? "Customer" : "Khách hàng",
|
||||
vbind: { row: existedCustomer },
|
||||
};
|
||||
}
|
||||
|
||||
const selected = (fieldName, value) => {
|
||||
const finalValue =
|
||||
value !== null && typeof value === "object"
|
||||
? value.id || value.index
|
||||
: value;
|
||||
record.value[fieldName] = finalValue;
|
||||
|
||||
if (errors.value[fieldName]) {
|
||||
delete errors.value[fieldName];
|
||||
}
|
||||
};
|
||||
|
||||
function checkError() {
|
||||
errors.value = {};
|
||||
|
||||
if ($empty(record.value.fullname)) {
|
||||
errors.value.fullname = "Họ tên không được bỏ trống";
|
||||
}
|
||||
|
||||
if ($empty(record.value.phone)) {
|
||||
errors.value.phone = "Số điện thoại không được bỏ trống";
|
||||
} else {
|
||||
let text = $errPhone(record.value.phone);
|
||||
if (text) errors.value.phone = text;
|
||||
}
|
||||
|
||||
if ($empty(record.value.dob)) {
|
||||
errors.value.dob = isVietnamese.value
|
||||
? "Ngày sinh không được bỏ trống"
|
||||
: "Date of birth cannot be empty";
|
||||
} else {
|
||||
if (record.value.dob > new Date()) {
|
||||
errors.value.dob = isVietnamese.value
|
||||
? "Ngày sinh không được lớn hơn ngày hiện tại"
|
||||
: "Date of birth cannot be greater than the current date";
|
||||
}
|
||||
if ($dayjs(new Date()).diff(new Date(record.value.dob), "year") < 18) {
|
||||
errors.value.dob = isVietnamese.value
|
||||
? "Khách hàng phải đủ 18 tuổi trở lên"
|
||||
: "Customer must be at least 18 years old";
|
||||
}
|
||||
}
|
||||
|
||||
if ($empty(record.value.legal_code)) {
|
||||
errors.value.legal_code = isVietnamese.value
|
||||
? "Mã số không được bỏ trống"
|
||||
: "Legal code cannot be empty";
|
||||
}
|
||||
|
||||
if ($empty(record.value.issued_date)) {
|
||||
errors.value.issued_date = isVietnamese.value
|
||||
? "Ngày cấp không được bỏ trống"
|
||||
: "Date of issue cannot be empty";
|
||||
}
|
||||
|
||||
if ($empty(record.value.issued_place)) {
|
||||
errors.value.issued_place = isVietnamese.value
|
||||
? "Nơi cấp không được bỏ trống"
|
||||
: "Place of issue cannot be empty";
|
||||
}
|
||||
return Object.keys(errors.value).length > 0;
|
||||
}
|
||||
function selectPeople(option, v, i) {
|
||||
let copy = $copy(v);
|
||||
copy.people = option.id;
|
||||
people.value[i] = copy;
|
||||
people.value = $copy(people.value);
|
||||
}
|
||||
function selectRelation(option, v, i) {
|
||||
let copy = $copy(v);
|
||||
copy.relation = option ? option.id : null;
|
||||
people.value[i] = copy;
|
||||
people.value = $copy(people.value);
|
||||
}
|
||||
function add() {
|
||||
people.value.push({});
|
||||
}
|
||||
async function remove(v, i) {
|
||||
if (v.id) await $deleteapi("customerpeople", v.id);
|
||||
people.value.splice(i, 1);
|
||||
if (people.value.length === 0) {
|
||||
setTimeout(() => (people.value = [{}]));
|
||||
}
|
||||
}
|
||||
async function update() {
|
||||
try {
|
||||
if (checkError()) return;
|
||||
|
||||
var isNewCustomer =
|
||||
!dataCustomer.value?.customer ||
|
||||
dataCustomer.value.customer === null ||
|
||||
dataCustomer.value.customer === undefined ||
|
||||
!record.value.id;
|
||||
if (record.value.id) isNewCustomer = false;
|
||||
if (isNewCustomer) {
|
||||
try {
|
||||
if (record.value.phone) {
|
||||
record.value.phone = record.value.phone.trim();
|
||||
let phoneCheck = await $getdata(
|
||||
"customer",
|
||||
{ phone: record.value.phone },
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
if (phoneCheck) {
|
||||
existedCustomer = phoneCheck;
|
||||
errors.value.phone = isVietnamese.value
|
||||
? "Số điện thoại đã tồn tại."
|
||||
: "Phone number already exists.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Kiểm tra email
|
||||
if (record.value.email && record.value.email.trim() !== "") {
|
||||
let emailCheck = await $getdata(
|
||||
"customer",
|
||||
{ email: record.value.email.trim() },
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
if (emailCheck) {
|
||||
errors.value.email = isVietnamese.value
|
||||
? "Email đã tồn tại."
|
||||
: "Email already exists.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Kiểm tra legal_code
|
||||
if (record.value.legal_code) {
|
||||
let legalCheck = await $getdata(
|
||||
"customer",
|
||||
{ legal_code: record.value.legal_code },
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
if (legalCheck) {
|
||||
errors.value.legal_code = isVietnamese.value
|
||||
? "Số CMND/CCCD đã tồn tại."
|
||||
: "ID card number already exists.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error checking duplicates:", error);
|
||||
}
|
||||
}
|
||||
|
||||
let dataToSend = $resetNull({ ...record.value });
|
||||
|
||||
if (isNewCustomer) {
|
||||
delete dataToSend.id;
|
||||
}
|
||||
|
||||
if (!dataToSend.note || dataToSend.note.trim() === "") {
|
||||
dataToSend.note = null;
|
||||
}
|
||||
|
||||
if (!dataToSend.creator) dataToSend.creator = store.login.id;
|
||||
dataToSend.updater = store.login.id;
|
||||
dataToSend.update_time = new Date();
|
||||
|
||||
let rs;
|
||||
if (isNewCustomer) {
|
||||
rs = await $insertapi("customer", dataToSend, undefined, false);
|
||||
} else {
|
||||
rs = await $updateapi("customer", dataToSend);
|
||||
}
|
||||
|
||||
if (rs === "error") {
|
||||
$snackbar("Có lỗi xảy ra khi lưu dữ liệu", "Lỗi", "Error");
|
||||
return;
|
||||
}
|
||||
record.value.id = rs.id;
|
||||
const customerData = await $getdata(
|
||||
"customer",
|
||||
{ id: rs.id },
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
|
||||
if (isNewCustomer) {
|
||||
// link user=customer
|
||||
await $getdata("linkusercustomer", undefined, { phone: rs.phone });
|
||||
$snackbar(
|
||||
`${
|
||||
isVietnamese.value
|
||||
? "Khách hàng đã được khởi tạo với mã"
|
||||
: "Customer has been created with code"
|
||||
} <b>${rs.code}</b>`,
|
||||
"Thành công",
|
||||
"Success"
|
||||
);
|
||||
} else {
|
||||
$snackbar(
|
||||
`${
|
||||
isVietnamese.value
|
||||
? "Khách hàng đã được cập nhật với mã"
|
||||
: "Customer has been updated with code"
|
||||
} <b>${rs.code}</b>`,
|
||||
"Thành công",
|
||||
"Success"
|
||||
);
|
||||
}
|
||||
|
||||
record.value = { ...record.value, ...customerData };
|
||||
emit("update", customerData);
|
||||
|
||||
//Xử lý people relationships nếu có
|
||||
if (people.value && people.value.length > 0) {
|
||||
let filter = people.value.filter((v) => v.people);
|
||||
if (filter.length > 0) {
|
||||
filter.map((v) => (v.customer = rs.id));
|
||||
await $insertapi("customerpeople", filter);
|
||||
}
|
||||
}
|
||||
|
||||
//Xử lý file uploads nếu có
|
||||
if (record.value.image && record.value.image.length > 0) {
|
||||
let arr = [];
|
||||
record.value.image.map((v) =>
|
||||
arr.push({ ref: record.value.id, file: v })
|
||||
);
|
||||
await $insertapi("customerfile", arr, undefined, false);
|
||||
}
|
||||
emit("update", customerData);
|
||||
emit("close");
|
||||
} catch (error) {
|
||||
console.error("Error in update:", error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await initData();
|
||||
isLoaded.value = true;
|
||||
} catch (error) {
|
||||
console.error("Error loading data:", error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user