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:
2025-12-01 09:56:01 +08:00
parent 83ce1f7fc8
commit 642b879dd4
207 changed files with 19487 additions and 3048 deletions

View File

@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\Models\Member;
use App\Models\MembershipPayment;
use App\Models\FinanceDocument;
use App\Models\Announcement;
use Illuminate\Http\Request;
class AdminDashboardController extends Controller
@@ -47,16 +48,26 @@ class AdminDashboardController extends Controller
// Documents pending user's approval
$user = auth()->user();
$myPendingApprovals = 0;
if ($user->hasRole('cashier')) {
if ($user->hasRole('finance_cashier')) {
$myPendingApprovals += FinanceDocument::where('status', FinanceDocument::STATUS_PENDING)->count();
}
if ($user->hasRole('accountant')) {
if ($user->hasRole('finance_accountant')) {
$myPendingApprovals += FinanceDocument::where('status', FinanceDocument::STATUS_APPROVED_CASHIER)->count();
}
if ($user->hasRole('chair')) {
if ($user->hasRole('finance_chair')) {
$myPendingApprovals += FinanceDocument::where('status', FinanceDocument::STATUS_APPROVED_ACCOUNTANT)->count();
}
// Recent announcements
$recentAnnouncements = Announcement::query()
->published()
->active()
->forAccessLevel($user)
->orderByDesc('is_pinned')
->orderByDesc('published_at')
->limit(5)
->get();
return view('admin.dashboard.index', compact(
'totalMembers',
'activeMembers',
@@ -70,7 +81,8 @@ class AdminDashboardController extends Controller
'pendingApprovals',
'fullyApprovedDocs',
'rejectedDocs',
'myPendingApprovals'
'myPendingApprovals',
'recentAnnouncements'
));
}
}