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

349 lines
11 KiB
Vue

<template>
<div>
<div class="columns is-multiline mx-0">
<div class="column is-8">
<div class="field">
<label class="label">{{ $lang("account") }}<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<SearchBox
v-bind="{
api: 'internalaccount',
field: 'label',
column: ['label'],
first: true,
optionid: record.account,
}"
:disabled="record.account"
@option="selected('_account', $event)"
v-if="!record.id"
></SearchBox>
<span v-else>{{ record.account__code }}</span>
</div>
<p
class="help is-danger"
v-if="errors._account"
>
{{ errors._account }}
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label">Ngày hạch toán<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<Datepicker
v-bind="{ record: record, attr: 'date', maxdate: new Date() }"
@date="selected('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">
<div class="field">
<label class="label">Thu / chi<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<SearchBox
v-bind="{
api: 'entrytype',
field: 'name',
column: ['name'],
first: true,
optionid: record.type,
}"
:disabled="record.type"
@option="selected('_type', $event)"
v-if="!record.id"
></SearchBox>
<span v-else>{{ record.type__name }}</span>
</div>
<p
class="help is-danger"
v-if="errors._type"
>
{{ errors._type }}
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label">{{ $lang("amount-only") }}<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<InputNumber
v-bind="{ record: record, attr: 'amount', placeholder: '' }"
@number="selected('amount', $event)"
></InputNumber>
</div>
<p
class="help is-danger"
v-if="errors.amount"
>
{{ errors.amount }}
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label">Phương thức thanh toán<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<SearchBox
v-bind="{
api: 'entrycategory',
field: 'name',
column: ['name'],
first: true,
optionid: record.type,
}"
:disabled="record.type"
@option="selected('_category', $event)"
v-if="!record.id"
></SearchBox>
<span v-else>{{ record.type__name }}</span>
</div>
<p
class="help is-danger"
v-if="errors._type"
>
{{ errors._type }}
</p>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label">Sản phẩm<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<SearchBox
v-bind="{
api: 'product',
field: 'label',
searchfield: ['code', 'trade_code', 'type__name', 'land_lot_size', 'zone_type__name'],
column: ['code', 'trade_code', 'type__name', 'land_lot_size', 'zone_type__name'],
first: true,
}"
@option="selected('product', $event)"
/>
</div>
<p
class="help is-danger"
v-if="errors._type"
>
{{ errors._type }}
</p>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label">Khách hàng<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,
}"
@option="selected('customer', $event)"
/>
</div>
<p
class="help is-danger"
v-if="errors._type"
>
{{ errors._type }}
</p>
</div>
</div>
<div class="column is-12">
<div class="field">
<label class="label">{{ $lang("content") }}<b class="ml-1 has-text-danger">*</b></label>
<div class="control">
<textarea
class="textarea"
rows="2"
v-model="record.content"
></textarea>
</div>
<p
class="help is-danger"
v-if="errors.content"
>
{{ errors.content }}
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label">Mã tham chiếu</label>
<div class="control">
<input
class="input has-text-black"
type="text"
placeholder="Tối đa 30 ký tự"
v-model="record.ref"
/>
</div>
</div>
</div>
<div
class="column is-12"
v-if="entry"
>
<div class="field">
<label class="label">Chứng từ đi kèm (nếu có)</label>
<div class="control">
<FileGallery
v-bind="{
row: entry,
pagename: pagename,
api: 'entryfile',
info: false,
}"
></FileGallery>
</div>
</div>
</div>
</div>
<div
class="mt-5 ml-3"
v-if="!entry"
>
<button
:class="['button is-primary has-text-white mr-2', isUpdating && 'is-loading']"
@click="confirm()"
>
{{ $lang("confirm") }}
</button>
</div>
<Modal
@close="showContractModal = undefined"
v-bind="showContractModal"
v-if="showContractModal"
></Modal>
<Modal
@close="showmodal = undefined"
v-bind="showmodal"
@confirm="update()"
v-if="showmodal"
></Modal>
</div>
</template>
<script>
import { useStore } from "~/stores/index";
export default {
setup() {
const store = useStore();
return { store };
},
props: ["pagename", "row", "option"],
data() {
return {
record: { date: this.$dayjs().format("YYYY-MM-DD") },
errors: {},
isUpdating: false,
showmodal: undefined,
showContractModal: undefined,
entry: undefined,
};
},
created() {
if (!this.option) return;
this.record.account = this.option.account;
this.record.type = this.option.type;
},
methods: {
selected(attr, obj) {
this.record[attr] = obj;
this.record = this.$copy(this.record);
},
checkError() {
this.errors = {};
if (this.$empty(this.record._account)) this.errors._account = "Chưa chọn tài khoản";
if (this.$empty(this.record._type)) this.errors._type = "Chưa chọn loại hạch toán";
if (this.$empty(this.record.amount)) this.errors.amount = "Chưa nhập số tiền";
else if (this.$formatNumber(this.record.amount) <= 0) this.errors.amount = "Số tiền phải > 0";
if (this.$empty(this.record.content)) this.errors.content = "Chưa nhập nội dung";
if (Object.keys(this.errors).length > 0) return true;
if (this.record._type.code === "DR" && this.record._account.balance < this.$formatNumber(this.record.amount)) {
this.errors._account = "Số tài khoản không đủ để trích nợ";
}
return Object.keys(this.errors).length > 0;
},
confirm() {
if (this.checkError()) return;
this.showmodal = {
component: `dialog/Confirm`,
vbind: { content: this.$lang("confirm-action"), duration: 10 },
title: this.$lang("confirm"),
width: "500px",
height: "100px",
};
},
async update() {
this.isUpdating = true;
let obj1 = {
code: this.record._account.code,
amount: this.record.amount,
content: this.record.content,
type: this.record._type.code,
category: this.record._category ? this.record._category.id : 1,
user: this.store.login.id,
ref: this.row ? this.row.code : !this.$empty(this.record.ref) ? this.record.ref.trim() : null,
customer: this.record.customer ? this.record.customer.id : null,
product: this.record.product ? this.record.product.id : null,
date: this.$empty(this.record.date) ? null : this.record.date,
};
let rs1 = await this.$insertapi("accountentry", obj1, undefined, false);
if (rs1 === "error") return;
if (this.record._category.id === 2) {
const genDoc = await this.$generateDocument({
doc_code: "PHIEU_THU_TIEN_MAT",
entry_id: rs1.id,
output_filename: `PHIEU_THU_TIEN_MAT-${rs1.code}`,
});
await this.$insertapi("file", {
name: genDoc.data.pdf,
user: this.store.login.id,
type: 4,
size: 1000,
file: genDoc.data.pdf, // or genDoc.data.pdf
});
this.showContractModal = {
component: "application/Contract",
title: "Phiếu thu tiền mặt",
width: "95%",
height: "95vh",
vbind: {
directDocument: genDoc.data,
},
};
}
this.entry = rs1;
if (this.pagename) {
let data = await this.$getdata("internalaccount", {
code__in: [this.record._account.code],
});
this.$updatepage(this.pagename, data);
}
this.isUpdating = false;
this.$emit("modalevent", { name: "entry", data: rs1 });
this.$dialog(
`Hạch toán <b>${this.record._type.name}</b> số tiền <b>${this.$numtoString(this.record.amount)}</b> vào tài khoản <b>${this.record._account.code}</b> thành công.`,
"Thành công",
"Success",
10,
);
},
},
};
</script>