Initial commit

This commit is contained in:
Viet An
2026-03-02 09:45:33 +07:00
commit d17a9e2588
415 changed files with 92113 additions and 0 deletions

View File

@@ -0,0 +1,301 @@
<template>
<div :id="docid" v-if="record">
<div>
<Caption v-bind="{ title: this.data && findFieldName('info')[this.lang] }"></Caption>
<div class="columns is-multiline mx-0">
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label"> khách hàng</label>
<div class="control">
<span class="hyperlink" @click="$copyToClipboard(record.code)">{{ record.code }}</span>
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Tên khách hàng</label>
<div class="control">
{{ record.fullname }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Điện thoại</label>
<div class="control">
<span class="hyperlink" @click="openPhone()">{{ record.phone }}</span>
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Email</label>
<div class="control" style="word-break: break-all">
{{ record.email || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Giấy tờ</label>
<div class="control">
{{ record.legal_type__name || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label"> số giấy tờ</label>
<div class="control">
{{ record.legal_code || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Ngày cấp</label>
<div class="control">
{{ record.issued_date ? $dayjs(record.issued_date).format("DD/MM/YYYY") : "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Nơi cấp</label>
<div class="control">
{{ record.issued_place__name || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Loại khách hàng</label>
<div class="control">
{{ record.type__name || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Quốc gia</label>
<div class="control">
{{ isVietnamese ? record.country__name : record.country__en || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Địa chỉ liên hệ</label>
<div class="control">
{{ record.contact_address || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Địa chỉ thường trú</label>
<div class="control">
{{ record.address || "/" }}
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Người tạo</label>
<div class="control">
<span class="hyperlink" @click="openUser(record.creator)">{{ record.creator__fullname || "/" }}</span>
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Thời gian tạo</label>
<div class="control">
<span
>{{ $dayjs(record.create_time).format("DD/MM/YYYY") }}
{{ $dayjs(record.create_time).format("HH:mm") }}</span
>
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Người cập nhật</label>
<div class="control">
<span class="hyperlink" @click="openUser(record.updater)">{{ record.updater__fullname || "/" }}</span>
</div>
</div>
</div>
<div class="column is-3 pb-1 px-0">
<div class="field">
<label class="label">Thời gian cập nhật</label>
<div class="control">
<span>
{{ record.update_time ? $dayjs(record.update_time).format("DD/MM/YYYY HH:mm") : '/' }}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="mt-3">
<Caption v-bind="{ title: isVietnamese ? 'Hình ảnh' : 'Images' }"></Caption>
<ImageGallery v-bind="{ row: record, api: 'customerfile', hideopt: true }"></ImageGallery>
</div>
<div class="mt-3">
<Caption v-bind="{ title: this.isIndividual ? 'Người liên quan' : 'Người đại diện pháp luật' }"></Caption>
<div class="mt-2">
<div
v-if="this.relatedPeople && this.relatedPeople.length > 0"
v-for="relatedPerson in this.relatedPeople"
class="columns is-0 mb-2"
>
<span class="column is-2">{{ relatedPerson.people__code }}</span>
<span class="column is-4 ">
<span class="has-text-primary hyperlink"
@click="openRelatedPerson(relatedPerson.people)"
>{{ relatedPerson.people__fullname }}</span>
<span> ({{ relatedPerson.relation__name }})</span>
</span>
<span class="column is-4">{{ relatedPerson.people__phone }}</span>
</div>
<div v-else class="has-text-grey">
Chưa {{ this.isIndividual ? 'người liên quan' : 'người đại diện pháp luật' }}
</div>
</div>
</div>
<div v-if="record.count_product >0" class="mt-3">
<Caption class="mb-2" v-bind="{ title: this.data && findFieldName('transaction')[this.lang] }"></Caption>
<DataView v-bind="{
setting: 'customer-all-transaction',
pagename: this.$id(),
api: 'customer',
params: {
filter: { id: this.row.customer || this.row.id },
/* copied from 02-connection.js */
values:
'id,update_time,creator,creator__fullname,country,country__name,country__en,issued_date,issued_place,issued_place__name,code,email,fullname,legal_code,phone,legal_type,legal_type__name,address,contact_address,note,type,type__name,updater,updater__fullname,create_time,update_time',
distinct_values: {
label: { type: 'Concat', field: ['code', 'fullname', 'phone', 'legal_code'] },
order: { type: 'RowNumber' },
image_count: { type: 'Count', field: 'id', subquery: { model: 'Customer_File', column: 'ref' } },
count_note: { type: 'Count', field: 'id', subquery: { model: 'Customer_Note', column: 'ref' } },
count_product: { type: 'Count', field: 'id', subquery: { model: 'Product_Booked', column: 'transaction__customer' } },
sum_product: { type: 'Sum', field: 'transaction__sale_price', subquery: { model: 'Product_Booked', column: 'transaction__customer' } },
sum_receiver: { type: 'Sum', field: 'transaction__amount_received', subquery: { model: 'Product_Booked', column: 'transaction__customer' } },
sum_remain: { type: 'Sum', field: 'transaction__amount_remain', subquery: { model: 'Product_Booked', column: 'transaction__customer' } }
},
summary: 'annotate',
},
}" />
</div>
<div class="mt-4 border-bottom" id="ignore"></div>
<div class="buttons mt-2 is-flex is-gap-1" id="ignore">
<button v-if="$getEditRights('edit', { code: 'customer', category: 'topmenu' })" class="button is-primary" @click="edit()">Chỉnh sửa</button>
<button class="button is-light" @click="$exportpdf(docid, record.code)">In thông tin</button>
</div>
<Modal @close="showmodal = undefined" v-bind="showmodal" @dataevent="changeInfo" v-if="showmodal"></Modal>
</div>
</template>
<script>
import { useStore } from "@/stores/index";
export default {
setup() {
const store = useStore();
return { store };
},
props: ["row", "pagename"],
data() {
return {
record: undefined,
relatedPeople: undefined,
errors: {},
showmodal: undefined,
docid: this.$id(),
data: this.store.common,
isEditMode: this.isEditMode,
};
},
computed: {
lang() {
return this.store.lang;
},
isVietnamese() {
return this.store.lang === "vi";
},
isIndividual() {
return this.record.type === 1;
}
},
async created() {
this.record = await this.$getdata("customer", { id: this.row.customer || this.row.id }, undefined, true);
if (this.isIndividual) {
this.relatedPeople = await this.$getdata("customerpeople", { customer: this.row.customer || this.row.id });
} else {
const org = await this.$getdata('organization', { customer: this.row.customer || this.row.id }, undefined, true);
this.relatedPeople = await this.$getdata("legalrep", { organization: org.id });
}
},
methods: {
findFieldName(code) {
let field = this.data.find((v) => v.code === code);
return field;
},
copy(value) {
this.$copyToClipboard(value);
this.$snackbar("Đã copy vào clipboard.", "Copy", "Success");
},
openPhone() {
this.showmodal = {
title: "Điện thoại",
height: "180px",
width: "400px",
component: "common/Phone",
vbind: { row: this.row, pagename: this.pagename },
};
},
selected(attr, obj) {
this.record[attr] = obj;
},
edit() {
this.showmodal = {
component: "customer/Customer",
width: "80%",
height: "600px",
title: this.store.lang === "en" ? "Edit Customer" : "Chỉnh sửa khách hàng",
vbind: { row: this.record, isEditMode: true },
};
},
async changeInfo(v) {
this.record = this.$copy(v);
// refetch relatedPeople
if (this.isIndividual) {
this.relatedPeople = await this.$getdata("customerpeople", { customer: this.row.customer || this.row.id });
} else {
const org = await this.$getdata('organization', { customer: this.row.customer || this.row.id }, undefined, true);
this.relatedPeople = await this.$getdata("legalrep", { organization: org.id });
}
},
openUser(userId) {
if (!userId) return;
this.showmodal = {
component: "user/UserInfo",
width: "50%",
height: "200px",
title: "User",
vbind: { userId: userId },
};
},
async openRelatedPerson(peopleId) {
const peopleRow = await this.$getdata('people', { id: peopleId }, undefined, true);
this.showmodal = {
component: "people/PeopleView",
vbind: { row: peopleRow },
title: 'Người liên quan',
width: '65%',
height: '400px',
}
}
},
};
</script>