Compare commits
5 Commits
98d18c00a3
...
c4809a311d
Author | SHA1 | Date | |
---|---|---|---|
c4809a311d | |||
15a71c9f5b | |||
14c0109efa | |||
4b429cbf20 | |||
2b06eca080 |
@ -49,7 +49,7 @@ class ServiceList extends Command
|
|||||||
));
|
));
|
||||||
|
|
||||||
foreach (Service::cursor() as $o) {
|
foreach (Service::cursor() as $o) {
|
||||||
if ((! $this->option('inactive')) && (! $o->isActive()))
|
if ((! $this->option('inactive')) && (! $o->is_active))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ($this->option('type') && ($o->product->getCategoryAttribute() !== $this->option('type')))
|
if ($this->option('type') && ($o->product->getCategoryAttribute() !== $this->option('type')))
|
||||||
|
@ -257,7 +257,7 @@ class Account extends Model implements IDs
|
|||||||
{
|
{
|
||||||
$svs = $this
|
$svs = $this
|
||||||
->services_active
|
->services_active
|
||||||
->filter(fn($item)=>$item->isBilled() && $item->invoice_next)
|
->filter(fn($item)=>$item->is_billed && $item->invoice_next)
|
||||||
->sortBy(fn($item)=>(string)$item->invoice_next);
|
->sortBy(fn($item)=>(string)$item->invoice_next);
|
||||||
|
|
||||||
// Collect all the invoice items for our active services
|
// Collect all the invoice items for our active services
|
||||||
@ -280,7 +280,7 @@ class Account extends Model implements IDs
|
|||||||
->flatten();
|
->flatten();
|
||||||
|
|
||||||
// Add any account charges (charges with no active service)
|
// Add any account charges (charges with no active service)
|
||||||
foreach ($this->charges->filter(function($item) { return $item->unprocessed && ((! $this->service_id) || (! $item->service->isBilled())); }) as $oo) {
|
foreach ($this->charges->filter(function($item) { return $item->unprocessed && ((! $this->service_id) || (! $item->service->is_billed)); }) as $oo) {
|
||||||
$ii = new InvoiceItem;
|
$ii = new InvoiceItem;
|
||||||
|
|
||||||
$ii->active = TRUE;
|
$ii->active = TRUE;
|
||||||
|
@ -23,18 +23,40 @@ use App\Traits\{ScopeAccountUserAuthorised,ScopeServiceActive,SiteID};
|
|||||||
* Class Service
|
* Class Service
|
||||||
* Services that belong to an account
|
* Services that belong to an account
|
||||||
*
|
*
|
||||||
* So each service attribute has:
|
* So each service attribute has:
|
||||||
* - Offering, what product we supply (we make offerings from supplier's supplied products) - in the DB these are products/*
|
* - Offering, what product we supply (we make offerings from supplier's supplied products) - in the DB these are products/*
|
||||||
* - Supplied, our supplier's product that is providing the service - in the DB these are supplier/*
|
* - Supplied, our supplier's product that is providing the service - in the DB these are supplier/*
|
||||||
* - Type, what service we are providing, made up of a product we supply - in the DB these are service/*
|
* - Type, what service we are providing, made up of a product we supply - in the DB these are service/*
|
||||||
*
|
*
|
||||||
* Attributes for services:
|
* Attributes for services:
|
||||||
* + additional_cost : Pending additional charges for this service (excluding setup) //@todo check all these are still valid
|
* + billing_charge : Charge for this service each invoice period (ex TAX)
|
||||||
* + billing_charge : Charge for this service each invoice period
|
* + billing_charge_normalised_taxed: Charge for this service each invoice period, normalised to MONTHLY (with Account TAX)
|
||||||
* + billing_interval : The period that this service is billed for by default
|
* + billing_charge_taxed : Charge for this service each invoice period (with Account TAX)
|
||||||
* + billing_interval_string : The period that this service is billed for by default as a name
|
* + billing_charge_orig : Charge for this service before being overridden by $this->price (ex TAX)
|
||||||
* + invoiced_to : When this service has been billed to
|
* + billing_charge_orig_normalised_taxed: Charge for this service before being overridden by $this->price, normalised to MONTHLY (with Account TAX)
|
||||||
|
* + billing_charge_orig_taxed : Charge for this service before being overridden by $this->price (with Account TAX)
|
||||||
|
* + billing_cost : Cost for this service each invoice period (ex TAX)
|
||||||
|
* + billing_cost_normalised_taxed: Cost for this service each invoice period, normalised to MONTHLY (with Account TAX)
|
||||||
|
* + billing_cost_taxed : Cost for this service each invoice period (with Account TAX)
|
||||||
|
* + billing_cost_orig : Cost for this service before being overridden by $this->cost (ex TAX)
|
||||||
|
* + billing_cost_orig_normalised_taxed: Cost for this service before being overridden by $this->cost, normalised to MONTHLY (with Account TAX)
|
||||||
|
* + billing_cost_orig_taxed : Cost for this service before being overridden by $this->cost (with Account TAX)
|
||||||
|
* + billing_interval : The period that this service is billed
|
||||||
|
* + billing_interval_name : The period that this service is billed as a name
|
||||||
* + contract_term : The term that this service must be active
|
* + contract_term : The term that this service must be active
|
||||||
|
* + is_active : Is this service active. It is active, if active=true, or the order_status is not in self::INACTIVE_STATUS[]
|
||||||
|
* + is_billed : Does this service generate an invoice
|
||||||
|
* + is_cancelled : Service that has been cancelled or never provisioned
|
||||||
|
* + is_charge_overridden : Has the price been overridden
|
||||||
|
* + is_contracted : Is this service on a contract
|
||||||
|
* + is_cost_overridden : Has the cost been overridden
|
||||||
|
* + is_pending_active : Has this service been ordered, waiting to be active
|
||||||
|
* + is_pending_change : Is this service changing
|
||||||
|
* + is_pending_cancel : Is this active service being cancelled
|
||||||
|
* + status : Service status (inactive/active)
|
||||||
|
*
|
||||||
|
* Attributes for services (OLD):
|
||||||
|
* + invoiced_to : When this service has been billed to
|
||||||
* + contract_end : The date that the contract ends for this service
|
* + contract_end : The date that the contract ends for this service
|
||||||
* + name : Service short name with service address
|
* + name : Service short name with service address
|
||||||
* + name_short : Service Product short name, eg: phone number, domain name, certificate CN
|
* + name_short : Service Product short name, eg: phone number, domain name, certificate CN
|
||||||
@ -42,15 +64,6 @@ use App\Traits\{ScopeAccountUserAuthorised,ScopeServiceActive,SiteID};
|
|||||||
* + product : Our product that is providing this service
|
* + product : Our product that is providing this service
|
||||||
* + sid : System ID for service
|
* + sid : System ID for service
|
||||||
* + supplied : The model of the supplier's product used for this service.
|
* + supplied : The model of the supplier's product used for this service.
|
||||||
*
|
|
||||||
* Methods:
|
|
||||||
* + isChargeOverridden : Has the price been overridden?
|
|
||||||
* + isCostOverridden : Has the cost been overridden?
|
|
||||||
* + isPending : Is this a pending active service
|
|
||||||
*
|
|
||||||
* @package App\Models
|
|
||||||
* @todo Add min_charge
|
|
||||||
* @todo Add charge_orig : The original chargeable price
|
|
||||||
*/
|
*/
|
||||||
class Service extends Model implements IDs
|
class Service extends Model implements IDs
|
||||||
{
|
{
|
||||||
@ -268,6 +281,46 @@ class Service extends Model implements IDs
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function __get($key): mixed
|
||||||
|
{
|
||||||
|
return match ($key) {
|
||||||
|
'billing_cost' => $this->billing_cost(),
|
||||||
|
'billing_cost_normalised_taxed' => $this->billing_cost_taxed*Invoice::billing_change($this->billing_interval,Invoice::BILL_MONTHLY),
|
||||||
|
'billing_cost_taxed' => $this->account->taxed($this->billing_cost),
|
||||||
|
'billing_cost_orig' => $this->product->base_cost,
|
||||||
|
'billing_cost_orig_normalised_taxed' => $this->billing_cost_orig_taxed*Invoice::billing_change($this->product->type->billing_interval,Invoice::BILL_MONTHLY),
|
||||||
|
'billing_cost_orig_taxed' => $this->account->taxed($this->billing_cost_orig),
|
||||||
|
|
||||||
|
'billing_charge_orig' => $this->product->getBaseChargeAttribute($this->billing_interval,$this->account->group),
|
||||||
|
'billing_charge_orig_normalised_taxed' => $this->billing_charge_orig_taxed*Invoice::billing_change($this->billing_interval,Invoice::BILL_MONTHLY),
|
||||||
|
'billing_charge_orig_taxed' => $this->account->taxed($this->billing_charge_orig),
|
||||||
|
'billing_charge' => $this->billing_charge(),
|
||||||
|
'billing_charge_normalised_taxed' => $this->billing_charge_taxed*Invoice::billing_change($this->billing_interval,Invoice::BILL_MONTHLY),
|
||||||
|
'billing_charge_taxed' => $this->account->taxed($this->billing_charge),
|
||||||
|
|
||||||
|
'billing_interval' => $this->recur_schedule ?: $this->product->billing_interval,
|
||||||
|
'billing_interval_name' => Invoice::billing_name($this->billing_interval),
|
||||||
|
|
||||||
|
'contract_term' => max($this->supplied->contract_term,$this->product->type->contract_term),
|
||||||
|
|
||||||
|
'is_active' => $this->active || ($this->order_status && (! in_array($this->order_status,self::INACTIVE_STATUS))),
|
||||||
|
'is_billed' => (! ($this->external_billing || $this->suspend_billing || ($this->price === 0))),
|
||||||
|
'is_cancelled' => in_array($this->order_status,self::INACTIVE_STATUS),
|
||||||
|
'is_charge_overridden' => (! is_null($this->price)),
|
||||||
|
'is_contracted' => $this->getContractEndAttribute() && $this->getContractEndAttribute()->greaterThan(Carbon::now()),
|
||||||
|
'is_cost_overridden' => (! is_null($this->cost)),
|
||||||
|
'is_pending_active' => (! $this->active) && (! is_null($this->order_status)) && (! in_array($this->order_status,array_merge(self::INACTIVE_STATUS,['INACTIVE']))),
|
||||||
|
'is_pending_change' => $this->active && $this->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->count(),
|
||||||
|
'is_pending_cancel' => $this->active && in_array(strtolower($this->order_status),['cancel-request','cancel-pending']),
|
||||||
|
|
||||||
|
'status' => $this->active
|
||||||
|
? strtolower($this->order_status)
|
||||||
|
: ((strtolower($this->order_status) === 'cancelled') ? 'cancelled' : 'inactive'),
|
||||||
|
|
||||||
|
default => parent::__get($key),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/* STATIC */
|
/* STATIC */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,7 +348,7 @@ class Service extends Model implements IDs
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getLIDattribute(): string
|
public function getLIDAttribute(): string
|
||||||
{
|
{
|
||||||
return sprintf('%05s',$this->id);
|
return sprintf('%05s',$this->id);
|
||||||
}
|
}
|
||||||
@ -464,37 +517,6 @@ class Service extends Model implements IDs
|
|||||||
|
|
||||||
/* SCOPES */
|
/* SCOPES */
|
||||||
|
|
||||||
/**
|
|
||||||
* Only query active categories
|
|
||||||
* @deprecated use ScopeServiceActive
|
|
||||||
*/
|
|
||||||
public function scopeActive($query)
|
|
||||||
{
|
|
||||||
throw new \Exception('deprecated');
|
|
||||||
return $query->where(
|
|
||||||
fn($query)=>
|
|
||||||
$query->where($this->getTable().'.active',TRUE)
|
|
||||||
->orWhereNotIn('order_status',self::INACTIVE_STATUS)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find inactive services.
|
|
||||||
*
|
|
||||||
* @param $query
|
|
||||||
* @return mixed
|
|
||||||
* @deprecated use ScopeServiceInactive
|
|
||||||
*/
|
|
||||||
public function scopeInactive($query)
|
|
||||||
{
|
|
||||||
dd('deprecated');
|
|
||||||
return $query->where(
|
|
||||||
fn($query)=>
|
|
||||||
$query->where($this->getTable().'.active',FALSE)
|
|
||||||
->orWhereIn('order_status',self::INACTIVE_STATUS)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for a record
|
* Search for a record
|
||||||
*
|
*
|
||||||
@ -525,62 +547,6 @@ class Service extends Model implements IDs
|
|||||||
|
|
||||||
/* ATTRIBUTES */
|
/* ATTRIBUTES */
|
||||||
|
|
||||||
/**
|
|
||||||
* How much do we charge for this service, base on the current recur schedule
|
|
||||||
* price in the DB overrides the base price used
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getBillingChargeAttribute(): float
|
|
||||||
{
|
|
||||||
return $this->account->taxed($this->billing_charge());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBillingCostAttribute(): float
|
|
||||||
{
|
|
||||||
return $this->account->taxed($this->billing_cost());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine a monthly price for a service, even if it is billed at a different frequency
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function getBillingChargeNormalisedAttribute(): float
|
|
||||||
{
|
|
||||||
return number_format(
|
|
||||||
$this->getBillingChargeAttribute()*Invoice::billing_change($this->getBillingIntervalAttribute(),$this->offering->billing_interval),
|
|
||||||
2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBillingCostNormalisedAttribute(): float
|
|
||||||
{
|
|
||||||
return number_format(
|
|
||||||
$this->getBillingCostAttribute()*Invoice::billing_change($this->getBillingIntervalAttribute(),$this->offering->billing_interval),
|
|
||||||
2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the service billing period
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getBillingIntervalAttribute(): int
|
|
||||||
{
|
|
||||||
return $this->recur_schedule ?: $this->product->getBillingIntervalAttribute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a human friendly name for the billing interval
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getBillingIntervalStringAttribute(): string
|
|
||||||
{
|
|
||||||
return Invoice::billing_name($this->getBillingIntervalAttribute());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the earliest date that the service can be canceled as per contract/billing intervals
|
* Return the earliest date that the service can be canceled as per contract/billing intervals
|
||||||
*
|
*
|
||||||
@ -618,7 +584,7 @@ class Service extends Model implements IDs
|
|||||||
if (! $this->start_at)
|
if (! $this->start_at)
|
||||||
return $this->type->expire_at;
|
return $this->type->expire_at;
|
||||||
|
|
||||||
$end = $this->start_at->clone()->addMonths($this->getContractTermAttribute());
|
$end = $this->start_at->clone()->addMonths($this->contract_term);
|
||||||
|
|
||||||
// If we dont have an expire date, use the start date + contract_term
|
// If we dont have an expire date, use the start date + contract_term
|
||||||
if (! $this->type->expire_at)
|
if (! $this->type->expire_at)
|
||||||
@ -628,17 +594,6 @@ class Service extends Model implements IDs
|
|||||||
return ($end < $this->type->expire_at) ? $this->type->expire_at : $end;
|
return ($end < $this->type->expire_at) ? $this->type->expire_at : $end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will determine the minimum contract term for a service, which is the maximum of
|
|
||||||
* supplied->contract_term, or the product->type->contract_term;
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getContractTermAttribute(): int
|
|
||||||
{
|
|
||||||
return max($this->supplied->contract_term,$this->product->type->contract_term);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the date for the next invoice
|
* Return the date for the next invoice
|
||||||
*
|
*
|
||||||
@ -692,9 +647,7 @@ class Service extends Model implements IDs
|
|||||||
*/
|
*/
|
||||||
public function getNameShortAttribute()
|
public function getNameShortAttribute()
|
||||||
{
|
{
|
||||||
return $this->type->getServiceNameAttribute()
|
return $this->type->getServiceNameAttribute() ?: 'SID:'.$this->sid;
|
||||||
? $this->type->getServiceNameAttribute()
|
|
||||||
: 'SID:'.$this->sid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -755,18 +708,6 @@ class Service extends Model implements IDs
|
|||||||
: NULL;
|
: NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Service Status
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getStatusAttribute(): string
|
|
||||||
{
|
|
||||||
return $this->active
|
|
||||||
? strtolower($this->order_status)
|
|
||||||
: ((strtolower($this->order_status) === 'cancelled') ? 'cancelled' : 'inactive');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the product that supplies this service
|
* Return the product that supplies this service
|
||||||
* ie: product/*
|
* ie: product/*
|
||||||
@ -917,14 +858,14 @@ class Service extends Model implements IDs
|
|||||||
*
|
*
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function billing_charge(): float
|
private function billing_charge(): float
|
||||||
{
|
{
|
||||||
// If recur_schedule is null, then we only bill this item once
|
// If recur_schedule is null, and we have already invoiced, then nothing further required
|
||||||
if (is_null($this->getBillingIntervalAttribute()) && $this->getInvoicedToAttribute())
|
if (is_null($this->billing_interval) && $this->getInvoicedToAttribute())
|
||||||
$this->price = 0;
|
$this->price = 0;
|
||||||
|
|
||||||
return is_null($this->price)
|
return is_null($this->price)
|
||||||
? $this->product->getBaseChargeAttribute($this->getBillingIntervalAttribute(),$this->account->group)
|
? $this->billing_charge_orig
|
||||||
: $this->price;
|
: $this->price;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -945,12 +886,12 @@ class Service extends Model implements IDs
|
|||||||
$max = max($date,$this->getCancelDateAttribute())->clone();
|
$max = max($date,$this->getCancelDateAttribute())->clone();
|
||||||
|
|
||||||
if (! $this->getPaidToAttribute())
|
if (! $this->getPaidToAttribute())
|
||||||
return $this->account->taxed($this->getContractTermAttribute()*$this->getBillingChargeNormalisedAttribute());
|
return $this->contract_term*$this->billing_charge_normalised_taxed;
|
||||||
|
|
||||||
if ($this->getPaidToAttribute()->lessThan($max)) {
|
if ($this->getPaidToAttribute()->lessThan($max)) {
|
||||||
$d = $this->getPaidToAttribute()->diffInDays($max);
|
$d = $this->getPaidToAttribute()->diffInDays($max);
|
||||||
|
|
||||||
return $this->account->taxed($d/30*$this->getBillingChargeNormalisedAttribute());
|
return $d/30*$this->billing_charge_normalised_taxed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -961,11 +902,11 @@ class Service extends Model implements IDs
|
|||||||
*
|
*
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function billing_cost(): float
|
private function billing_cost(): float
|
||||||
{
|
{
|
||||||
return is_null($this->cost)
|
return is_null($this->cost)
|
||||||
? $this->product->getBaseCostAttribute()
|
? $this->product->getBaseCostAttribute()
|
||||||
: $this->cost*Invoice::billing_change($this->product->type->billing_interval,$this->product->billing_interval);
|
: $this->cost*Invoice::billing_change($this->product->type->billing_interval,$this->billing_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -985,12 +926,12 @@ class Service extends Model implements IDs
|
|||||||
$max = max($date,$this->getCancelDateAttribute())->clone();
|
$max = max($date,$this->getCancelDateAttribute())->clone();
|
||||||
|
|
||||||
if (! $this->getInvoicedToAttribute())
|
if (! $this->getInvoicedToAttribute())
|
||||||
return $this->account->taxed($this->getContractTermAttribute()*$this->getBillingChargeNormalisedAttribute());
|
return $this->contract_term*$this->billing_cost_normalised_taxed;
|
||||||
|
|
||||||
if ($this->getInvoicedToAttribute()->lessThan($max)) {
|
if ($this->getInvoicedToAttribute()->lessThan($max)) {
|
||||||
$d = $this->getInvoicedToAttribute()->diffInDays($max);
|
$d = $this->getInvoicedToAttribute()->diffInDays($max);
|
||||||
|
|
||||||
return $this->account->taxed($d/30*$this->getBillingCostNormalisedAttribute());
|
return $d/30*$this->billing_cost_normalised_taxed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1047,17 +988,6 @@ class Service extends Model implements IDs
|
|||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a service is active. It is active, if active=1, or the order_status is not in self::INACTIVE_STATUS[]
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isActive(): bool
|
|
||||||
{
|
|
||||||
return $this->attributes['active']
|
|
||||||
|| ($this->order_status && (! in_array($this->order_status,self::INACTIVE_STATUS)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the current user has the role for this service
|
* Determine if the current user has the role for this service
|
||||||
*
|
*
|
||||||
@ -1107,53 +1037,6 @@ class Service extends Model implements IDs
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Do we bill for this service
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isBilled(): bool
|
|
||||||
{
|
|
||||||
return ! ($this->external_billing || $this->suspend_billing || ($this->price === 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Has the price for this service been overridden
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isChargeOverridden(): bool
|
|
||||||
{
|
|
||||||
return ! is_null($this->price);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isCostOverridden(): bool
|
|
||||||
{
|
|
||||||
return ! is_null($this->cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isContract(): bool
|
|
||||||
{
|
|
||||||
return $this->getContractEndAttribute() && $this->getContractEndAttribute()->greaterThan(Carbon::now());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Identify if a service is being ordered, ie: not active yet nor cancelled
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isPending(): bool
|
|
||||||
{
|
|
||||||
return (! $this->active)
|
|
||||||
&& (! is_null($this->order_status))
|
|
||||||
&& (! in_array($this->order_status,array_merge(self::INACTIVE_STATUS,['INACTIVE'])));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isPendingCancel(): bool
|
|
||||||
{
|
|
||||||
return in_array(strtolower($this->order_status),['cancel-request','cancel-pending']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a collection of invoice_item objects that will be billed for the next invoice
|
* Generate a collection of invoice_item objects that will be billed for the next invoice
|
||||||
*
|
*
|
||||||
@ -1163,7 +1046,7 @@ class Service extends Model implements IDs
|
|||||||
*/
|
*/
|
||||||
public function next_invoice_items(Carbon $billdate=NULL): Collection
|
public function next_invoice_items(Carbon $billdate=NULL): Collection
|
||||||
{
|
{
|
||||||
if ($this->wasCancelled() || (! $this->isBilled()))
|
if ($this->is_cancelled || (! $this->is_billed))
|
||||||
return collect();
|
return collect();
|
||||||
|
|
||||||
$o = collect();
|
$o = collect();
|
||||||
@ -1172,7 +1055,7 @@ class Service extends Model implements IDs
|
|||||||
// Connection charges are only charged once, so ignore if if we have already billed them
|
// Connection charges are only charged once, so ignore if if we have already billed them
|
||||||
if ((! $this->invoiced_items()->where('item_type',InvoiceItem::INVOICEITEM_SETUP)->count())
|
if ((! $this->invoiced_items()->where('item_type',InvoiceItem::INVOICEITEM_SETUP)->count())
|
||||||
&& (InvoiceItem::distinct('invoice_id')->where('service_id',$this->id)->count() < 2)
|
&& (InvoiceItem::distinct('invoice_id')->where('service_id',$this->id)->count() < 2)
|
||||||
&& $this->product->getSetupChargeAttribute($this->getBillingIntervalAttribute(),$this->account->group))
|
&& $this->product->getSetupChargeAttribute($this->billing_interval,$this->account->group))
|
||||||
{
|
{
|
||||||
$ii = new InvoiceItem;
|
$ii = new InvoiceItem;
|
||||||
|
|
||||||
@ -1180,7 +1063,7 @@ class Service extends Model implements IDs
|
|||||||
$ii->service_id = $this->id;
|
$ii->service_id = $this->id;
|
||||||
$ii->product_id = $this->product_id;
|
$ii->product_id = $this->product_id;
|
||||||
$ii->item_type = InvoiceItem::INVOICEITEM_SETUP;
|
$ii->item_type = InvoiceItem::INVOICEITEM_SETUP;
|
||||||
$ii->price_base = $this->product->getSetupChargeAttribute($this->getBillingIntervalAttribute(),$this->account->group);
|
$ii->price_base = $this->product->getSetupChargeAttribute($this->billing_interval,$this->account->group);
|
||||||
$ii->start_at = $this->invoice_next;
|
$ii->start_at = $this->invoice_next;
|
||||||
$ii->stop_at = $this->invoice_next;
|
$ii->stop_at = $this->invoice_next;
|
||||||
$ii->quantity = 1;
|
$ii->quantity = 1;
|
||||||
@ -1196,14 +1079,14 @@ class Service extends Model implements IDs
|
|||||||
|
|
||||||
while ($invoiced_to <= ($this->stop_at ?: $billdate)) {
|
while ($invoiced_to <= ($this->stop_at ?: $billdate)) {
|
||||||
$ii = new InvoiceItem;
|
$ii = new InvoiceItem;
|
||||||
$period = Invoice::invoice_period($invoiced_to,$this->getBillingIntervalAttribute(),(bool)$this->product->price_recur_strict);
|
$period = Invoice::invoice_period($invoiced_to,$this->billing_interval,(bool)$this->product->price_recur_strict);
|
||||||
|
|
||||||
$ii->active = TRUE;
|
$ii->active = TRUE;
|
||||||
$ii->service_id = $this->id;
|
$ii->service_id = $this->id;
|
||||||
$ii->product_id = $this->product_id;
|
$ii->product_id = $this->product_id;
|
||||||
$ii->item_type = InvoiceItem::INVOICEITEM_SERVICE;
|
$ii->item_type = InvoiceItem::INVOICEITEM_SERVICE;
|
||||||
$ii->price_base = $this->billing_charge();
|
$ii->price_base = $this->billing_charge;
|
||||||
$ii->recur_schedule = $this->getBillingIntervalAttribute();
|
$ii->recur_schedule = $this->billing_interval;
|
||||||
$ii->start_at = $invoiced_to;
|
$ii->start_at = $invoiced_to;
|
||||||
$ii->stop_at = ($this->stop_at && ($this->stop_at < Arr::get($period,'end'))) ? $this->stop_at : Arr::get($period,'end');
|
$ii->stop_at = ($this->stop_at && ($this->stop_at < Arr::get($period,'end'))) ? $this->stop_at : Arr::get($period,'end');
|
||||||
$ii->quantity = Invoice::invoice_quantity($ii->start_at,$ii->stop_at,$period);
|
$ii->quantity = Invoice::invoice_quantity($ii->start_at,$ii->stop_at,$period);
|
||||||
@ -1252,14 +1135,4 @@ class Service extends Model implements IDs
|
|||||||
{
|
{
|
||||||
return $this->order_info ? $this->order_info->get($key) : NULL;
|
return $this->order_info ? $this->order_info->get($key) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Service that was cancelled or never provisioned
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function wasCancelled(): bool
|
|
||||||
{
|
|
||||||
return in_array($this->order_status,self::INACTIVE_STATUS);
|
|
||||||
}
|
|
||||||
}
|
}
|
7
resources/views/components/ribbons/change.blade.php
Normal file
7
resources/views/components/ribbons/change.blade.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@if($change)
|
||||||
|
<div class="ribbon-wrapper ribbon-lg">
|
||||||
|
<div class="ribbon bg-warning">
|
||||||
|
Change
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
7
resources/views/components/ribbons/pending.blade.php
Normal file
7
resources/views/components/ribbons/pending.blade.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@if($pending)
|
||||||
|
<div class="ribbon-wrapper ribbon-lg">
|
||||||
|
<div class="ribbon bg-warning">
|
||||||
|
Pending
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
@ -24,7 +24,7 @@
|
|||||||
<td>{{ $so->stop_at ? $so->stop_at->format('Y-m-d') : '-' }}</td>
|
<td>{{ $so->stop_at ? $so->stop_at->format('Y-m-d') : '-' }}</td>
|
||||||
<td>{{ $so->invoice_to ? $so->invoice_to->format('Y-m-d') : '-' }}</td>
|
<td>{{ $so->invoice_to ? $so->invoice_to->format('Y-m-d') : '-' }}</td>
|
||||||
<td>{{ $so->active ? 'YES' : 'NO' }}</td>
|
<td>{{ $so->active ? 'YES' : 'NO' }}</td>
|
||||||
<td class="text-right">{{ $a=number_format($so->billing_charge_normalised,2) }}</td>
|
<td class="text-right">{{ $a=number_format($so->billing_charge_normalised_taxed,2) }}</td>
|
||||||
<td class="text-right">{{ $b=number_format($so->product->cost_normalized(),2) }}</td>
|
<td class="text-right">{{ $b=number_format($so->product->cost_normalized(),2) }}</td>
|
||||||
<td><button class="btn btn-sm @if($a<$b)btn-danger @else btn-success @endif"><small>@if($a<$b)<i class="fas fa-fw fa-exclamation"></i> @else <i class="fas fa-fw fa-check"></i> @endif</small></button></td>
|
<td><button class="btn btn-sm @if($a<$b)btn-danger @else btn-success @endif"><small>@if($a<$b)<i class="fas fa-fw fa-exclamation"></i> @else <i class="fas fa-fw fa-check"></i> @endif</small></button></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<div class="col-8 col-sm-5 col-md-12 col-lg-6">
|
<div class="col-8 col-sm-5 col-md-12 col-lg-6">
|
||||||
<x-leenooks::form.date name="change_date" icon="fa-calendar" label="Request Change Date" :value="Carbon::now()->addDays(7)->format('Y-m-d')"/>
|
<x-leenooks::form.date name="change_date" icon="fa-calendar" label="Request Change Date" :value="Carbon::now()->addDays(7)->format('Y-m-d')"/>
|
||||||
</div>
|
</div>
|
||||||
@if($so->isContract())
|
@if($so->is_contracted)
|
||||||
<div class="col-12 col-sm-7 col-md-12 col-lg-6">
|
<div class="col-12 col-sm-7 col-md-12 col-lg-6">
|
||||||
<strong>NOTE</strong>: This service is in a contract until <strong>{{ $so->contract_end->format('Y-m-d') }}</strong>, thus it may not be able to change plans.
|
<strong>NOTE</strong>: This service is in a contract until <strong>{{ $so->contract_end->format('Y-m-d') }}</strong>, thus it may not be able to change plans.
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,9 +45,9 @@
|
|||||||
<td>{{ $oo->service_expire ? $oo->service_expire->format('Y-m-d') : '-' }}</td>
|
<td>{{ $oo->service_expire ? $oo->service_expire->format('Y-m-d') : '-' }}</td>
|
||||||
<td>{{ $oo->registrar->name }}</td>
|
<td>{{ $oo->registrar->name }}</td>
|
||||||
<td>{{ $oo->registrar_ns }}</td>
|
<td>{{ $oo->registrar_ns }}</td>
|
||||||
<td>@if ($oo->service->isBilled()) {{ $oo->service->invoice_next->format('Y-m-d') }}@else - @endif</td>
|
<td>@if ($oo->service->is_billed) {{ $oo->service->invoice_next->format('Y-m-d') }}@else - @endif</td>
|
||||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
||||||
<td>{{ $oo->service->billing_interval_string }}</td>
|
<td>{{ $oo->service->billing_interval_name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -49,9 +49,9 @@
|
|||||||
<td>{{ $oo->admin_url }}</td>
|
<td>{{ $oo->admin_url }}</td>
|
||||||
<td>@if($oo->admin_user){{ $oo->admin_user }}/{{ $oo->admin_pass }}@else @endif</td>
|
<td>@if($oo->admin_user){{ $oo->admin_user }}/{{ $oo->admin_pass }}@else @endif</td>
|
||||||
<td class="text-right">{{ number_format($oo->accounts ?: 0) }}</td>
|
<td class="text-right">{{ number_format($oo->accounts ?: 0) }}</td>
|
||||||
<td>@if ($oo->service->isBilled()) {{ $oo->service->invoice_next->format('Y-m-d') }} @else - @endif</td>
|
<td>@if ($oo->service->is_billed) {{ $oo->service->invoice_next->format('Y-m-d') }} @else - @endif</td>
|
||||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
||||||
<td>{{ $oo->service->billing_interval_string }}</td>
|
<td>{{ $oo->service->billing_interval_name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
<li class="nav-item ml-auto"><a class="nav-link" href="#billing" data-toggle="tab">Billing History</a></li>
|
<li class="nav-item ml-auto"><a class="nav-link" href="#billing" data-toggle="tab">Billing History</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#internal" data-toggle="tab">Internal</a></li>
|
<li class="nav-item"><a class="nav-link" href="#internal" data-toggle="tab">Internal</a></li>
|
||||||
<li class="nav-item"><a @class(['nav-link','active'=>session()->has('service_update')]) href="#update" data-toggle="tab">Update</a></li>
|
<li class="nav-item"><a @class(['nav-link','active'=>session()->has('service_update')]) href="#update" data-toggle="tab">Update</a></li>
|
||||||
@if($o->active || $o->isPending())
|
@if($o->active || $o->is_pending_active)
|
||||||
<li class="nav-item"><a @class(['nav-link','active'=>session()->has('charge_add')]) href="#charge" data-toggle="tab">Charge</a></li>
|
<li class="nav-item"><a @class(['nav-link','active'=>session()->has('charge_add')]) href="#charge" data-toggle="tab">Charge</a></li>
|
||||||
@endif
|
@endif
|
||||||
@endcan
|
@endcan
|
||||||
@ -95,7 +95,7 @@
|
|||||||
@include('theme.backend.adminlte.service.widget.update')
|
@include('theme.backend.adminlte.service.widget.update')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($o->active || $o->isPending())
|
@if($o->active || $o->is_pending_active)
|
||||||
<div @class(['tab-pane','fade','show active'=>session()->pull('charge_add')]) id="charge">
|
<div @class(['tab-pane','fade','show active'=>session()->pull('charge_add')]) id="charge">
|
||||||
@include('theme.backend.adminlte.service.widget.charge')
|
@include('theme.backend.adminlte.service.widget.charge')
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,9 +43,9 @@
|
|||||||
<td>{{ $oo->service->name }}</td>
|
<td>{{ $oo->service->name }}</td>
|
||||||
<td>{{ $oo->service_expire ? $oo->service_expire->format('Y-m-d') : '-' }}</td>
|
<td>{{ $oo->service_expire ? $oo->service_expire->format('Y-m-d') : '-' }}</td>
|
||||||
<td>{{ $oo->service->product->supplier->name }}</td>
|
<td>{{ $oo->service->product->supplier->name }}</td>
|
||||||
<td>@if ($oo->service->isBilled()) {{ $oo->service->invoice_next->format('Y-m-d') }}@else - @endif</td>
|
<td>@if ($oo->service->is_billed) {{ $oo->service->invoice_next->format('Y-m-d') }}@else - @endif</td>
|
||||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
||||||
<td>{{ $oo->service->billing_interval_string }}</td>
|
<td>{{ $oo->service->billing_interval_name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
<td>{{ $o->name }}</td>
|
<td>{{ $o->name }}</td>
|
||||||
<td>{{ $o->product->name }}</td>
|
<td>{{ $o->product->name }}</td>
|
||||||
<td>{{ $o->supplierid }}</td>
|
<td>{{ $o->supplierid }}</td>
|
||||||
<td class="text-right">{{ number_format($o->billing_charge_normalised,2) }}</td>
|
<td class="text-right">{{ number_format($o->billing_charge_normalised_taxed,2) }}</td>
|
||||||
<td class="text-right">{{ number_format($o->billing_cost_normalised,2) }}</td>
|
<td class="text-right">{{ number_format($o->billing_cost_normalised_taxed,2) }}</td>
|
||||||
<td class="text-right">{{ $o->product->hasUsage() ? number_format($o->type->usage_summary(0)->sum()/1000,1) : '-' }}</td>
|
<td class="text-right">{{ $o->product->hasUsage() ? number_format($o->type->usage_summary(0)->sum()/1000,1) : '-' }}</td>
|
||||||
<td>{{ $o->product->supplier->name }}</td>
|
<td>{{ $o->product->supplier->name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
<!-- $o=Service\Broadband::class -->
|
<!-- $o=Service\Broadband::class -->
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@if($o->service->isPending())
|
<x-ribbons.change :change="$o->service->is_pending_change"/>
|
||||||
<div class="ribbon-wrapper ribbon-lg">
|
<x-ribbons.pending :pending="$o->service->is_pending_active"/>
|
||||||
<div class="ribbon bg-warning">
|
|
||||||
Pending
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card-header bg-gray-dark">
|
<div class="card-header bg-gray-dark">
|
||||||
<h3 class="card-title">Broadband Details</h3>
|
<h3 class="card-title">Broadband Details</h3>
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
<!-- $o=Service\Domain::class -->
|
<!-- $o=Service\Domain::class -->
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@if($o->service->isPending())
|
<x-ribbons.change :change="$o->service->is_pending_change"/>
|
||||||
<div class="ribbon-wrapper ribbon-lg">
|
<x-ribbons.pending :pending="$o->service->is_pending_active"/>
|
||||||
<div class="ribbon bg-warning">
|
|
||||||
Pending
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card-header bg-gray-dark">
|
<div class="card-header bg-gray-dark">
|
||||||
<h3 class="card-title">Domain Details</h3>
|
<h3 class="card-title">Domain Details</h3>
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
<!-- $o=Service\Email::class -->
|
<!-- $o=Service\Email::class -->
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@if($o->service->isPending())
|
<x-ribbons.change :change="$o->service->is_pending_change"/>
|
||||||
<div class="ribbon-wrapper ribbon-lg">
|
<x-ribbons.pending :pending="$o->service->is_pending_active"/>
|
||||||
<div class="ribbon bg-warning">
|
|
||||||
Pending
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card-header bg-gray-dark">
|
<div class="card-header bg-gray-dark">
|
||||||
<h3 class="card-title">Email Hosting Details</h3>
|
<h3 class="card-title">Email Hosting Details</h3>
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
<!-- $o=Service\Host::class -->
|
<!-- $o=Service\Host::class -->
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@if($o->service->isPending())
|
<x-ribbons.change :change="$o->service->is_pending_change"/>
|
||||||
<div class="ribbon-wrapper ribbon-lg">
|
<x-ribbons.pending :pending="$o->service->is_pending_active"/>
|
||||||
<div class="ribbon bg-warning">
|
|
||||||
Pending
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card-header bg-gray-dark">
|
<div class="card-header bg-gray-dark">
|
||||||
<h3 class="card-title">Hosting Details</h3>
|
<h3 class="card-title">Hosting Details</h3>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<td><x-button.status :status="$o->status" :substatus="$o->order_status"/></td>
|
<td><x-button.status :status="$o->status" :substatus="$o->order_status"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
@if($o->isPendingCancel())
|
@if($o->is_pending_cancel)
|
||||||
<tr>
|
<tr>
|
||||||
<th>Cancel Date</th>
|
<th>Cancel Date</th>
|
||||||
<td>{{ $o->stop_at->format('Y-m-d') }}</td>
|
<td>{{ $o->stop_at->format('Y-m-d') }}</td>
|
||||||
@ -34,26 +34,26 @@
|
|||||||
<td>{{ $o->order_info_reference ?? '' }}</td>
|
<td>{{ $o->order_info_reference ?? '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
@if($o->start_at && $o->isPending())
|
@if($o->start_at && $o->is_pending_active)
|
||||||
<tr>
|
<tr>
|
||||||
<th>Pending Connection</th>
|
<th>Pending Connection</th>
|
||||||
<td>{{ $o->start_at->format('Y-m-d') }}</td>
|
<td>{{ $o->start_at->format('Y-m-d') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
@if(($o->active || $o->isPending()) && (! $o->external_billing))
|
@if(($o->active || $o->is_pending_active) && (! $o->external_billing))
|
||||||
<tr>
|
<tr>
|
||||||
<th>Billed</th>
|
<th>Billed</th>
|
||||||
<td>{{ $o->billing_interval_string }}</td>
|
<td>{{ $o->billing_interval_name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
@if($o->isChargeOverridden())
|
@if($o->is_charge_overridden)
|
||||||
<td>@if($o->billing_charge < $o->charge_orig)<del>${{ number_format($o->charge_orig,2) }}</del> @endif${{ number_format($o->billing_charge,2) }}</td>
|
<td>@if($o->billing_charge < $o->billing_charge_orig)<del>${{ number_format($o->billing_charge_orig_taxed,2) }}</del> @endif${{ number_format($o->billing_charge_taxed,2) }}</td>
|
||||||
@else
|
@else
|
||||||
<td>${{ number_format($o->billing_charge,2) }}</td>
|
<td>${{ number_format($o->billing_charge_taxed,2) }}</td>
|
||||||
@endif
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
@if($o->isActive() && $o->invoiced_to)
|
@if($o->is_active && $o->invoiced_to)
|
||||||
<tr>
|
<tr>
|
||||||
<th>Invoiced To</th>
|
<th>Invoiced To</th>
|
||||||
<td>{{ $o->invoiced_to->format('Y-m-d') }}</td>
|
<td>{{ $o->invoiced_to->format('Y-m-d') }}</td>
|
||||||
@ -83,7 +83,7 @@
|
|||||||
<td>@if($o->billing)Direct Debit @else Invoice @endif</td>
|
<td>@if($o->billing)Direct Debit @else Invoice @endif</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@elseif($o->wasCancelled())
|
@elseif($o->is_cancelled)
|
||||||
<tr>
|
<tr>
|
||||||
<th>Cancelled</th>
|
<th>Cancelled</th>
|
||||||
<td>{{ ($o->stop_at ?: $o->paid_to)?->format('Y-m-d') }}</td>
|
<td>{{ ($o->stop_at ?: $o->paid_to)?->format('Y-m-d') }}</td>
|
||||||
@ -92,7 +92,7 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($o->active || $o->isPending())
|
@if($o->active || $o->is_pending_active)
|
||||||
<div class="card-footer sm">
|
<div class="card-footer sm">
|
||||||
<strong><sup>*</sup>NOTE:</strong> Estimated Invoice does not include any setup, connection nor all current billing cycle usage charges.
|
<strong><sup>*</sup>NOTE:</strong> Estimated Invoice does not include any setup, connection nor all current billing cycle usage charges.
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
<th> </th>
|
<th> </th>
|
||||||
@endif
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th>Client</th>
|
<th>Client</th>
|
||||||
@ -32,13 +33,14 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Product</th>
|
<th>Product</th>
|
||||||
<td><a href="{{ url('a/product/details',$o->product_id) }}">#{{ $o->product_id }}: {{ $o->product->name }}</a></td>
|
<td><a href="{{ route('product',['pdo'=>$o->product_id]) }}">#{{ $o->product_id }}: {{ $o->product->name }}</a></td>
|
||||||
<td><a href="{{ url('a/product/details',$c->id) }}">#{{ $c->supplied->id }}: {{ $c->supplied->name_long }}</a></td>
|
<td><a href="{{ route('supplier.product.type',['id'=>$c->supplied->id,'spo'=>$c->supplied->supplier_detail_id,'type'=>$c->supplied->category]) }}">#{{ $c->supplied->id }}: {{ $c->supplied->name_long }}</a></td>
|
||||||
@if($p->exists)
|
|
||||||
<th> </th>
|
|
||||||
<td class="text-center" colspan="2">#{{ $p->supplied->id }}: {{ $p->supplied->name_long }}</td>
|
|
||||||
@endif
|
|
||||||
<td>{{ $c->category_name }}</td>
|
<td>{{ $c->category_name }}</td>
|
||||||
|
@if($p->exists)
|
||||||
|
<th><a href="{{ route('product',['pdo'=>$p->id]) }}">#{{ $p->id }}: {{ $p->name }}</a></th>
|
||||||
|
<td class="text-center"><a href="{{ route('supplier.product.type',['id'=>$p->supplied->id,'spo'=>$p->supplied->supplier_detail_id,'type'=>$p->supplied->category]) }}">#{{ $p->supplied->id }}: {{ $p->supplied->name_long }}</a></td>
|
||||||
|
<td> </td>
|
||||||
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
@ -55,11 +57,11 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Billed</th>
|
<th>Billed</th>
|
||||||
<td>{{ $o->billing_interval_string }}</td>
|
<td>{{ $o->billing_interval_name }}</td>
|
||||||
<td>{{ $c->type->billing_interval_string }}</td>
|
<td>{{ $c->type->billing_interval_string }}</td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
@if($p->exists)
|
@if($p->exists)
|
||||||
<td>{{ $o->billing_interval_string }}</td>
|
<td>{{ $o->billing_interval_name }}</td>
|
||||||
<td>{{ $p->type->billing_interval_string }}</td>
|
<td>{{ $p->type->billing_interval_string }}</td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
@endif
|
@endif
|
||||||
@ -67,11 +69,11 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Billing Price</th>
|
<th>Billing Price</th>
|
||||||
<td @if($o->isChargeOverridden())class="text-danger"@endif>${{ number_format($b=$o->billing_charge,2) }}</td>
|
<td @class(['text-danger'=>$o->is_charge_overridden])>${{ number_format($b=$o->billing_charge_taxed,2) }}</td>
|
||||||
<td @if($o->isCostOverridden())class="text-danger"@endif>${{ number_format($a=$o->billing_cost,2) }}</td>
|
<td @class(['text-danger'=>$o->is_cost_overridden])>${{ number_format($a=$o->billing_cost_taxed,2) }}</td>
|
||||||
<td>{!! markup($a,$b) !!}</td>
|
<td>{!! markup($a,$b) !!}</td>
|
||||||
@if($p->exists)
|
@if($p->exists)
|
||||||
<td @if($o->isChargeOverridden())class="text-danger"@endif>${{ number_format($b=$o->account->taxed($p->base_charge),2) }}</td>
|
<td @if($o->is_charge_overridden)class="text-danger"@endif>${{ number_format($b=$o->account->taxed($p->base_charge),2) }}</td>
|
||||||
<td>${{ number_format($a=$o->account->taxed($p->base_cost),2) }}</td>
|
<td>${{ number_format($a=$o->account->taxed($p->base_cost),2) }}</td>
|
||||||
<td>{!! markup($a,$b) !!}</td>
|
<td>{!! markup($a,$b) !!}</td>
|
||||||
@endif
|
@endif
|
||||||
@ -79,24 +81,24 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Monthly Price</th>
|
<th>Monthly Price</th>
|
||||||
<td @if($x=$o->isChargeOverridden()) class="text-danger" @endif>
|
<td @class(['text-danger'=>$o->is_charge_overridden])>
|
||||||
@if($x)
|
@if($o->is_charge_overridden)
|
||||||
<abbr title="${{ number_format($b=$o->account->taxed($c->base_charge)*Invoice::billing_change($o->billing_interval,Invoice::BILL_MONTHLY),2) }}">${{ number_format($b=$o->billing_charge_normalised,2) }}
|
<abbr title="${{ number_format($o->billing_charge_orig_normalised_taxed,2) }}">${{ number_format($b=$o->billing_charge_normalised_taxed,2) }}
|
||||||
@else
|
@else
|
||||||
${{ number_format($b=$o->billing_charge_normalised,2) }}
|
${{ number_format($b=$o->billing_charge_normalised_taxed,2) }}
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td @if($x=$o->isCostOverridden()) class="text-danger" @endif>
|
<td @class(['text-danger'=>$o->is_cost_overridden])>
|
||||||
@if($x)
|
@if($o->is_cost_overridden)
|
||||||
<abbr title="${{ number_format($a=$o->account->taxed($c->base_cost)*Invoice::billing_change($o->billing_interval,Invoice::BILL_MONTHLY),2) }}">${{ number_format($b=$o->billing_cost_normalised,2) }}
|
<abbr title="${{ number_format($o->billing_cost_orig_normalised_taxed,2) }}">${{ number_format($a=$o->billing_cost_normalised_taxed,2) }}
|
||||||
@else
|
@else
|
||||||
${{ number_format($a=$o->billing_cost_normalised,2) }}
|
${{ number_format($a=$o->billing_cost_normalised_taxed,2) }}
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td>{!! markup($a,$b) !!}</td>
|
<td>{!! markup($a,$b) !!}</td>
|
||||||
@if($p->exists)
|
@if($p->exists)
|
||||||
<td @if($x=$o->isChargeOverridden()) class="text-danger" @endif>${{ number_format($b=$o->account->taxed($p->base_charge)*Invoice::billing_change($o->billing_interval,Invoice::BILL_MONTHLY),2) }}</td>
|
<td @class(['text-danger'=>$o->is_charge_overridden])>${{ number_format($b=$o->account->taxed($p->base_charge)*Invoice::billing_change($o->billing_interval,Invoice::BILL_MONTHLY),2) }}</td>
|
||||||
<td>${{ number_format($a=$o->account->taxed($p->base_cost)*Invoice::billing_change($o->billing_interval,Invoice::BILL_MONTHLY),2) }}</td>
|
<td @class(['text-danger'=>$o->is_cost_overridden])>${{ number_format($a=$o->account->taxed($p->base_cost)*Invoice::billing_change($o->billing_interval,Invoice::BILL_MONTHLY),2) }}</td>
|
||||||
<td>{!! markup($a,$b) !!}</td>
|
<td>{!! markup($a,$b) !!}</td>
|
||||||
@endif
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
@ -129,15 +131,18 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Contract Left</th>
|
<th>Contract Left</th>
|
||||||
@if($o->isContract())
|
@if($o->is_contracted)
|
||||||
<td>${{ number_format($o->billing_charge_to($o->contract_end),2) }} (<small>{{ $o->paid_to?->format('Y-m-d') }}</small>)</td>
|
<td>${{ number_format($o->billing_charge_to($o->contract_end),2) }} (<small>{{ $o->paid_to?->format('Y-m-d') }}</small>)</td>
|
||||||
<td>${{ number_format($o->billing_cost_to($o->contract_end),2) }} (<small>{{ $o->invoiced_to?->format('Y-m-d') }}</small>)</td>
|
<td>${{ number_format($o->billing_cost_to($o->contract_end),2) }} (<small>{{ $o->invoiced_to?->format('Y-m-d') }}</small>)</td>
|
||||||
<td>{{ $o->contract_end->format('Y-m-d') }}<br><small>({{ $o->contract_end->diffForHumans(now(),CarbonInterface::DIFF_RELATIVE_TO_OTHER,FALSE,2) }} today)</small></td>
|
<td>{{ $o->contract_end->format('Y-m-d') }}<br><small>({{ $o->contract_end->diffForHumans(now(),CarbonInterface::DIFF_RELATIVE_TO_OTHER,FALSE,2) }} today)</small></td>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<td colspan="2" class="text-center">Not on contract</td>
|
<td colspan="2" class="text-center">Not on contract</td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if($p->exists)
|
||||||
|
<td colspan="3"> </td>
|
||||||
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
@ -1,13 +1,8 @@
|
|||||||
<!-- $o=Service\Phone::class -->
|
<!-- $o=Service\Phone::class -->
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@if($o->service->isPending())
|
<x-ribbons.change :change="$o->service->is_pending_change"/>
|
||||||
<div class="ribbon-wrapper ribbon-lg">
|
<x-ribbons.pending :pending="$o->service->is_pending_active"/>
|
||||||
<div class="ribbon bg-warning">
|
|
||||||
Pending
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card-header bg-gray-dark">
|
<div class="card-header bg-gray-dark">
|
||||||
<h3 class="card-title">Phone Details</h3>
|
<h3 class="card-title">Phone Details</h3>
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
@if($o->service->isPending())
|
<x-ribbons.change :change="$o->service->is_pending_change"/>
|
||||||
<div class="ribbon-wrapper ribbon-lg">
|
<x-ribbons.pending :pending="$o->service->is_pending_active"/>
|
||||||
<div class="ribbon bg-warning">
|
|
||||||
Pending
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card-header bg-gray-dark">
|
<div class="card-header bg-gray-dark">
|
||||||
<h3 class="card-title">SSL Details</h3>
|
<h3 class="card-title">SSL Details</h3>
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
<!-- PRODUCT -->
|
<!-- PRODUCT -->
|
||||||
<x-leenooks::form.select name="product_id" icon="fa-list" label="Product" :helper="$o->product->category_name"
|
<x-leenooks::form.select name="product_id" icon="fa-list" label="Product" :helper="$o->product->category_name"
|
||||||
:value="$o->product_id"
|
:value="$o->product_id"
|
||||||
:options="Product::get()
|
:options="Product::with(['type.supplied','translate'])
|
||||||
|
->get()
|
||||||
->filter(fn($item)=>($item->category === $o->product->category))
|
->filter(fn($item)=>($item->category === $o->product->category))
|
||||||
->sortBy('name')
|
->sortBy('name')
|
||||||
->map(fn($item)=>[
|
->map(fn($item)=>[
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
<td class="text-right">${{ number_format($a=$oo->sum('base'),2) }}</td>
|
<td class="text-right">${{ number_format($a=$oo->sum('base'),2) }}</td>
|
||||||
<td class="text-right">${{ number_format($oo->sum('excess'),2) }}</td>
|
<td class="text-right">${{ number_format($oo->sum('excess'),2) }}</td>
|
||||||
<td class="text-right">${{ number_format($x=$oo->sum('cost'),2) }}</td>
|
<td class="text-right">${{ number_format($x=$oo->sum('cost'),2) }}</td>
|
||||||
<td class="text-right">${{ number_format($b=$oo->first()->service->billing_charge_normalised,2) }}</td>
|
<td class="text-right">${{ number_format($b=$oo->first()->service->billing_charge_normalised_taxed,2) }}</td>
|
||||||
<td class="text-right {{ $b-$a < 0 ? 'text-danger' : '' }}">${{ number_format($b-$a,2) }}</td>
|
<td class="text-right {{ $b-$a < 0 ? 'text-danger' : '' }}">${{ number_format($b-$a,2) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@php($cost += $x)
|
@php($cost += $x)
|
||||||
@ -66,7 +66,7 @@
|
|||||||
<td class="text-right">${{ number_format($a=$oo->sum('base'),2) }}</td>
|
<td class="text-right">${{ number_format($a=$oo->sum('base'),2) }}</td>
|
||||||
<td class="text-right">${{ number_format($oo->sum('excess'),2) }}</td>
|
<td class="text-right">${{ number_format($oo->sum('excess'),2) }}</td>
|
||||||
<td class="text-right">${{ number_format($x=$oo->sum('cost'),2) }}</td>
|
<td class="text-right">${{ number_format($x=$oo->sum('cost'),2) }}</td>
|
||||||
<td class="text-right">${{ number_format($b=$oo->first()->service->billing_charge_normalised,2) }}</td>
|
<td class="text-right">${{ number_format($b=$oo->first()->service->billing_charge_normalised_taxed,2) }}</td>
|
||||||
<td class="text-right {{ $b-$a < 0 ? 'text-danger' : '' }}">${{ number_format($b-$a,2) }}</td>
|
<td class="text-right {{ $b-$a < 0 ? 'text-danger' : '' }}">${{ number_format($b-$a,2) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@php($cost += $x)
|
@php($cost += $x)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user