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:
310
resources/views/admin/trial-balance/index.blade.php
Normal file
310
resources/views/admin/trial-balance/index.blade.php
Normal file
@@ -0,0 +1,310 @@
|
||||
<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">
|
||||
<!-- Filter Form -->
|
||||
<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.trial-balance.index') }}" class="space-y-4">
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||
<!-- Start Date -->
|
||||
<div>
|
||||
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
開始日期
|
||||
</label>
|
||||
<input type="date" name="start_date" id="start_date" value="{{ $startDate }}"
|
||||
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-700 dark:text-gray-100">
|
||||
</div>
|
||||
|
||||
<!-- End Date -->
|
||||
<div>
|
||||
<label for="end_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
結束日期
|
||||
</label>
|
||||
<input type="date" name="end_date" id="end_date" value="{{ $endDate }}"
|
||||
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-700 dark:text-gray-100">
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="flex items-end gap-4">
|
||||
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
|
||||
產生
|
||||
</button>
|
||||
<a href="{{ route('admin.trial-balance.index') }}" class="inline-flex justify-center rounded-md bg-white dark:bg-gray-700 px-4 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
重設
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Balance Status Alert -->
|
||||
@if($isBalanced)
|
||||
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4 border border-green-200 dark:border-green-800">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-green-400" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-green-800 dark:text-green-200">
|
||||
借貸平衡
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-green-700 dark:text-green-300">
|
||||
借方總計等於貸方總計,試算表正確
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4 border border-red-200 dark:border-red-800">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-red-800 dark:text-red-200">
|
||||
借貸不平衡
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-red-700 dark:text-red-300">
|
||||
差額: NT$ {{ number_format(abs($difference), 2) }}
|
||||
({{ $difference > 0 ? '借方多' : '貸方多' }})
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Summary Cards -->
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||
<!-- Debit Total -->
|
||||
<div class="bg-blue-50 dark:bg-blue-900/30 shadow sm:rounded-lg border-l-4 border-blue-400">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<dt class="text-sm font-medium text-blue-800 dark:text-blue-200">
|
||||
借方總計
|
||||
</dt>
|
||||
<dd class="mt-1 text-3xl font-semibold text-blue-900 dark:text-blue-100">
|
||||
NT$ {{ number_format($grandDebitTotal, 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Credit Total -->
|
||||
<div class="bg-purple-50 dark:bg-purple-900/30 shadow sm:rounded-lg border-l-4 border-purple-400">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<dt class="text-sm font-medium text-purple-800 dark:text-purple-200">
|
||||
貸方總計
|
||||
</dt>
|
||||
<dd class="mt-1 text-3xl font-semibold text-purple-900 dark:text-purple-100">
|
||||
NT$ {{ number_format($grandCreditTotal, 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Difference -->
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg border-l-4 {{ $isBalanced ? 'border-green-400' : 'border-red-400' }}">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
差額
|
||||
</dt>
|
||||
<dd class="mt-1 text-3xl font-semibold {{ $isBalanced ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
|
||||
NT$ {{ number_format(abs($difference), 2) }}
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$typeLabels = [
|
||||
'asset' => '資產 (Assets)',
|
||||
'liability' => '負債 (Liabilities)',
|
||||
'net_asset' => '淨資產/基金 (Net Assets)',
|
||||
'income' => '收入 (Income)',
|
||||
'expense' => '支出 (Expenses)',
|
||||
];
|
||||
$typeOrder = ['asset', 'liability', 'net_asset', 'income', 'expense'];
|
||||
@endphp
|
||||
|
||||
<!-- Accounts by Type -->
|
||||
@if($accounts->count() > 0)
|
||||
@foreach($typeOrder as $type)
|
||||
@if(isset($accountsByType[$type]) && $accountsByType[$type]->count() > 0)
|
||||
<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 flex items-center">
|
||||
@switch($type)
|
||||
@case('asset')
|
||||
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-green-100 dark:bg-green-900/50 text-green-600 dark:text-green-400 mr-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
</span>
|
||||
@break
|
||||
@case('liability')
|
||||
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-red-100 dark:bg-red-900/50 text-red-600 dark:text-red-400 mr-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 14l6-6m-5.5.5h.01m4.99 5h.01M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16l3.5-2 3.5 2 3.5-2 3.5 2z" />
|
||||
</svg>
|
||||
</span>
|
||||
@break
|
||||
@case('net_asset')
|
||||
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-indigo-100 dark:bg-indigo-900/50 text-indigo-600 dark:text-indigo-400 mr-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
</span>
|
||||
@break
|
||||
@case('income')
|
||||
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-emerald-100 dark:bg-emerald-900/50 text-emerald-600 dark:text-emerald-400 mr-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
||||
</svg>
|
||||
</span>
|
||||
@break
|
||||
@case('expense')
|
||||
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-orange-100 dark:bg-orange-900/50 text-orange-600 dark:text-orange-400 mr-2">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 17h8m0 0V9m0 8l-8-8-4 4-6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
@break
|
||||
@endswitch
|
||||
{{ $typeLabels[$type] ?? ucfirst($type) }}
|
||||
</h3>
|
||||
|
||||
<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 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-blue-600 dark:text-blue-400">
|
||||
借方
|
||||
</th>
|
||||
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-purple-600 dark:text-purple-400">
|
||||
貸方
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
|
||||
@php $typeDebitTotal = 0; $typeCreditTotal = 0; @endphp
|
||||
@foreach($accountsByType[$type] as $item)
|
||||
@php
|
||||
$typeDebitTotal += $item['debit_total'];
|
||||
$typeCreditTotal += $item['credit_total'];
|
||||
@endphp
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm font-mono text-gray-900 dark:text-gray-100">
|
||||
<a href="{{ route('admin.general-ledger.index', ['account_id' => $item['account']->id, 'start_date' => $startDate, 'end_date' => $endDate]) }}"
|
||||
class="text-indigo-600 dark:text-indigo-400 hover:underline">
|
||||
{{ $item['account']->account_code }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
{{ $item['account']->account_name_zh }}
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ $item['account']->account_name_en }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-blue-600 dark:text-blue-400">
|
||||
{{ $item['debit_total'] > 0 ? number_format($item['debit_total'], 2) : '' }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-purple-600 dark:text-purple-400">
|
||||
{{ $item['credit_total'] > 0 ? number_format($item['credit_total'], 2) : '' }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
<!-- Type Subtotal -->
|
||||
<tr class="bg-gray-50 dark:bg-gray-700 font-semibold">
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100" colspan="2">
|
||||
小計
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-blue-700 dark:text-blue-300">
|
||||
{{ $typeDebitTotal > 0 ? number_format($typeDebitTotal, 2) : '' }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-purple-700 dark:text-purple-300">
|
||||
{{ $typeCreditTotal > 0 ? number_format($typeCreditTotal, 2) : '' }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
<!-- Grand Total -->
|
||||
<div class="bg-gray-900 dark:bg-gray-950 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full">
|
||||
<tbody>
|
||||
<tr class="text-white">
|
||||
<td class="px-4 py-4 text-lg font-bold">
|
||||
總計
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-4 text-right">
|
||||
<span class="text-sm text-gray-400">借方</span>
|
||||
<div class="text-2xl font-bold text-blue-400">
|
||||
NT$ {{ number_format($grandDebitTotal, 2) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-4 text-right">
|
||||
<span class="text-sm text-gray-400">貸方</span>
|
||||
<div class="text-2xl font-bold text-purple-400">
|
||||
NT$ {{ number_format($grandCreditTotal, 2) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-4 py-4 text-right">
|
||||
<span class="text-sm text-gray-400">差額</span>
|
||||
<div class="text-2xl font-bold {{ $isBalanced ? 'text-green-400' : 'text-red-400' }}">
|
||||
NT$ {{ number_format(abs($difference), 2) }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<!-- No Data -->
|
||||
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="px-4 py-12 text-center">
|
||||
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-gray-100">
|
||||
無會計分錄
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
所選期間內沒有會計分錄
|
||||
</p>
|
||||
<div class="mt-6">
|
||||
<a href="{{ route('admin.finance.create') }}" class="inline-flex items-center rounded-md 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">
|
||||
<svg class="-ml-1 mr-2 h-5 w-5" 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
Reference in New Issue
Block a user