osb/app/Models/InvoiceItem.php
2024-07-09 20:17:30 +10:00

179 lines
4.8 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Leenooks\Carbon as LeenooksCarbon;
use App\Traits\PushNew;
/**
* Class Invoice Items
* Items that belong on an invoice
*
* Attributes for services:
* + sub_total : Value of item
* + tax : Total of all taxes
* + total : Total including taxes
*/
class InvoiceItem extends Model
{
use PushNew;
protected $dates = [
'start_at',
'stop_at',
];
// Array of items that can be updated with PushNew
protected $pushable = ['taxes'];
// @todo Change these to CONSTS so it's easier to reference through out the code
public const type = [
0 => 'Service Charge',
1 => 'Hardware', // *
2 => 'Service Relocation Fee', // * Must have corresponding SERVICE_ID
3 => 'Service Change', // * Must have corresponding SERVICE_ID
4 => 'Service Connection', // * Must have corresponding SERVICE_ID
6 => 'Service Cancellation', // * Must have corresponding SERVICE_ID
7 => 'Extra Product/Service Charge', // * Service Billing in advance, Must have corresponding SERVICE_ID
8 => 'Product Addition', // * Additional Product Customisation, Must have corresponding SERVICE_ID
9 => 'Usage Charge',
120 => 'Credit/Debit Transfer', // * SERVICE_ID is NULL, MODULE_ID is NULL, MODULE_REF is NULL : INVOICE_ID is NOT NULL
123 => 'Shipping',
124 => 'Late Payment Fee', // * SERVICE_ID is NULL, MODULE_ID = CHECKOUT MODULE,
125 => 'Payment Fee', // * SERVICE_ID is NULL, MODULE_ID = CHECKOUT MODULE, MODULE_REF = CHECKOUT NAME
126 => 'Other', // * MODEL_ID should be a module
127 => 'Rounding', // * SERVICE_ID is NULL, MODULE_ID is NULL, MODULE_REF is NULL
];
/* RELATIONS */
public function invoice()
{
return $this->belongsTo(Invoice::class);
}
public function product()
{
return $this->belongsTo(Product::class);
}
public function service()
{
return $this->belongsTo(Service::class);
}
public function taxes()
{
return $this->hasMany(InvoiceItemTax::class);
}
/* ATTRIBUTES */
public function getItemTypeNameAttribute()
{
switch ($this->item_type) {
// * Line Charge Topic on Invoice.
case 0:
if ($this->start_at)
return sprintf('%s [%s]','Product/Service',
(($this->start_at == $this->stop_at) || (! $this->stop_at)) ? $this->start_at->format('Y-m-d') : sprintf('%s -> %s',$this->start_at->format('Y-m-d'),$this->stop_at->format('Y-m-d')));
else
return 'Product/Service';
// * Excess Service Item, of item 0, must have corresponding SERVICE_ID
case 5:
return sprintf('%s [%s] (%s)','Excess Usage',
$this->start_at == $this->stop_at ? $this->start_at->format('Y-m-d') : sprintf('%s -> %s',$this->start_at->format('Y-m-d'),$this->stop_at->format('Y-m-d')),
$this->module_text()
);
default:
return ($this->module_id == 30 ? 'Additional Charge: ' : '').Arr::get(self::type,$this->item_type,'Unknown');
}
}
/**
* We need to cast some dates to LeenooksCarbon to get access to startOfHalf()/endOfHalf() methods
*
* @param $value
* @return LeenooksCarbon
*/
public function getStartAtAttribute($value): LeenooksCarbon
{
return LeenooksCarbon::create($value);
}
/**
* We need to cast some dates to LeenooksCarbon to get access to startOfHalf()/endOfHalf() methods
*
* @param $value
* @return LeenooksCarbon
*/
public function getStopAtAttribute($value): LeenooksCarbon
{
return LeenooksCarbon::create($value);
}
/**
* Sub total of item
*
* @return float
*/
public function getSubTotalAttribute(): float
{
return sprintf('%3.2f',$this->quantity * ($this->price_base - $this->discount_amt));
}
/**
* Total of all taxes
*
* @return mixed
*/
public function getTaxAttribute(): float
{
return sprintf('%3.2f',$this->taxes->sum('amount'));
}
/**
* Total including taxes
*
* @return float
*/
public function getTotalAttribute(): float
{
return sprintf('%3.2f',$this->getSubTotalAttribute()+$this->getTaxAttribute());
}
/* METHODS */
/**
* Add taxes to this record
*/
public function addTaxes(Collection $taxes)
{
// Refuse to change an existing record
if ($this->exists)
throw new \Exception('Refusing to add Taxes to existing record');
foreach($taxes as $to) {
$iit = new InvoiceItemTax;
$iit->tax_id = $to->id;
$iit->amount = round($this->quantity*$this->price_base*$to->rate,3);
$iit->site_id = 1;
$this->taxes->push($iit);
}
}
public function module_text(){
switch ($this->module_id) {
// Charges Module
case 30: return Charge::findOrFail($this->module_ref)->name;
default: abort(500,'Unable to handle '.$this->module_id);
}
}
}