Add membership fee system with disability discount and fix document permissions
Features: - Implement two fee types: entrance fee and annual fee (both NT$1,000) - Add 50% discount for disability certificate holders - Add disability certificate upload in member profile - Integrate disability verification into cashier approval workflow - Add membership fee settings in system admin Document permissions: - Fix hard-coded role logic in Document model - Use permission-based authorization instead of role checks Additional features: - Add announcements, general ledger, and trial balance modules - Add income management and accounting entries - Add comprehensive test suite with factories - Update UI translations to Traditional Chinese 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
272
resources/views/admin/incomes/create.blade.php
Normal file
272
resources/views/admin/incomes/create.blade.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||
新增收入記錄
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<form method="POST" action="{{ route('admin.incomes.store') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
<div class="space-y-6">
|
||||
{{-- 基本資訊 --}}
|
||||
<div>
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">基本資訊</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">輸入收入的基本資料。</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||||
{{-- 標題 --}}
|
||||
<div class="sm:col-span-2">
|
||||
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
標題 <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" name="title" id="title" value="{{ old('title') }}" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="例如:2024年度會費收入">
|
||||
@error('title')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 收入日期 --}}
|
||||
<div>
|
||||
<label for="income_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
收入日期 <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="date" name="income_date" id="income_date" value="{{ old('income_date', date('Y-m-d')) }}" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
@error('income_date')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 金額 --}}
|
||||
<div>
|
||||
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
金額 (NT$) <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="number" name="amount" id="amount" value="{{ old('amount') }}" required
|
||||
step="0.01" min="0.01"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="0.00">
|
||||
@error('amount')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 收入類型 --}}
|
||||
<div>
|
||||
<label for="income_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
收入類型 <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<select name="income_type" id="income_type" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">請選擇收入類型</option>
|
||||
<option value="membership_fee" @selected(old('income_type') == 'membership_fee')>會費</option>
|
||||
<option value="entrance_fee" @selected(old('income_type') == 'entrance_fee')>入會費</option>
|
||||
<option value="donation" @selected(old('income_type') == 'donation')>捐款</option>
|
||||
<option value="activity" @selected(old('income_type') == 'activity')>活動收入</option>
|
||||
<option value="grant" @selected(old('income_type') == 'grant')>補助款</option>
|
||||
<option value="interest" @selected(old('income_type') == 'interest')>利息收入</option>
|
||||
<option value="other" @selected(old('income_type') == 'other')>其他</option>
|
||||
</select>
|
||||
@error('income_type')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 會計科目 --}}
|
||||
<div>
|
||||
<label for="chart_of_account_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
會計科目 <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<select name="chart_of_account_id" id="chart_of_account_id" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">請選擇會計科目</option>
|
||||
@foreach ($chartOfAccounts as $account)
|
||||
<option value="{{ $account->id }}" @selected(old('chart_of_account_id') == $account->id)>
|
||||
{{ $account->account_code }} - {{ $account->account_name_zh }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('chart_of_account_id')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="border-gray-200 dark:border-gray-700">
|
||||
|
||||
{{-- 付款資訊 --}}
|
||||
<div>
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">付款資訊</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">記錄付款方式與相關資訊。</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||||
{{-- 付款方式 --}}
|
||||
<div>
|
||||
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
付款方式 <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<select name="payment_method" id="payment_method" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">請選擇付款方式</option>
|
||||
<option value="cash" @selected(old('payment_method') == 'cash')>現金</option>
|
||||
<option value="bank_transfer" @selected(old('payment_method') == 'bank_transfer')>銀行轉帳</option>
|
||||
<option value="check" @selected(old('payment_method') == 'check')>支票</option>
|
||||
</select>
|
||||
@error('payment_method')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 銀行帳號 --}}
|
||||
<div>
|
||||
<label for="bank_account" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
銀行帳號
|
||||
</label>
|
||||
<input type="text" name="bank_account" id="bank_account" value="{{ old('bank_account') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="例如:012-12345678">
|
||||
@error('bank_account')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 付款人姓名 --}}
|
||||
<div>
|
||||
<label for="payer_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
付款人姓名
|
||||
</label>
|
||||
<input type="text" name="payer_name" id="payer_name" value="{{ old('payer_name') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="付款人姓名">
|
||||
@error('payer_name')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 關聯會員 --}}
|
||||
<div>
|
||||
<label for="member_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
關聯會員
|
||||
</label>
|
||||
<select name="member_id" id="member_id"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">不關聯會員</option>
|
||||
@foreach ($members as $member)
|
||||
<option value="{{ $member->id }}" @selected(old('member_id', $selectedMember?->id) == $member->id)>
|
||||
{{ $member->full_name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('member_id')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 收據編號 --}}
|
||||
<div>
|
||||
<label for="receipt_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
收據編號
|
||||
</label>
|
||||
<input type="text" name="receipt_number" id="receipt_number" value="{{ old('receipt_number') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="收據編號">
|
||||
@error('receipt_number')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 交易參考號 --}}
|
||||
<div>
|
||||
<label for="transaction_reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
交易參考號
|
||||
</label>
|
||||
<input type="text" name="transaction_reference" id="transaction_reference" value="{{ old('transaction_reference') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="銀行交易參考號">
|
||||
@error('transaction_reference')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="border-gray-200 dark:border-gray-700">
|
||||
|
||||
{{-- 說明與備註 --}}
|
||||
<div>
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">說明與備註</h3>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-6">
|
||||
{{-- 說明 --}}
|
||||
<div>
|
||||
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
說明
|
||||
</label>
|
||||
<textarea name="description" id="description" rows="3"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="收入來源說明">{{ old('description') }}</textarea>
|
||||
@error('description')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 備註 --}}
|
||||
<div>
|
||||
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
內部備註
|
||||
</label>
|
||||
<textarea name="notes" id="notes" rows="2"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
|
||||
placeholder="內部備註(僅管理員可見)">{{ old('notes') }}</textarea>
|
||||
@error('notes')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- 附件 --}}
|
||||
<div>
|
||||
<label for="attachment" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
附件
|
||||
</label>
|
||||
<input type="file" name="attachment" id="attachment"
|
||||
class="mt-1 block w-full text-sm text-gray-500 dark:text-gray-400
|
||||
file:mr-4 file:py-2 file:px-4
|
||||
file:rounded-md file:border-0
|
||||
file:text-sm file:font-semibold
|
||||
file:bg-indigo-50 file:text-indigo-700
|
||||
dark:file:bg-indigo-900 dark:file:text-indigo-300
|
||||
hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800">
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">支援 PDF、圖片等格式,最大 10MB</p>
|
||||
@error('attachment')
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 提交按鈕 --}}
|
||||
<div class="flex justify-end space-x-3 pt-6">
|
||||
<a href="{{ route('admin.incomes.index') }}"
|
||||
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
取消
|
||||
</a>
|
||||
<button type="submit"
|
||||
class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
|
||||
建立收入記錄
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
234
resources/views/admin/incomes/index.blade.php
Normal file
234
resources/views/admin/incomes/index.blade.php
Normal file
@@ -0,0 +1,234 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||
收入管理
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-4">
|
||||
@if (session('status'))
|
||||
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
|
||||
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('error'))
|
||||
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
|
||||
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Statistics Cards --}}
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">待確認收入</dt>
|
||||
<dd class="mt-1 text-2xl font-semibold text-yellow-600 dark:text-yellow-400">
|
||||
{{ $statistics['pending_count'] }} 筆
|
||||
</dd>
|
||||
<dd class="text-sm text-gray-500 dark:text-gray-400">
|
||||
NT$ {{ number_format($statistics['pending_amount'], 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">已確認收入</dt>
|
||||
<dd class="mt-1 text-2xl font-semibold text-green-600 dark:text-green-400">
|
||||
{{ $statistics['confirmed_count'] }} 筆
|
||||
</dd>
|
||||
<dd class="text-sm text-gray-500 dark:text-gray-400">
|
||||
NT$ {{ number_format($statistics['confirmed_amount'], 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">收入記錄列表</h3>
|
||||
<div class="flex space-x-2">
|
||||
<a href="{{ route('admin.incomes.statistics') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
統計報表
|
||||
</a>
|
||||
@can('record_income')
|
||||
<a href="{{ route('admin.incomes.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
新增收入
|
||||
</a>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Filters --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<form method="GET" action="{{ route('admin.incomes.index') }}" class="grid grid-cols-1 gap-4 sm:grid-cols-5">
|
||||
{{-- 狀態篩選 --}}
|
||||
<div>
|
||||
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
|
||||
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">全部狀態</option>
|
||||
<option value="pending" @selected(request('status') == 'pending')>待確認</option>
|
||||
<option value="confirmed" @selected(request('status') == 'confirmed')>已確認</option>
|
||||
<option value="cancelled" @selected(request('status') == 'cancelled')>已取消</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{-- 收入類型篩選 --}}
|
||||
<div>
|
||||
<label for="income_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">收入類型</label>
|
||||
<select name="income_type" id="income_type" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">全部類型</option>
|
||||
<option value="membership_fee" @selected(request('income_type') == 'membership_fee')>會費</option>
|
||||
<option value="entrance_fee" @selected(request('income_type') == 'entrance_fee')>入會費</option>
|
||||
<option value="donation" @selected(request('income_type') == 'donation')>捐款</option>
|
||||
<option value="activity" @selected(request('income_type') == 'activity')>活動收入</option>
|
||||
<option value="grant" @selected(request('income_type') == 'grant')>補助款</option>
|
||||
<option value="interest" @selected(request('income_type') == 'interest')>利息收入</option>
|
||||
<option value="other" @selected(request('income_type') == 'other')>其他</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{-- 付款方式篩選 --}}
|
||||
<div>
|
||||
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">付款方式</label>
|
||||
<select name="payment_method" id="payment_method" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">全部方式</option>
|
||||
<option value="cash" @selected(request('payment_method') == 'cash')>現金</option>
|
||||
<option value="bank_transfer" @selected(request('payment_method') == 'bank_transfer')>銀行轉帳</option>
|
||||
<option value="check" @selected(request('payment_method') == 'check')>支票</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{-- 日期範圍 --}}
|
||||
<div>
|
||||
<label for="date_from" class="block text-sm font-medium text-gray-700 dark:text-gray-300">起始日期</label>
|
||||
<input type="date" name="date_from" id="date_from" value="{{ request('date_from') }}" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
</div>
|
||||
|
||||
{{-- 篩選按鈕 --}}
|
||||
<div class="flex items-end space-x-2">
|
||||
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
篩選
|
||||
</button>
|
||||
<a href="{{ route('admin.incomes.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
重設
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Table --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700" role="table">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
收入編號
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
標題
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
收入類型
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
金額
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
付款方式
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
狀態
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
日期
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
|
||||
<span class="sr-only">操作</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
|
||||
@forelse ($incomes as $income)
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
<div class="font-mono text-xs">{{ $income->income_number }}</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
<div class="font-medium">{{ $income->title }}</div>
|
||||
@if ($income->member)
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400">
|
||||
會員:{{ $income->member->full_name }}
|
||||
</div>
|
||||
@elseif ($income->payer_name)
|
||||
<div class="text-xs text-gray-500 dark:text-gray-400">
|
||||
付款人:{{ $income->payer_name }}
|
||||
</div>
|
||||
@endif
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->getIncomeTypeText() }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
<span class="font-semibold">NT$ {{ number_format($income->amount, 2) }}</span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->getPaymentMethodText() }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm">
|
||||
@if ($income->isCancelled())
|
||||
<span class="inline-flex rounded-full bg-red-100 dark:bg-red-900 px-2 text-xs font-semibold leading-5 text-red-800 dark:text-red-200">
|
||||
{{ $income->getStatusText() }}
|
||||
</span>
|
||||
@elseif ($income->isConfirmed())
|
||||
<span class="inline-flex rounded-full bg-green-100 dark:bg-green-900 px-2 text-xs font-semibold leading-5 text-green-800 dark:text-green-200">
|
||||
{{ $income->getStatusText() }}
|
||||
</span>
|
||||
@else
|
||||
<span class="inline-flex rounded-full bg-yellow-100 dark:bg-yellow-900 px-2 text-xs font-semibold leading-5 text-yellow-800 dark:text-yellow-200">
|
||||
{{ $income->getStatusText() }}
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->income_date->format('Y-m-d') }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-right text-sm">
|
||||
<a href="{{ route('admin.incomes.show', $income) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
|
||||
檢視
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
|
||||
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<p class="mt-2 text-sm font-semibold">尚無收入記錄</p>
|
||||
<p class="mt-1 text-sm">點選「新增收入」開始建立。</p>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{{ $incomes->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
329
resources/views/admin/incomes/show.blade.php
Normal file
329
resources/views/admin/incomes/show.blade.php
Normal file
@@ -0,0 +1,329 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||
收入詳情 - {{ $income->income_number }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-6">
|
||||
@if (session('status'))
|
||||
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
|
||||
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('error'))
|
||||
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
|
||||
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- 狀態卡片 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
|
||||
{{ $income->title }}
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
收入編號:{{ $income->income_number }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
@if ($income->isCancelled())
|
||||
<span class="inline-flex items-center rounded-full bg-red-100 dark:bg-red-900 px-3 py-1 text-sm font-medium text-red-800 dark:text-red-200">
|
||||
{{ $income->getStatusText() }}
|
||||
</span>
|
||||
@elseif ($income->isConfirmed())
|
||||
<span class="inline-flex items-center rounded-full bg-green-100 dark:bg-green-900 px-3 py-1 text-sm font-medium text-green-800 dark:text-green-200">
|
||||
{{ $income->getStatusText() }}
|
||||
</span>
|
||||
@else
|
||||
<span class="inline-flex items-center rounded-full bg-yellow-100 dark:bg-yellow-900 px-3 py-1 text-sm font-medium text-yellow-800 dark:text-yellow-200">
|
||||
{{ $income->getStatusText() }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 操作按鈕 --}}
|
||||
<div class="mt-6 flex space-x-3">
|
||||
@if ($income->canBeConfirmed())
|
||||
@can('confirm_income')
|
||||
<form method="POST" action="{{ route('admin.incomes.confirm', $income) }}" class="inline">
|
||||
@csrf
|
||||
<button type="submit" onclick="return confirm('確定要確認此收入嗎?將會自動產生出納日記帳和會計分錄。')"
|
||||
class="inline-flex items-center rounded-md border border-transparent bg-green-600 dark:bg-green-500 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
確認收入
|
||||
</button>
|
||||
</form>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@if ($income->canBeCancelled())
|
||||
@can('cancel_income')
|
||||
<form method="POST" action="{{ route('admin.incomes.cancel', $income) }}" class="inline">
|
||||
@csrf
|
||||
<button type="submit" onclick="return confirm('確定要取消此收入嗎?')"
|
||||
class="inline-flex items-center rounded-md border border-red-300 dark:border-red-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
取消收入
|
||||
</button>
|
||||
</form>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@if ($income->attachment_path)
|
||||
<a href="{{ route('admin.incomes.download', $income) }}"
|
||||
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
下載附件
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 金額與日期資訊 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">金額與日期</h4>
|
||||
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">金額</dt>
|
||||
<dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
||||
NT$ {{ number_format($income->amount, 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收入日期</dt>
|
||||
<dd class="mt-1 text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ $income->income_date->format('Y-m-d') }}
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收入類型</dt>
|
||||
<dd class="mt-1 text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ $income->getIncomeTypeText() }}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 會計資訊 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">會計資訊</h4>
|
||||
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">會計科目</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
@if ($income->chartOfAccount)
|
||||
{{ $income->chartOfAccount->account_code }} - {{ $income->chartOfAccount->account_name_zh }}
|
||||
@else
|
||||
<span class="text-gray-400">未指定</span>
|
||||
@endif
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款方式</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->getPaymentMethodText() }}
|
||||
</dd>
|
||||
</div>
|
||||
@if ($income->bank_account)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">銀行帳號</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->bank_account }}
|
||||
</dd>
|
||||
</div>
|
||||
@endif
|
||||
@if ($income->receipt_number)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收據編號</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->receipt_number }}
|
||||
</dd>
|
||||
</div>
|
||||
@endif
|
||||
@if ($income->transaction_reference)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">交易參考號</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->transaction_reference }}
|
||||
</dd>
|
||||
</div>
|
||||
@endif
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 付款人資訊 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">付款人資訊</h4>
|
||||
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
@if ($income->member)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">關聯會員</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
<a href="{{ route('admin.members.show', $income->member) }}" class="text-indigo-600 dark:text-indigo-400 hover:underline">
|
||||
{{ $income->member->full_name }}
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
@endif
|
||||
@if ($income->payer_name)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款人姓名</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->payer_name }}
|
||||
</dd>
|
||||
</div>
|
||||
@endif
|
||||
@if (!$income->member && !$income->payer_name)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款人</dt>
|
||||
<dd class="mt-1 text-sm text-gray-400">未記錄</dd>
|
||||
</div>
|
||||
@endif
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 說明與備註 --}}
|
||||
@if ($income->description || $income->notes)
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">說明與備註</h4>
|
||||
<dl class="space-y-4">
|
||||
@if ($income->description)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">說明</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap">{{ $income->description }}</dd>
|
||||
</div>
|
||||
@endif
|
||||
@if ($income->notes)
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">內部備註</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap">{{ $income->notes }}</dd>
|
||||
</div>
|
||||
@endif
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- 處理記錄 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">處理記錄</h4>
|
||||
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">出納記錄人</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->recordedByCashier?->name ?? '不適用' }}
|
||||
</dd>
|
||||
@if ($income->recorded_at)
|
||||
<dd class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ $income->recorded_at->format('Y-m-d H:i') }}
|
||||
</dd>
|
||||
@endif
|
||||
</div>
|
||||
@if ($income->isConfirmed())
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">會計確認人</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $income->confirmedByAccountant?->name ?? '不適用' }}
|
||||
</dd>
|
||||
@if ($income->confirmed_at)
|
||||
<dd class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ $income->confirmed_at->format('Y-m-d H:i') }}
|
||||
</dd>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 關聯記錄 --}}
|
||||
@if ($income->isConfirmed() && ($income->cashierLedgerEntry || $income->accountingEntries->count() > 0))
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">關聯記錄</h4>
|
||||
|
||||
@if ($income->cashierLedgerEntry)
|
||||
<div class="mb-4">
|
||||
<h5 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">出納日記帳</h5>
|
||||
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3">
|
||||
<a href="{{ route('admin.cashier-ledger.show', $income->cashierLedgerEntry) }}" class="text-indigo-600 dark:text-indigo-400 hover:underline">
|
||||
查看出納日記帳記錄
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($income->accountingEntries->count() > 0)
|
||||
<div>
|
||||
<h5 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">會計分錄</h5>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">會計科目</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">借方</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">貸方</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
@foreach ($income->accountingEntries as $entry)
|
||||
<tr>
|
||||
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $entry->chartOfAccount->account_code }} - {{ $entry->chartOfAccount->account_name_zh }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
@if ($entry->entry_type === 'debit')
|
||||
NT$ {{ number_format($entry->amount, 2) }}
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
@if ($entry->entry_type === 'credit')
|
||||
NT$ {{ number_format($entry->amount, 2) }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- 返回按鈕 --}}
|
||||
<div class="flex justify-start">
|
||||
<a href="{{ route('admin.incomes.index') }}"
|
||||
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||
</svg>
|
||||
返回列表
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
216
resources/views/admin/incomes/statistics.blade.php
Normal file
216
resources/views/admin/incomes/statistics.blade.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||
收入統計報表
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
|
||||
{{-- 篩選器 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<form method="GET" action="{{ route('admin.incomes.statistics') }}" class="flex items-end space-x-4">
|
||||
<div>
|
||||
<label for="year" class="block text-sm font-medium text-gray-700 dark:text-gray-300">年度</label>
|
||||
<select name="year" id="year" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
@for ($y = date('Y'); $y >= date('Y') - 5; $y--)
|
||||
<option value="{{ $y }}" @selected($year == $y)>{{ $y }}</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="month" class="block text-sm font-medium text-gray-700 dark:text-gray-300">月份</label>
|
||||
<select name="month" id="month" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
|
||||
<option value="">全年</option>
|
||||
@for ($m = 1; $m <= 12; $m++)
|
||||
<option value="{{ $m }}" @selected($month == $m)>{{ $m }}月</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
|
||||
查詢
|
||||
</button>
|
||||
<a href="{{ route('admin.incomes.export', ['date_from' => $year . '-01-01', 'date_to' => $year . '-12-31']) }}"
|
||||
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
匯出 CSV
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 總計 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
|
||||
{{ $year }}年{{ $month ? $month . '月' : '' }}收入總計
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div class="bg-indigo-50 dark:bg-indigo-900/30 rounded-lg p-4">
|
||||
<dt class="text-sm font-medium text-indigo-600 dark:text-indigo-400">總收入金額</dt>
|
||||
<dd class="mt-1 text-3xl font-semibold text-indigo-900 dark:text-indigo-100">
|
||||
NT$ {{ number_format($total['amount'], 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-green-50 dark:bg-green-900/30 rounded-lg p-4">
|
||||
<dt class="text-sm font-medium text-green-600 dark:text-green-400">收入筆數</dt>
|
||||
<dd class="mt-1 text-3xl font-semibold text-green-900 dark:text-green-100">
|
||||
{{ number_format($total['count']) }} 筆
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||
{{-- 依收入類型統計 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依收入類型統計</h3>
|
||||
@if ($byType->count() > 0)
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">類型</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">筆數</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">金額</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
@foreach ($byType as $item)
|
||||
<tr>
|
||||
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ \App\Models\Income::getIncomeTypeLabel($item->income_type) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
{{ number_format($item->count) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
NT$ {{ number_format($item->total_amount, 2) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">此期間無收入資料</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 依會計科目統計 --}}
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依會計科目統計</h3>
|
||||
@if ($byAccount->count() > 0)
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">科目</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">筆數</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">金額</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
@foreach ($byAccount as $item)
|
||||
<tr>
|
||||
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
|
||||
@if ($item->chartOfAccount)
|
||||
{{ $item->chartOfAccount->account_code }} - {{ $item->chartOfAccount->account_name_zh }}
|
||||
@else
|
||||
未分類
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
{{ number_format($item->count) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
NT$ {{ number_format($item->total_amount, 2) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">此期間無收入資料</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 依月份統計 --}}
|
||||
@if (!$month)
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ $year }}年月度收入趨勢</h3>
|
||||
@if ($byMonth->count() > 0)
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">月份</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">筆數</th>
|
||||
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">金額</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">圖示</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
@php
|
||||
$maxAmount = $byMonth->max('total_amount') ?: 1;
|
||||
@endphp
|
||||
@for ($m = 1; $m <= 12; $m++)
|
||||
@php
|
||||
$monthData = $byMonth->firstWhere('month', $m);
|
||||
$amount = $monthData->total_amount ?? 0;
|
||||
$count = $monthData->count ?? 0;
|
||||
$percentage = ($amount / $maxAmount) * 100;
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $m }}月
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
{{ number_format($count) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
|
||||
NT$ {{ number_format($amount, 2) }}
|
||||
</td>
|
||||
<td class="px-4 py-2">
|
||||
<div class="w-full bg-gray-200 dark:bg-gray-600 rounded-full h-2">
|
||||
<div class="bg-indigo-600 dark:bg-indigo-500 h-2 rounded-full" style="width: {{ $percentage }}%"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endfor
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">此年度無收入資料</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- 返回按鈕 --}}
|
||||
<div class="flex justify-start">
|
||||
<a href="{{ route('admin.incomes.index') }}"
|
||||
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||
</svg>
|
||||
返回收入列表
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
Reference in New Issue
Block a user