917 lines
35 KiB
Plaintext
917 lines
35 KiB
Plaintext
<%@ Page Title="餘額核銷" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" EnableEventValidation="false" CodeFile="balance_reconcile.aspx.cs" Inherits="admin_transfer_balance_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="balance-app">
|
||
<v-app>
|
||
<v-container>
|
||
<v-card>
|
||
<v-card-title class="bg-warning 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 balance-reconcile-table"
|
||
item-key="id"
|
||
>
|
||
<template v-slot:item.follower="{ item }">
|
||
<div>
|
||
<div class="font-weight-bold">
|
||
<a
|
||
:href="`../follower/reg.aspx?num=${item.f_num}`"
|
||
target="_blank"
|
||
class="text-decoration-none"
|
||
:title="`查看 ${item.follower} 的詳細資料`"
|
||
>
|
||
{{ item.follower }}
|
||
<v-icon small color="primary" class="ml-1">mdi-open-in-new</v-icon>
|
||
</a>
|
||
</div>
|
||
<div class="caption text--secondary" v-if="item.phone">
|
||
{{ item.phone }}
|
||
</div>
|
||
<div class="caption text--secondary" v-if="item.phone2">
|
||
{{ item.phone2 }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.bank_info="{ item }">
|
||
<div>
|
||
<div class="font-weight-bold">{{ item.acc_name }}</div>
|
||
<div class="caption text--secondary">{{ item.check_date | date }}</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.amount_info="{ item }">
|
||
<div>
|
||
<div class="font-weight-bold text-primary">
|
||
已入帳:{{ item.check_amount }}
|
||
</div>
|
||
<div class="text-success">
|
||
已沖帳:{{ item.check_amount - item.remain_amount }}
|
||
</div>
|
||
<div class="text-warning font-weight-bold">
|
||
待核銷:{{ item.remain_amount }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<template v-slot:item.detail_info="{ item }">
|
||
<v-btn
|
||
color="info"
|
||
outlined
|
||
@click="showDetailDialog(item)"
|
||
>
|
||
<v-icon small class="mr-1">mdi-information-outline</v-icon>
|
||
詳細
|
||
</v-btn>
|
||
</template>
|
||
<!-- 選取項目欄位 -->
|
||
<template v-slot:item.select_items="{ item }">
|
||
<div style="min-width: 200px;">
|
||
<v-text-field
|
||
v-model="item.selected_items_text"
|
||
placeholder="項目名稱"
|
||
dense
|
||
outlined
|
||
readonly
|
||
hide-details
|
||
style="font-size: 12px;"
|
||
>
|
||
<template v-slot:append>
|
||
<v-btn
|
||
small
|
||
color="primary"
|
||
icon
|
||
@click="showItemSelectDialog(item)"
|
||
style="margin-right: -8px;"
|
||
>
|
||
<v-icon small>mdi-table</v-icon>
|
||
</v-btn>
|
||
</template>
|
||
</v-text-field>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- 狀態與操作欄位 -->
|
||
<template v-slot:item.status_action="{ item }">
|
||
<div style="min-width: 280px;">
|
||
<v-row no-gutters>
|
||
<v-col cols="6" class="pr-1">
|
||
<v-select
|
||
v-model="item.new_status"
|
||
:items="statusOptions"
|
||
dense
|
||
outlined
|
||
hide-details
|
||
placeholder="狀態"
|
||
style="font-size: 12px;"
|
||
></v-select>
|
||
</v-col>
|
||
<v-col cols="6" class="pl-1">
|
||
<v-btn
|
||
color="primary"
|
||
block
|
||
@click="processBalance(item)"
|
||
:disabled="!canUpdate(item)"
|
||
>
|
||
更新狀態
|
||
</v-btn>
|
||
</v-col>
|
||
</v-row>
|
||
<v-row no-gutters class="mt-2">
|
||
<v-col cols="12">
|
||
<v-text-field
|
||
v-model="item.verify_note"
|
||
dense
|
||
outlined
|
||
hide-details
|
||
placeholder="核對記錄"
|
||
style="font-size: 12px;"
|
||
></v-text-field>
|
||
</v-col>
|
||
</v-row>
|
||
</div>
|
||
</template>
|
||
</v-data-table>
|
||
</v-card-text>
|
||
</v-card>
|
||
</v-container>
|
||
|
||
<!-- 餘額處理對話框 -->
|
||
<v-dialog v-model="dialog.show" max-width="800px">
|
||
<v-card>
|
||
<v-card-title class="grey lighten-2">
|
||
<v-icon color="warning" class="mr-2">mdi-cash-multiple</v-icon>
|
||
餘額處理
|
||
<v-spacer></v-spacer>
|
||
<v-btn icon @click="dialog.show = false">
|
||
<v-icon>mdi-close</v-icon>
|
||
</v-btn>
|
||
</v-card-title>
|
||
|
||
<v-card-text class="pb-0">
|
||
<div v-if="dialog.selected">
|
||
<v-row class="my-3">
|
||
<v-col cols="12" md="6">
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">信眾:</span>
|
||
{{ dialog.selected.follower }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">入帳銀行:</span>
|
||
{{ dialog.selected.acc_name }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">入帳日期:</span>
|
||
{{ dialog.selected.check_date | date }}
|
||
</div>
|
||
</v-col>
|
||
<v-col cols="12" md="6">
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">入帳金額:</span>
|
||
<span class="text-primary">{{ dialog.selected.check_amount | currency }}</span>
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">剩餘金額:</span>
|
||
<span class="text-warning font-weight-bold">{{ dialog.selected.remain_amount | currency }}</span>
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">狀態:</span>
|
||
<v-chip small color="warning" text-color="white">
|
||
{{ getStatusText(dialog.selected.check_status) }}
|
||
</v-chip>
|
||
</div>
|
||
</v-col>
|
||
</v-row>
|
||
|
||
<!-- 歷史沖帳記錄 -->
|
||
<v-divider class="my-3"></v-divider>
|
||
<h6 class="mb-3">
|
||
<v-icon color="info" class="mr-1">mdi-history</v-icon>
|
||
歷史沖帳記錄
|
||
</h6>
|
||
<v-data-table
|
||
:headers="dialog.historyHeaders"
|
||
:items="dialog.historyItems"
|
||
class="elevation-1 mb-4"
|
||
hide-default-footer
|
||
:disable-pagination="true"
|
||
dense
|
||
>
|
||
<template v-slot:item.reconcile_amount="{ item }">
|
||
<span>{{ item.reconcile_amount | currency }}</span>
|
||
</template>
|
||
<template v-slot:item.reconcile_date="{ item }">
|
||
<span>{{ item.reconcile_date | date }}</span>
|
||
</template>
|
||
</v-data-table>
|
||
|
||
<!-- 餘額處理選項 -->
|
||
<v-divider class="my-3"></v-divider>
|
||
<h6 class="mb-3">
|
||
<v-icon color="warning" class="mr-1">mdi-cash-multiple</v-icon>
|
||
餘額處理方式
|
||
</h6>
|
||
<v-radio-group v-model="dialog.balanceAction" class="mt-0">
|
||
<v-radio
|
||
label="轉入下次活動"
|
||
value="transfer"
|
||
color="primary"
|
||
></v-radio>
|
||
<v-radio
|
||
label="現金退費"
|
||
value="refund_cash"
|
||
color="success"
|
||
></v-radio>
|
||
<v-radio
|
||
label="銀行轉帳退費"
|
||
value="refund_bank"
|
||
color="success"
|
||
></v-radio>
|
||
<v-radio
|
||
label="結餘處理"
|
||
value="balance_off"
|
||
color="grey"
|
||
></v-radio>
|
||
</v-radio-group>
|
||
|
||
<!-- 處理說明 -->
|
||
<v-textarea
|
||
v-model="dialog.memo"
|
||
label="處理說明"
|
||
outlined
|
||
rows="3"
|
||
placeholder="請輸入處理說明..."
|
||
class="mt-3"
|
||
></v-textarea>
|
||
</div>
|
||
</v-card-text>
|
||
|
||
<v-card-actions class="pa-4">
|
||
<div v-if="dialog.errorMessage" class="text-danger">
|
||
❌ {{ dialog.errorMessage }}
|
||
</div>
|
||
<v-spacer></v-spacer>
|
||
<v-btn color="grey" text @click="dialog.show = false">取消</v-btn>
|
||
<v-btn
|
||
color="warning"
|
||
@click="confirmBalance"
|
||
:disabled="!dialog.balanceAction || dialog.loading"
|
||
:loading="dialog.loading"
|
||
>
|
||
確認處理
|
||
</v-btn>
|
||
</v-card-actions>
|
||
</v-card>
|
||
</v-dialog>
|
||
|
||
|
||
|
||
<!-- 詳細資訊對話框 -->
|
||
<v-dialog v-model="detailDialog.show" max-width="900px">
|
||
<v-card>
|
||
<v-card-title class="grey lighten-2">
|
||
<v-icon color="info" class="mr-2">mdi-information-outline</v-icon>
|
||
詳細資訊
|
||
<v-spacer></v-spacer>
|
||
<v-btn icon @click="detailDialog.show = false">
|
||
<v-icon>mdi-close</v-icon>
|
||
</v-btn>
|
||
</v-card-title>
|
||
|
||
<v-tabs v-model="detailDialog.tab" background-color="grey lighten-4">
|
||
<v-tab>
|
||
<v-icon small class="mr-2">mdi-information</v-icon>
|
||
基本資訊
|
||
</v-tab>
|
||
<v-tab>
|
||
<v-icon small class="mr-2">mdi-table</v-icon>
|
||
沖帳明細
|
||
</v-tab>
|
||
<v-tab>
|
||
<v-icon small class="mr-2">mdi-image</v-icon>
|
||
證明圖片
|
||
</v-tab>
|
||
</v-tabs>
|
||
|
||
<v-tabs-items v-model="detailDialog.tab">
|
||
<!-- Tab 1: 基本資訊 -->
|
||
<v-tab-item>
|
||
<v-card-text>
|
||
<div v-if="detailDialog.selected">
|
||
<v-row>
|
||
<v-col cols="12" md="6">
|
||
<h6 class="mb-3 text-primary">
|
||
<v-icon color="primary" small class="mr-1">mdi-account</v-icon>
|
||
匯款人資訊
|
||
</h6>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">姓名:</span>
|
||
{{ detailDialog.selected.name }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">支付方式:</span>
|
||
{{ payTypeText[detailDialog.selected.pay_type] || detailDialog.selected.pay_type }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">帳號後5碼:</span>
|
||
{{ detailDialog.selected.account_last5 || '-' }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">支付型態:</span>
|
||
{{ detailDialog.selected.pay_mode }}
|
||
</div>
|
||
</v-col>
|
||
<v-col cols="12" md="6">
|
||
<h6 class="mb-3 text-success">
|
||
<v-icon color="success" small class="mr-1">mdi-cash</v-icon>
|
||
入帳資訊
|
||
</h6>
|
||
<div class="mb-2">
|
||
<div class="font-weight-bold">{{ detailDialog.selected.acc_name }}</div>
|
||
<div class="caption text--secondary">{{ detailDialog.selected.check_date | date }}</div>
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold text-primary">已入帳:{{ detailDialog.selected.check_amount }}</span>
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="text-success">已沖帳:{{ detailDialog.selected.check_amount - detailDialog.selected.remain_amount }}</span>
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="text-warning font-weight-bold">待核銷:{{ detailDialog.selected.remain_amount }}</span>
|
||
</div>
|
||
</v-col>
|
||
</v-row>
|
||
|
||
<v-divider class="my-4"></v-divider>
|
||
|
||
<v-row>
|
||
<v-col cols="12" md="6">
|
||
<h6 class="mb-3 text-purple">
|
||
<v-icon color="purple" small class="mr-1">mdi-calendar-check</v-icon>
|
||
活動資訊
|
||
</h6>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">活動名稱:</span>
|
||
{{ detailDialog.selected.activity_name || '-' }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">開始日期:</span>
|
||
{{ detailDialog.selected.activity_start_date | date }}
|
||
</div>
|
||
</v-col>
|
||
<v-col cols="12" md="6">
|
||
<h6 class="mb-3 text-info">
|
||
<v-icon color="info" small class="mr-1">mdi-clipboard-check</v-icon>
|
||
核對記錄
|
||
</h6>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">核對記錄:</span>
|
||
{{ detailDialog.selected.verify_note || '-' }}
|
||
</div>
|
||
<div class="mb-2">
|
||
<span class="font-weight-bold">帳簿備註:</span>
|
||
{{ detailDialog.selected.check_memo || '-' }}
|
||
</div>
|
||
</v-col>
|
||
</v-row>
|
||
</div>
|
||
</v-card-text>
|
||
</v-tab-item>
|
||
|
||
<!-- Tab 2: 沖帳明細表格 -->
|
||
<v-tab-item>
|
||
<v-card-text>
|
||
<div v-if="detailDialog.selected">
|
||
<v-data-table
|
||
:headers="detailDialog.reconcileHeaders"
|
||
:items="detailDialog.reconcileItems"
|
||
class="elevation-1"
|
||
hide-default-footer
|
||
:disable-pagination="true"
|
||
>
|
||
<template v-slot:item.reconcile="{ item }">
|
||
<span class="font-weight-bold text-success">{{ item.reconcile | currency }}</span>
|
||
</template>
|
||
<template v-slot:item.register_date="{ item }">
|
||
<span>{{ item.register_date | date }}</span>
|
||
</template>
|
||
<template v-slot:item.price="{ item }">
|
||
<span>{{ item.price | currency }}</span>
|
||
</template>
|
||
</v-data-table>
|
||
</div>
|
||
</v-card-text>
|
||
</v-tab-item>
|
||
|
||
<!-- Tab 3: 證明圖片 -->
|
||
<v-tab-item>
|
||
<v-card-text>
|
||
<div v-if="detailDialog.selected">
|
||
<div v-if="detailDialog.selected.proof_img">
|
||
<h6 class="mb-3 text-orange">
|
||
<v-icon color="orange" small class="mr-1">mdi-image</v-icon>
|
||
證明圖片
|
||
</h6>
|
||
<div class="text-center">
|
||
<img
|
||
:src="detailDialog.selected.proof_img"
|
||
alt="證明圖片"
|
||
style="max-width: 100%; max-height: 500px;"
|
||
class="elevation-3"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div v-else class="text-center py-5">
|
||
<v-icon size="64" color="grey lighten-2">mdi-image-off</v-icon>
|
||
<div class="mt-3 text--secondary">無證明圖片</div>
|
||
</div>
|
||
</div>
|
||
</v-card-text>
|
||
</v-tab-item>
|
||
</v-tabs-items>
|
||
</v-card>
|
||
</v-dialog>
|
||
|
||
<!-- 活動品項選擇對話框 -->
|
||
<v-dialog v-model="search_dialog.show" max-width="700px">
|
||
<v-card>
|
||
<v-card-title class="justify-space-between grey lighten-2">
|
||
查詢:{{search_dialog.current.title}}
|
||
<v-btn icon @click="search_dialog.show=false"><v-icon>mdi-close</v-icon></v-btn>
|
||
</v-card-title>
|
||
<v-card-text >
|
||
<v-row>
|
||
|
||
<v-col v-for="item in search_dialog.current.keys"
|
||
:cols="search_dialog.current.keys.length>1?6:12" >
|
||
<v-text-field v-model="item.value" :label="item.title" v-if="item.visible===undefined || item.visible==true "></v-text-field>
|
||
</v-col>
|
||
<v-col cols="12" sm="4" md="3">
|
||
<v-checkbox
|
||
v-model="search_is_reconcile"
|
||
label="核銷項目"
|
||
:true-value="'Y'"
|
||
:false-value="''"
|
||
hide-details
|
||
@change="search_get"
|
||
></v-checkbox>
|
||
</v-col>
|
||
<v-col cols="12" class="text-end">
|
||
<v-btn color="primary" elevation="0" @click="search_get()">查詢</v-btn>
|
||
<v-btn elevation="0" @click="search_clear()">清除條件</v-btn>
|
||
</v-col>
|
||
</v-row>
|
||
<v-data-table
|
||
:headers="search_headers()"
|
||
:items="search_dialog.list"
|
||
:footer-props="search_dialog.footer"
|
||
:items-per-page="10"
|
||
:server-items-length="search_dialog.count"
|
||
:page.sync="search_dialog.page"
|
||
:options.sync="options"
|
||
@click:row="search_select"
|
||
:loading="search_dialog.loading"
|
||
></v-data-table>
|
||
</v-card-text>
|
||
<v-card-actions>
|
||
</v-card-actions>
|
||
</v-card>
|
||
</v-dialog>
|
||
</v-app>
|
||
</div>
|
||
</asp:Content>
|
||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" runat="Server">
|
||
<style>
|
||
.code-textarea textarea {
|
||
font-family: 'Courier New', monospace !important;
|
||
font-size: 12px !important;
|
||
}
|
||
/* 增加表格每列高度,讓內容不擁擠 */
|
||
.v-data-table.balance-reconcile-table .v-data-table__wrapper tr {
|
||
}
|
||
.v-data-table.balance-reconcile-table .v-data-table__wrapper td {
|
||
min-height: 110px !important;
|
||
height: 110px !important;
|
||
vertical-align: middle !important;
|
||
}
|
||
</style>
|
||
<script src="draft-utils.js"></script>
|
||
<script>
|
||
new Vue({
|
||
el: '#balance-app',
|
||
vuetify: new Vuetify(),
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
headers: [
|
||
{ text: '信眾', value: 'follower' },
|
||
{ text: '入帳帳戶/日期', value: 'bank_info' },
|
||
{ text: '金額', value: 'amount_info' },
|
||
{ text: '詳細資訊', value: 'detail_info', sortable: false },
|
||
{ text: '選取項目', value: 'select_items', sortable: false, width: '200px' },
|
||
{ text: '狀態 | 核對記錄', value: 'status_action', sortable: false, width: '280px' }
|
||
],
|
||
items: [],
|
||
dialog: {
|
||
show: false,
|
||
selected: null,
|
||
balanceAction: null,
|
||
memo: '',
|
||
loading: false,
|
||
errorMessage: '',
|
||
historyHeaders: [
|
||
{ text: '法會', value: 'activity_name' },
|
||
{ text: '項目', value: 'item_name' },
|
||
{ text: '沖帳金額', value: 'reconcile_amount' },
|
||
{ text: '沖帳日期', value: 'reconcile_date' }
|
||
],
|
||
historyItems: [
|
||
{
|
||
activity_name: '2025新春法會',
|
||
item_name: '護持金',
|
||
reconcile_amount: 12000,
|
||
reconcile_date: '2025-01-15T00:00:00'
|
||
}
|
||
]
|
||
},
|
||
detailDialog: {
|
||
show: false,
|
||
selected: null,
|
||
tab: 0,
|
||
reconcileHeaders: [
|
||
{ text: '法會活動', value: 'activity_name' },
|
||
{ text: '報名項目', value: 'actitem_name' },
|
||
{ text: '原始金額', value: 'price' },
|
||
{ text: '沖帳金額', value: 'reconcile' },
|
||
{ text: '報名日期', value: 'register_date' },
|
||
{ text: '訂單編號', value: 'order_no' }
|
||
],
|
||
reconcileItems: []
|
||
},
|
||
statusOptions: [
|
||
{ text: '沖帳有剩餘', value: '90' },
|
||
{ text: '未聯絡', value: '91' },
|
||
{ text: '已聯絡', value: '92' },
|
||
{ text: '餘額核銷', value: '95' }
|
||
],
|
||
search_dialog: {
|
||
controls: {
|
||
search5: {
|
||
id: 'search5',
|
||
title: '活動品項',
|
||
text_prop: 'subject',
|
||
value_prop: 'num',
|
||
keys: [
|
||
{ id: 'subject', title: '項目名稱', value: '' },
|
||
{ id: 'kindTxt', title: '項目分類' },
|
||
{ id: 'num', visible: false },
|
||
],
|
||
api_url: '../../api/activity/GetOrderList',
|
||
columns: [
|
||
{ id: 'subject', title: '項目名稱' },
|
||
{ id: 'kindTxt', title: '項目分類' },
|
||
{ id: 'price', title: '價格' },
|
||
],
|
||
selected: {},
|
||
currentRow: null, // 儲存當前正在編輯的行
|
||
select(vueInstance, selectedItem) {
|
||
// 當選擇項目時的處理邏輯
|
||
if (this.currentRow) {
|
||
// 將選中的 actItem 的 num 儲存到 balance_act_item 欄位
|
||
this.currentRow.balance_act_item = selectedItem.num;
|
||
// 顯示項目名稱給用戶看
|
||
this.currentRow.selected_items_text = selectedItem.subject;
|
||
// 如果有價格,也可以顯示
|
||
if (selectedItem.price) {
|
||
this.currentRow.selected_items_text += ` (NT$${Number(selectedItem.price).toLocaleString()})`;
|
||
}
|
||
console.log('已選擇項目:', selectedItem.subject, '項目編號:', selectedItem.num);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
show: false,
|
||
current: {},
|
||
list: [],
|
||
count: 0,
|
||
page: 1,
|
||
loading: false,
|
||
footer: {
|
||
showFirstLastPage: true,
|
||
disableItemsPerPage: true,
|
||
itemsPerPageAllText: '',
|
||
itemsPerPageText: '',
|
||
},
|
||
},
|
||
options: {},
|
||
payTypeText: {
|
||
1: '現金',
|
||
2: '匯款',
|
||
3: '支票'
|
||
},
|
||
search_is_reconcile: "Y",
|
||
}
|
||
},
|
||
mounted() {
|
||
this.loadTableData();
|
||
this.search_dialog.current = this.search_dialog.controls.search5; // 設定預設搜尋控制項
|
||
},
|
||
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: {
|
||
// 使用全域 DraftUtils 工具函數
|
||
loadTableData() {
|
||
this.loading = true;
|
||
axios.get('../../api/transfer_register/balance_reconcile_list')
|
||
.then(res => {
|
||
this.items = res.data.map(item => ({
|
||
...item,
|
||
// 初始化表單欄位
|
||
selected_items_text: item.balance_act_item ? (item.balance_actitem_name || '已選擇項目') : '', // 如果已有選中項目,顯示項目名稱
|
||
new_status: item.check_status,
|
||
balance_act_item: item.balance_act_item, // 保持現有的選中項目
|
||
verify_note: item.verify_note || '' // 初始化核對記錄欄位
|
||
}));
|
||
})
|
||
.catch(err => {
|
||
console.error('載入資料失敗:', err);
|
||
alert('載入資料失敗,請重新整理頁面');
|
||
this.items = [];
|
||
})
|
||
.finally(() => {
|
||
this.loading = false;
|
||
});
|
||
},
|
||
getStatusColor(status) {
|
||
switch(status) {
|
||
case '90': return 'warning';
|
||
case '99': return 'success';
|
||
default: return 'grey';
|
||
}
|
||
},
|
||
getStatusText(status) {
|
||
switch(status) {
|
||
case '90': return '沖帳有剩餘';
|
||
case '91': return '未聯絡';
|
||
case '92': return '已聯絡';
|
||
case '95': return '餘額核銷';
|
||
case '99': return '沖帳完成';
|
||
default: return '未知狀態';
|
||
}
|
||
},
|
||
showBalanceDialog(item) {
|
||
this.dialog.selected = item;
|
||
this.dialog.balanceAction = null;
|
||
this.dialog.memo = '';
|
||
this.dialog.errorMessage = '';
|
||
this.dialog.show = true;
|
||
|
||
// 載入歷史記錄
|
||
if (item.draft) {
|
||
const detailItems = window.DraftUtils.getDraftField(item.draft, 'pro_order_detail_items');
|
||
if (detailItems && Array.isArray(detailItems)) {
|
||
this.dialog.historyItems = detailItems.map(item => ({
|
||
activity_name: item.activity_name || '未知活動',
|
||
item_name: item.actitem_name || '未知項目',
|
||
reconcile_amount: item.reconcile || 0,
|
||
reconcile_date: item.register_date || '2025-01-15T00:00:00'
|
||
}));
|
||
} else {
|
||
this.dialog.historyItems = [];
|
||
}
|
||
}
|
||
},
|
||
|
||
confirmBalance() {
|
||
if (!this.dialog.balanceAction) {
|
||
this.dialog.errorMessage = '請選擇處理方式';
|
||
return;
|
||
}
|
||
|
||
if (!this.dialog.memo.trim()) {
|
||
this.dialog.errorMessage = '請輸入處理說明';
|
||
return;
|
||
}
|
||
|
||
this.dialog.loading = true;
|
||
this.dialog.errorMessage = '';
|
||
|
||
// 模擬 API 調用
|
||
setTimeout(() => {
|
||
alert(`餘額處理完成:${this.getActionText(this.dialog.balanceAction)}`);
|
||
this.dialog.show = false;
|
||
this.dialog.loading = false;
|
||
// 這裡之後會重新載入資料
|
||
}, 1500);
|
||
},
|
||
getActionText(action) {
|
||
switch(action) {
|
||
case 'transfer': return '轉入下次活動';
|
||
case 'refund_cash': return '現金退費';
|
||
case 'refund_bank': return '銀行轉帳退費';
|
||
case 'balance_off': return '結餘處理';
|
||
default: return '未知操作';
|
||
}
|
||
},
|
||
showDetailDialog(item) {
|
||
this.detailDialog.selected = item;
|
||
this.detailDialog.tab = 0; // 重置到第一個tab
|
||
|
||
// 解析沖帳明細 JSON 並轉為表格資料
|
||
this.loadReconcileItems(item.draft, item.id);
|
||
|
||
this.detailDialog.show = true;
|
||
},
|
||
async loadReconcileItems(draft, transferRegisterId) {
|
||
this.detailDialog.reconcileItems = [];
|
||
|
||
if (!draft) return;
|
||
|
||
const detailItems = window.DraftUtils.getDraftField(draft, 'pro_order_detail_items');
|
||
if (detailItems && Array.isArray(detailItems)) {
|
||
// 使用新格式的 pro_order_detail_items
|
||
this.detailDialog.reconcileItems = detailItems.map((item, index) => {
|
||
return {
|
||
pro_order_detail_num: item.pro_order_detail_num,
|
||
activity_name: item.activity_name || '未知活動',
|
||
actitem_name: item.actitem_name || '未知項目',
|
||
price: item.price || 0,
|
||
reconcile: item.reconcile,
|
||
register_date: item.register_date,
|
||
order_no: item.order_no || ''
|
||
};
|
||
});
|
||
} else {
|
||
// 如果沒有詳細資料,嘗試使用 API 取得資料
|
||
try {
|
||
const response = await axios.get(`../../api/transfer_register/reconcile_detail?transfer_register_id=${transferRegisterId}`);
|
||
this.detailDialog.reconcileItems = response.data;
|
||
} catch (error) {
|
||
console.error('載入沖帳明細失敗:', error);
|
||
}
|
||
}
|
||
},
|
||
|
||
search_show(curr) {
|
||
this.search_dialog.current = curr;
|
||
this.search_clear();
|
||
this.search_dialog.show = true;
|
||
},
|
||
search_clear() {
|
||
if (!this.search_dialog.current.keys) return;
|
||
this.search_dialog.current.keys.forEach((t, i) => { t.value = '' });
|
||
this.search_get();
|
||
},
|
||
search_get() {
|
||
if (!this.search_dialog.current.keys) return;
|
||
let api_url = this.search_dialog.current.api_url;
|
||
let keys = this.search_dialog.current.keys;
|
||
|
||
this.search_dialog.page = this.options.page ?? 1;
|
||
let params = { page: this.search_dialog.page, pageSize: 10 };
|
||
var search = {};
|
||
keys.forEach((t, i) => {
|
||
search[t.id] = t.value;
|
||
});
|
||
|
||
// 只有活動品項 Dialog 查詢時才帶 is_reconcile
|
||
if (this.search_dialog.current.id === 'search5' && this.search_is_reconcile === 'Y') {
|
||
search.is_reconcile = 'Y';
|
||
}
|
||
|
||
console.log("search_get", api_url, search, params, this.options);
|
||
this.search_dialog.loading = true;
|
||
|
||
axios.post(api_url, search, { params: params })
|
||
.then(response => {
|
||
this.search_dialog.list = response.data.list;
|
||
this.search_dialog.count = response.data.count;
|
||
this.search_dialog.loading = false;
|
||
})
|
||
.catch(error => {
|
||
console.log(error);
|
||
this.search_dialog.list = [];
|
||
this.search_dialog.count = 0;
|
||
this.search_dialog.loading = false;
|
||
alert("錯誤:" + error);
|
||
});
|
||
},
|
||
search_headers() {
|
||
if (!this.search_dialog.current.columns) return;
|
||
let r = [];
|
||
this.search_dialog.current.columns.forEach((t, i) => {
|
||
r.push({
|
||
text: t.title,
|
||
width: t.width,
|
||
align: 'start',
|
||
sortable: false,
|
||
value: t.id,
|
||
});
|
||
});
|
||
return r;
|
||
},
|
||
search_select(row) {
|
||
let curr = this.search_dialog.current;
|
||
curr.selected = row;
|
||
|
||
if (curr.select instanceof Function) {
|
||
curr.select(this, row);
|
||
}
|
||
this.search_dialog.show = false;
|
||
console.log('Selected row:', row);
|
||
},
|
||
showItemSelectDialog(item) {
|
||
// 設定當前正在編輯的行
|
||
this.search_dialog.controls.search5.currentRow = item;
|
||
this.search_dialog.current = this.search_dialog.controls.search5;
|
||
this.search_is_reconcile = "Y"; // 預設勾選
|
||
this.search_clear();
|
||
this.search_get(); // Dialog 一打開就查詢
|
||
this.search_dialog.show = true;
|
||
},
|
||
processBalance(item) {
|
||
if (!item.new_status) {
|
||
alert('請選擇狀態');
|
||
return;
|
||
}
|
||
|
||
if (!item.balance_act_item) {
|
||
alert('請先選擇項目');
|
||
return;
|
||
}
|
||
|
||
// 準備更新資料
|
||
const updateData = {
|
||
id: item.id,
|
||
check_status: item.new_status,
|
||
balance_act_item: item.balance_act_item,
|
||
verify_note: item.verify_note || ''
|
||
};
|
||
|
||
// 發送到後端更新
|
||
axios.post('../../api/transfer_register/update_balance', updateData)
|
||
.then(response => {
|
||
const statusText = this.statusOptions.find(opt => opt.value === item.new_status)?.text || '';
|
||
alert(`核銷餘額處理完成\n信眾:${item.follower}\n狀態:${statusText}\n項目:${item.selected_items_text}`);
|
||
|
||
// 如果狀態是「餘額核銷」(95),則從表格中移除該列
|
||
if (item.new_status === '95') {
|
||
const index = this.items.findIndex(i => i.id === item.id);
|
||
if (index !== -1) {
|
||
this.items.splice(index, 1);
|
||
}
|
||
} else {
|
||
// 如果狀態不是「餘額核銷」,則只更新該列的狀態
|
||
const index = this.items.findIndex(i => i.id === item.id);
|
||
if (index !== -1) {
|
||
this.items[index].check_status = item.new_status;
|
||
this.items[index].verify_note = item.verify_note || '';
|
||
this.items[index].balance_act_item = item.balance_act_item;
|
||
// 確保 selected_items_text 也得到更新
|
||
this.items[index].selected_items_text = item.selected_items_text;
|
||
}
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('更新失敗:', error);
|
||
alert('更新失敗,請重試');
|
||
});
|
||
},
|
||
canUpdate(item) {
|
||
// 所有狀態都必須選取項目才可按
|
||
if (!item.balance_act_item) {
|
||
return false;
|
||
}
|
||
|
||
// 狀態為「餘額核銷」時,必須選取項目才可按
|
||
if (item.new_status === '95') {
|
||
return true;
|
||
}
|
||
// 狀態為「未聯絡」或「已聯絡」時,皆可按
|
||
if (item.new_status === '91' || item.new_status === '92') {
|
||
return true;
|
||
}
|
||
// 其他狀態不可按
|
||
return false;
|
||
},
|
||
|
||
}
|
||
});
|
||
</script>
|
||
</asp:Content> |