adjusted_balance = $model->adjusted_balance ?? (float) $model->calculateAdjustedBalance(); $model->discrepancy_amount = $model->discrepancy_amount ?? (float) $model->calculateDiscrepancy(); $model->reconciliation_status = $model->reconciliation_status ?? self::STATUS_PENDING; }); } protected $fillable = [ 'reconciliation_month', 'bank_statement_balance', 'bank_statement_date', 'bank_statement_file_path', 'system_book_balance', 'outstanding_checks', 'deposits_in_transit', 'bank_charges', 'adjusted_balance', 'discrepancy_amount', 'reconciliation_status', 'prepared_by_cashier_id', 'reviewed_by_accountant_id', 'approved_by_manager_id', 'prepared_at', 'reviewed_at', 'approved_at', 'notes', ]; protected $casts = [ 'reconciliation_month' => '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 { $adjusted = $this->adjusted_balance ?? $this->calculateAdjustedBalance(); return abs($adjusted - floatval($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 || $this->discrepancy_amount > 0.01; } /** * 是否可以被會計覆核 */ public function canBeReviewed(): bool { return $this->isPending() && $this->reviewed_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; $checksCount = 0; if ($this->outstanding_checks) { foreach ($this->outstanding_checks as $check) { $checksTotal += floatval($check['amount'] ?? 0); $checksCount++; } } $depositsTotal = 0; $depositsCount = 0; if ($this->deposits_in_transit) { foreach ($this->deposits_in_transit as $deposit) { $depositsTotal += floatval($deposit['amount'] ?? 0); $depositsCount++; } } $chargesTotal = 0; $chargesCount = 0; if ($this->bank_charges) { foreach ($this->bank_charges as $charge) { $chargesTotal += floatval($charge['amount'] ?? 0); $chargesCount++; } } return [ 'total_outstanding_checks' => $checksTotal, 'outstanding_checks_count' => $checksCount, 'total_deposits_in_transit' => $depositsTotal, 'deposits_in_transit_count' => $depositsCount, 'total_bank_charges' => $chargesTotal, 'bank_charges_count' => $chargesCount, 'net_adjustment' => $depositsTotal - $checksTotal - $chargesTotal, ]; } }