'date', 'cashier_verified_at' => 'datetime', 'accountant_verified_at' => 'datetime', 'chair_verified_at' => 'datetime', 'rejected_at' => 'datetime', 'base_amount' => 'decimal:2', 'discount_amount' => 'decimal:2', 'final_amount' => 'decimal:2', 'disability_discount' => 'boolean', ]; // Relationships public function member() { return $this->belongsTo(Member::class); } public function submittedBy() { return $this->belongsTo(User::class, 'submitted_by_user_id'); } public function verifiedByCashier() { return $this->belongsTo(User::class, 'verified_by_cashier_id'); } public function verifiedByAccountant() { return $this->belongsTo(User::class, 'verified_by_accountant_id'); } public function verifiedByChair() { return $this->belongsTo(User::class, 'verified_by_chair_id'); } public function rejectedBy() { return $this->belongsTo(User::class, 'rejected_by_user_id'); } // Status check methods public function isPending(): bool { return $this->status === self::STATUS_PENDING; } public function isApprovedByCashier(): bool { return $this->status === self::STATUS_APPROVED_CASHIER; } public function isApprovedByAccountant(): bool { return $this->status === self::STATUS_APPROVED_ACCOUNTANT; } public function isFullyApproved(): bool { return $this->status === self::STATUS_APPROVED_CHAIR; } public function isRejected(): bool { return $this->status === self::STATUS_REJECTED; } // Workflow validation methods public function canBeApprovedByCashier(): bool { return $this->isPending(); } public function canBeApprovedByAccountant(): bool { return $this->isApprovedByCashier(); } public function canBeApprovedByChair(): bool { return $this->isApprovedByAccountant(); } // Accessor for status label public function getStatusLabelAttribute(): string { return match($this->status) { self::STATUS_PENDING => '待審核', self::STATUS_APPROVED_CASHIER => '出納已審', self::STATUS_APPROVED_ACCOUNTANT => '會計已審', self::STATUS_APPROVED_CHAIR => '主席已審', self::STATUS_REJECTED => '已拒絕', default => $this->status, }; } // Accessor for payment method label public function getPaymentMethodLabelAttribute(): string { return match($this->payment_method) { self::METHOD_BANK_TRANSFER => '銀行轉帳', self::METHOD_CONVENIENCE_STORE => '超商繳費', self::METHOD_CASH => '現金', self::METHOD_CREDIT_CARD => '信用卡', default => $this->payment_method ?? '未指定', }; } // Accessor for fee type label public function getFeeTypeLabelAttribute(): string { return match($this->fee_type) { self::FEE_TYPE_ENTRANCE => '入會會費', self::FEE_TYPE_ANNUAL => '常年會費', default => $this->fee_type ?? '未指定', }; } /** * 是否有使用身心障礙優惠 */ public function hasDisabilityDiscount(): bool { return (bool) $this->disability_discount; } /** * 取得折扣說明 */ public function getDiscountDescriptionAttribute(): ?string { if (!$this->hasDisabilityDiscount()) { return null; } return '身心障礙優惠 50%'; } // Clean up receipt file when payment is deleted protected static function boot() { parent::boot(); static::deleting(function ($payment) { if ($payment->receipt_path && Storage::disk('private')->exists($payment->receipt_path)) { Storage::disk('private')->delete($payment->receipt_path); } }); } }