2018-05-20 12:53:14 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
2020-02-08 11:51:50 +00:00
|
|
|
use Illuminate\Database\Eloquent\Collection;
|
2018-05-20 12:53:14 +00:00
|
|
|
use Illuminate\Database\Eloquent\Model;
|
2020-01-11 11:05:05 +00:00
|
|
|
use Illuminate\Support\Arr;
|
2022-04-22 04:41:18 +00:00
|
|
|
use Leenooks\Carbon as LeenooksCarbon;
|
2020-02-08 11:51:50 +00:00
|
|
|
|
2020-04-01 12:35:06 +00:00
|
|
|
use App\Traits\PushNew;
|
2018-05-20 12:53:14 +00:00
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2018-05-20 12:53:14 +00:00
|
|
|
class InvoiceItem extends Model
|
|
|
|
{
|
2024-07-04 05:03:11 +00:00
|
|
|
use PushNew;
|
2020-02-10 11:07:46 +00:00
|
|
|
|
2022-04-22 04:41:18 +00:00
|
|
|
protected $dates = [
|
|
|
|
'start_at',
|
|
|
|
'stop_at',
|
|
|
|
];
|
2018-05-20 12:53:14 +00:00
|
|
|
|
2020-07-06 06:02:59 +00:00
|
|
|
// Array of items that can be updated with PushNew
|
|
|
|
protected $pushable = ['taxes'];
|
|
|
|
|
2024-07-29 13:12:53 +00:00
|
|
|
public const INVOICEITEM_SERVICE = 0;
|
|
|
|
public const INVOICEITEM_SETUP = 4;
|
|
|
|
|
2022-06-12 08:32:54 +00:00
|
|
|
// @todo Change these to CONSTS so it's easier to reference through out the code
|
2021-10-01 04:59:04 +00:00
|
|
|
public const type = [
|
2024-07-29 13:12:53 +00:00
|
|
|
self::INVOICEITEM_SERVICE => 'Service Charge',
|
2021-10-01 04:59:04 +00:00
|
|
|
1 => 'Hardware', // *
|
|
|
|
2 => 'Service Relocation Fee', // * Must have corresponding SERVICE_ID
|
|
|
|
3 => 'Service Change', // * Must have corresponding SERVICE_ID
|
2024-07-29 13:12:53 +00:00
|
|
|
self::INVOICEITEM_SETUP => 'Service Connection', // * Must have corresponding SERVICE_ID
|
2021-10-01 04:59:04 +00:00
|
|
|
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
|
2022-06-11 07:39:25 +00:00
|
|
|
9 => 'Usage Charge',
|
2021-10-01 04:59:04 +00:00
|
|
|
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
|
|
|
|
];
|
|
|
|
|
2024-08-03 00:06:25 +00:00
|
|
|
/* STATIC */
|
|
|
|
|
|
|
|
public static function boot()
|
|
|
|
{
|
|
|
|
parent::boot();
|
|
|
|
|
|
|
|
static::created(function($model) {
|
|
|
|
// If this items were a charge, we'll update the charge to processed
|
|
|
|
if (($model->module_id === 30) && $model->module_ref) {
|
|
|
|
$o = Charge::findOrfail($model->module_ref);
|
|
|
|
$o->processed = TRUE;
|
|
|
|
$o->save();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/* RELATIONS */
|
2018-05-20 12:53:14 +00:00
|
|
|
|
2018-08-07 04:26:33 +00:00
|
|
|
public function invoice()
|
2018-08-01 07:09:38 +00:00
|
|
|
{
|
2018-08-07 04:26:33 +00:00
|
|
|
return $this->belongsTo(Invoice::class);
|
2018-08-01 07:09:38 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 04:26:33 +00:00
|
|
|
public function product()
|
2018-05-20 12:53:14 +00:00
|
|
|
{
|
2018-08-07 04:26:33 +00:00
|
|
|
return $this->belongsTo(Product::class);
|
2018-05-20 12:53:14 +00:00
|
|
|
}
|
|
|
|
|
2018-08-01 07:09:38 +00:00
|
|
|
public function service()
|
|
|
|
{
|
|
|
|
return $this->belongsTo(Service::class);
|
|
|
|
}
|
|
|
|
|
2018-05-20 12:53:14 +00:00
|
|
|
public function taxes()
|
|
|
|
{
|
|
|
|
return $this->hasMany(InvoiceItemTax::class);
|
|
|
|
}
|
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/* ATTRIBUTES */
|
2019-07-04 04:55:05 +00:00
|
|
|
|
2018-08-01 07:09:38 +00:00
|
|
|
public function getItemTypeNameAttribute()
|
|
|
|
{
|
2022-04-22 04:41:18 +00:00
|
|
|
switch ($this->item_type) {
|
2018-08-01 07:09:38 +00:00
|
|
|
// * Line Charge Topic on Invoice.
|
|
|
|
case 0:
|
2022-04-22 04:41:18 +00:00
|
|
|
if ($this->start_at)
|
2021-10-01 04:59:04 +00:00
|
|
|
return sprintf('%s [%s]','Product/Service',
|
2022-04-22 04:41:18 +00:00
|
|
|
(($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')));
|
2021-10-01 04:59:04 +00:00
|
|
|
else
|
|
|
|
return 'Product/Service';
|
2018-08-01 07:09:38 +00:00
|
|
|
|
|
|
|
// * Excess Service Item, of item 0, must have corresponding SERVICE_ID
|
|
|
|
case 5:
|
|
|
|
return sprintf('%s [%s] (%s)','Excess Usage',
|
2022-04-22 04:41:18 +00:00
|
|
|
$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')),
|
2018-08-01 07:09:38 +00:00
|
|
|
$this->module_text()
|
|
|
|
);
|
|
|
|
|
|
|
|
default:
|
2022-04-22 04:41:18 +00:00
|
|
|
return ($this->module_id == 30 ? 'Additional Charge: ' : '').Arr::get(self::type,$this->item_type,'Unknown');
|
2018-08-01 07:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-22 04:41:18 +00:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/**
|
|
|
|
* Sub total of item
|
|
|
|
*
|
|
|
|
* @return float
|
|
|
|
*/
|
|
|
|
public function getSubTotalAttribute(): float
|
2018-05-20 12:53:14 +00:00
|
|
|
{
|
2024-07-09 10:17:30 +00:00
|
|
|
return sprintf('%3.2f',$this->quantity * ($this->price_base - $this->discount_amt));
|
2018-05-20 12:53:14 +00:00
|
|
|
}
|
2020-04-01 12:35:06 +00:00
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/**
|
|
|
|
* Total of all taxes
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getTaxAttribute(): float
|
2018-05-20 12:53:14 +00:00
|
|
|
{
|
2021-07-23 07:25:26 +00:00
|
|
|
return sprintf('%3.2f',$this->taxes->sum('amount'));
|
2018-05-20 12:53:14 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/**
|
|
|
|
* Total including taxes
|
|
|
|
*
|
|
|
|
* @return float
|
|
|
|
*/
|
|
|
|
public function getTotalAttribute(): float
|
2018-05-20 12:53:14 +00:00
|
|
|
{
|
2021-07-23 07:25:26 +00:00
|
|
|
return sprintf('%3.2f',$this->getSubTotalAttribute()+$this->getTaxAttribute());
|
2018-05-20 12:53:14 +00:00
|
|
|
}
|
2019-07-04 04:55:05 +00:00
|
|
|
|
2021-07-23 07:25:26 +00:00
|
|
|
/* METHODS */
|
2019-07-04 04:55:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add taxes to this record
|
|
|
|
*/
|
2020-02-08 11:51:50 +00:00
|
|
|
public function addTaxes(Collection $taxes)
|
2019-07-04 04:55:05 +00:00
|
|
|
{
|
|
|
|
// Refuse to change an existing record
|
|
|
|
if ($this->exists)
|
|
|
|
throw new \Exception('Refusing to add Taxes to existing record');
|
|
|
|
|
2022-04-22 04:41:18 +00:00
|
|
|
foreach($taxes as $to) {
|
2019-07-04 04:55:05 +00:00
|
|
|
$iit = new InvoiceItemTax;
|
|
|
|
$iit->tax_id = $to->id;
|
|
|
|
$iit->amount = round($this->quantity*$this->price_base*$to->rate,3);
|
2020-04-01 12:35:06 +00:00
|
|
|
$iit->site_id = 1;
|
2019-07-04 04:55:05 +00:00
|
|
|
$this->taxes->push($iit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-22 04:41:18 +00:00
|
|
|
public function module_text(){
|
|
|
|
switch ($this->module_id) {
|
2019-07-04 04:55:05 +00:00
|
|
|
// Charges Module
|
|
|
|
case 30: return Charge::findOrFail($this->module_ref)->name;
|
|
|
|
|
|
|
|
default: abort(500,'Unable to handle '.$this->module_id);
|
|
|
|
}
|
|
|
|
}
|
2018-05-20 12:53:14 +00:00
|
|
|
}
|