203 lines
6.2 KiB
Vue
203 lines
6.2 KiB
Vue
<script setup>
|
|
import AllocateForm from '@/components/transaction/AllocateForm.vue';
|
|
|
|
const props = defineProps({
|
|
paymentSchedule: Object,
|
|
i: Number,
|
|
});
|
|
|
|
const emit = defineEmits(['refresh'])
|
|
const {
|
|
$insertapi,
|
|
$snackbar,
|
|
$remove,
|
|
} = useNuxtApp();
|
|
|
|
const allocations = ref([{}]);
|
|
const showConfirmModal = ref();
|
|
const isSubmitting = ref(false);
|
|
const resetKey = ref(0);
|
|
|
|
function addAllocation() {
|
|
allocations.value.push({});
|
|
}
|
|
|
|
async function removeAllocation(index) {
|
|
$remove(allocations.value, index);
|
|
if (allocations.value.length === 0) {
|
|
allocations.value = [{}];
|
|
}
|
|
}
|
|
|
|
function setAllo({ key, value, i }) {
|
|
allocations.value[i][key] = value;
|
|
}
|
|
|
|
function openConfirmModal() {
|
|
showConfirmModal.value = {
|
|
component: 'dialog/Confirm',
|
|
title: 'Xác nhận',
|
|
width: '600px',
|
|
height: '150px',
|
|
vbind: { content: `Xác nhận phân bổ tay cho lịch thanh toán ${props.paymentSchedule.code}?` },
|
|
onConfirm: update
|
|
}
|
|
}
|
|
|
|
async function update() {
|
|
const allocationsToSend = allocations.value
|
|
.map(({ ref, date, type, amount }) => ({ ref, date, type, amount }));
|
|
|
|
const payload = {
|
|
product: props.paymentSchedule.txn_detail__transaction__product,
|
|
schedule_id: props.paymentSchedule.id,
|
|
allocation_list: allocationsToSend,
|
|
};
|
|
|
|
isSubmitting.value = true;
|
|
const res = await $insertapi('manualallocate', payload);
|
|
if (res.success) {
|
|
emit('refresh');
|
|
allocations.value = [{}];
|
|
resetKey.value++;
|
|
$snackbar(res.message);
|
|
} else {
|
|
$snackbar(res.message || "Đã có lỗi khi phân bổ tay");
|
|
}
|
|
|
|
isSubmitting.value = false;
|
|
}
|
|
|
|
const totalByRef = computed(() => {
|
|
const map = {};
|
|
for (const allo of allocations.value) {
|
|
if (allo.ref) {
|
|
map[allo.ref] = (map[allo.ref] || 0) + (allo.amount || 0);
|
|
}
|
|
}
|
|
return map;
|
|
});
|
|
|
|
const formValid = computed(() => {
|
|
if (allocations.value.some(allo => {
|
|
if (Object.keys(allo).length === 0) return true;
|
|
if (allo.amount === undefined || allo.type === undefined) return true;
|
|
if (allo.ref && totalByRef.value[allo.ref] > allo.allocation_remain) return true;
|
|
})) return false;
|
|
|
|
return true;
|
|
});
|
|
</script>
|
|
<template>
|
|
<div class="fs-15 is-flex is-gap-2">
|
|
<div class="is-flex is-flex-direction-column is-align-items-center is-gap-1">
|
|
<p class="fsb-17 is-flex is-justify-content-center is-align-items-center" style="
|
|
border: 3px solid rgb(52, 92, 103);
|
|
border-radius: 9999px;
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
">
|
|
{{ i + 1 }}
|
|
</p>
|
|
<div style="
|
|
border: 3px solid #dddddd;
|
|
border-radius: 9999px;
|
|
flex-grow: 1;
|
|
width: min-content;
|
|
">
|
|
</div>
|
|
</div>
|
|
<div class="is-flex-grow-1">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<p><span class="has-text-weight-semibold">{{ paymentSchedule.code }}</span> - {{ paymentSchedule.type__name }}</p>
|
|
</div>
|
|
<div class="column">
|
|
<span class="has-text-weight-semibold">Từ ngày: </span>
|
|
<FormatDate :date="paymentSchedule.from_date" />
|
|
</div>
|
|
<div class="column">
|
|
<span class="has-text-weight-semibold">Đến ngày: </span>
|
|
<FormatDate :date="paymentSchedule.to_date" />
|
|
</div>
|
|
<div class="column">
|
|
<span class="has-text-weight-semibold">Ngày tính lãi: </span>
|
|
<FormatDate :date="paymentSchedule.batch_date" />
|
|
</div>
|
|
<div class="column">
|
|
<span class="has-text-weight-semibold">Quá hạn: </span>
|
|
<span>{{ paymentSchedule.ovd_days }} ngày</span>
|
|
</div>
|
|
</div>
|
|
<div class="columns">
|
|
<div class="column">
|
|
<p class="has-text-weight-semibold">Số tiền theo HĐ (Gốc)</p>
|
|
<FormatNumber :value="paymentSchedule.amount" />
|
|
</div>
|
|
<div class="column">
|
|
<p class="has-text-weight-semibold">Đã thu theo HĐ</p>
|
|
<FormatNumber :value="paymentSchedule.paid_amount" />
|
|
</div>
|
|
<div class="column">
|
|
<p class="has-text-weight-semibold">Số tiền còn theo HĐ</p>
|
|
<FormatNumber :value="paymentSchedule.amount_remain" />
|
|
</div>
|
|
<div class="column">
|
|
<p class="has-text-weight-semibold">Lãi phạt</p>
|
|
<FormatNumber :value="paymentSchedule.penalty_amount" color="red" />
|
|
</div>
|
|
<div class="column">
|
|
<p class="has-text-weight-semibold">Lãi còn lại</p>
|
|
<FormatNumber :value="paymentSchedule.penalty_remain" color="red" />
|
|
</div>
|
|
<div class="column">
|
|
<p class="has-text-weight-semibold">Tổng tiền còn lại</p>
|
|
<FormatNumber :value="paymentSchedule.remain_amount" />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<AllocateForm
|
|
v-for="(allo, i) in allocations"
|
|
:key="`${resetKey}-${i}`"
|
|
v-bind="{
|
|
allo,
|
|
i,
|
|
length: allocations.length,
|
|
productId: paymentSchedule.txn_detail__transaction__product,
|
|
amount_remain: paymentSchedule.amount_remain,
|
|
totalByRef,
|
|
onSetAllo: setAllo,
|
|
onRemoveAllocation: removeAllocation,
|
|
}"
|
|
/>
|
|
<button class="button is-pulled-right is-info is-light mb-4" @click="addAllocation">
|
|
<span class="icon">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
height="12"
|
|
width="12"
|
|
viewBox="0 0 448 512"
|
|
>
|
|
<path
|
|
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
|
|
/>
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
<button
|
|
@click="openConfirmModal"
|
|
:class="`button is-secondary ${isSubmitting ? 'is-loading' : ''}`"
|
|
:disabled="isSubmitting || !formValid"
|
|
>
|
|
<span>Phân bổ</span>
|
|
</button>
|
|
<Modal
|
|
v-bind="showConfirmModal"
|
|
v-if="showConfirmModal"
|
|
@close="showConfirmModal = undefined"
|
|
/>
|
|
<!-- <pre class="fs-12">{{ JSON.stringify(allocations, null, 2) }}</pre> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template> |