'date', 'bank_statement_balance' => 'decimal:2', 'bank_statement_date' => 'date', 'system_book_balance' => 'decimal:2', 'outstanding_checks' => 'array', 'deposits_in_transit' => 'array', 'bank_charges' => 'array', 'adjusted_balance' => 'decimal:2', 'discrepancy_amount' => 'decimal:2', 'prepared_at' => 'datetime', 'reviewed_at' => 'datetime', 'approved_at' => 'datetime', ]; /** * 狀態常數 */ const STATUS_PENDING = 'pending'; const STATUS_COMPLETED = 'completed'; const STATUS_DISCREPANCY = 'discrepancy'; /** * 製作調節表的出納人員 */ public function preparedByCashier(): BelongsTo { return $this->belongsTo(User::class, 'prepared_by_cashier_id'); } /** * 覆核的會計人員 */ public function reviewedByAccountant(): BelongsTo { return $this->belongsTo(User::class, 'reviewed_by_accountant_id'); } /** * 核准的主管 */ public function approvedByManager(): BelongsTo { return $this->belongsTo(User::class, 'approved_by_manager_id'); } /** * 計算調整後餘額 */ public function calculateAdjustedBalance(): float { $adjusted = $this->system_book_balance; // 加上在途存款 if ($this->deposits_in_transit) { foreach ($this->deposits_in_transit as $deposit) { $adjusted += floatval($deposit['amount'] ?? 0); } } // 減去未兌現支票 if ($this->outstanding_checks) { foreach ($this->outstanding_checks as $check) { $adjusted -= floatval($check['amount'] ?? 0); } } // 減去銀行手續費 if ($this->bank_charges) { foreach ($this->bank_charges as $charge) { $adjusted -= floatval($charge['amount'] ?? 0); } } return $adjusted; } /** * 計算差異金額 */ public function calculateDiscrepancy(): float { return abs($this->adjusted_balance - $this->bank_statement_balance); } /** * 檢查是否有差異 */ public function hasDiscrepancy(float $tolerance = 0.01): bool { return $this->calculateDiscrepancy() > $tolerance; } /** * 是否待覆核 */ public function isPending(): bool { return $this->reconciliation_status === self::STATUS_PENDING; } /** * 是否已完成 */ public function isCompleted(): bool { return $this->reconciliation_status === self::STATUS_COMPLETED; } /** * 是否有差異待處理 */ public function hasUnresolvedDiscrepancy(): bool { return $this->reconciliation_status === self::STATUS_DISCREPANCY; } /** * 是否可以被會計覆核 */ public function canBeReviewed(): bool { return $this->isPending() && $this->prepared_at !== null; } /** * 是否可以被主管核准 */ public function canBeApproved(): bool { return $this->reviewed_at !== null && $this->approved_at === null; } /** * 取得狀態文字 */ public function getStatusText(): string { return match ($this->reconciliation_status) { self::STATUS_PENDING => '待覆核', self::STATUS_COMPLETED => '已完成', self::STATUS_DISCREPANCY => '有差異', default => '未知', }; } /** * 取得未達帳項總計 */ public function getOutstandingItemsSummary(): array { $checksTotal = 0; if ($this->outstanding_checks) { foreach ($this->outstanding_checks as $check) { $checksTotal += floatval($check['amount'] ?? 0); } } $depositsTotal = 0; if ($this->deposits_in_transit) { foreach ($this->deposits_in_transit as $deposit) { $depositsTotal += floatval($deposit['amount'] ?? 0); } } $chargesTotal = 0; if ($this->bank_charges) { foreach ($this->bank_charges as $charge) { $chargesTotal += floatval($charge['amount'] ?? 0); } } return [ 'outstanding_checks_total' => $checksTotal, 'deposits_in_transit_total' => $depositsTotal, 'bank_charges_total' => $chargesTotal, 'net_adjustment' => $depositsTotal - $checksTotal - $chargesTotal, ]; } }