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

@@ -6,6 +6,7 @@ use App\Mail\PaymentSubmittedMail;
use App\Models\Member;
use App\Models\MembershipPayment;
use App\Models\User;
use App\Services\MembershipFeeCalculator;
use App\Support\AuditLogger;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@@ -14,6 +15,13 @@ use Illuminate\Validation\Rule;
class MemberPaymentController extends Controller
{
protected MembershipFeeCalculator $feeCalculator;
public function __construct(MembershipFeeCalculator $feeCalculator)
{
$this->feeCalculator = $feeCalculator;
}
/**
* Show payment submission form
*/
@@ -32,7 +40,10 @@ class MemberPaymentController extends Controller
->with('error', __('You cannot submit payment at this time. You may already have a pending payment or your membership is already active.'));
}
return view('member.submit-payment', compact('member'));
// Calculate fee details
$feeDetails = $this->feeCalculator->calculateNextFee($member);
return view('member.submit-payment', compact('member', 'feeDetails'));
}
/**
@@ -47,8 +58,11 @@ class MemberPaymentController extends Controller
->with('error', __('You cannot submit payment at this time.'));
}
// Calculate fee details
$feeDetails = $this->feeCalculator->calculateNextFee($member);
$validated = $request->validate([
'amount' => ['required', 'numeric', 'min:0'],
'amount' => ['required', 'numeric', 'min:' . $feeDetails['final_amount']],
'paid_at' => ['required', 'date', 'before_or_equal:today'],
'payment_method' => ['required', Rule::in([
MembershipPayment::METHOD_BANK_TRANSFER,
@@ -65,10 +79,15 @@ class MemberPaymentController extends Controller
$receiptFile = $request->file('receipt');
$receiptPath = $receiptFile->store('payment-receipts', 'private');
// Create payment record
// Create payment record with fee details
$payment = MembershipPayment::create([
'member_id' => $member->id,
'fee_type' => $feeDetails['fee_type'],
'amount' => $validated['amount'],
'base_amount' => $feeDetails['base_amount'],
'discount_amount' => $feeDetails['discount_amount'],
'final_amount' => $feeDetails['final_amount'],
'disability_discount' => $feeDetails['disability_discount'],
'paid_at' => $validated['paid_at'],
'payment_method' => $validated['payment_method'],
'reference' => $validated['reference'] ?? null,