682 lines
26 KiB
Plaintext
682 lines
26 KiB
Plaintext
<%@ Page Title="共同-沖帳流程" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" EnableEventValidation="false" CodeFile="group_reconcile.aspx.cs" Inherits="admin_transfer_group_reconcile" %>
|
||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" runat="Server">
|
||
</asp:Content>
|
||
<asp:Content ID="Content3" ContentPlaceHolderID="page_nav" runat="Server">
|
||
<h5 class="mb-0">共同 - 沖帳流程</h5>
|
||
</asp:Content>
|
||
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
|
||
<div id="group-reconcile-app">
|
||
<v-app>
|
||
<v-container>
|
||
<v-card>
|
||
<v-card-title class="bg-primary white--text text-center">
|
||
<h5 class="mb-0">共同 - 沖帳流程</h5>
|
||
</v-card-title>
|
||
<v-card-text>
|
||
<v-data-table
|
||
:headers="headers"
|
||
:items="items"
|
||
:loading="loading"
|
||
loading-text="載入中..."
|
||
class="elevation-1"
|
||
item-key="id"
|
||
>
|
||
<template v-slot:item.follower="{ item }">
|
||
<span :title="item.f_num">{{ item.follower }}</span>
|
||
</template>
|
||
<template v-slot:item.activity_info="{ item }">
|
||
<div>
|
||
<div class="font-weight-bold">{{ item.activity_name }}</div>
|
||
<div class="caption text--secondary">
|
||
<span v-if="hasFollowerList(item.draft)" style="margin-right: 4px;">👥</span>
|
||
{{ item.acc_name }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.check_date="{ item }">
|
||
<span>{{ item.check_date | date }}</span>
|
||
</template>
|
||
<template v-slot:item.check_memo="{ item }">
|
||
<span>{{ item.check_memo }}</span>
|
||
</template>
|
||
<template v-slot:item.verify_note="{ item }">
|
||
<span>{{ item.verify_note }}</span>
|
||
</template>
|
||
<template v-slot:item.follower_selection="{ item }">
|
||
<div>
|
||
<v-btn
|
||
small
|
||
color="primary"
|
||
outlined
|
||
@click="showFollowerSelection(item)"
|
||
class="mb-1"
|
||
>
|
||
<v-icon left small>mdi-account-multiple</v-icon>
|
||
選擇支付人
|
||
</v-btn>
|
||
<div v-if="hasFollowerList(item.draft)" class="caption text-success mt-1">
|
||
<v-icon small color="success">mdi-check-circle</v-icon>
|
||
已選擇 {{ getFollowerCount(item.draft) }} 位
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.actions="{ item }">
|
||
<v-btn
|
||
small
|
||
color="success"
|
||
@click="showGroupReconcileDialog(item)"
|
||
:disabled="!hasFollowerList(item.draft)"
|
||
>
|
||
<v-icon left small>mdi-receipt</v-icon>
|
||
{{ hasFollowerList(item.draft) ? '共同沖帳' : '請先選擇支付人' }}
|
||
</v-btn>
|
||
</template>
|
||
</v-data-table>
|
||
</v-card-text>
|
||
</v-card>
|
||
</v-container>
|
||
|
||
<!-- 選擇共同支付人對話框 -->
|
||
<v-dialog v-model="followerDialog.show" max-width="800px">
|
||
<v-card>
|
||
<v-card-title class="grey lighten-2">
|
||
<v-icon color="primary" class="mr-2">mdi-account-multiple</v-icon>
|
||
選擇共同支付人
|
||
<v-spacer></v-spacer>
|
||
<v-btn icon @click="followerDialog.show = false">
|
||
<v-icon>mdi-close</v-icon>
|
||
</v-btn>
|
||
</v-card-title>
|
||
<v-card-text class="mt-4">
|
||
<div v-if="followerDialog.selected">
|
||
<h6 class="mb-3">法會:{{ followerDialog.selected.activity_name }}</h6>
|
||
<v-text-field
|
||
v-model="followerDialog.search"
|
||
label="搜尋信眾"
|
||
dense
|
||
outlined
|
||
prepend-inner-icon="mdi-magnify"
|
||
@input="searchActivityFollowers"
|
||
></v-text-field>
|
||
<v-data-table
|
||
:headers="followerDialog.headers"
|
||
:items="followerDialog.items"
|
||
:loading="followerDialog.loading"
|
||
item-key="f_num"
|
||
class="elevation-1 mt-2"
|
||
show-select
|
||
v-model="followerDialog.selectedFollowers"
|
||
hide-default-footer
|
||
:disable-pagination="true"
|
||
>
|
||
<template v-slot:item.follower_name="{ item }">
|
||
<div>
|
||
<div class="font-weight-bold">{{ item.follower_name }}</div>
|
||
<div class="caption text--secondary">編號: {{ item.f_num }}</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.total_due="{ item }">
|
||
<span class="text-danger">{{ item.total_due | currency }}</span>
|
||
</template>
|
||
<template v-slot:item.item_count="{ item }">
|
||
<span class="text-info">{{ item.item_count }} 項</span>
|
||
</template>
|
||
</v-data-table>
|
||
</div>
|
||
</v-card-text>
|
||
<v-card-actions class="pa-4">
|
||
<v-spacer></v-spacer>
|
||
<v-btn color="grey" @click="followerDialog.show = false">取消</v-btn>
|
||
<v-btn color="primary" @click="confirmFollowerSelection" :disabled="followerDialog.selectedFollowers.length === 0">
|
||
確認選擇 ({{ followerDialog.selectedFollowers.length }})
|
||
</v-btn>
|
||
</v-card-actions>
|
||
</v-card>
|
||
</v-dialog>
|
||
|
||
<!-- 共同沖帳明細對話框 -->
|
||
<v-dialog v-model="reconcileDialog.show" max-width="1200px">
|
||
<v-card>
|
||
<v-card-title class="grey lighten-2">
|
||
<v-icon color="success" class="mr-2">mdi-receipt</v-icon>
|
||
共同沖帳明細
|
||
<v-spacer></v-spacer>
|
||
<v-btn icon @click="reconcileDialog.show = false">
|
||
<v-icon>mdi-close</v-icon>
|
||
</v-btn>
|
||
</v-card-title>
|
||
|
||
<v-card-text class="mb-0 pb-0">
|
||
<div v-if="reconcileDialog.selected">
|
||
<div class="row my-2">
|
||
<h6 class="col">共同支付人:{{ getSelectedFollowersText() }}</h6>
|
||
<div class="col">
|
||
<span class="font-weight-bold">入帳金額:</span>
|
||
<span class="text-primary">{{ reconcileDialog.selected.check_amount | currency }}</span>
|
||
</div>
|
||
<div class="col">
|
||
<span class="font-weight-bold">已沖金額:</span>
|
||
<span :class="{'text-danger': isOverPaid, 'text-dark': !isOverPaid}">{{ sumReconcile | currency }}</span>
|
||
</div>
|
||
<div class="col">
|
||
<span class="font-weight-bold">未繳餘款:</span>
|
||
<span class="text-danger">{{ remainDue | currency }}</span>
|
||
</div>
|
||
<div class="col">
|
||
<span class="font-weight-bold">入帳後餘額:</span>
|
||
<span class="text-success">{{ overPaid | currency }}</span>
|
||
</div>
|
||
</div>
|
||
<v-data-table
|
||
:headers="reconcileDialog.headers"
|
||
:items="reconcileDialog.items"
|
||
class="elevation-1 mt-3"
|
||
hide-default-footer
|
||
:disable-pagination="true"
|
||
>
|
||
<template v-slot:item.follower_info="{ item }">
|
||
<div>
|
||
<div class="font-weight-bold text-primary">{{ item.follower_name }}</div>
|
||
<div class="text-muted" style="font-size:12px;">{{ item.order_no }}</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.activity_name="{ item }">
|
||
<div>
|
||
<div>{{ item.activity_name }}</div>
|
||
<div class="text-muted" style="font-size:12px;">{{ item.reg_time | date }}</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.paid="{ item }">
|
||
<span>{{ item.paid | currency }}</span>
|
||
</template>
|
||
<template v-slot:item.due="{ item }">
|
||
<span>{{ item.due | currency }}</span>
|
||
</template>
|
||
<template v-slot:item.reconcile="{ item, index }">
|
||
<v-text-field
|
||
v-model="item.reconcile"
|
||
type="number"
|
||
dense
|
||
outlined
|
||
hide-details="auto"
|
||
:rules="[
|
||
v => !isNaN(Number(v)) || '請輸入數字',
|
||
v => Number(v) >= 0 || '不可小於 0',
|
||
v => Number(v) <= Number(item.due) || `不可大於待繳金額 ${item.due}`
|
||
]"
|
||
@blur="validateAndUpdateReconcile($event.target.value, item, index)"
|
||
></v-text-field>
|
||
</template>
|
||
</v-data-table>
|
||
</div>
|
||
</v-card-text>
|
||
<v-card-actions class="pa-4">
|
||
<div>
|
||
<div v-if="hasUnallocated && remainDue > 0" class="text-dark mb-2">
|
||
⚠️ 尚有未分配的入帳金額,請確認是否全部分配
|
||
</div>
|
||
<div v-if="hasUnallocated && remainDue === 0" class="text-info mb-2">
|
||
ℹ️ 已無未繳項目,剩餘入帳金額將成為餘額
|
||
</div>
|
||
<div v-if="!canConfirm && buttonErrorMessage" class="text-danger">
|
||
❌ {{ buttonErrorMessage }}
|
||
</div>
|
||
</div>
|
||
<v-spacer></v-spacer>
|
||
<v-btn color="info" @click="redistributeReconcile" class="mr-2">重新分配</v-btn>
|
||
<v-btn color="orange" @click="saveDraft" class="mr-2">暫存</v-btn>
|
||
<v-btn color="primary" @click="confirmGroupReconcile" :disabled="!canConfirm">確認沖帳</v-btn>
|
||
</v-card-actions>
|
||
</v-card>
|
||
</v-dialog>
|
||
</v-app>
|
||
</div>
|
||
</asp:Content>
|
||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" runat="Server">
|
||
<script src="draft-utils.js"></script>
|
||
<script>
|
||
// 確保 DraftUtils 已載入
|
||
if (typeof window.DraftUtils === 'undefined') {
|
||
console.warn('DraftUtils 未載入,使用備用方案');
|
||
window.DraftUtils = {
|
||
hasFollowerList: function(draft) { return false; },
|
||
getFollowerList: function(draft) { return []; },
|
||
updateFollowerList: function(draft, list) {
|
||
return { follower_list: list };
|
||
},
|
||
getDraftField: function(draft, field) { return null; },
|
||
updateDraftField: function(draft, field, value) {
|
||
return { [field]: value };
|
||
}
|
||
};
|
||
}
|
||
|
||
new Vue({
|
||
el: '#group-reconcile-app',
|
||
vuetify: new Vuetify(),
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
headers: [
|
||
{ text: '匯款人', value: 'follower' },
|
||
{ text: '法會/入帳帳戶', value: 'activity_info' },
|
||
{ text: '入帳日期', value: 'check_date' },
|
||
{ text: '帳簿備註', value: 'check_memo' },
|
||
{ text: '入帳金額', value: 'check_amount' },
|
||
{ text: '核對記錄', value: 'verify_note' },
|
||
{ text: '選擇共同支付人', value: 'follower_selection', sortable: false },
|
||
{ text: '共同沖帳', value: 'actions', sortable: false }
|
||
],
|
||
items: [],
|
||
followerDialog: {
|
||
show: false,
|
||
selected: null,
|
||
search: '',
|
||
loading: false,
|
||
items: [],
|
||
selectedFollowers: [],
|
||
headers: [
|
||
{ text: '信眾', value: 'follower_name' },
|
||
{ text: '待繳金額', value: 'total_due' },
|
||
{ text: '項目數', value: 'item_count' }
|
||
]
|
||
},
|
||
reconcileDialog: {
|
||
show: false,
|
||
selected: null,
|
||
headers: [
|
||
{ text: '信眾/報名單號', value: 'follower_info' },
|
||
{ text: '法會/報名日期', value: 'activity_name' },
|
||
{ text: '項目', value: 'actitem_name' },
|
||
{ text: '應繳金額', value: 'price', sortable: false },
|
||
{ text: '已繳金額', value: 'paid', sortable: false },
|
||
{ text: '待繳金額', value: 'due', sortable: false },
|
||
{ text: '沖帳金額', value: 'reconcile', sortable: false }
|
||
],
|
||
items: [],
|
||
loading: false,
|
||
errorMessage: ''
|
||
},
|
||
hasUnallocated: false,
|
||
draftDataChanged: false
|
||
}
|
||
},
|
||
computed: {
|
||
sumReconcile() {
|
||
return this.reconcileDialog.items.reduce((sum, item) => sum + (Number(item.reconcile) || 0), 0);
|
||
},
|
||
remainDue() {
|
||
const totalDue = this.reconcileDialog.items.reduce((sum, item) => sum + (Number(item.due) || 0), 0);
|
||
return totalDue - this.sumReconcile;
|
||
},
|
||
overPaid() {
|
||
if (!this.reconcileDialog.selected) return 0;
|
||
return this.reconcileDialog.selected.check_amount - this.sumReconcile;
|
||
},
|
||
isOverPaid() {
|
||
if (!this.reconcileDialog.selected) return false;
|
||
return this.sumReconcile > this.reconcileDialog.selected.check_amount;
|
||
},
|
||
canConfirm() {
|
||
if (!this.reconcileDialog.selected) return false;
|
||
|
||
const hasReconcile = this.reconcileDialog.items.some(item => Number(item.reconcile) > 0);
|
||
if (!hasReconcile) return false;
|
||
|
||
const validAmounts = this.reconcileDialog.items.every(item => {
|
||
const amount = Number(item.reconcile) || 0;
|
||
return amount >= 0 && amount <= Number(item.due);
|
||
});
|
||
if (!validAmounts) return false;
|
||
|
||
if (this.sumReconcile > this.reconcileDialog.selected.check_amount) return false;
|
||
|
||
if (this.hasUnallocated && this.remainDue > 0) return false;
|
||
|
||
return true;
|
||
},
|
||
buttonErrorMessage() {
|
||
if (!this.reconcileDialog.selected) return '';
|
||
|
||
const hasReconcile = this.reconcileDialog.items.some(item => Number(item.reconcile) > 0);
|
||
if (!hasReconcile) return '請至少輸入一筆沖帳金額';
|
||
|
||
const invalidItem = this.reconcileDialog.items.find(item => {
|
||
const amount = Number(item.reconcile) || 0;
|
||
return amount < 0 || amount > Number(item.due);
|
||
});
|
||
if (invalidItem) return '沖帳金額超出可沖帳範圍';
|
||
|
||
if (this.sumReconcile > this.reconcileDialog.selected.check_amount) {
|
||
return '已沖金額不可大於入帳金額';
|
||
}
|
||
|
||
if (this.hasUnallocated && this.remainDue > 0) {
|
||
return '尚有未繳項目,請將入帳金額完全分配';
|
||
}
|
||
|
||
return '';
|
||
}
|
||
},
|
||
mounted() {
|
||
this.loadTableData();
|
||
},
|
||
filters: {
|
||
currency(val) {
|
||
if (!val) return '0';
|
||
return Number(val).toLocaleString();
|
||
},
|
||
date(val) {
|
||
if (!val) return '';
|
||
const date = new Date(val);
|
||
return date.toLocaleDateString();
|
||
}
|
||
},
|
||
methods: {
|
||
// 檢查是否有 follower_list
|
||
hasFollowerList(draft) {
|
||
return window.DraftUtils && window.DraftUtils.hasFollowerList && window.DraftUtils.hasFollowerList(draft);
|
||
},
|
||
// 取得已選擇的支付人數量
|
||
getFollowerCount(draft) {
|
||
if (!window.DraftUtils || !window.DraftUtils.getFollowerList) return 0;
|
||
const followerList = window.DraftUtils.getFollowerList(draft);
|
||
return followerList ? followerList.length : 0;
|
||
},
|
||
loadTableData() {
|
||
this.loading = true;
|
||
axios.get('../../api/transfer_register/group_reconcile_list')
|
||
.then(res => {
|
||
this.items = res.data;
|
||
})
|
||
.catch(() => {
|
||
this.items = [];
|
||
})
|
||
.finally(() => {
|
||
this.loading = false;
|
||
});
|
||
},
|
||
showGroupReconcileDialog(item) {
|
||
// 檢查是否已有選擇的共同支付人
|
||
const followerList = window.DraftUtils.getFollowerList(item.draft);
|
||
if (followerList && followerList.length > 0) {
|
||
// 直接顯示沖帳明細
|
||
this.showReconcileDetail(item, followerList);
|
||
} else {
|
||
// 先選擇共同支付人
|
||
this.showFollowerSelection(item);
|
||
}
|
||
},
|
||
showFollowerSelection(item) {
|
||
this.followerDialog.selected = item;
|
||
this.followerDialog.selectedFollowers = [];
|
||
this.followerDialog.items = [];
|
||
this.followerDialog.show = true;
|
||
this.searchActivityFollowers();
|
||
},
|
||
searchActivityFollowers() {
|
||
if (!this.followerDialog.selected || !this.followerDialog.selected.activity_num) return;
|
||
|
||
this.followerDialog.loading = true;
|
||
axios.get('../../api/transfer_register/activity_followers', {
|
||
params: { activity_num: this.followerDialog.selected.activity_num }
|
||
})
|
||
.then(res => {
|
||
let items = res.data;
|
||
// 如果有搜尋關鍵字,過濾結果
|
||
if (this.followerDialog.search && this.followerDialog.search.trim()) {
|
||
const keyword = this.followerDialog.search.trim().toLowerCase();
|
||
items = items.filter(item =>
|
||
item.follower_name.toLowerCase().includes(keyword)
|
||
);
|
||
}
|
||
this.followerDialog.items = items;
|
||
})
|
||
.catch(() => {
|
||
this.followerDialog.items = [];
|
||
})
|
||
.finally(() => {
|
||
this.followerDialog.loading = false;
|
||
});
|
||
},
|
||
confirmFollowerSelection() {
|
||
if (this.followerDialog.selectedFollowers.length === 0) {
|
||
alert('請選擇至少一位共同支付人');
|
||
return;
|
||
}
|
||
|
||
if (!this.followerDialog.selected) {
|
||
alert('系統錯誤:未選擇記錄');
|
||
return;
|
||
}
|
||
|
||
// 儲存選擇的共同支付人到 draft
|
||
const followerList = this.followerDialog.selectedFollowers.map(f => ({
|
||
f_num: f.f_num,
|
||
f_name: f.follower_name,
|
||
activity_num: this.followerDialog.selected.activity_num
|
||
}));
|
||
|
||
const draftData = window.DraftUtils.updateFollowerList(this.followerDialog.selected.draft, followerList);
|
||
this.updateFollowerDraftToDB(this.followerDialog.selected.id, draftData)
|
||
.then(() => {
|
||
this.followerDialog.selected.draft = JSON.stringify(draftData);
|
||
this.followerDialog.show = false;
|
||
// 重新載入資料以更新顯示
|
||
this.loadTableData();
|
||
// 顯示沖帳明細
|
||
this.showReconcileDetail(this.followerDialog.selected, followerList);
|
||
})
|
||
.catch(err => {
|
||
alert('儲存失敗,請重試');
|
||
console.error(err);
|
||
});
|
||
},
|
||
showReconcileDetail(item, followerList) {
|
||
this.reconcileDialog.selected = item;
|
||
this.reconcileDialog.items = [];
|
||
this.reconcileDialog.show = true;
|
||
|
||
// 取得所選信眾的訂單明細
|
||
const fNums = followerList.map(f => f.f_num).join(',');
|
||
axios.get('../../api/transfer_register/group_follower_orders', {
|
||
params: {
|
||
activity_num: item.activity_num,
|
||
f_nums: fNums
|
||
}
|
||
})
|
||
.then(res => {
|
||
this.reconcileDialog.items = res.data.map(item => ({
|
||
...item,
|
||
reconcile: 0 // 初始化沖帳金額
|
||
}));
|
||
this.autoDistributeReconcile();
|
||
})
|
||
.catch(() => {
|
||
this.reconcileDialog.items = [];
|
||
this.updateSumReconcile();
|
||
});
|
||
},
|
||
getSelectedFollowersText() {
|
||
if (!this.reconcileDialog.selected) return '';
|
||
const followerList = window.DraftUtils.getFollowerList(this.reconcileDialog.selected.draft);
|
||
return followerList.map(f => f.f_name).join('、');
|
||
},
|
||
autoDistributeReconcile() {
|
||
// 先進先出分配沖帳金額
|
||
let remainAmount = this.reconcileDialog.selected ? this.reconcileDialog.selected.check_amount : 0;
|
||
|
||
// 先將所有項目的 reconcile 清為 0
|
||
this.reconcileDialog.items.forEach(item => {
|
||
this.$set(item, 'reconcile', 0);
|
||
});
|
||
|
||
// 依報名日期排序(先進先出)
|
||
const sortedItems = [...this.reconcileDialog.items].sort((a, b) =>
|
||
new Date(a.reg_time) - new Date(b.reg_time)
|
||
);
|
||
|
||
// 逐項分配
|
||
sortedItems.forEach(item => {
|
||
if (remainAmount > 0) {
|
||
const canPay = Math.min(item.due, remainAmount);
|
||
const originalItem = this.reconcileDialog.items.find(i => i === item);
|
||
if (originalItem) {
|
||
this.$set(originalItem, 'reconcile', canPay);
|
||
}
|
||
remainAmount -= canPay;
|
||
}
|
||
});
|
||
|
||
this.updateSumReconcile();
|
||
},
|
||
redistributeReconcile() {
|
||
this.autoDistributeReconcile();
|
||
},
|
||
updateSumReconcile() {
|
||
const maxTotal = this.reconcileDialog.selected ? (this.reconcileDialog.selected.check_amount || 0) : 0;
|
||
this.hasUnallocated = maxTotal > this.sumReconcile;
|
||
},
|
||
saveDraft() {
|
||
try {
|
||
// 組成新的資料
|
||
const followerList = window.DraftUtils.getFollowerList(this.reconcileDialog.selected.draft);
|
||
const reconcileData = this.reconcileDialog.items
|
||
.filter(item => Number(item.reconcile) > 0)
|
||
.map(item => ({
|
||
f_num: item.f_num,
|
||
follower_name: item.follower_name,
|
||
pro_order_detail_num: item.num,
|
||
reconcile: Number(item.reconcile)
|
||
}));
|
||
|
||
const draftData = {
|
||
transfer_draft: [],
|
||
pro_order_detail_items: reconcileData,
|
||
follower_list: followerList
|
||
};
|
||
|
||
this.updateDraftToDB(this.reconcileDialog.selected.id, draftData)
|
||
.then(() => {
|
||
alert('暫存成功!');
|
||
this.reconcileDialog.selected.draft = JSON.stringify(draftData);
|
||
});
|
||
|
||
} catch (e) {
|
||
alert('暫存失敗:資料格式錯誤');
|
||
}
|
||
},
|
||
updateFollowerDraftToDB(id, draftData) {
|
||
const selectedItem = this.followerDialog.selected;
|
||
const updateData = {
|
||
id: id,
|
||
activity_num: selectedItem.activity_num,
|
||
name: selectedItem.name,
|
||
phone: selectedItem.phone,
|
||
pay_type: selectedItem.pay_type,
|
||
account_last5: selectedItem.account_last5,
|
||
amount: selectedItem.amount,
|
||
pay_mode: selectedItem.pay_mode,
|
||
note: selectedItem.note,
|
||
proof_img: selectedItem.proof_img,
|
||
status: selectedItem.status,
|
||
f_num_match: selectedItem.f_num_match,
|
||
f_num: selectedItem.f_num,
|
||
acc_num: selectedItem.acc_num,
|
||
check_date: selectedItem.check_date,
|
||
check_amount: selectedItem.check_amount,
|
||
check_memo: selectedItem.check_memo,
|
||
check_status: selectedItem.check_status,
|
||
acc_kind: selectedItem.acc_kind,
|
||
member_num: selectedItem.member_num,
|
||
verify_time: selectedItem.verify_time,
|
||
verify_note: selectedItem.verify_note,
|
||
draft: JSON.stringify(draftData)
|
||
};
|
||
|
||
return axios.put(`../../api/transfer_register/${id}`, updateData);
|
||
},
|
||
updateDraftToDB(id, draftData) {
|
||
const updateData = {
|
||
id: id,
|
||
activity_num: this.reconcileDialog.selected.activity_num,
|
||
name: this.reconcileDialog.selected.name,
|
||
phone: this.reconcileDialog.selected.phone,
|
||
pay_type: this.reconcileDialog.selected.pay_type,
|
||
account_last5: this.reconcileDialog.selected.account_last5,
|
||
amount: this.reconcileDialog.selected.amount,
|
||
pay_mode: this.reconcileDialog.selected.pay_mode,
|
||
note: this.reconcileDialog.selected.note,
|
||
proof_img: this.reconcileDialog.selected.proof_img,
|
||
status: this.reconcileDialog.selected.status,
|
||
f_num_match: this.reconcileDialog.selected.f_num_match,
|
||
f_num: this.reconcileDialog.selected.f_num,
|
||
acc_num: this.reconcileDialog.selected.acc_num,
|
||
check_date: this.reconcileDialog.selected.check_date,
|
||
check_amount: this.reconcileDialog.selected.check_amount,
|
||
check_memo: this.reconcileDialog.selected.check_memo,
|
||
check_status: this.reconcileDialog.selected.check_status,
|
||
acc_kind: this.reconcileDialog.selected.acc_kind,
|
||
member_num: this.reconcileDialog.selected.member_num,
|
||
verify_time: this.reconcileDialog.selected.verify_time,
|
||
verify_note: this.reconcileDialog.selected.verify_note,
|
||
draft: JSON.stringify(draftData)
|
||
};
|
||
|
||
return axios.put(`../../api/transfer_register/${id}`, updateData);
|
||
},
|
||
confirmGroupReconcile() {
|
||
if (!this.canConfirm) return;
|
||
|
||
this.reconcileDialog.loading = true;
|
||
const overPayment = this.reconcileDialog.selected.check_amount - this.sumReconcile;
|
||
const postData = {
|
||
transfer_register_id: this.reconcileDialog.selected.id,
|
||
details: this.reconcileDialog.items
|
||
.filter(item => item.reconcile > 0)
|
||
.map(item => ({
|
||
f_num: item.f_num,
|
||
pro_order_detail_num: item.num,
|
||
amount: Number(item.reconcile),
|
||
reg_time: new Date().toISOString()
|
||
})),
|
||
over_payment: overPayment
|
||
};
|
||
|
||
axios.post('../../api/transfer_register/group_reconcile', postData)
|
||
.then(res => {
|
||
const message = res.data && res.data.message ? res.data.message : '共同沖帳完成';
|
||
alert(message);
|
||
|
||
this.reconcileDialog.show = false;
|
||
this.loadTableData(); // 重新載入清單
|
||
})
|
||
.catch(err => {
|
||
let errorMessage = '沖帳失敗,請聯繫系統管理員';
|
||
if (err.response && err.response.data) {
|
||
if (typeof err.response.data === 'string') {
|
||
errorMessage = err.response.data;
|
||
} else if (err.response.data.message) {
|
||
errorMessage = err.response.data.message;
|
||
}
|
||
}
|
||
alert(errorMessage);
|
||
})
|
||
.finally(() => {
|
||
this.reconcileDialog.loading = false;
|
||
});
|
||
},
|
||
validateAndUpdateReconcile(value, item, index) {
|
||
let numValue = Number(value);
|
||
if (isNaN(numValue)) {
|
||
numValue = 0;
|
||
}
|
||
numValue = Math.round(numValue);
|
||
|
||
this.$set(item, 'reconcile', numValue);
|
||
this.updateSumReconcile();
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
</asp:Content> |