169 lines
4.4 KiB
PHP
169 lines
4.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 PaymentOrder extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $fillable = [
|
|
'finance_document_id',
|
|
'payee_name',
|
|
'payee_bank_code',
|
|
'payee_account_number',
|
|
'payee_bank_name',
|
|
'payment_amount',
|
|
'payment_method',
|
|
'created_by_accountant_id',
|
|
'payment_order_number',
|
|
'notes',
|
|
'verified_by_cashier_id',
|
|
'verified_at',
|
|
'verification_status',
|
|
'verification_notes',
|
|
'executed_by_cashier_id',
|
|
'executed_at',
|
|
'execution_status',
|
|
'transaction_reference',
|
|
'payment_receipt_path',
|
|
'status',
|
|
];
|
|
|
|
protected $casts = [
|
|
'payment_amount' => 'decimal:2',
|
|
'verified_at' => 'datetime',
|
|
'executed_at' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* 狀態常數
|
|
*/
|
|
const STATUS_DRAFT = 'draft';
|
|
const STATUS_PENDING_VERIFICATION = 'pending_verification';
|
|
const STATUS_VERIFIED = 'verified';
|
|
const STATUS_EXECUTED = 'executed';
|
|
const STATUS_CANCELLED = 'cancelled';
|
|
|
|
const VERIFICATION_PENDING = 'pending';
|
|
const VERIFICATION_APPROVED = 'approved';
|
|
const VERIFICATION_REJECTED = 'rejected';
|
|
|
|
const EXECUTION_PENDING = 'pending';
|
|
const EXECUTION_COMPLETED = 'completed';
|
|
const EXECUTION_FAILED = 'failed';
|
|
|
|
const PAYMENT_METHOD_BANK_TRANSFER = 'bank_transfer';
|
|
const PAYMENT_METHOD_CHECK = 'check';
|
|
const PAYMENT_METHOD_CASH = 'cash';
|
|
|
|
/**
|
|
* 關聯到財務申請單
|
|
*/
|
|
public function financeDocument(): BelongsTo
|
|
{
|
|
return $this->belongsTo(FinanceDocument::class);
|
|
}
|
|
|
|
/**
|
|
* 會計製單人
|
|
*/
|
|
public function createdByAccountant(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'created_by_accountant_id');
|
|
}
|
|
|
|
/**
|
|
* 出納覆核人
|
|
*/
|
|
public function verifiedByCashier(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'verified_by_cashier_id');
|
|
}
|
|
|
|
/**
|
|
* 出納執行人
|
|
*/
|
|
public function executedByCashier(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'executed_by_cashier_id');
|
|
}
|
|
|
|
/**
|
|
* 產生付款單號
|
|
*/
|
|
public static function generatePaymentOrderNumber(): string
|
|
{
|
|
$date = now()->format('Ymd');
|
|
$latest = self::where('payment_order_number', 'like', "PO-{$date}%")->latest('id')->first();
|
|
|
|
if ($latest) {
|
|
$lastNumber = (int) substr($latest->payment_order_number, -4);
|
|
$newNumber = $lastNumber + 1;
|
|
} else {
|
|
$newNumber = 1;
|
|
}
|
|
|
|
return sprintf('PO-%s%04d', $date, $newNumber);
|
|
}
|
|
|
|
/**
|
|
* 檢查是否可以被出納覆核
|
|
*/
|
|
public function canBeVerifiedByCashier(): bool
|
|
{
|
|
return $this->status === self::STATUS_PENDING_VERIFICATION &&
|
|
$this->verification_status === self::VERIFICATION_PENDING;
|
|
}
|
|
|
|
/**
|
|
* 檢查是否可以執行付款
|
|
*/
|
|
public function canBeExecuted(): bool
|
|
{
|
|
return $this->status === self::STATUS_VERIFIED &&
|
|
$this->verification_status === self::VERIFICATION_APPROVED &&
|
|
$this->execution_status === self::EXECUTION_PENDING;
|
|
}
|
|
|
|
/**
|
|
* 是否已執行
|
|
*/
|
|
public function isExecuted(): bool
|
|
{
|
|
return $this->status === self::STATUS_EXECUTED &&
|
|
$this->execution_status === self::EXECUTION_COMPLETED;
|
|
}
|
|
|
|
/**
|
|
* 取得付款方式文字
|
|
*/
|
|
public function getPaymentMethodText(): string
|
|
{
|
|
return match ($this->payment_method) {
|
|
self::PAYMENT_METHOD_BANK_TRANSFER => '銀行轉帳',
|
|
self::PAYMENT_METHOD_CHECK => '支票',
|
|
self::PAYMENT_METHOD_CASH => '現金',
|
|
default => '未知',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 取得狀態文字
|
|
*/
|
|
public function getStatusText(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_DRAFT => '草稿',
|
|
self::STATUS_PENDING_VERIFICATION => '待出納覆核',
|
|
self::STATUS_VERIFIED => '已覆核',
|
|
self::STATUS_EXECUTED => '已執行付款',
|
|
self::STATUS_CANCELLED => '已取消',
|
|
default => '未知',
|
|
};
|
|
}
|
|
}
|