2025-01-16 17:37:32 -05:00

111 lines
2.8 KiB
PHP

<?php
namespace App\Models;
use App\Enums\InvoiceStatus;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\SoftDeletes;
class Invoice extends Model
{
use HasFactory, SoftDeletes;
protected $fillable = [
'internal_id',
'customer_id',
'status',
'subtotal',
'total',
'pst_rate',
'gst_rate',
'pst_amount',
'gst_amount',
'has_pst',
'has_gst',
'date',
'due_date',
];
protected $casts = [
'has_gst' => 'boolean',
'has_pst' => 'boolean',
'date' => 'datetime',
'total' => 'decimal:2',
'subtotal' => 'decimal:2',
'status' => InvoiceStatus::class,
];
public static function boot(): void
{
parent::boot();
static::created(function (Invoice $model) {
$model->attributes['internal_id'] = 'TN4'.str_pad($model->id, 4, '0', STR_PAD_LEFT);
$model->save();
});
}
public function calculateTotals(): void
{
if (empty($this->orders)) {
$this->subtotal = 0;
$this->gst_amount = 0;
$this->pst_amount = 0;
$this->total = 0;
$this->save();
return;
}
$subtotal = $this->orders->sum(fn (Order $order) => $order->total_service_price);
$this->subtotal = $subtotal;
$gstAmount = $this->calculateTaxAmount($subtotal, $this->gst_rate, $this->has_gst);
$pstAmount = $this->calculateTaxAmount($subtotal, $this->pst_rate, $this->has_pst);
$this->gst_amount = $gstAmount;
$this->pst_amount = $pstAmount;
$this->total = $subtotal + $gstAmount + $pstAmount;
$this->save();
}
private function calculateTaxAmount(float $amount, float $rate, ?bool $apply): float
{
return $apply ? $amount * ($rate / 100) : 0;
}
public function setStatus(InvoiceStatus $status): void
{
if ($this->status !== $status) {
$this->status = $status;
$this->save();
}
}
public function orders(): HasMany
{
return $this->HasMany(Order::class);
}
public function customer(): BelongsTo
{
return $this->belongsTo(Customer::class);
}
public function productServices(): HasManyThrough
{
return $this->hasManyThrough(ProductService::class, Order::class);
}
public function invoiceReports(): BelongsToMany
{
return $this->belongsToMany(InvoiceReport::class);
}
}