214 lines
5.4 KiB
PHP
214 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
class BankReconciliation extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
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
|
|
{
|
|
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,
|
|
];
|
|
}
|
|
}
|